[comp.os.minix] UUPC for Minix, part 5/5

housel@en.ecn.purdue.edu (Peter S. Housel) (07/03/89)

echo 'x - qmail'
sed 's/^X//' <<'**-qmail-EOF-**' >qmail
Xid=`expr $$ % 1000`
Xhost=`cat /etc/uucpname`
Xsender=`whoami`
X#
Xspool=/usr/spool/uucp
Xremote='remote'		# change to suit
Xdfile=D.${host}$id
Xtmp=$spool/$dfile
Xxfile=D.${host}X$id
Xrxfile=X.$host$id
X#
Xif test -t 0 ; then
X	echo -n "Subject: "; read subj
Xfi
Xecho "From: ${sender}@${host}.UUCP" > $tmp
Xecho "Date: `date`" >> $tmp
Xecho "To: $*" >> $tmp
Xif test "X" != "X$subj"; then
X	echo "Subject: $subj" >> $tmp
Xfi
Xecho >> $tmp
Xcat >> $tmp
Xif test -t 0 ; then
X	echo "EOF"
Xfi
Xcat << --EOF-- > $spool/C.$remote$id
XS $dfile $dfile $sender - $dfile 0666
XS $xfile $rxfile $sender - $xfile 0666
X--EOF--
Xcat << --EOF2-- > $spool/$xfile
XU $sender $host
XR $sender
XF $dfile
XI $dfile
XC rmail $*
X--EOF2--
Xexit 0
**-qmail-EOF-**
echo 'x - uuclean'
sed 's/^X//' <<'**-uuclean-EOF-**' >uuclean
X#!/bin/sh
Xrm -f /usr/spool/uucp/LCK..*
**-uuclean-EOF-**
echo 'x - uux.c'
sed 's/^X//' <<'**-uux.c-EOF-**' >uux.c
X/* file: uux.c
X** author: Peter S. Housel (housel@ecn.purdue.edu)
X*/
X
X/* This entire program is a quick, ugly hack. Sloppiness abounds. There isn't
X** much error checking. I'm ashamed of it.
X** However, it does handle the restricted cases that it needs to - 
X** in particular running remote rmail and remote rnews. As long as you're
X** gentle with it.
X*/
X
X#include <stdio.h>
X#include <pwd.h>
X#include <ctype.h>
X
X/* from dcp.h - move out eventually */
X#define NODENAME	"/etc/uucpname"
X#define LSYS		"/usr/lib/uucp/L.sys"
X#define SPOOLDIR	"/usr/spool/uucp"
X#define SPOOLSEQ	"/usr/lib/uucp/SPOOLSEQ"
X#define LSPOOLSEQ	"/usr/lib/uucp/SPOOLSEQ.lock"
X#define CICO		"/usr/lib/uucp/uucico"
X
X#define SITENAMELEN	32	/* max length of sitename */
X#define DEFGRADE	'a'	/* or whatever */
X
Xextern int getopt();
Xextern int optind;
Xextern char *optarg;
Xextern char *index(/* char *string, char c */);
Xextern char *rindex(/* char *string, char c */);
Xextern char *mktemp(/* char *template */);
Xextern FILE *fopen();
Xextern struct passwd *getpwuid();
X
Xvoid usage(), dostdin(), doarg();
Xchar *uucpname(), *whoami();
Xchar *filesite(/* char *filename */), *filepath(/* char *filename */);
Xchar *basename(/* char *filename */);
Xint getseq();
X
Xchar tempname[] = "/usr/spool/uucp/TM.XXXXXX";
Xchar luser[16];			/* local user name */
Xchar mysite[SITENAMELEN];	/* this host's uucpname */
Xchar cmdsite[SITENAMELEN];	/* site where command is run */
Xchar cmd[64];			/* remote command name */
Xchar arglist[2048] = "";	/* remote argument list */
XFILE *commandfile;		/* the "C." spool command file */
XFILE *execfile;			/* the "X." remote spool execute file */
Xchar grade = DEFGRADE;		/* transfer grade */
Xint nocico = 0;			/* "don't run uucico" flag */
Xint trylink = 0;		/* try spoolfile links before copying */
Xint readstdin = 0;		/* read standard input ("-" or "-p") */
X
Xmain(argc, argv)
Xint argc; char *argv[];
X{
X int c;				/* option character */
X int seq;			/* 'seq number' of X. file */
X char scratch[256];		/* ubiquitous scratch buffer */
X char *p;			/* equally ubiquitous scratch pointer */
X 
X strcpy(mysite, uucpname());
X if(strlen(mysite) == 0)
X   {
X    fprintf(stderr, "uux: can't get my own uucpname\n");
X    exit(1);
X   }
X strcpy(luser, whoami());
X
X while((c = getopt(argc, argv, "lprva:g:")) != EOF)
X      {
X       switch(c)
X	     {
X	      case 'r':
X			nocico = 1;
X			break;
X
X	      case 'g':
X			if(isalnum(optarg[0]) && '\0' == optarg[1])
X			  grade = optarg[0];
X			else
X			  fprintf(stderr, "uux: %s: illegal grade\n", optarg);
X			break;
X
X	      case 'l':
X			trylink = 1;
X			break;
X
X	      case 'p':
X			readstdin = 1;
X			break;
X
X	      case 'a':
X			break;
X
X	      default:
X			usage();
X			exit(1);
X	     }
X      }
X
X if(optind < argc && strcmp(argv[optind], "-") == 0)
X   {
X    ++optind;
X    readstdin = 1;
X   }
X
X if(optind >= argc)
X   {
X    usage();
X    exit(1);
X   }
X 
X if(NULL == (p = filesite(argv[optind])))
X   {
X    fprintf(stderr, "uux: illegal command\n");
X    exit(1);
X   }
X strcpy(cmdsite, p);
X if(NULL == (p = filepath(argv[optind])))
X   {
X    fprintf(stderr, "uux: illegal command\n");
X    exit(1);
X   }
X strcpy(cmd, p);
X ++optind;
X
X if(strlen(cmdsite) == 0)
X   {
X    fprintf(stderr, "uux: local commands not implemented yet\n");
X    exit(1);
X   }
X else if(!knowhost(cmdsite))
X   {
X    fprintf(stderr, "uux: site %s unknown\n", cmdsite);
X    exit(1);
X   }
X
X if(NULL == (commandfile = fopen(mktemp(tempname), "w")))
X   {
X    fprintf(stderr, "uux: can't open ");
X    perror(tempname);
X    exit(1);
X   }
X 
X seq = getseq();
X sprintf(scratch, "%s/D.%s%c%04d", SPOOLDIR, mysite, 'X', seq);
X if(NULL == (execfile = fopen(scratch, "w")))
X   {
X    fprintf(stderr, "uux: can't open ");
X    perror(scratch);
X    exit(1);
X   }
X fprintf(commandfile, "S D.%s%c%04d X.%s%c%04d %s - D.%s%c%04d 0666\n",
X		      mysite, 'X', seq, mysite, 'X', seq, luser,
X		      mysite, 'X', seq);
X
X fprintf(execfile, "U %s %s\nR %s\n", luser, mysite, luser);
X
X if(readstdin)
X    dostdin();
X
X while(optind < argc)
X       doarg(argv[optind++]);
X
X fprintf(execfile, "C %s %s\n", cmd, arglist);
X fclose(execfile);
X fclose(commandfile);
X sprintf(scratch, "%s/C.%s%c%04d", SPOOLDIR, cmdsite, grade, seq);
X if(link(tempname, scratch) == 0)
X    unlink(tempname);
X else
X   {
X    fprintf(stderr, "uux: couldn't rename commandfile");
X    exit(1);
X   }
X
X if(nocico)
X    exit(0);
X else
X    execl(CICO, "-r1", (char *)NULL);
X}
X
Xvoid usage()
X{
X fprintf(stderr, "usage: uux [-plrv] [-g grade] [-a user] [-] host!cmd arg ...\n");
X}
X
Xvoid dostdin()
X{
X char name[128], spoolname[128];	/* spool data filename */
X FILE *data;				/* spool data file */
X int seq;				/* spool sequence number */
X int c;					/* char from stdin */
X
X seq = getseq();
X sprintf(name, "D.%s%c%04d", mysite, grade, seq);
X sprintf(spoolname, "%s/%s", SPOOLDIR, name);
X if(NULL == (data = fopen(spoolname, "w")))
X   {
X    fprintf(stderr, "uux: can't copy stdin\n");
X    return;
X   }
X while(EOF != (c = getc(stdin)))
X       putc(c, data);
X fclose(data);
X
X fprintf(execfile, "F %s\nI %s\n", name, name);
X fprintf(commandfile, "S %s %s %s - %s 0666\n", name, name, luser, name);
X}
X
Xvoid doarg(arg)
Xchar *arg;
X{
X char name[128], spoolname[128];	/* spool data filename */
X FILE *data;				/* spool data file */
X FILE *source;				/* source data file */
X int seq;				/* spool sequence number */
X int c;					/* char from input */
X
X if('(' == arg[0] && ')' == arg[strlen(arg) - 1])
X   {
X    strcat(arglist, arg + 1);
X    arglist[strlen(arglist) - 1] = '\0';
X   }
X else if(NULL == index(arg, '!'))
X    strcat(arglist, arg);
X else if(strcmp(filesite(arg), cmdsite) == 0)
X   {
X    strcat(arglist, filepath(arg));
X   }
X else if(strlen(filesite(arg)) == 0)
X   {
X    seq = getseq();
X    sprintf(name, "D.%s%c%04d", mysite, grade, seq);
X    sprintf(spoolname, "%s/%s", SPOOLDIR, name);
X
X    if(!trylink || link(filepath(arg), spoolname) < 0)
X      {
X       if(NULL == (data = fopen(spoolname, "w"))
X	  || NULL == (source = fopen(filepath(arg), "r")))
X	 {
X	  fprintf(stderr, "uux: can't copy %s to spool directory",
X		  filepath(arg));
X	  exit(1);
X	 }
X       while(EOF != (c = getc(source)))
X	     putc(c, data);
X       fclose(data);
X       fclose(source);
X      }
X    fprintf(commandfile, "S %s %s %s - %s 0666\n", filepath(arg), name,
X	    luser, name);
X    fprintf(execfile, "F %s %s\n", name, basename(filepath(arg)));
X    strcat(arglist, basename(filepath(arg)));
X   }
X else
X   {
X    fprintf(stderr, "uux: illegal argument %s\n", arg);
X    return;
X   }
X
X strcat(arglist, " ");
X}
X  
X/*
X * |uucpname()| returns a pointer to the local host's UUCP nodename.
X * There are several possible means of determining this, depending
X * on the operating system version. For now, this version just reads
X * one line from the |NODENAME| file, which is usually either "/etc/cpu"
X * or "/etc/uucpname".
X */
Xchar *uucpname()
X{
X FILE *uufile;
X static char uuname[SITENAMELEN];
X
X if(NULL == (uufile = fopen(NODENAME, "r")))
X    return "";
X fgets(uuname, sizeof uuname, uufile);
X uuname[strlen(uuname) - 1] = '\0';	/* remove '\n' */
X fclose(uufile);
X
X return uuname;
X}
X
Xint knowhost(host)
Xchar *host;
X{
X FILE *sysfile;
X char line[256];
X char *p, *q;
X
X if(NULL == (sysfile = fopen(LSYS, "r")))
X    return 0;
X while(fgets(line, sizeof line, sysfile) != NULL)
X      {
X       for(p = host, q = line; !isspace(*q); p++, q++)
X           if(*p != *q)
X              break;
X       if('\0' == *p && isspace(*q))
X         {
X          fclose(sysfile);
X          return 1;
X         }
X      }
X fclose(sysfile);
X return 0;
X}
X
Xint getseq()
X{
X int i = 0;
X char seqline[10];
X FILE *spoolseq;
X
X if(access(SPOOLSEQ, 0) != 0)
X    close(creat(SPOOLSEQ, 0600));
X
X while(link(SPOOLSEQ, LSPOOLSEQ) != 0)
X      {
X       sleep(5);
X       if(++i > 5)
X         {
X          fprintf(stderr, "uux: can't lock %s\n", SPOOLSEQ);
X	  exit(1);
X         }
X      }
X
X spoolseq = fopen(SPOOLSEQ, "r");
X fgets(seqline, sizeof seqline, spoolseq);
X fclose(spoolseq);
X unlink(LSPOOLSEQ);
X
X i = (atoi(seqline) + 1) % 1000;
X
X if(NULL == (spoolseq = fopen(SPOOLSEQ, "w")))
X   {
X    fprintf(stderr, "uux: can't write %s\n", SPOOLSEQ);
X    exit(1);
X   }
X fprintf(spoolseq, "%d\n", i);
X fclose(spoolseq);
X
X return i;
X}
X
Xchar *whoami()
X{
X struct passwd *pw;
X
X if(NULL != (pw = getpwuid(getuid())))
X    return pw->pw_name;
X else
X    return "nobody";
X}
X
Xchar *filesite(name)
Xchar *name;
X{
X static char site[SITENAMELEN];
X char *p;
X char *q;
X
X if(NULL == (p = index(name, '!')))
X    return NULL;
X
X q = site;
X while(name < p)
X       *q++ = *name++;
X *q = '\0';
X
X return site;
X}
X
Xchar *filepath(name)
Xchar *name;
X{
X char *p;
X
X if(NULL == (p = rindex(name, '!')))
X    return NULL;
X
X return p + 1;
X}
X
Xchar *basename(name)
Xchar *name;
X{
X char *p;
X
X if(NULL == (p = rindex(name, '/')))
X    return name;
X else
X    return p + 1;
X}
**-uux.c-EOF-**