[comp.sources.misc] map article id's to file names

allbery@ncoast.UUCP (06/12/87)

This program takes a file where the first blank separated word on each
line is an article id, looks that up in the history.{dir,pag} and the
history file, and prints out the article id and file name(s) holding
that article.  The rest of the input line is ignored.

This is useful if you lose news items and want to bring your system up
to date.  You copy your feed's history file to your machine (you only
need the article id's really).  Run idart on that to find which
articles you are missing (missing or expired articles are reported on
stderr), send that list back to your news feed, and run idart on that
list again.  You can then use a simple awk script (or an editor) to
create a list of file names to be hand fed to the batching program.

This only works on those systems that are configured to use the dbm
library to access their history database.

I hope someone finds this useful.  Sorry about the lack of a manual
page.

Ben Golding.	bgg@yarra.oz.au   seismo!munnari!yarra.oz!bgg
		(I am not working here any more, but mail should
		still get to me).
--
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Makefile
#	idart.c
# This archive created: Fri Jun 12 11:48:20 1987
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'

idart:	idart.o
	$(CC) idart.o -ldbm -o idart
SHAR_EOF
fi
if test -f 'idart.c'
then
	echo shar: "will not over-write existing file 'idart.c'"
else
cat << \SHAR_EOF > 'idart.c'

#include <stdio.h>
#include <ctype.h>

/*
 * This program takes a newline separated file of article id's and
 * prints out a line with the id and the file name(s) containing the
 * articles.  Article id's are the first blank separated word on each
 * line and are surrounded by a '<' and '>' - just like the history file.
 * This only works on news systems that are configured with the dbm
 * routines.
 *
 * This does not understand any locking.
 *
 * Usage:  idart [file]
 *
 *	Ben Golding.  June 8, 1987.
 */

#define	HISTORY	"/usr/lib/news/history"

typedef struct	{
	char	*dptr;
	int	dsize;
} datum;

char	*malloc();
datum	fetch();

main(argc, argv)
int	argc;
char	*argv[];
{
	register i;
	char	id[512], fname[8192];
	datum	d, art;
	long	off;
	FILE	*hp;

	if (argc > 1) {
		if (freopen(argv[1], "r", stdin) == (FILE *)NULL) {
			perror(argv[1]);
			exit(1);
		}
	}
	if ((d.dptr = malloc(1024)) == 0) {
		perror("malloc");
		exit(1);
	}
	if (dbminit(HISTORY) != 0) {
		fprintf(stderr, "dbminit: %s\n", HISTORY);
		exit(1);
	}
	if ((hp = fopen(HISTORY, "r")) == (FILE *)NULL) {
		perror(HISTORY);
		exit(1);
	}
	while (scanf("%s%*[^\n]\n", id) != EOF) {
		d.dptr = &id[0];
		d.dsize = strlen(id) + 1;	/* includes the null!(?) */
		for (i = 0; id[i] != '\0'; i++)
			if (isupper(id[i]))
				id[i] = tolower(id[i]);
		art = fetch(d);
		if (art.dptr == (char *)NULL)
			fprintf(stderr, "%s: not found in history\n", id);
		else {
			bcopy(art.dptr, &off, sizeof(long));
			if (fseek(hp, off, 0) < 0) {
				perror(HISTORY);
				continue;
			}
			if (fscanf(hp, "%s%*s%*s%[^\n]\n", id, fname) != 2)
				fprintf(stderr, "%s: error in history\n", id);
			else {
				if (strcmp(fname, "") == 0
				||  strcmp(fname, "\t") == 0)
					fprintf(stderr, "%s: expired\n", id);
				else
					printf("%s\t%s\n", id, fname);
			}
		}
	}
	dbmclose();
	exit(0);
}
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 

Ben Golding.	bgg@yarra.oz.au   seismo!munnari!yarra.oz!bgg