[comp.sources.misc] v04i008: relink news cross postings

ronald@ibmpcug.UUCP (Ronald Khoo) (07/28/88)

Posting-number: Volume 4, Issue 8
Submitted-by: "Ronald Khoo" <ronald@ibmpcug.UUCP>
Archive-name: relink

[The copyright in this one was rather interesting; unfortunately, it would not
have had the desired effect from a legal standpoint, so I have deleted it
with the author's permission.  ++bsa]

	I'm not sure if any existing program does this, if so, tell me
please! (Then I'll trash this program!)

[afio and gnu@hoptoad.UUCP's PD tar both are available in source, so you
can compile them medium or large model and avoid overflowing the link tables.
Fixing the real bug is preferable to repairing the damage it causes.  ++bsa]

Basically, after using cpio or tar to save and restore my /usr/spool/news,
I wind up with multiple copies of cross postings, since my Xenix cpio/tar
are 8086 small model binaries (courtesy of SCO :-( ) so this prog goes through
the Xref: lines in the files and unlinks/relinks cross postings.  I think
that its functionality should be in expire, but I can't find it, so..
(I recently needed to reclaim some much needed filespace, hence this program !)

As noted in the README, I'm off on a LONG holiday, and can't be reached for
a couple of months at least, hence this rather rushed posting (ie no .8 file)

Cheers.
Ronald

---- cut here ------ for those who haven't bothered to install unshar! ------
#! /bin/sh
# or should that be : use /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 the files:
#	README
#	relink.c
# This archive created: Wed Jul 27 22:36:22 1988
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
Here is a small program to go through all your news files and rebuild
links bewtween crosspostings which have died.  Why should this ever happen?
Well.. on my system (Xenix System V 2.2) the 'tar' and 'cpio' programs
supplied are SMALL MODEL 8086 binaries! (SCO say it's a lot easier to
just maintain one set of binaries :-( ) Hence, when I tar off the news
partition and put it back - a lot of the link information is lost (bigger :-( )
and I wind up with megs of store used up duplicating crosspostings, so I wrote
this program to restore them - I just freed a much needed couple of megs with
it yesterday!  Maybe someone else can find a use for it, I don't know.

OPERATION
	goes through every file which /usr/lib/news/active believes is there,
looking for Xref: lines.  Check to see that the inode of current file ==
xref'd files, if not, then unlinks xref'd file, and links current file to
xref'd file.  IGNORES hostname in Xref: line. Does NOT build a history of
what it did, so it goes through each Xref again when it comes to it next time.
(sorry) - It doesn't need to be a quick program after all - I just run it
after I do a massive restore of my news partition + expire -r -e lots.

OPTIONS
	-a active		instead of /usr/lib/news/active
	-s spool		instead of /usr/spool/news
	-v			be verbose
	-V			be VERY verbose
	-r			just report, don't do anything
	-R			be very verbose version of -r

RASH ASSUMPTIONS:
	1) active file is up to date: I suppose expire -r would fix this?
	2) all the /usr/spool/news directories are present
	3) /usr/spool/news is on one filesystem - but if it isn't, you've
	   probably hacked news about quite a bit anyway... so this won't be
	   of any use to you in any case.

Disclaimer:  I have used this program without trashing my own news system,
	     but your mileage may vary.  DO NOT USE if you intend to sue
	     me  if anything goes wrong.  No warranties, express or implied,
	     etc, etc, etc....

I'm on holiday for a while, probably won't be back 'till October, so
if you send any gripes to me, don't hold your breath....

Plausible mail addresses:

	ronald@ibmpcug.UUCP
	ronald%ibmpcug.uucp@ukc.AC.UK
	uunet!mcvax!ukc!pyrltd!slxsys!ibmpcug!ronald

in the middle of registering
	ronald@ibmpcug.CO.UK
but the registration procedure over here is REALLY convoluted (goes via 3
universities 4 times!) so it won't work for a while :-(
SHAR_EOF
fi # end of overwriting check
if test -f 'relink.c'
then
	echo shar: will not over-write existing file "'relink.c'"
else
cat << \SHAR_EOF > 'relink.c'
#ifndef lint
static char sccsid[] = "%W%	%E%	No, I don't have RCS :-(";
#endif /* lint */

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

#define ACTIVE			"/usr/lib/news/active"
#define SPOOLDIR		"/usr/spool/news/"

#define MAXLEN			256

char *p_active			= ACTIVE;
char *p_spooldir		= SPOOLDIR;

char fullpath[MAXLEN+1] = SPOOLDIR;
char *path = fullpath + (sizeof SPOOLDIR - 1);
char group[MAXLEN+1];
char line[MAXLEN+1];
char file[10];

FILE *active, *mesg;
int Verbose = 0, verbose=0, report=0, Report=0;	/* Verbose is Very verbose */

main(argc, argv)
	char **argv;
{
	int opt ; extern char *optarg;
	int i, first, last;
	register char *p;

	while ( (opt=getopt(argc, argv, "VvRra:s:")) != EOF) switch (opt) {
	case 'a':
		p_active = optarg; break;
	case 's':
		p_spooldir = optarg; break;
	case 'R':
		Report=1;
	case 'r':
		report=1; break;
	case 'V':
		Verbose=1;
	case 'v':
		verbose=1; break;
	default:
		exit(1);
	}

	if (report) verbose = 1;
	if (Report) Verbose = 1;

	if (chdir(p_spooldir)<0) {
		perror(p_spooldir); exit(1);
	}
	if ((active = fopen(p_active, "r"))== 0) {
		perror(p_active); exit(1);
	}
	
	while (fgets(line, MAXLEN, active)) {
		chdir(p_spooldir);
		sscanf(line, "%s%d%d", group, &last, &first);
		if (verbose) fputs(group, stdout);
		for (p=group; *p ; p++)
			if (*p == '.') *p = '/';
		if (chdir(group) < 0) {
			if (verbose) puts(": no directory");
			continue;
		}
		if (verbose) putchar('\n');
		if (last != 0) for (i=first; i<=last; i++) {
			sprintf(file, "%d", i);
			if (Verbose) fputs(file, stdout);
			if ((mesg=fopen(file, "r"))==0) {
				if (Verbose)
					perror("");
				continue;
			}
			if (Verbose) putchar('\n');
			dolink();
			fclose(mesg);
		}
	}
}

char *skipws(s) char *s; { while (*s && isspace(*s)) s++; return s; }
char *skiptows(s) char *s; { while (*s && !isspace(*s)) s++; return s; }

#include <sys/types.h>
#include <sys/stat.h>
dolink()
{
	struct stat stbuf; int ino;
	register char *p, *q;
	while ((p=fgets(line, MAXLEN, mesg)) != 0) {
		if (*line == 0) return;
		for (p=line; *p && p < line+4; p++)
			*p = tolower(*p);
		if (strncmp(line, "xref:", 5)==0)
			break;
	}
	if (p == 0) return;
	fstat(fileno(mesg), &stbuf);
	ino = stbuf.st_ino;
	if (verbose) printf("%s: %s", file, line);
	p = line + 5;		/* first char past Xref:	*/
	p = skipws(p);		/* skip to hostname		*/
	p = skiptows(p);	/* skip past hostname		*/
	while (*p) {		/* for each cross reference	*/
		p = skipws(p);	/* skip to cross reference	*/
		q = path;	/* setup pointer to full path	*/
		while (*p && !isspace(*p))
			*q++ =  (*p == ':' || *p == '.')?p++,'/':*p++;
		if (! *p) break;/* end of Xref: list		*/
		*q = '\0';
		if (verbose) fputs(path, stdout);
		stat(fullpath, &stbuf);
		if (stbuf.st_ino == ino) {
			if (verbose) puts(": Link OK");
		} else if (report) {
			puts(": Link broken");
		} else {
			if (verbose) puts(": Relinked");
			unlink(fullpath);
			link(file, fullpath);
		}
	}
}
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
Ronald Khoo @ The IBM PC User Group, PO Box 830, London SE1 0DB, UK.
Phone:	+44 -1- 620 2244			UKNet:	ronald@ibmpcug.uucp
Path:	...!ukc!pyrltd!slxsys!ibmpcug!ronald	Domain:	ronald%ibmpcug@ukc.ac.uk
Disclaimer: When I persuade my boss to believe me, what I say will be official.