152081424Ssam #ifndef lint 2*109b7051Ssam static char sccsid[] = "@(#)uuxqt.c 5.2 (Berkeley) 07/02/83"; 352081424Ssam #endif 452081424Ssam 552081424Ssam #include "uucp.h" 652081424Ssam #include <sys/types.h> 752081424Ssam #include <sys/stat.h> 852081424Ssam #ifdef NDIR 952081424Ssam #include "ndir.h" 1052081424Ssam #else 11*109b7051Ssam #include <sys/dir.h> 1252081424Ssam #endif 1352081424Ssam 1452081424Ssam #define APPCMD(d) {\ 1552081424Ssam char *p;\ 1652081424Ssam for (p = d; *p != '\0';) *cmdp++ = *p++;\ 1752081424Ssam *cmdp++ = ' ';\ 1852081424Ssam *cmdp = '\0';} 1952081424Ssam 2052081424Ssam /* 2152081424Ssam * uuxqt will execute commands set up by a uux command, 2252081424Ssam * usually from a remote machine - set by uucp. 2352081424Ssam */ 2452081424Ssam 2552081424Ssam #define NCMDS 50 2652081424Ssam char *Cmds[NCMDS]; 2752081424Ssam 2852081424Ssam int notiok = 1; 2952081424Ssam int nonzero = 0; 3052081424Ssam 3152081424Ssam char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin"; 3252081424Ssam /* to remove restrictions from uuxqt 3352081424Ssam * define ALLOK 1 3452081424Ssam * 3552081424Ssam * to add allowable commands, add to the file CMDFILE 3652081424Ssam * A line of form "PATH=..." changes the search path 3752081424Ssam */ 3852081424Ssam 3952081424Ssam 4052081424Ssam main(argc, argv) 4152081424Ssam char *argv[]; 4252081424Ssam { 4352081424Ssam char xcmd[MAXFULLNAME]; 4452081424Ssam int argnok; 4552081424Ssam char xfile[MAXFULLNAME], user[32], buf[BUFSIZ]; 4652081424Ssam char lbuf[30]; 4752081424Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME]; 4852081424Ssam char file[NAMESIZE]; 4952081424Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; 5052081424Ssam register FILE *xfp, *fp; 5152081424Ssam FILE *dfp; 5252081424Ssam char path[MAXFULLNAME]; 5352081424Ssam char cmd[BUFSIZ]; 5452081424Ssam /* set size of prm to something large -- cmcl2!salkind */ 5552081424Ssam char *cmdp, prm[1000], *ptr; 5652081424Ssam char *getprm(), *lastpart(); 5752081424Ssam int uid, ret, badfiles; 5852081424Ssam register int i; 5952081424Ssam int stcico = 0; 6052081424Ssam char retstat[30]; 6152081424Ssam int orig_uid = getuid(); 6252081424Ssam 6352081424Ssam strcpy(Progname, "uuxqt"); 6452081424Ssam uucpname(Myname); 6552081424Ssam 6652081424Ssam /* Try to run as uucp -- rti!trt */ 6752081424Ssam setgid(getegid()); 6852081424Ssam setuid(geteuid()); 6952081424Ssam 7052081424Ssam umask(WFMASK); 7152081424Ssam Ofn = 1; 7252081424Ssam Ifn = 0; 7352081424Ssam while (argc>1 && argv[1][0] == '-') { 7452081424Ssam switch(argv[1][1]){ 7552081424Ssam case 'x': 7652081424Ssam chkdebug(orig_uid); 7752081424Ssam Debug = atoi(&argv[1][2]); 7852081424Ssam if (Debug <= 0) 7952081424Ssam Debug = 1; 8052081424Ssam break; 8152081424Ssam default: 8252081424Ssam fprintf(stderr, "unknown flag %s\n", argv[1]); 8352081424Ssam break; 8452081424Ssam } 8552081424Ssam --argc; argv++; 8652081424Ssam } 8752081424Ssam 8852081424Ssam DEBUG(4, "\n\n** %s **\n", "START"); 8952081424Ssam subchdir(Spool); 9052081424Ssam strcpy(Wrkdir, Spool); 9152081424Ssam uid = getuid(); 9252081424Ssam guinfo(uid, User, path); 9352081424Ssam DEBUG(4, "User - %s\n", User); 9452081424Ssam if (ulockf(X_LOCK, (time_t) X_LOCKTIME) != 0) 9552081424Ssam exit(0); 9652081424Ssam 9752081424Ssam fp = fopen(CMDFILE, "r"); 9852081424Ssam if (fp == NULL) { 9952081424Ssam /* Fall-back if CMDFILE missing. Sept 1982, rti!trt */ 10052081424Ssam logent("CAN'T OPEN", CMDFILE); 10152081424Ssam Cmds[0] = "rmail"; 10252081424Ssam Cmds[1] = "rnews"; 10352081424Ssam Cmds[2] = "ruusend"; 10452081424Ssam Cmds[3] = NULL; 10552081424Ssam goto doprocess; 10652081424Ssam } 10752081424Ssam DEBUG(5, "%s opened\n", CMDFILE); 10852081424Ssam for (i=0; i<NCMDS-1 && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) { 10952081424Ssam xcmd[strlen(xcmd)-1] = '\0'; 11052081424Ssam if (strncmp(xcmd, "PATH=", 5) == 0) { 11152081424Ssam strcpy(PATH, xcmd); 11252081424Ssam i--; /* kludge */ 11352081424Ssam continue; 11452081424Ssam } 11552081424Ssam DEBUG(5, "xcmd = %s\n", xcmd); 11652081424Ssam Cmds[i] = malloc((unsigned)(strlen(xcmd)+1)); 11752081424Ssam strcpy(Cmds[i], xcmd); 11852081424Ssam } 11952081424Ssam Cmds[i] = 0; 12052081424Ssam fclose(fp); 12152081424Ssam 12252081424Ssam doprocess: 12352081424Ssam DEBUG(4, "process %s\n", ""); 12452081424Ssam while (gtxfile(xfile) > 0) { 12552081424Ssam ultouch(); /* rti!trt */ 12652081424Ssam DEBUG(4, "xfile - %s\n", xfile); 12752081424Ssam 12852081424Ssam xfp = fopen(subfile(xfile), "r"); 12952081424Ssam ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0); 13052081424Ssam 13152081424Ssam /* initialize to default */ 13252081424Ssam strcpy(user, User); 13352081424Ssam strcpy(fin, "/dev/null"); 13452081424Ssam strcpy(fout, "/dev/null"); 13552081424Ssam sprintf(sysout, "%.7s", Myname); 13652081424Ssam badfiles = 0; /* this was missing -- rti!trt */ 13752081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 13852081424Ssam switch (buf[0]) { 13952081424Ssam case X_USER: 14052081424Ssam sscanf(&buf[1], "%s%s", user, Rmtname); 14152081424Ssam break; 14252081424Ssam case X_STDIN: 14352081424Ssam sscanf(&buf[1], "%s", fin); 14452081424Ssam i = expfile(fin); 14552081424Ssam /* rti!trt: do not check permissions of 14652081424Ssam * vanilla spool file */ 14752081424Ssam if (i != 0 14852081424Ssam && (chkpth("", "", fin) || anyread(fin) != 0)) 14952081424Ssam badfiles = 1; 15052081424Ssam break; 15152081424Ssam case X_STDOUT: 15252081424Ssam sscanf(&buf[1], "%s%s", fout, sysout); 15352081424Ssam sysout[7] = '\0'; 15452081424Ssam /* rti!trt: do not check permissions of 15552081424Ssam * vanilla spool file. DO check permissions 15652081424Ssam * of writing on a non-vanilla file */ 15752081424Ssam i = 1; 15852081424Ssam if (fout[0] != '~' || prefix(sysout, Myname)) 15952081424Ssam i = expfile(fout); 16052081424Ssam if (i != 0 16152081424Ssam && (chkpth("", "", fout) 16252081424Ssam || chkperm(fout, (char *)1))) 16352081424Ssam badfiles = 1; 16452081424Ssam break; 16552081424Ssam case X_CMD: 16652081424Ssam strcpy(cmd, &buf[2]); 16752081424Ssam if (*(cmd + strlen(cmd) - 1) == '\n') 16852081424Ssam *(cmd + strlen(cmd) - 1) = '\0'; 16952081424Ssam break; 17052081424Ssam case X_NONOTI: 17152081424Ssam notiok = 0; 17252081424Ssam break; 17352081424Ssam case X_NONZERO: 17452081424Ssam nonzero = 1; 17552081424Ssam break; 17652081424Ssam default: 17752081424Ssam break; 17852081424Ssam } 17952081424Ssam } 18052081424Ssam 18152081424Ssam fclose(xfp); 18252081424Ssam DEBUG(4, "fin - %s, ", fin); 18352081424Ssam DEBUG(4, "fout - %s, ", fout); 18452081424Ssam DEBUG(4, "sysout - %s, ", sysout); 18552081424Ssam DEBUG(4, "user - %s\n", user); 18652081424Ssam DEBUG(4, "cmd - %s\n", cmd); 18752081424Ssam 18852081424Ssam /* command execution */ 18952081424Ssam if (strcmp(fout, "/dev/null") == SAME) 19052081424Ssam strcpy(dfile,"/dev/null"); 19152081424Ssam else 19252081424Ssam gename(DATAPRE, sysout, 'O', dfile); 19352081424Ssam 19452081424Ssam /* expand file names where necessary */ 19552081424Ssam expfile(dfile); 19652081424Ssam strcpy(buf, PATH); 19752081424Ssam strcat(buf, ";export PATH;"); 19852081424Ssam cmdp = buf + strlen(buf); 19952081424Ssam ptr = cmd; 20052081424Ssam xcmd[0] = '\0'; 20152081424Ssam argnok = 0; 20252081424Ssam while ((ptr = getprm(ptr, prm)) != NULL) { 20352081424Ssam if (prm[0] == ';' || prm[0] == '^' 20452081424Ssam || prm[0] == '&' || prm[0] == '|') { 20552081424Ssam xcmd[0] = '\0'; 20652081424Ssam APPCMD(prm); 20752081424Ssam continue; 20852081424Ssam } 20952081424Ssam 21052081424Ssam if ((argnok = argok(xcmd, prm)) != 0) 21152081424Ssam /* command not valid */ 21252081424Ssam break; 21352081424Ssam 21452081424Ssam if (prm[0] == '~') 21552081424Ssam expfile(prm); 21652081424Ssam APPCMD(prm); 21752081424Ssam } 21852081424Ssam if (argnok || badfiles) { 21952081424Ssam sprintf(lbuf, "%s XQT DENIED", user); 22052081424Ssam logent(cmd, lbuf); 22152081424Ssam DEBUG(4, "bad command %s\n", prm); 22252081424Ssam notify(user, Rmtname, cmd, "DENIED"); 22352081424Ssam goto rmfiles; 22452081424Ssam } 22552081424Ssam sprintf(lbuf, "%s XQT", user); 22652081424Ssam logent(buf, lbuf); 22752081424Ssam DEBUG(4, "cmd %s\n", buf); 22852081424Ssam 22952081424Ssam mvxfiles(xfile); 23052081424Ssam subchdir(XQTDIR); 23152081424Ssam ret = shio(buf, fin, dfile, (char *)NULL); 23252081424Ssam /* watcgl.11, dmmartindale, signal and exit values were reversed */ 23352081424Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377, 23452081424Ssam (ret>>8) & 0377); 23552081424Ssam if (strcmp(xcmd, "rmail") == SAME) 23652081424Ssam notiok = 0; 23752081424Ssam if (strcmp(xcmd, "rnews") == SAME) 23852081424Ssam nonzero = 1; 23952081424Ssam if (notiok && (!nonzero || (nonzero && ret != 0))) 24052081424Ssam notify(user, Rmtname, cmd, retstat); 24152081424Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) { 24252081424Ssam /* mail failed - return letter to sender */ 24352081424Ssam retosndr(user, Rmtname, fin); 24452081424Ssam sprintf(buf, "ret (%o) from %s!%s", ret, Rmtname, user); 24552081424Ssam logent("MAIL FAIL", buf); 24652081424Ssam } 24752081424Ssam DEBUG(4, "exit cmd - %d\n", ret); 24852081424Ssam subchdir(Spool); 24952081424Ssam rmxfiles(xfile); 25052081424Ssam if (ret != 0) { 25152081424Ssam /* exit status not zero */ 25252081424Ssam dfp = fopen(subfile(dfile), "a"); 25352081424Ssam ASSERT(dfp != NULL, "CAN'T OPEN", dfile, 0); 25452081424Ssam fprintf(dfp, "exit status %d", ret); 25552081424Ssam fclose(dfp); 25652081424Ssam } 25752081424Ssam if (strcmp(fout, "/dev/null") != SAME) { 25852081424Ssam if (prefix(sysout, Myname)) { 25952081424Ssam xmv(dfile, fout); 26052081424Ssam chmod(fout, BASEMODE); 26152081424Ssam } 26252081424Ssam else { 26352081424Ssam gename(CMDPRE, sysout, 'O', cfile); 26452081424Ssam fp = fopen(subfile(cfile), "w"); 26552081424Ssam ASSERT(fp != NULL, "OPEN", cfile, 0); 26652081424Ssam fprintf(fp, "S %s %s %s - %s 0666\n", 26752081424Ssam dfile, fout, user, lastpart(dfile)); 26852081424Ssam fclose(fp); 26952081424Ssam } 27052081424Ssam } 27152081424Ssam rmfiles: 27252081424Ssam xfp = fopen(subfile(xfile), "r"); 27352081424Ssam ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0); 27452081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 27552081424Ssam if (buf[0] != X_RQDFILE) 27652081424Ssam continue; 27752081424Ssam sscanf(&buf[1], "%s", file); 27852081424Ssam unlink(subfile(file)); 27952081424Ssam } 28052081424Ssam unlink(subfile(xfile)); 28152081424Ssam fclose(xfp); 28252081424Ssam } 28352081424Ssam 28452081424Ssam if (stcico) 28552081424Ssam xuucico(""); 28652081424Ssam cleanup(0); 28752081424Ssam } 28852081424Ssam 28952081424Ssam 29052081424Ssam cleanup(code) 29152081424Ssam int code; 29252081424Ssam { 29352081424Ssam logcls(); 29452081424Ssam rmlock(CNULL); 29552081424Ssam exit(code); 29652081424Ssam } 29752081424Ssam 29852081424Ssam 29952081424Ssam /******* 30052081424Ssam * gtxfile(file) get a file to execute 30152081424Ssam * char *file; 30252081424Ssam * 30352081424Ssam * return codes: 0 - no file | 1 - file to execute 30452081424Ssam * Mod to recheck for X-able files. Sept 1982, rti!trt. 30552081424Ssam * Suggested by utzoo.2458 (utzoo!henry) 30652081424Ssam * Uses iswrk/gtwrkf to keep files in sequence, May 1983. 30752081424Ssam */ 30852081424Ssam 30952081424Ssam gtxfile(file) 31052081424Ssam register char *file; 31152081424Ssam { 31252081424Ssam char pre[3]; 31352081424Ssam register int rechecked; 31452081424Ssam 31552081424Ssam pre[0] = XQTPRE; 31652081424Ssam pre[1] = '.'; 31752081424Ssam pre[2] = '\0'; 31852081424Ssam rechecked = 0; 31952081424Ssam retry: 32052081424Ssam if (!gtwrkf(Spool, file)) { 32152081424Ssam if (rechecked) 32252081424Ssam return(0); 32352081424Ssam rechecked = 1; 32452081424Ssam DEBUG(4, "iswrk\n", ""); 32552081424Ssam if (!iswrk(file, "get", Spool, pre)) 32652081424Ssam return(0); 32752081424Ssam } 32852081424Ssam DEBUG(4, "file - %s\n", file); 32952081424Ssam #ifndef UUDIR 33052081424Ssam /* skip spurious subdirectories */ 33152081424Ssam if (strcmp(pre, file) == SAME) 33252081424Ssam goto retry; 33352081424Ssam #endif 33452081424Ssam if (gotfiles(file)) 33552081424Ssam return(1); 33652081424Ssam goto retry; 33752081424Ssam } 33852081424Ssam 33952081424Ssam 34052081424Ssam /*** 34152081424Ssam * gotfiles(file) check for needed files 34252081424Ssam * char *file; 34352081424Ssam * 34452081424Ssam * return codes: 0 - not ready | 1 - all files ready 34552081424Ssam */ 34652081424Ssam 34752081424Ssam gotfiles(file) 34852081424Ssam register char *file; 34952081424Ssam { 35052081424Ssam struct stat stbuf; 35152081424Ssam register FILE *fp; 35252081424Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME]; 35352081424Ssam 35452081424Ssam fp = fopen(subfile(file), "r"); 35552081424Ssam if (fp == NULL) 35652081424Ssam return(0); 35752081424Ssam 35852081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 35952081424Ssam DEBUG(4, "%s\n", buf); 36052081424Ssam if (buf[0] != X_RQDFILE) 36152081424Ssam continue; 36252081424Ssam sscanf(&buf[1], "%s", rqfile); 36352081424Ssam expfile(rqfile); 36452081424Ssam if (stat(subfile(rqfile), &stbuf) == -1) { 36552081424Ssam fclose(fp); 36652081424Ssam return(0); 36752081424Ssam } 36852081424Ssam } 36952081424Ssam 37052081424Ssam fclose(fp); 37152081424Ssam return(1); 37252081424Ssam } 37352081424Ssam 37452081424Ssam 37552081424Ssam /*** 37652081424Ssam * rmxfiles(xfile) remove execute files to x-directory 37752081424Ssam * char *xfile; 37852081424Ssam * 37952081424Ssam * return codes - none 38052081424Ssam */ 38152081424Ssam 38252081424Ssam rmxfiles(xfile) 38352081424Ssam register char *xfile; 38452081424Ssam { 38552081424Ssam register FILE *fp; 38652081424Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; 38752081424Ssam char tfull[MAXFULLNAME]; 38852081424Ssam 38952081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 39052081424Ssam return; 39152081424Ssam 39252081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 39352081424Ssam if (buf[0] != X_RQDFILE) 39452081424Ssam continue; 39552081424Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2) 39652081424Ssam continue; 39752081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 39852081424Ssam unlink(subfile(tfull)); 39952081424Ssam } 40052081424Ssam fclose(fp); 40152081424Ssam return; 40252081424Ssam } 40352081424Ssam 40452081424Ssam 40552081424Ssam /*** 40652081424Ssam * mvxfiles(xfile) move execute files to x-directory 40752081424Ssam * char *xfile; 40852081424Ssam * 40952081424Ssam * return codes - none 41052081424Ssam */ 41152081424Ssam 41252081424Ssam mvxfiles(xfile) 41352081424Ssam char *xfile; 41452081424Ssam { 41552081424Ssam register FILE *fp; 41652081424Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; 41752081424Ssam char tfull[MAXFULLNAME]; 41852081424Ssam int ret; 41952081424Ssam 42052081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 42152081424Ssam return; 42252081424Ssam 42352081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 42452081424Ssam if (buf[0] != X_RQDFILE) 42552081424Ssam continue; 42652081424Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) 42752081424Ssam continue; 42852081424Ssam expfile(ffile); 42952081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 43052081424Ssam /* duke!rti, ncsu!mcm: use xmv, not link(II) */ 43152081424Ssam unlink(subfile(tfull)); 43252081424Ssam ret = xmv(ffile, tfull); 43352081424Ssam ASSERT(ret == 0, "XQTDIR ERROR", "", ret); 43452081424Ssam } 43552081424Ssam fclose(fp); 43652081424Ssam return; 43752081424Ssam } 43852081424Ssam 43952081424Ssam 44052081424Ssam /*** 44152081424Ssam * argok(xc, cmd) check for valid command/argumanet 44252081424Ssam * *NOTE - side effect is to set xc to the 44352081424Ssam * command to be executed. 44452081424Ssam * char *xc, *cmd; 44552081424Ssam * 44652081424Ssam * return 0 - ok | 1 nok 44752081424Ssam */ 44852081424Ssam 44952081424Ssam argok(xc, cmd) 45052081424Ssam register char *xc, *cmd; 45152081424Ssam { 45252081424Ssam register char **ptr; 45352081424Ssam 45452081424Ssam #ifndef ALLOK 45552081424Ssam /* don't allow sh command strings `....` */ 45652081424Ssam /* don't allow redirection of standard in or out */ 45752081424Ssam /* don't allow other funny stuff */ 45852081424Ssam /* but there are probably total holes here */ 45952081424Ssam /* post-script. ittvax!swatt has a uuxqt that solves this. */ 46052081424Ssam /* This version of uuxqt will shortly disappear */ 46152081424Ssam if (index(cmd, '`') != NULL 46252081424Ssam || index(cmd, '>') != NULL 46352081424Ssam || index(cmd, ';') != NULL 46452081424Ssam || index(cmd, '^') != NULL 46552081424Ssam || index(cmd, '&') != NULL 46652081424Ssam || index(cmd, '|') != NULL 46752081424Ssam || index(cmd, '<') != NULL) 46852081424Ssam return(1); 46952081424Ssam #endif 47052081424Ssam 47152081424Ssam if (xc[0] != '\0') 47252081424Ssam return(0); 47352081424Ssam 47452081424Ssam #ifndef ALLOK 47552081424Ssam ptr = Cmds; 47652081424Ssam while(*ptr != NULL) { 47752081424Ssam if (strcmp(cmd, *ptr) == SAME) 47852081424Ssam break; 47952081424Ssam ptr++; 48052081424Ssam } 48152081424Ssam if (*ptr == NULL) 48252081424Ssam return(1); 48352081424Ssam #endif 48452081424Ssam strcpy(xc, cmd); 48552081424Ssam return(0); 48652081424Ssam } 48752081424Ssam 48852081424Ssam 48952081424Ssam /*** 49052081424Ssam * notify send mail to user giving execution results 49152081424Ssam * return code - none 49252081424Ssam * This program assumes new mail command - send remote mail 49352081424Ssam */ 49452081424Ssam 49552081424Ssam notify(user, rmt, cmd, str) 49652081424Ssam char *user, *rmt, *cmd, *str; 49752081424Ssam { 49852081424Ssam char text[MAXFULLNAME]; 49952081424Ssam char ruser[MAXFULLNAME]; 50052081424Ssam 50152081424Ssam sprintf(text, "uuxqt cmd (%.50s) status (%s)", cmd, str); 50252081424Ssam if (prefix(rmt, Myname)) 50352081424Ssam strcpy(ruser, user); 50452081424Ssam else 50552081424Ssam sprintf(ruser, "%s!%s", rmt, user); 50652081424Ssam mailst(ruser, text, ""); 50752081424Ssam return; 50852081424Ssam } 50952081424Ssam 51052081424Ssam /*** 51152081424Ssam * retosndr - return mail to sender 51252081424Ssam * 51352081424Ssam * return code - none 51452081424Ssam */ 51552081424Ssam 51652081424Ssam retosndr(user, rmt, file) 51752081424Ssam char *user, *rmt, *file; 51852081424Ssam { 51952081424Ssam char ruser[100]; 52052081424Ssam 52152081424Ssam if (strcmp(rmt, Myname) == SAME) 52252081424Ssam strcpy(ruser, user); 52352081424Ssam else 52452081424Ssam sprintf(ruser, "%s!%s", rmt, user); 52552081424Ssam 52652081424Ssam if (anyread(file) == 0) 52752081424Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file); 52852081424Ssam else 52952081424Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", ""); 53052081424Ssam return; 53152081424Ssam } 532