1*13697Ssam #ifndef lint 2*13697Ssam static char sccsid[] = "@(#)uuxqt.c 5.1 (Berkeley) 07/02/83"; 3*13697Ssam #endif 4*13697Ssam 5*13697Ssam #include "uucp.h" 6*13697Ssam #include <sys/types.h> 7*13697Ssam #include <sys/stat.h> 8*13697Ssam #ifdef NDIR 9*13697Ssam #include "ndir.h" 10*13697Ssam #else 11*13697Ssam #include <dir.h> 12*13697Ssam #endif 13*13697Ssam 14*13697Ssam #define APPCMD(d) {\ 15*13697Ssam char *p;\ 16*13697Ssam for (p = d; *p != '\0';) *cmdp++ = *p++;\ 17*13697Ssam *cmdp++ = ' ';\ 18*13697Ssam *cmdp = '\0';} 19*13697Ssam 20*13697Ssam /* 21*13697Ssam * uuxqt will execute commands set up by a uux command, 22*13697Ssam * usually from a remote machine - set by uucp. 23*13697Ssam */ 24*13697Ssam 25*13697Ssam #define NCMDS 50 26*13697Ssam char *Cmds[NCMDS]; 27*13697Ssam 28*13697Ssam int notiok = 1; 29*13697Ssam int nonzero = 0; 30*13697Ssam 31*13697Ssam char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin"; 32*13697Ssam /* to remove restrictions from uuxqt 33*13697Ssam * define ALLOK 1 34*13697Ssam * 35*13697Ssam * to add allowable commands, add to the file CMDFILE 36*13697Ssam * A line of form "PATH=..." changes the search path 37*13697Ssam */ 38*13697Ssam 39*13697Ssam 40*13697Ssam main(argc, argv) 41*13697Ssam char *argv[]; 42*13697Ssam { 43*13697Ssam char xcmd[MAXFULLNAME]; 44*13697Ssam int argnok; 45*13697Ssam char xfile[MAXFULLNAME], user[32], buf[BUFSIZ]; 46*13697Ssam char lbuf[30]; 47*13697Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME]; 48*13697Ssam char file[NAMESIZE]; 49*13697Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; 50*13697Ssam register FILE *xfp, *fp; 51*13697Ssam FILE *dfp; 52*13697Ssam char path[MAXFULLNAME]; 53*13697Ssam char cmd[BUFSIZ]; 54*13697Ssam /* set size of prm to something large -- cmcl2!salkind */ 55*13697Ssam char *cmdp, prm[1000], *ptr; 56*13697Ssam char *getprm(), *lastpart(); 57*13697Ssam int uid, ret, badfiles; 58*13697Ssam register int i; 59*13697Ssam int stcico = 0; 60*13697Ssam char retstat[30]; 61*13697Ssam int orig_uid = getuid(); 62*13697Ssam 63*13697Ssam strcpy(Progname, "uuxqt"); 64*13697Ssam uucpname(Myname); 65*13697Ssam 66*13697Ssam /* Try to run as uucp -- rti!trt */ 67*13697Ssam setgid(getegid()); 68*13697Ssam setuid(geteuid()); 69*13697Ssam 70*13697Ssam umask(WFMASK); 71*13697Ssam Ofn = 1; 72*13697Ssam Ifn = 0; 73*13697Ssam while (argc>1 && argv[1][0] == '-') { 74*13697Ssam switch(argv[1][1]){ 75*13697Ssam case 'x': 76*13697Ssam chkdebug(orig_uid); 77*13697Ssam Debug = atoi(&argv[1][2]); 78*13697Ssam if (Debug <= 0) 79*13697Ssam Debug = 1; 80*13697Ssam break; 81*13697Ssam default: 82*13697Ssam fprintf(stderr, "unknown flag %s\n", argv[1]); 83*13697Ssam break; 84*13697Ssam } 85*13697Ssam --argc; argv++; 86*13697Ssam } 87*13697Ssam 88*13697Ssam DEBUG(4, "\n\n** %s **\n", "START"); 89*13697Ssam subchdir(Spool); 90*13697Ssam strcpy(Wrkdir, Spool); 91*13697Ssam uid = getuid(); 92*13697Ssam guinfo(uid, User, path); 93*13697Ssam DEBUG(4, "User - %s\n", User); 94*13697Ssam if (ulockf(X_LOCK, (time_t) X_LOCKTIME) != 0) 95*13697Ssam exit(0); 96*13697Ssam 97*13697Ssam fp = fopen(CMDFILE, "r"); 98*13697Ssam if (fp == NULL) { 99*13697Ssam /* Fall-back if CMDFILE missing. Sept 1982, rti!trt */ 100*13697Ssam logent("CAN'T OPEN", CMDFILE); 101*13697Ssam Cmds[0] = "rmail"; 102*13697Ssam Cmds[1] = "rnews"; 103*13697Ssam Cmds[2] = "ruusend"; 104*13697Ssam Cmds[3] = NULL; 105*13697Ssam goto doprocess; 106*13697Ssam } 107*13697Ssam DEBUG(5, "%s opened\n", CMDFILE); 108*13697Ssam for (i=0; i<NCMDS-1 && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) { 109*13697Ssam xcmd[strlen(xcmd)-1] = '\0'; 110*13697Ssam if (strncmp(xcmd, "PATH=", 5) == 0) { 111*13697Ssam strcpy(PATH, xcmd); 112*13697Ssam i--; /* kludge */ 113*13697Ssam continue; 114*13697Ssam } 115*13697Ssam DEBUG(5, "xcmd = %s\n", xcmd); 116*13697Ssam Cmds[i] = malloc((unsigned)(strlen(xcmd)+1)); 117*13697Ssam strcpy(Cmds[i], xcmd); 118*13697Ssam } 119*13697Ssam Cmds[i] = 0; 120*13697Ssam fclose(fp); 121*13697Ssam 122*13697Ssam doprocess: 123*13697Ssam DEBUG(4, "process %s\n", ""); 124*13697Ssam while (gtxfile(xfile) > 0) { 125*13697Ssam ultouch(); /* rti!trt */ 126*13697Ssam DEBUG(4, "xfile - %s\n", xfile); 127*13697Ssam 128*13697Ssam xfp = fopen(subfile(xfile), "r"); 129*13697Ssam ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0); 130*13697Ssam 131*13697Ssam /* initialize to default */ 132*13697Ssam strcpy(user, User); 133*13697Ssam strcpy(fin, "/dev/null"); 134*13697Ssam strcpy(fout, "/dev/null"); 135*13697Ssam sprintf(sysout, "%.7s", Myname); 136*13697Ssam badfiles = 0; /* this was missing -- rti!trt */ 137*13697Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 138*13697Ssam switch (buf[0]) { 139*13697Ssam case X_USER: 140*13697Ssam sscanf(&buf[1], "%s%s", user, Rmtname); 141*13697Ssam break; 142*13697Ssam case X_STDIN: 143*13697Ssam sscanf(&buf[1], "%s", fin); 144*13697Ssam i = expfile(fin); 145*13697Ssam /* rti!trt: do not check permissions of 146*13697Ssam * vanilla spool file */ 147*13697Ssam if (i != 0 148*13697Ssam && (chkpth("", "", fin) || anyread(fin) != 0)) 149*13697Ssam badfiles = 1; 150*13697Ssam break; 151*13697Ssam case X_STDOUT: 152*13697Ssam sscanf(&buf[1], "%s%s", fout, sysout); 153*13697Ssam sysout[7] = '\0'; 154*13697Ssam /* rti!trt: do not check permissions of 155*13697Ssam * vanilla spool file. DO check permissions 156*13697Ssam * of writing on a non-vanilla file */ 157*13697Ssam i = 1; 158*13697Ssam if (fout[0] != '~' || prefix(sysout, Myname)) 159*13697Ssam i = expfile(fout); 160*13697Ssam if (i != 0 161*13697Ssam && (chkpth("", "", fout) 162*13697Ssam || chkperm(fout, (char *)1))) 163*13697Ssam badfiles = 1; 164*13697Ssam break; 165*13697Ssam case X_CMD: 166*13697Ssam strcpy(cmd, &buf[2]); 167*13697Ssam if (*(cmd + strlen(cmd) - 1) == '\n') 168*13697Ssam *(cmd + strlen(cmd) - 1) = '\0'; 169*13697Ssam break; 170*13697Ssam case X_NONOTI: 171*13697Ssam notiok = 0; 172*13697Ssam break; 173*13697Ssam case X_NONZERO: 174*13697Ssam nonzero = 1; 175*13697Ssam break; 176*13697Ssam default: 177*13697Ssam break; 178*13697Ssam } 179*13697Ssam } 180*13697Ssam 181*13697Ssam fclose(xfp); 182*13697Ssam DEBUG(4, "fin - %s, ", fin); 183*13697Ssam DEBUG(4, "fout - %s, ", fout); 184*13697Ssam DEBUG(4, "sysout - %s, ", sysout); 185*13697Ssam DEBUG(4, "user - %s\n", user); 186*13697Ssam DEBUG(4, "cmd - %s\n", cmd); 187*13697Ssam 188*13697Ssam /* command execution */ 189*13697Ssam if (strcmp(fout, "/dev/null") == SAME) 190*13697Ssam strcpy(dfile,"/dev/null"); 191*13697Ssam else 192*13697Ssam gename(DATAPRE, sysout, 'O', dfile); 193*13697Ssam 194*13697Ssam /* expand file names where necessary */ 195*13697Ssam expfile(dfile); 196*13697Ssam strcpy(buf, PATH); 197*13697Ssam strcat(buf, ";export PATH;"); 198*13697Ssam cmdp = buf + strlen(buf); 199*13697Ssam ptr = cmd; 200*13697Ssam xcmd[0] = '\0'; 201*13697Ssam argnok = 0; 202*13697Ssam while ((ptr = getprm(ptr, prm)) != NULL) { 203*13697Ssam if (prm[0] == ';' || prm[0] == '^' 204*13697Ssam || prm[0] == '&' || prm[0] == '|') { 205*13697Ssam xcmd[0] = '\0'; 206*13697Ssam APPCMD(prm); 207*13697Ssam continue; 208*13697Ssam } 209*13697Ssam 210*13697Ssam if ((argnok = argok(xcmd, prm)) != 0) 211*13697Ssam /* command not valid */ 212*13697Ssam break; 213*13697Ssam 214*13697Ssam if (prm[0] == '~') 215*13697Ssam expfile(prm); 216*13697Ssam APPCMD(prm); 217*13697Ssam } 218*13697Ssam if (argnok || badfiles) { 219*13697Ssam sprintf(lbuf, "%s XQT DENIED", user); 220*13697Ssam logent(cmd, lbuf); 221*13697Ssam DEBUG(4, "bad command %s\n", prm); 222*13697Ssam notify(user, Rmtname, cmd, "DENIED"); 223*13697Ssam goto rmfiles; 224*13697Ssam } 225*13697Ssam sprintf(lbuf, "%s XQT", user); 226*13697Ssam logent(buf, lbuf); 227*13697Ssam DEBUG(4, "cmd %s\n", buf); 228*13697Ssam 229*13697Ssam mvxfiles(xfile); 230*13697Ssam subchdir(XQTDIR); 231*13697Ssam ret = shio(buf, fin, dfile, (char *)NULL); 232*13697Ssam /* watcgl.11, dmmartindale, signal and exit values were reversed */ 233*13697Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377, 234*13697Ssam (ret>>8) & 0377); 235*13697Ssam if (strcmp(xcmd, "rmail") == SAME) 236*13697Ssam notiok = 0; 237*13697Ssam if (strcmp(xcmd, "rnews") == SAME) 238*13697Ssam nonzero = 1; 239*13697Ssam if (notiok && (!nonzero || (nonzero && ret != 0))) 240*13697Ssam notify(user, Rmtname, cmd, retstat); 241*13697Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) { 242*13697Ssam /* mail failed - return letter to sender */ 243*13697Ssam retosndr(user, Rmtname, fin); 244*13697Ssam sprintf(buf, "ret (%o) from %s!%s", ret, Rmtname, user); 245*13697Ssam logent("MAIL FAIL", buf); 246*13697Ssam } 247*13697Ssam DEBUG(4, "exit cmd - %d\n", ret); 248*13697Ssam subchdir(Spool); 249*13697Ssam rmxfiles(xfile); 250*13697Ssam if (ret != 0) { 251*13697Ssam /* exit status not zero */ 252*13697Ssam dfp = fopen(subfile(dfile), "a"); 253*13697Ssam ASSERT(dfp != NULL, "CAN'T OPEN", dfile, 0); 254*13697Ssam fprintf(dfp, "exit status %d", ret); 255*13697Ssam fclose(dfp); 256*13697Ssam } 257*13697Ssam if (strcmp(fout, "/dev/null") != SAME) { 258*13697Ssam if (prefix(sysout, Myname)) { 259*13697Ssam xmv(dfile, fout); 260*13697Ssam chmod(fout, BASEMODE); 261*13697Ssam } 262*13697Ssam else { 263*13697Ssam gename(CMDPRE, sysout, 'O', cfile); 264*13697Ssam fp = fopen(subfile(cfile), "w"); 265*13697Ssam ASSERT(fp != NULL, "OPEN", cfile, 0); 266*13697Ssam fprintf(fp, "S %s %s %s - %s 0666\n", 267*13697Ssam dfile, fout, user, lastpart(dfile)); 268*13697Ssam fclose(fp); 269*13697Ssam } 270*13697Ssam } 271*13697Ssam rmfiles: 272*13697Ssam xfp = fopen(subfile(xfile), "r"); 273*13697Ssam ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0); 274*13697Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 275*13697Ssam if (buf[0] != X_RQDFILE) 276*13697Ssam continue; 277*13697Ssam sscanf(&buf[1], "%s", file); 278*13697Ssam unlink(subfile(file)); 279*13697Ssam } 280*13697Ssam unlink(subfile(xfile)); 281*13697Ssam fclose(xfp); 282*13697Ssam } 283*13697Ssam 284*13697Ssam if (stcico) 285*13697Ssam xuucico(""); 286*13697Ssam cleanup(0); 287*13697Ssam } 288*13697Ssam 289*13697Ssam 290*13697Ssam cleanup(code) 291*13697Ssam int code; 292*13697Ssam { 293*13697Ssam logcls(); 294*13697Ssam rmlock(CNULL); 295*13697Ssam exit(code); 296*13697Ssam } 297*13697Ssam 298*13697Ssam 299*13697Ssam /******* 300*13697Ssam * gtxfile(file) get a file to execute 301*13697Ssam * char *file; 302*13697Ssam * 303*13697Ssam * return codes: 0 - no file | 1 - file to execute 304*13697Ssam * Mod to recheck for X-able files. Sept 1982, rti!trt. 305*13697Ssam * Suggested by utzoo.2458 (utzoo!henry) 306*13697Ssam * Uses iswrk/gtwrkf to keep files in sequence, May 1983. 307*13697Ssam */ 308*13697Ssam 309*13697Ssam gtxfile(file) 310*13697Ssam register char *file; 311*13697Ssam { 312*13697Ssam char pre[3]; 313*13697Ssam register int rechecked; 314*13697Ssam 315*13697Ssam pre[0] = XQTPRE; 316*13697Ssam pre[1] = '.'; 317*13697Ssam pre[2] = '\0'; 318*13697Ssam rechecked = 0; 319*13697Ssam retry: 320*13697Ssam if (!gtwrkf(Spool, file)) { 321*13697Ssam if (rechecked) 322*13697Ssam return(0); 323*13697Ssam rechecked = 1; 324*13697Ssam DEBUG(4, "iswrk\n", ""); 325*13697Ssam if (!iswrk(file, "get", Spool, pre)) 326*13697Ssam return(0); 327*13697Ssam } 328*13697Ssam DEBUG(4, "file - %s\n", file); 329*13697Ssam #ifndef UUDIR 330*13697Ssam /* skip spurious subdirectories */ 331*13697Ssam if (strcmp(pre, file) == SAME) 332*13697Ssam goto retry; 333*13697Ssam #endif 334*13697Ssam if (gotfiles(file)) 335*13697Ssam return(1); 336*13697Ssam goto retry; 337*13697Ssam } 338*13697Ssam 339*13697Ssam 340*13697Ssam /*** 341*13697Ssam * gotfiles(file) check for needed files 342*13697Ssam * char *file; 343*13697Ssam * 344*13697Ssam * return codes: 0 - not ready | 1 - all files ready 345*13697Ssam */ 346*13697Ssam 347*13697Ssam gotfiles(file) 348*13697Ssam register char *file; 349*13697Ssam { 350*13697Ssam struct stat stbuf; 351*13697Ssam register FILE *fp; 352*13697Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME]; 353*13697Ssam 354*13697Ssam fp = fopen(subfile(file), "r"); 355*13697Ssam if (fp == NULL) 356*13697Ssam return(0); 357*13697Ssam 358*13697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 359*13697Ssam DEBUG(4, "%s\n", buf); 360*13697Ssam if (buf[0] != X_RQDFILE) 361*13697Ssam continue; 362*13697Ssam sscanf(&buf[1], "%s", rqfile); 363*13697Ssam expfile(rqfile); 364*13697Ssam if (stat(subfile(rqfile), &stbuf) == -1) { 365*13697Ssam fclose(fp); 366*13697Ssam return(0); 367*13697Ssam } 368*13697Ssam } 369*13697Ssam 370*13697Ssam fclose(fp); 371*13697Ssam return(1); 372*13697Ssam } 373*13697Ssam 374*13697Ssam 375*13697Ssam /*** 376*13697Ssam * rmxfiles(xfile) remove execute files to x-directory 377*13697Ssam * char *xfile; 378*13697Ssam * 379*13697Ssam * return codes - none 380*13697Ssam */ 381*13697Ssam 382*13697Ssam rmxfiles(xfile) 383*13697Ssam register char *xfile; 384*13697Ssam { 385*13697Ssam register FILE *fp; 386*13697Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; 387*13697Ssam char tfull[MAXFULLNAME]; 388*13697Ssam 389*13697Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 390*13697Ssam return; 391*13697Ssam 392*13697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 393*13697Ssam if (buf[0] != X_RQDFILE) 394*13697Ssam continue; 395*13697Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2) 396*13697Ssam continue; 397*13697Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 398*13697Ssam unlink(subfile(tfull)); 399*13697Ssam } 400*13697Ssam fclose(fp); 401*13697Ssam return; 402*13697Ssam } 403*13697Ssam 404*13697Ssam 405*13697Ssam /*** 406*13697Ssam * mvxfiles(xfile) move execute files to x-directory 407*13697Ssam * char *xfile; 408*13697Ssam * 409*13697Ssam * return codes - none 410*13697Ssam */ 411*13697Ssam 412*13697Ssam mvxfiles(xfile) 413*13697Ssam char *xfile; 414*13697Ssam { 415*13697Ssam register FILE *fp; 416*13697Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; 417*13697Ssam char tfull[MAXFULLNAME]; 418*13697Ssam int ret; 419*13697Ssam 420*13697Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 421*13697Ssam return; 422*13697Ssam 423*13697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 424*13697Ssam if (buf[0] != X_RQDFILE) 425*13697Ssam continue; 426*13697Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) 427*13697Ssam continue; 428*13697Ssam expfile(ffile); 429*13697Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 430*13697Ssam /* duke!rti, ncsu!mcm: use xmv, not link(II) */ 431*13697Ssam unlink(subfile(tfull)); 432*13697Ssam ret = xmv(ffile, tfull); 433*13697Ssam ASSERT(ret == 0, "XQTDIR ERROR", "", ret); 434*13697Ssam } 435*13697Ssam fclose(fp); 436*13697Ssam return; 437*13697Ssam } 438*13697Ssam 439*13697Ssam 440*13697Ssam /*** 441*13697Ssam * argok(xc, cmd) check for valid command/argumanet 442*13697Ssam * *NOTE - side effect is to set xc to the 443*13697Ssam * command to be executed. 444*13697Ssam * char *xc, *cmd; 445*13697Ssam * 446*13697Ssam * return 0 - ok | 1 nok 447*13697Ssam */ 448*13697Ssam 449*13697Ssam argok(xc, cmd) 450*13697Ssam register char *xc, *cmd; 451*13697Ssam { 452*13697Ssam register char **ptr; 453*13697Ssam 454*13697Ssam #ifndef ALLOK 455*13697Ssam /* don't allow sh command strings `....` */ 456*13697Ssam /* don't allow redirection of standard in or out */ 457*13697Ssam /* don't allow other funny stuff */ 458*13697Ssam /* but there are probably total holes here */ 459*13697Ssam /* post-script. ittvax!swatt has a uuxqt that solves this. */ 460*13697Ssam /* This version of uuxqt will shortly disappear */ 461*13697Ssam if (index(cmd, '`') != NULL 462*13697Ssam || index(cmd, '>') != NULL 463*13697Ssam || index(cmd, ';') != NULL 464*13697Ssam || index(cmd, '^') != NULL 465*13697Ssam || index(cmd, '&') != NULL 466*13697Ssam || index(cmd, '|') != NULL 467*13697Ssam || index(cmd, '<') != NULL) 468*13697Ssam return(1); 469*13697Ssam #endif 470*13697Ssam 471*13697Ssam if (xc[0] != '\0') 472*13697Ssam return(0); 473*13697Ssam 474*13697Ssam #ifndef ALLOK 475*13697Ssam ptr = Cmds; 476*13697Ssam while(*ptr != NULL) { 477*13697Ssam if (strcmp(cmd, *ptr) == SAME) 478*13697Ssam break; 479*13697Ssam ptr++; 480*13697Ssam } 481*13697Ssam if (*ptr == NULL) 482*13697Ssam return(1); 483*13697Ssam #endif 484*13697Ssam strcpy(xc, cmd); 485*13697Ssam return(0); 486*13697Ssam } 487*13697Ssam 488*13697Ssam 489*13697Ssam /*** 490*13697Ssam * notify send mail to user giving execution results 491*13697Ssam * return code - none 492*13697Ssam * This program assumes new mail command - send remote mail 493*13697Ssam */ 494*13697Ssam 495*13697Ssam notify(user, rmt, cmd, str) 496*13697Ssam char *user, *rmt, *cmd, *str; 497*13697Ssam { 498*13697Ssam char text[MAXFULLNAME]; 499*13697Ssam char ruser[MAXFULLNAME]; 500*13697Ssam 501*13697Ssam sprintf(text, "uuxqt cmd (%.50s) status (%s)", cmd, str); 502*13697Ssam if (prefix(rmt, Myname)) 503*13697Ssam strcpy(ruser, user); 504*13697Ssam else 505*13697Ssam sprintf(ruser, "%s!%s", rmt, user); 506*13697Ssam mailst(ruser, text, ""); 507*13697Ssam return; 508*13697Ssam } 509*13697Ssam 510*13697Ssam /*** 511*13697Ssam * retosndr - return mail to sender 512*13697Ssam * 513*13697Ssam * return code - none 514*13697Ssam */ 515*13697Ssam 516*13697Ssam retosndr(user, rmt, file) 517*13697Ssam char *user, *rmt, *file; 518*13697Ssam { 519*13697Ssam char ruser[100]; 520*13697Ssam 521*13697Ssam if (strcmp(rmt, Myname) == SAME) 522*13697Ssam strcpy(ruser, user); 523*13697Ssam else 524*13697Ssam sprintf(ruser, "%s!%s", rmt, user); 525*13697Ssam 526*13697Ssam if (anyread(file) == 0) 527*13697Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file); 528*13697Ssam else 529*13697Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", ""); 530*13697Ssam return; 531*13697Ssam } 532