larry@ihuxf.UUCP (Larry Marek) (10/15/83)
Most people like to keep the "active" file in some specific order, so that certain related newsgroups can be read sequentially. Rather than edit the file by hand, my friend Alan Hastings came up with this program. When it complete, the active file will be sorted according to the template "master", any groups that did not have a match will be at the end of the file. It will leave the original file in "active.old" Usage: asort active < master asort.c: ----- #define PARANOID /* copy file before nuking it */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/signal.h> /* * asort.c * sort active newsgroup file according to template file * * Alan Hastings BTL IH 7/28/82 * * assumptions: active files don't get very big, newsgroups not found in * the template belong at the end, pathname does not exceed * LSIZE characters, directory where active file lives is * writable. * * A temporary file is created in the same directory as the target * file, so it may be built and linked in, minimizing the chance * of corrupting the active file. Signals are ignored. */ #define LSIZE 128 /* max chars/input line */ #define MAXGRP 500 /* max newsgroups in active file */ #define EOA (char *)(-1) /* End Of Array marker */ #define USED (char *)0 /* marker to remove name from array */ #define AMODE 0666 /* active file mode: rw-rw-rw */ char temp[LSIZE]; /* temp file name */ main(argc, argv) int argc; char **argv; { extern char *malloc(), *strcpy(), *strrchr(), *mktemp(), *strchr(); extern int (*signal())(); FILE *in, *out; char lbuf[LSIZE], *a[MAXGRP]; register char *ta, *tta, **t; int count; struct stat stbuf; unsigned asize; if (argc != 2) { fprintf(stderr, "usage: %s pathname\n", argv[0]); return(1); } (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); /* * only argument is pathname of file to sort */ if ((in = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]); return(2); } /* * fstat to get size */ if (fstat(fileno(in), &stbuf) < 0) { fprintf(stderr, "%s: cannot stat %s\n", argv[0], argv[1]); return(3); } /* * create a virtual file in data space */ if ((tta = malloc(asize = (unsigned)stbuf.st_size)) == (char *)0) { fprintf(stderr, "%s: not enough mem\n", argv[0]); return(4); } if (fread(tta, sizeof(char), (int)asize, in) != (int)asize) { fprintf(stderr, "%s: read error on %s\n", argv[0], argv[1]); return(5); } (void) fclose(in); /* * replace \n with \0 in our `virtual' file * and set up pointers to the resulting strings */ for (t = a, ta = tta; ta < tta + asize && t < &a[MAXGRP]; t++) { for (*t = ta; *ta != '\n' && ta < tta + asize; ta++) ; *ta++ = '\0'; } *t = EOA; /* * make a unique file name -- .../ASORTxxxxxx */ (void) strcpy(temp, argv[1]); if (tta = strrchr(temp, '/')) *++tta = '\0'; else tta = temp; (void) strcpy(tta, "ASORTXXXXXX"); (void) mktemp(tta); if ((out = fopen(temp, "w")) == NULL) { fprintf(stderr, "%s: cannot creat %s\n", argv[0], temp); return(6); } (void) chmod(temp, AMODE); /* * template had better be on stdin... */ while (gets(lbuf) != NULL) for (t = a; *t != EOA; t++) { count = abs((int) (*t) - (int) strchr(*t, ' ')); if (*t != USED && strncmp(*t, lbuf, count) == 0) { /* * found one, print it + mark it used */ fprintf(out, "%s\n", *t); *t = USED; } } /* * find names that weren't in the template and stuff them on the end */ for (t = a; *t != EOA; t++) if (*t != USED) fprintf(out, "%s\n", *t); (void) fclose(out); #ifdef PARANOID { char savname[LSIZE], *strcat(); (void) strcat(strcpy(savname, argv[1]), ".old"); (void) unlink(savname); /* in case it's there */ if (link(argv[1], savname) < 0) { fprintf(stderr, "%s: cannot link %s to %s\n", argv[0], argv[1], savname); done(7); } } #endif PARANOID /* * check to see if the active file has changed whilst we were * mucking about */ if (stat(argv[1], &stbuf) < 0) { fprintf(stderr, "%s: cannot re-stat %s!!!\n", argv[0], argv[1]); done(8); } if ((unsigned)stbuf.st_size != asize) { fprintf(stderr, "%s: new newsgroup arrived--aborting\n", argv[0]); done(9); } (void) unlink(argv[1]); if (link(temp, argv[1]) < 0) { fprintf(stderr, "%s: cannot link %s to %s!!!!\n", argv[0], temp, argv[1]); return(10); /* leave the temp file there... */ } done(0); /* NOTREACHED */ } done(retval) int retval; { (void) unlink(temp); exit(retval); } -- Larry Marek ihnp4!ihuxf!larry