[alt.sources] Multicasting software

mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) (05/17/89)

Due to the large number of requests that I had for this software, I have
decided to post it.  I did not write it, Shane McCarron and Steve McDowell
wrote it.

We, in Minnesota, have been using this software for the better part of 3
years without a hitch.  It makes feeding a bunch of news sites a whole lot
easier.  If you have comments or suggestions about the software, you can
direct them either to Shane (ahby@bungia.mn.org), or to me
(mark@jhereg.mn.org).

-- 
Mark H. Colburn                          mark@jhereg.mn.org
Minnetech Consulting, Inc.

      o /                     o /                    o /
------ x ------ Cut Here ----- x ----- Cut Here ----- x ----- Cut Here ------
      o \                     o \                    o \

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile multibatch.c multisend.sh uucast.c
#   uucast.h
# Wrapped by mark@jhereg on Tue May 16 13:26:13 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(4214 characters\)
sed "s/^X//" >README <<'END_OF_README'
XINSTALLATION
X============
X
XFirst, be sure to customize Makefile for your site.  The variables should
Xbe the same as news 2.10.3 and beyond.
X
XUucast may have to be customized for you site so that the uucp file
Xnames that are used are recognized by your uucico.  The only real option 
Xis HDB.  Sites running HDB UUCP should just have to define
XHDB in Makefile.  I hope that this works :-).  If you don't have HDB,
Xthe other configuration should work just fine for you.  There are two
XGRADE values that are defined in the file uucast.h.  These are the
Xgrade values that can be used by 4.3 BSD to regulate traffic flow.  In
Xthe case of uucast they should be used to guarantee a unique job file
Xname.  If your uux generates jobs like:
X
X	C.ihnp4AD8471	local command file
X	D.mecctsXA8471	remote command file (becomes X. file on ihnp4)
X	D.ihnp4BC8471	data to transmit
X
Xthen the grade is AD.  Choose a grade that doesn't conflict with this.
XThe defaults are MA and XM.  Uucast would have generated:
X
X	C.ihnp4MA8471	local command file
X	D.mecctsXM8471	remote command file (becomes X. file on ihnp4)
X	D.ihnp4MA8471	data to transmit
X
XNote that while the grades in the data and local command files are not
Xdifferent, UUCP doesn't seem to care about this.  If it cares on your
Xsystem, you should define a third grade (GRADE3) and use that as well.
XAlso note that the remote command file usually must have an X in it's
Xname so that it is recognized as such by the system.  This is a little
Xcurious, but since I don't have source I can't puzzle it out on my
Xown.
X
XOn Ultrix systems the UUCP datafiles are in a strange place, and job
Xfiles are in different directories.  This can all be specified by
Xchanging the CDIR, DDIR, and XDIR definitions in uucast.h.  There may
Xbe other systems where this is weird as well.  In any case, you can
Xspecify the location of each type of file individually.  See uucast.h
Xfor more information.
X
XAll of this stuff is different for each implementation of uucp, so
XI have made it as easy as possible to change.  If you need to hack it for your
Xsystem, please send those hacks to ahby@MECC.COM, so I can incorporate them into
Xfuture releases.
X
XA word of warning:  you WILL have trouble installing this software.  It
Xis not perfect, nor is it forgiving.  If you are unsure about the
Xstability of any of the modules on your system, there are ways in each
Xof them to preserve the original state of things.  Please be careful
Xwhen using this software, as it can be very detrimental to your news
Xsystem, as well as all of your downstream sites.
X
XAlso note that there is no make install option in the Makefile.  This
Xis really just laziness on my part.  Move all of the generated files
Xinto LIBDIR.  Remember that uucast MUST be suid to uucp so that it can
Xgenerate job files with the correct ownership.
X
X
XOPERATION
X=========
X
XExample sys file.  
X
Xmeccsd:mod,usa,na,net,world,comp,news,sci,rec,misc,soc,talk,to.meccsd:M:master
Xkarau:net.sources,news.admin,news.software.b,to.karau:M:master
Xnis:mod,usa,na,net,world,comp,news,sci,rec,misc,soc,talk,to.nis:M:master
Xzeke:mod,usa,na,net,world,comp,news,sci,rec,misc,soc,talk,to.zeke:M:master
Xmaster:all:OF:/usr/spool/batch/master
X
XThe M indicates that the site is being multicast to.  The
Xword master is the name of a dummy entry in the sys file which gives
Xthe information about what to do with these multi cast sites.  Site
X"master" is receiving all articles, is the destination of a multicast
X(O) and is a batched feed (F).  The file it places things into is
X/usr/spool/batch/master, just like a normal batched entry.
X
XIn your crontab, replace the sendbatches with something like:
X
X	55 18-5 * * * cat /usr/spool/batch/master >> /usr/spool/batch/hold; /usr/lib/news/multibatch -c master >> /usr/lib/cron/cast-log
X
XThis preserves the batch file (just in case) and then multibatches the
Xarticles indicated in file master compressed (-c flag for multisend).
X
XRemember that multibatch calls the script multisend, and expects
Xmultisend to be in the $(LIBDIR) directory for news.  Multisend calls
Xuucast, which should be in the path or in your $(LIBDIR) directory.
X
XGood luck!  If you have any problems, please drop me a line.
X
XCopyright (C) Shane McCarron, 1987.
END_OF_README
if test 4214 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(778 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# Makefile for multibatch and uucast.
X#
X# Copyright (C) Shane McCarron, 1987.
X#
X# Note that the symbols used here are compatible with those of
X# news 2.10.3 and beyond...
X
X# Directory where news batch files are kept.
XBATCHDIR = /usr/spool/batch
X
X# Directory with news software is kept.
XLIBDIR = /usr/lib/news
X
X# Define WANTZ if you don't want uux completion notices from other systems.
XDEFS =	-DBATCHDIR=\"$(BATCHDIR)\" -DLIBDIR=\"$(LIBDIR)\" -DWANTZ
XCFLAGS = -O -DHDB
X
XFILES = multibatch multisend uucast
X
Xall: $(FILES)
X
Xmultibatch: Makefile
X	$(CC) $(CFLAGS) $(DEFS) multibatch.c -o multibatch
X
Xmultisend: Makefile multisend.sh
X	sed -e 's;LIBDIR;$(LIBDIR);g' < multisend.sh > multisend
X	chmod +x multisend
X
Xuucast: Makefile uucast.h
X	$(CC) $(CFLAGS) $(DEFS) uucast.c -o uucast
END_OF_Makefile
if test 778 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f multibatch.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"multibatch.c\"
else
echo shar: Extracting \"multibatch.c\" \(3964 characters\)
sed "s/^X//" >multibatch.c <<'END_OF_multibatch.c'
X/*	multibatch.c - program to send news batches to multiple systems.
X *
X *	86/06/14.	2.1	Shane P. McCarron (MECC)
X *
X *	Copyright (C) Shane McCarron, 1987.
X *
X *	Multibatch will take a batch file created with the Multicasting 
X *	option of news 2.10.3 and later, and distribute common articles to
X *	sites using the broadcasting facility of uucast (also included in
X *	this software package).
X *
X *	The format of this command is:
X *
X *	multibatch [-s size] [ -c ] [ -c7 ] [ -obBC ] multicast
X *
X *	all parameters are like those of sendbatch except multicast, which
X *	is used in place of site.  Multicast is the name of the file which 
X *	contains the inews generated lines about article name and destination
X *	sites.  Multibatch will cluster those articles which need to go to the
X *	same sites, and feed that list to a sendbatch like script.
X *
X *	Since the parameters (options) are not really used by this
X *	program, but are used by the script it calls, the options are
X *	just ripped out of argv and placed in a string.
X */
X
X#include  <stdio.h>
X#include  <errno.h>
X
X#ifndef	PATH_MAX
X#define	PATH_MAX	255
X#endif	PATH_MAX
X
X#ifndef	LIBDIR
X#define	LIBDIR		"/usr/lib/news"
X#endif	LIBDIR
X
X#ifndef	BATCHDIR
X#define	BATCHDIR	"/usr/spool/batch"
X#endif	BATCHDIR
X
Xextern	int	errno;
X
Xtypedef	struct	node
X{
X	struct	node	*link;		/* forward link */
X	char	*line;			/* line from file */
X} NODE;
X
Xtypedef	NODE	*NODEPTR;
X
XFILE	*outfile;
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	FILE	*fopen();
X	char	*getsys();
X	char	*malloc();
X	void	error();
X	void	printart();
X
X	NODE	arts;
X	NODEPTR	last = &arts;
X	char	argstr[BUFSIZ];
X	char	filename[PATH_MAX];
X	char	flags[BUFSIZ];
X	char	instr[BUFSIZ];
X	char	oldname[PATH_MAX];
X	char	*systems;
X
X	int	artsleft;
X	int	i = 1;
X	int	numarts = 0;
X
X	arts.link = NULL;
X	while ((i < argc) && (argv[i][0] == '-'))
X	{
X		strcat(flags, argv[i]);
X		strcat(flags, " ");
X		i++;
X	} /* end while */
X	if (i == argc) 
X	{
X		fprintf(stderr, "usage: %s options batch\n", argv[0]);
X		exit(2);
X	} /* end if */
X
X	fclose(stdin);	/* we don't need this */
X	(void) sprintf(oldname, "%s/%s", BATCHDIR, argv[i]);
X	(void) sprintf(filename, "%s.work", oldname);
X	if (link(oldname, filename) == -1)
X	{
X		if (errno == ENOENT)
X			exit(1);
X		else
X			error(errno);
X	}  /* end if */
X
X	/* get rid of the original file */
X
X	(void) unlink(oldname);
X
X	if (fopen(filename, "r") == NULL)
X		error(errno);
X	while (gets(instr) != NULL)
X	{
X		if ((last->link = (NODEPTR) malloc(sizeof(NODE))) == NULL)
X			error(2);
X		last = last->link;
X		if ((last->line = malloc((unsigned) strlen(instr) + 1)) == NULL)
X			error(2);
X		strcpy(last->line, instr);
X		numarts++;
X	} /* end while */
X
X	/* If you are testing this, then comment out the unlink */
X
X	unlink(filename);
X
X	/* start processing these articles */
X
X	artsleft = numarts;
X	while (artsleft > 0)
X	{
X		last = arts.link;		/* start with first node */
X		while (last->line == NULL)
X			last = last->link;
X		systems = getsys(last->line);
X		strcpy(filename, "/tmp/mbXXXXXX");
X		if (mktemp(filename) == NULL)
X			error(254);
X		if ((outfile = fopen(filename, "w")) == NULL)
X			error(errno);
X		printart(last->line);
X		last->line = NULL;
X		last = last->link;
X		artsleft--;
X		while (last)
X		{
X			if (last->line != NULL)
X				if (strcmp(systems, getsys(last->line)) == 0)
X				{
X					printart(last->line);
X					last->line = NULL;
X					artsleft--;
X				} /* end if */
X			last = last->link;
X		} /* end while */
X		fclose(outfile);
X		(void) sprintf(argstr, "%s/multisend %s -S %s %s", LIBDIR, flags, filename, systems);
X		i = system(argstr); 
X		unlink(filename);
X		if (i != 0)
X			error(i);
X	} /* end while */
X
X	return(0);
X}
X
Xchar	*getsys(line)
Xchar	*line;
X{
X	char	*s = line;
X
X	while (*s != ' ') s++;
X	return(++s);
X}
X
Xvoid	printart(line)
Xchar	*line;
X{
X	int	i = 0;
X
X	while (line[i] != ' ') 
X	{
X		putc(line[i], outfile);
X		i++;
X	} /* end while */
X	putc('\n', outfile);
X}
X
Xvoid	error(err)
Xint	err;
X{
X	fprintf(stderr, "Program blew off.  Error = %d.\n", err);
X	exit(err);
X}
END_OF_multibatch.c
if test 3964 -ne `wc -c <multibatch.c`; then
    echo shar: \"multibatch.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f multisend.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"multisend.sh\"
else
echo shar: Extracting \"multisend.sh\" \(1251 characters\)
sed "s/^X//" >multisend.sh <<'END_OF_multisend.sh'
X: '@(#)multisend.sh	2.1	5/29/87'
X#	Copyright (C) Shane McCarron, 1987.
X#
X#	This script is intended to be called only by multibatch.
X#	Any parameters you give multibatch are passed onto this
X#	script with the exception of the MULTICAST generated batch
X#	file.
X#
X#	Note that the interface to multisend is pretty much like
X#	sendbatch.  However, it does not support the ihave flags.
X#	Also the flag -S is used to indicate that the rest of the
X#	parameters are system names.  It is supplied by multibatch.
X
X
Xcflags=
XLIM=50000
XECHO=
XCOMP=
XC7=
XRNEWS=rnews
Xdate
Xecho $*
X
Xwhile [ $1 != '-S' ]
Xdo
X	case $1 in
X	-[bBC]*)	cflags="$cflags $rmt"; continue;;
X	-s*)	LIM=`expr "$rmt" : '-s\(.*\)'` ;;
X	-c7) 	COMP='| LIBDIR/compress $cflags'
X		C7='| LIBDIR/encode'
X		ECHO='echo "#! c7unbatch"' ;;
X	-c)	COMP='| LIBDIR/compress $cflags'
X		ECHO='echo "#! cunbatch"' ;;
X	-o*)	ECHO=`expr "$rmt" : '-o\(.*\)'`
X		RNEWS='cunbatch' ;;
X	esac
X	shift
Xdone
X
Xshift
XFILE=$1
Xshift
XSYSTEMS=$*
X
Xif test -n "$COMP"
Xthen
X	LIM=`expr $LIM \* 2`
Xfi
X
X: make sure $? is zero
Xwhile test $? -eq 0 -a \( -s $FILE -o -s $FILE.work \)
Xdo
X	file=`date +10/16/86M%S`
X	(eval $ECHO; eval LIBDIR/batch $FILE $LIM $COMP $C7) > /tmp/msend$$
X	LIBDIR/uucast /tmp/msend$$ $RNEWS $SYSTEMS
X	rm /tmp/msend$$
Xdone
END_OF_multisend.sh
if test 1251 -ne `wc -c <multisend.sh`; then
    echo shar: \"multisend.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f uucast.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"uucast.c\"
else
echo shar: Extracting \"uucast.c\" \(10968 characters\)
sed "s/^X//" >uucast.c <<'END_OF_uucast.c'
X/* $Source$
X *
X * $Revision$
X *
X *	uucast - Cast a UUX command to multiple systems.
X *
X * SYNOPSIS
X *
X * 	uucast
X *
X * DESCRIPTION
X *
X *	Note:	this program must run suid uucp.  It will create the
X *		files in the uucp directories owned by user uucp, with
X *		mask MASK.
X *
X * AUTHORS
X *
X * 	Mark Colburn, NAPS International (mark@jhereg.mn.org) 1/5/89
X * 	Shane McCarron, NAPS International (ahby@bungia.mn.org) 12/8/86
X *
X *	Copyright (C) Shane McCarron, 1987, 1989
X *
X * $Log$
X */
X
X#include <pwd.h>
X#include <stdio.h>
X#include <errno.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "uucast.h"
X#ifndef	NODE
X#include <sys/utsname.h>
X#endif				/* NODE */
X
X#define	NAMELEN	(14 + 1)	/* length of file names */
X
Xchar	       *rcsid = "$Header$";
X
X
X#ifdef	NODE
Xchar            node[] = NODE,
X#else				/* NODE */
Xchar            node[8],	/* variable for node name from uname */
X#endif				/* !NODE */
X                user[] = USER,	/* the user that is doing the sending */
X                comname[NAMELEN],	/* name of command file */
X                remname[NAMELEN],	/* name of remote command file */
X                nremname[NAMELEN],	/* name of remote data file */
X                locname[NAMELEN];	/* name of local data file */
Xextern          errno;
X
X
Xint main(argc, argv)
Xint             argc;
Xchar          **argv;
X{
X    void     	    makename();
X    void     	    usage();
X    struct passwd  *getpwnam();
X
X    char            file[128],	/* file name to transmit */
X                    path[128],	/* temporary path name */
X                   *command = argv[2],	/* command to UUX */
X                   *sysname[MAXSYS];	/* array of system names */
X    FILE           *fptr;	/* file descriptor */
X    int             i,		/* looping variable */
X                    result,	/* result of link call */
X                    seq,	/* sequence number */
X                    syscount = 0;	/* number of systems to send to */
X    struct passwd  *uucp;	/* struct for user uucp information */
X#ifdef HDB
X    struct stat	    sbuf;	/* struct for check directries */
X#endif
X    
X    if (argc < 4) {
X	usage(argv[0]);
X    }
X    
X    if ((uucp = getpwnam("uucp")) >= 0) {
X	setuid(uucp->pw_uid);
X	setgid(uucp->pw_gid);
X    }
X
X    strcpy(file, argv[1]);	/* get the data file name */
X
X    for (i = 3; i < argc; i++) {/* get the system names */
X	sysname[i - 3] = argv[i];
X	syscount++;
X    }
X#ifndef	NODE
X    (void) getnode(node);	/* get the node name */
X#endif				/* NODE */
X    (void) umask(MASK);		/* clear the mask bits */
X    seq = getpid();		/* get the process id */
X    i = 0;
X    while (i < syscount) {
X
X#ifdef HDB
X	(void) sprintf(path, "%s/%s", XDIR, sysname[i]);
X	if (stat(path, &sbuf) == -1 && errno == ENOENT) {
X	    if (mkdir(path, 0755) < 0) {
X		(void) fprintf(stderr, "%s: unable to create directory %s\n", 
X			       command, path);
X		/*
X		 * If the directory cannot be created, there is little
X		 * sense going through the rest of the motions to copy
X		 * the file the the non-existant directory...
X		 */
X		continue;
X	    }
X	}
X#endif
X
X	/*
X	 * Cleaned up logic a bit - MHC 
X	 */
X	do {
X	    makename(sysname[i], seq++);
X#ifdef HDB
X	    (void) sprintf(path, "%s/%s/%s", XDIR, sysname[i], remname);
X#else
X	    (void) sprintf(path, "%s/%s", XDIR, remname);
X#endif				/* HDB */
X	} while (!access(path, 0));
X
X#ifdef HDB
X	(void) sprintf(path, "%s/%s/%s", DDIR, sysname[i], comname);
X#else
X	(void) sprintf(path, "%s/%s", DDIR, comname);
X#endif				/* HDB */
X
X	if ((result = link(file, path)) == -1 && (errno == EXDEV)) {
X	    /*
X	     * Link failed due to target directoring being on a different
X	     * file system.  Try doing a copy. If copy works then move path
X	     * to file so that it can be used as a source to link the rest of
X	     * the files. 
X	     */
X
X	    /* changed to do strcpy only if copy works - MHC */
X
X	    if (result = copy(file, path) == 0) {
X		strcpy(file, path);
X	    }
X	    
X	} else if (result != 0) {
X	    fprintf(stderr, "uucast: Link failed from %s to %s: %d\n",
X		    file, path, errno);
X	    exit(errno);
X	}			/* end else */
X# ifdef HDB
X	(void) sprintf(path, "%s/%s/%s", XDIR, sysname[i], remname);
X#else
X	(void) sprintf(path, "%s/%s", XDIR, remname);
X#endif
X	fptr = fopen(path, "w");
X#ifdef	WANTZ
X	fprintf(fptr, "U %s %s\nN\nZ\nR %s\nF %s\nI %s\nC %s\n",
X		user, node, user, comname, comname, command);
X#else
X	fprintf(fptr, "U %s %s\nF %s\nI %s\nC %s\n", user, node,
X		comname, comname, command);
X#endif
X	fclose(fptr);
X#ifdef HDB
X	(void) sprintf(path, "%s/%s/%s", CDIR, sysname[i], locname);
X#else
X	(void) sprintf(path, "%s/%s", CDIR, locname);
X#endif
X	fptr = fopen(path, "w");
X#ifdef HDB
X	fprintf(fptr, "S %s %s %s - %s 0666 %s\nS %s %s %s - %s 0666 %s\n",
X		comname, comname, user, comname, user, remname, nremname,
X		user, remname, user);
X#else
X	fprintf(fptr, "S %s %s %s - %s 0666\nS %s %s %s - %s 0666\n",
X		comname, comname, user, comname, remname, nremname,
X		user, remname);
X#endif
X	fclose(fptr);
X	i++;
X    }				/* end for */
X}
X
X
X/* copy - copy a file from one spot to another
X *
X * DESCRIPTION
X *
X *	Copy copies a file using the system copy command.
X *
X * PARAMETERS
X *
X *	char *file1	- file to copy data from
X *	char *file2	- file to copy data to
X *
X * RETURNS
X *
X *	The result of the system cp(1) command.
X */
X
X#ifdef __STDC__
X
Xint copy(char *file1, char *file2)
X
X#else
X
Xint copy(file1, file2)
Xchar           *file1,
X               *file2;		/* source and destination name */
X
X#endif
X{
X    char            cmd[BUFSIZ];/* make a command string */
X
X    (void) sprintf(cmd, "cp %s %s", file1, file2);
X    return (system(cmd));
X}
X
X
X#ifndef	NODE
X
X/* getnode - get the nodename for the system
X *
X * DESCRIPTION
X *
X * 	Getnode attempts to get the node name of the system which
X *	this program is being executed on via the uname call.  If
X *	the uname call succeeds, the name of the system will be 
X *	copied into the array pointed to by name.
X *
X * PARAMETERS
X *
X *	char *name	- array to save node name in
X *
X * RETURNS
X *
X *	Getnode returns 0 if the uname call was successfull and 
X *	the node name was copied into the array pointed at by 
X *	name.  If the uname call fails, then the node name is
X *	not copied into the array pointed at by name, and getnode
X *	returns a value of -1 to the caller.
X */
X
X#ifdef __STDC__
X
Xint getnode(char *name)
X
X#else
X
Xint getnode(name)
Xchar           *name;
X
X#endif
X{
X    struct utsname  buffer;
X
X    if (uname(&buffer) == 0) {
X	strcpy(name, buffer.nodename);
X	return(0);
X    }
X    return(-1);
X}
X
X#endif /* NODE */
X
X
X/* makename - make the name files for casting.
X *
X * DESCRIPTION
X *
X *	remname and nremname use grade2 because on some systems (Ultrix)
X *	the remote command file must have an X in its name.  On normal
X *	systems, just make GRADE and GRADE2 the same.
X *
X * PARAMETERS
X *
X *	char *sysnam 	- name of system to send to
X *	int  num	- sequnce number to use for sending
X *
X */
X
X#ifdef __STDC__
X
Xvoid makename(char *sysnam, int num)
X
X#else
X
Xvoid makename(sysnam, num)	/* make file names */
Xchar           *sysnam;		/* system name */
Xint             num;		/* sequence number */
X
X#endif
X{
X    while (num > (10000 - 1))
X	num = num - 10000;
X#ifdef HDB
X    (void) sprintf(comname, "D.%.5s%s%04d", node, GRADE, num);
X    (void) sprintf(remname, "D.%.5s%04da12c", sysnam, num);
X    (void) sprintf(nremname, "X.%.7s%s%04d", sysnam, GRADE, num);
X    (void) sprintf(locname, "C.%.7s%s%04d", sysnam, GRADE, num);
X#else
X#ifndef	GRADE2
X    (void) sprintf(comname, "D.%.6s%s%04d", sysnam, GRADE, num);
X    (void) sprintf(remname, "D.%.6s%s%04d", node, GRADE, num);
X    (void) sprintf(nremname, "X.%.6s%s%04d", node, GRADE, num);
X    (void) sprintf(locname, "C.%.6s%s%04d", sysnam, GRADE, num);
X#else
X    (void) sprintf(comname, "D.%.6s%s%04d", sysnam, GRADE, num);
X    (void) sprintf(remname, "D.%.6s%s%04d", node, GRADE2, num);
X    (void) sprintf(nremname, "X.%.6s%s%04d", node, GRADE2, num);
X    (void) sprintf(locname, "C.%.6s%s%04d", sysnam, GRADE, num);
X#endif	!GRADE2
X#endif	HDB
X}
X
X
X/* usage - print a usage message and exit
X *
X * DESCRIPTION
X *
X *	Usage prints out a helpful usage message on standard output
X *	and terminates the program.
X *
X * RETURNS
X *
X *	Usage returns a value of 1 to the parent process.
X */
X
X#ifdef __STDC__
X
Xvoid usage(char *command)
X
X#else
X
Xvoid usage(command)
Xchar           *command;
X
X#endif
X{
X    fprintf(stderr, "usage: %s file command system(s)\n", command);
X    exit(1);
X}
X
X
X/* mkdir - make a directory
X *
X * DESCRIPTION
X *
X * 	Mkdir will make a directory of the name "dpath" with a mode of
X *	"dmode".  This is consistent with the BSD mkdir() function and the
X *	P1003.1 definitions of MKDIR.
X *
X *	Special considerations are taken into account since this will be
X *	running on a system which is running suid'ed.
X *
X * PARAMETERS
X *
X *	dpath		- name of directory to create
X *	dmode		- mode of the directory
X *
X * RETURNS
X *
X *	Returns 0 if the directory was successfully created, otherwise a
X *	non-zero return value will be passed back to the calling function
X *	and the value of errno should reflect the error.
X */
X
X#ifdef __STDC__
X
Xint mkdir(char *dpath, int dmode)
X
X#else
X    
Xint mkdir(dpath, dmode)
Xchar           *dpath;
Xint             dmode;
X
X#endif
X{
X    int             cpid, status;
X    int		    oldid;
X    struct stat     statbuf;
X    extern int      errno;
X    char            buff[256];
X
X    if (stat(dpath, &statbuf) == 0) {
X	errno = EEXIST;		/* Stat worked, so it already exists */
X	return (-1);
X    }
X    /* If stat fails for a reason other than non-existence, return error */
X    if (errno != ENOENT)
X	return (-1);
X
X    switch (cpid = fork()) {
X
X    case -1:			/* Error in fork() */
X	return (-1);		/* Errno is set already */
X
X    case 0:			/* Child process */
X
X	status = umask(0);	/* Get current umask */
X	status = umask(status | (0777 & ~dmode));	/* Set for mkdir */
X	(void) sprintf(buff, "/bin/mkdir %s", dpath);
X	if (system(buff) == 0) {
X
X	    /*
X	     * We are going to play a cute little game here.  We know
X	     * that we are running set-uid.  therefore, when we create
X	     * the directory, it will be owned by uid(getuid()) and 
X	     * gid(getgid()), rather than uid(geteuid()) and 
X	     * gid(getegid()), since mkdir is also set-uid.  Due to the
X	     * way that the chown system call works, we have to change
X	     * our effective user-id to our real-user-id in order to 
X	     * change the ownership of the file to our effecitve-user-id.
X	     * Got all that?  Since we are in a child, we don't care
X	     * anyways...
X	     */
X
X	     oldid = geteuid();
X	     if (setuid(getuid()) == 0) {
X		 /* give away the file...only works on some systems */
X		 chown(dpath, oldid, getuid());
X	     }
X	    _exit(0);
X	} else {
X	    _exit(-1);		/* Can't exec /bin/mkdir */
X	}
X
X    default:			/* Parent process */
X	while (cpid != wait(&status)) {
X	    /* Wait for child to finish */
X	}
X    }
X
X    if ((status & 0x7F) != 0 || (status >> 8) != 0) {
X	errno = EIO;		/* We don't know why, but */
X	return (-1);		/* /bin/mkdir failed */
X    }
X
X    return (0);
X}
X
END_OF_uucast.c
if test 10968 -ne `wc -c <uucast.c`; then
    echo shar: \"uucast.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f uucast.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"uucast.h\"
else
echo shar: Extracting \"uucast.h\" \(856 characters\)
sed "s/^X//" >uucast.h <<'END_OF_uucast.h'
X/*
X**	uucast.h - Header file for uucast.
X*/
X
X/* #define	NODE	"foobar"	/* name of this node, define if system
X				call uname is not available.  This name can
X				be no longer than 7 characters. */
X#define	MASK	026			/* umask for files */
X#define	CDIR	"/usr/spool/uucp"	/* local command files directory */
X#define	DDIR	"/usr/spool/uucp"	/* data files directory */
X#define	XDIR	"/usr/spool/uucp"	/* remote command files directory */
X
X/*  For HoneyDanBer users:  Grades are a single character, so use M and
X *  X (for example).
X */
X
X#define GRADE	"M"			/* grade to use for uucico files.
X					   Should not be used by anyone else */
X#define	GRADE2	"X"			/* other grade to use for files
X					   This grade should start
X					   with an X. */
X#define	USER	"news"		/* name of news user on your system */
X#define	MAXSYS	20			/* maximum number of systems per cast */
END_OF_uucast.h
if test 856 -ne `wc -c <uucast.h`; then
    echo shar: \"uucast.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
Mark H. Colburn                          mark@jhereg.mn.org
Minnetech Consulting, Inc.