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-**