[net.sources] mkhistory.c - recreate the B news history file

solomon (03/26/83)

/* mkhistory.c - munge around in the spool files and see what's there.
 * Written by solomon@uwisc, 3/23/83.
 *
 * To compile:
 *   cc mkhistory.o header.o funcs.o getdate.o rextern.o
 *
 * Currrent version produces (on stdout) a replica of what
 * /usr/lib/news/history should look like, modulo the following differences:
 * The history file contains "file names" that are longer than 14 characters,
 * and in the case of multiple file names for the same item, the file names
 * are in arbitrary order.  The output of this program has the actual file
 * names (truncated to 14 chars) and lists them in alphabetical order.
 * For example, the line
 *  zehntel.838	Fri Mar 11 05:48:22 1983	net.unix-wizards/1769 
 * would appear
 *  zehntel.838	Fri Mar 11 05:48:22 1983	net.unix-wizar/1769 
 * and
 *  spanky.236	Fri Mar 11 05:47:01 1983	net.politics/245 net.philosophy/68 
 * would appear
 *  spanky.236	Fri Mar 11 05:47:01 1983	net.philosophy/68 net.politics/245
 *
 * See the shell file "fixhist.sh" for a program that takes the history file
 * produces something suitable for diff.
 *
 */
#include "params.h"
#include <dir.h>

#define MAXID 16
#define MAXFNAME 24
#define MAXITEMS 3000

struct item {
	char id[MAXID];
	time_t dtime;
	char fname[MAXFNAME];
	short inum;
} table[MAXITEMS];

int nitems = 0;

#define SPOOLDIR "/usr/spool/news"
#define NAMESIZE 256

char *sprintf(), *strncpy(), *ctime();

main(argc,argv)
char **argv;
{
	char group[NAMESIZE], file[NAMESIZE];
	char groupname[NAMESIZE], filename[NAMESIZE];
	int spool, dir, i;
	FILE *item;
	int comp();

	spool = open(SPOOLDIR,0);
	if (spool<0) {
		perror(SPOOLDIR);
		exit(1);
	}
	while (getname(spool,group)) {
		(void) sprintf(groupname,"%s/%s",SPOOLDIR,group);
		dir = open(groupname,0);
		if (dir<0) {
			perror(groupname);
			exit(1);
		}
		while (i = getname(dir,file)) {
			(void) sprintf(filename,"%s/%s",groupname,file);
			item = fopen(filename,"r");
			if (item==NULL) {
				perror(filename);
				exit(1);
			}
			dofile(item,group,file,i);
			(void) fclose(item);
		}
		(void) close(dir);
	}
	fprintf(stderr,"start of sort\n");
	(void) fflush(stderr);
	qsort(table,nitems,sizeof (struct item),comp);
	dumpitems();
	exit(0);
}

int
comp(a,b)
struct item *a, *b;
{
	register temp;
	if (temp = a->dtime - b->dtime) return temp;
	return strcmp(a->fname,b->fname);
}

int
getname(fd,result)
int fd;
char *result;
{
	struct dir dirent;
	int n;

	/* Get the next file name from fd (which is an open directory file).
	 * Skip all names that start with ".".  Return 0 for EOF, the inum
	 * of the file ow.
	 * Terminate result with a NULL (assume there is room for DIRSIZ+1
	 * chars).
	 */
	for(;;){
		n = read(fd,(char *)(&dirent),sizeof dirent);
		if (n!=sizeof dirent) return 0;
		if (dirent.d_ino==0) continue;
		if (dirent.d_name[0]=='.') continue;
		strncpy(result,dirent.d_name,DIRSIZ);
		result[DIRSIZ] = '\0';
		return dirent.d_ino;
	}
}

dofile(fi,group,file,ino)
FILE *fi;
char *group, *file;
{
	register struct item *iptr;

	if (hread(&header,fi)==NULL) {
		fprintf(stderr,"%s/%s\n",group,file);
		printf("syntax error\n");
		return;
	}
	iptr = &table[nitems++];
	strncpy(iptr->id,header.ident,MAXID);
	(void) sprintf(iptr->fname,"%s/%s",group,file);
	iptr->dtime = cgtdate(header.recdate);
	iptr->inum = ino;
}

dumpitems()
{
	register int i,j;
	char *temp;


	table[nitems].inum = 0; /* sentinel */
	for(i=0; i<nitems;) {
		for (j=i+1;table[j].inum == table[i].inum; j++)
			;
		/*
		 * now table[i..j-1] contain the same inum
		 */
		temp = ctime(&table[i].dtime);
		(void) nstrip(temp);
		printf("%s\t%s\t",table[i].id, temp);
		while (i<j) {
			printf("%s ",table[i++].fname);
		}
		putchar('\n');
	}
}

xerror(message)
char *message;
{
	printf("mkhistory: %s.\n", message);
	(void) fflush(stdout);
	exit(1);
}
/* last line of mkhistory.c */