[net.sources] uusquish.c

rjk (12/22/82)

/*	Uusquish - compacts the uucp spooling directory.  Should be
 *	run once per day if you have Usenet links.  If there are sub
 *	directories under UUCPDR, they will remain intact, but not
 *	compacted.
 *						RJKing WECo-Mg6565 Dec 82
 */

#include	<stdio.h>
#include	<fcntl.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<sys/dir.h>

#define	BLKSIZ	512				/* Bytes per block */
#define	SPLDIR	"/usr/spool"			/* Spooling directory */
#define	UUCPDR	"uucp"				/* UUCP spooling directory */
#define	UU_UID	5				/* UUCP uid */
#define	UU_GID	8				/* UUCP gid */
#define	UUMODE	0777				/* UUCPDR mode */

char	*malloc(), *mktemp(), *strncpy();

int	vflag;					/* Verbose option flag */

extern	int optind;

main(argc, argv)
char *argv[];
{	register int i;
	register char *memp;
	register struct direct *dirp;
	int	td, nbyt, nent;
	char	trash[16], newfile[24];
	struct	stat sb;
	struct	direct dirent;
	unsigned memsize;

	while((i = getopt(argc, argv, "v")) != EOF)
	{	switch(i)
		{	case 'v':	++vflag;
					break;
			default:	exit(1);
		}
	}
	argc -= (optind -1);  argv += (optind -1);

	if(chdir(SPLDIR) < 0)
	{	fprintf(stderr, "cannot chdir to ");
		perror(SPLDIR);
		exit(1);
	}
	strncpy(trash, mktemp("OuucpXXXXXX"), sizeof(trash));
	if(link(UUCPDR, trash) < 0)
	{	fprintf(stderr, "cannot link %s to ", UUCPDR);
		perror(trash);
		exit(1);
	}
	if(unlink(UUCPDR) < 0)
	{	fprintf(stderr, "cannot unlink ");
		perror(UUCPDR);
		exit(1);
	}
	newuudir();
	if(chdir(trash) < 0)
	{	fprintf(stderr, "cannot chdir to ");
		perror(trash);
		exit(1);
	}
	if((td = open(".", O_RDONLY)) < 0)
	{	fprintf(stderr, "cannot open ");
		perror(trash);
		exit(1);
	}
	fstat(td, &sb);
	memsize = (unsigned)sb.st_size;
	if(vflag)
		fprintf(stderr, "%s: %u blocks\n", trash, memsize /BLKSIZ);
	while((memp = malloc(memsize)) == NULL)
	{	memsize /= 2;
		if(memsize < 1024)
		{	fprintf(stderr, "uusquish: malloc failed\n");
			exit(1);
		}
	}
	if(vflag)
		fprintf(stderr, "reading %u blocks\n", memsize /BLKSIZ);
	while((nbyt = read(td, memp, memsize)) > 0)
	{	dirp = (struct direct *)memp;
		nent = nbyt /sizeof(dirent);
		if(vflag)
			fprintf(stderr, "reading %d entries this pass\n", nent);
		for(i=0; i<nent; ++i, ++dirp)
		{
			if(strcmp(dirp->d_name, ".") == 0)
				continue;
			if(strcmp(dirp->d_name, "..") == 0)
				continue;
			if(dirp->d_ino == 0)
				continue;
			sprintf(newfile, "../%s/%s", UUCPDR, dirp->d_name);
			if(link(dirp->d_name, newfile) < 0)
			{	fprintf(stderr, "cannot link %s to ",
					dirp->d_name);
				perror(newfile);
				continue;
			}
			if(unlink(dirp->d_name) < 0)
			{	fprintf(stderr, "cannot unlink ");
				perror(dirp->d_name);
			}
			if(vflag)
				fprintf(stderr, "mv ./%s %s\n", dirp->d_name,
					newfile);
		}
	}
	if(chdir(SPLDIR) < 0)
	{	fprintf(stderr, "cannot return to ");
		perror(SPLDIR);
		exit(1);
	}
	switch(fork())
	{	case -1:	fprintf(stderr, "cannot fork to remove ");
				perror(trash);
				exit(1);
		case 0:		execl("/bin/rm", "rm", "-r", trash, 0);
				perror("/bin/rm");
				exit(1);
	}
	exit(0);
}
/*	Newuudir() - make a new uucp spooling directory
 */
newuudir()
{	int	exst;

	switch(fork())
	{	case -1:	fprintf(stderr, "cannot fork to mkdir ");
				perror(UUCPDR);
				exit(1);
		case 0:		execl("/bin/mkdir", "mkdir", UUCPDR, 0);
				perror("/bin/mkdir");
				exit(1);
	}
	wait(&exst);
	if(exst != 0)
	{	fprintf(stderr, "mkdir exit status %d\n", exst);
		exit(1);
	}
	if(chown(UUCPDR, UU_UID, UU_GID) < 0)
	{	fprintf(stderr, "cannot chown ");
		perror(UUCPDR);
		fprintf(stderr, "please chown when uusquish completes\n");
	}
	if(chmod(UUCPDR, UUMODE) < 0)
	{	fprintf(stderr, "cannot chmod ");
		perror(UUCPDR);
		fprintf(stderr, "please chmod when uusquish completes\n");
	}
}