[net.sources] Asort - active file sorting program

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