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