 /*
  * xzsort - Sort the .xznol file (or another file
  * if specified.  This will read in the file,
  * sort by username (the first line) and will then
  * re-write out the file.  It will not lose any
  * information.  It may, in the future, be able to
  * add to and delete from the file, but not yet....
  *
  * Created by:     Derek Atkins
  *
  */

#include <strings.h>
#include <stdio.h>

#define DEF_FILE ".xznol"

typedef struct _entry {
    char *name;
    char *info;
    struct _entry *left;
    struct _entry *right;
} entry;

entry *namelist;
char *whoami;
int num;
extern char *malloc(), *realloc();

main(argc, argv)
int argc;
char *argv[];

{
    int arg;
    char *filename = NULL, *temp;

    whoami = argv[0];

    arg = 1;
    for (;arg<argc;arg++) {
	if (*argv[arg] == '-') {

	    if(strlen(argv[arg]) > 2)
		usage(whoami);

	    switch (argv[arg][1]) {
	    case 'f':
		if (arg == argc)
		    usage(whoami);
		arg++;
		filename = argv[arg];
		break;
	    default:
		usage(whoami);
	    }
	}
    }

    if (filename == NULL) {
	temp = (char *) getenv("HOME");
	filename = malloc(strlen(temp) + strlen(DEF_FILE) + 1);
	strcpy(filename,temp);
	strcpy(filename,DEF_FILE);
    }

    if (loadfile(filename)) {
	printf("%s: Error while loading file %s.\n",whoami,filename);
	exit(1);
    }
    printf("%d names loaded from %s.\n",num,filename);

    if (savefile(filename)) {
	printf("%s: error while saving file %s.\n",whoami,filename);
	exit(1);
    }

    exit(0);
}

loadfile(filename)
char *filename;

{
    FILE *fp, *fp2;
    int flag;
    entry *new;
    char *buf, name[BUFSIZ], *fname;
    entry *addname();

    num = 0;
    namelist = NULL;
    fname = malloc(strlen(filename)+2);

    if ((fp = fopen(filename, "r")) == NULL) {
	printf("Cannot open file %s.\n",filename);
	return(1);
    }
    strcpy(fname, filename);
    strcat(fname, "~");
    if ((fp2 = fopen(fname, "w")) == NULL) {
	printf("Cannot open file %s to write.\n", fname);
	return(1);
    }
    flag = 0;
    while (getline(fp, name) != EOF) {
	fprintf(fp2, "%s\n", name);
	if (!flag) {
	    new = (entry *) malloc(sizeof(entry));
	    new->name = malloc(strlen(name)+1);
	    new->info = NULL;
	    new->left = new->right = NULL;
	    strcpy(new->name, name);
	    buf = NULL;
	    flag = 1;
	} else {
	    if (strcmp(name, ".")) {
		if (buf == NULL) {
		    buf = malloc(strlen(name)+1);
		    strcpy(buf,name);
		} else {
		    buf = realloc(buf,strlen(buf) + strlen(name)+2);
		    strcat(buf,"\n");
		    strcat(buf,name);
		}
	    } else {
		if (buf != NULL) {
		    new->info = malloc(strlen(buf)+1);
		    strcpy(new->info, buf);
		} else
		    new->info = NULL;
		flag = 0;
		namelist = addname(new, namelist);
		num++;
	    }
	}
    }
    fclose(fp2);
    fclose(fp);
    return(0);
}

getline(fp, line)
FILE *fp;
char line[];

{
    int i = 0, ch;

    while((i < BUFSIZ) && ((ch = getc(fp)) != EOF) && (ch != '\n')) {
	line[i++] = ch;
    }
    line[i] = '\0';

    if (ch == '\n')
	return i;
    else
	return ch;
}
    

entry *addname(new, root)
entry *new, *root;

{
    int cond;

    if (root == NULL) {
	root = new;
    } else if ((cond = strcmp(root->name, new->name)) == 0) {
	printf("Name repeated twice:  %s.\n", new->name);
	return root;
    } else if (cond < 0)
	root->right = addname(new, root->right);
    else 
	root->left = addname(new, root->left);
    return root;
}

savefile(filename)
char *filename;

{
    FILE *fp;
    void printout();

    if ((fp = fopen(filename, "w")) == NULL) {
	printf("Cannot write to file %s.\n",filename);
	return(1);
    }

    printout(fp, namelist);

    fclose(fp);
    return(0);
}

void printout(fp, root)
FILE *fp;
entry *root;

{
    if (root != NULL) {
	printout(fp, root->left);
	fprintf(fp, "%s\n", root->name);
	if (root->info != NULL)
	    fprintf(fp, "%s\n", root->info);
	fprintf(fp, ".\n");
	printout(fp, root->right);
    }
}

usage(name)
char *name;

{
    printf("Usage:  %s [-f filename]\n", name);
    exit(1);
}
