152081424Ssam #ifndef lint 2*a92c1dbeSrick static char sccsid[] = "@(#)uuxqt.c 5.12 (Berkeley) 05/13/88"; 352081424Ssam #endif 452081424Ssam 552081424Ssam #include "uucp.h" 652081424Ssam #include <sys/stat.h> 752081424Ssam #ifdef NDIR 852081424Ssam #include "ndir.h" 952081424Ssam #else 10109b7051Ssam #include <sys/dir.h> 1152081424Ssam #endif 12e21537dbSralph #include <signal.h> 1352081424Ssam 142f96a7e7Sralph #define BADCHARS "&^|(`\\<>;\"{}\n'" 152f96a7e7Sralph #define RECHECKTIME 60*10 /* 10 minutes */ 16dbb6249cSralph 1752081424Ssam #define APPCMD(d) {\ 1852081424Ssam char *p;\ 19e21537dbSralph for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';} 2052081424Ssam 212bba3b8bSrick extern char Filent[LLEN][NAMESIZE]; 222bba3b8bSrick 2352081424Ssam /* 2452081424Ssam * uuxqt will execute commands set up by a uux command, 2552081424Ssam * usually from a remote machine - set by uucp. 2652081424Ssam */ 2752081424Ssam 2852081424Ssam #define NCMDS 50 29e21537dbSralph char *Cmds[NCMDS+1]; 30e21537dbSralph int Notify[NCMDS+1]; 31e21537dbSralph #define NT_YES 0 /* if should notify on execution */ 32e21537dbSralph #define NT_ERR 1 /* if should notify if non-zero exit status (-z equivalent) */ 33e21537dbSralph #define NT_NO 2 /* if should not notify ever (-n equivalent) */ 34e21537dbSralph 35e21537dbSralph extern int Nfiles; 3652081424Ssam 372f96a7e7Sralph int TransferSucceeded = 1; 3852081424Ssam int notiok = 1; 3952081424Ssam int nonzero = 0; 4052081424Ssam 4198a5b756Sbloom struct timeb Now; 4298a5b756Sbloom 43e21537dbSralph char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin:/usr/ucb"; 442cbba08fSrick char UU_MACHINE[MAXFULLNAME]; 452f96a7e7Sralph char Shell[MAXFULLNAME]; 462f96a7e7Sralph char HOME[MAXFULLNAME]; 472f96a7e7Sralph 482f96a7e7Sralph extern char **environ; 492f96a7e7Sralph char *nenv[] = { 502f96a7e7Sralph PATH, 512f96a7e7Sralph Shell, 522f96a7e7Sralph HOME, 532cbba08fSrick UU_MACHINE, 542f96a7e7Sralph 0 552f96a7e7Sralph }; 562f96a7e7Sralph 5752081424Ssam /* to remove restrictions from uuxqt 5852081424Ssam * define ALLOK 1 5952081424Ssam * 6052081424Ssam * to add allowable commands, add to the file CMDFILE 6152081424Ssam * A line of form "PATH=..." changes the search path 6252081424Ssam */ 6352081424Ssam main(argc, argv) 6452081424Ssam char *argv[]; 6552081424Ssam { 662bba3b8bSrick char xcmd[BUFSIZ*2]; 6752081424Ssam int argnok; 68e21537dbSralph int notiflg; 692bba3b8bSrick char xfile[MAXFULLNAME], user[MAXFULLNAME], buf[BUFSIZ*2]; 70e21537dbSralph char lbuf[MAXFULLNAME]; 7152081424Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME]; 7252081424Ssam char file[NAMESIZE]; 7352081424Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; 7452081424Ssam register FILE *xfp, *fp; 7552081424Ssam FILE *dfp; 7652081424Ssam char path[MAXFULLNAME]; 772bba3b8bSrick char cmd[BUFSIZ*2]; 7852081424Ssam char *cmdp, prm[1000], *ptr; 7952081424Ssam char *getprm(), *lastpart(); 802cbba08fSrick int uid, ret, badfiles; 8152081424Ssam register int i; 8252081424Ssam int stcico = 0; 832f96a7e7Sralph time_t xstart, xnow; 8452081424Ssam char retstat[30]; 852cbba08fSrick extern char *optarg; 862cbba08fSrick extern int optind; 8752081424Ssam 8852081424Ssam strcpy(Progname, "uuxqt"); 8952081424Ssam uucpname(Myname); 90f2386554Srick strcpy(Rmtname, Myname); 9152081424Ssam 9252081424Ssam umask(WFMASK); 9352081424Ssam Ofn = 1; 9452081424Ssam Ifn = 0; 952cbba08fSrick while ((i = getopt(argc, argv, "x:S:")) != EOF) 962cbba08fSrick switch(i) { 9752081424Ssam case 'x': 98e21537dbSralph chkdebug(); 992cbba08fSrick Debug = atoi(optarg); 10052081424Ssam if (Debug <= 0) 10152081424Ssam Debug = 1; 10252081424Ssam break; 1032bba3b8bSrick case 'S': 1042cbba08fSrick Spool = optarg; 1052bba3b8bSrick DEBUG(1, "Spool set to %s", Spool); 1062bba3b8bSrick break; 1072cbba08fSrick case '?': 10852081424Ssam default: 1092cbba08fSrick fprintf(stderr, "unknown flag %s\n", argv[optind-1]); 11052081424Ssam break; 11152081424Ssam } 11252081424Ssam 1132f96a7e7Sralph DEBUG(4, "\n\n** START **\n", CNULL); 1142cbba08fSrick if (subchdir(Spool) < 0) { 1152cbba08fSrick syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool); 1162cbba08fSrick cleanup(1); 1172cbba08fSrick } 11852081424Ssam strcpy(Wrkdir, Spool); 11952081424Ssam uid = getuid(); 1202bba3b8bSrick if (guinfo(uid, User, path) != SUCCESS) { 1212cbba08fSrick syslog(LOG_WARNING, "Can't find username for uid %d", uid); 1222bba3b8bSrick DEBUG(1, "Using username", "uucp"); 1232bba3b8bSrick strcpy(User, "uucp"); 1242bba3b8bSrick } 125e21537dbSralph setgid(getegid()); 126e21537dbSralph setuid(geteuid()); 127e21537dbSralph 12852081424Ssam DEBUG(4, "User - %s\n", User); 1291a575e59Sbloom if (ulockf(X_LOCK, X_LOCKTIME) != 0) 13052081424Ssam exit(0); 13152081424Ssam 13252081424Ssam fp = fopen(CMDFILE, "r"); 13352081424Ssam if (fp == NULL) { 134e21537dbSralph logent(CANTOPEN, CMDFILE); 13552081424Ssam Cmds[0] = "rmail"; 13652081424Ssam Cmds[1] = "rnews"; 13752081424Ssam Cmds[2] = "ruusend"; 13852081424Ssam Cmds[3] = NULL; 13952081424Ssam goto doprocess; 14052081424Ssam } 14152081424Ssam DEBUG(5, "%s opened\n", CMDFILE); 142e21537dbSralph for (i=0; i<NCMDS && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) { 143e21537dbSralph int j; 144e21537dbSralph /* strip trailing whitespace */ 145e21537dbSralph for (j = strlen(xcmd)-1; j >= 0; --j) 146e21537dbSralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t') 147e21537dbSralph xcmd[j] = '\0'; 148e21537dbSralph else 149e21537dbSralph break; 150e21537dbSralph /* look for imbedded whitespace */ 151e21537dbSralph for (; j >= 0; --j) 152e21537dbSralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t') 153e21537dbSralph break; 154e21537dbSralph /* skip this entry if it has embedded whitespace */ 155e21537dbSralph /* This defends against a bad PATH=, for example */ 156e21537dbSralph if (j >= 0) { 157e21537dbSralph logent(xcmd, "BAD WHITESPACE"); 158e21537dbSralph continue; 159e21537dbSralph } 16052081424Ssam if (strncmp(xcmd, "PATH=", 5) == 0) { 16152081424Ssam strcpy(PATH, xcmd); 16252081424Ssam i--; /*kludge */ 16352081424Ssam continue; 16452081424Ssam } 16552081424Ssam DEBUG(5, "xcmd = %s\n", xcmd); 166e21537dbSralph 167e21537dbSralph if ((ptr = index(xcmd, ',')) != NULL) { 168e21537dbSralph *ptr++ = '\0'; 169e21537dbSralph if (strncmp(ptr, "Err", 3) == SAME) 170e21537dbSralph Notify[i] = NT_ERR; 171e21537dbSralph else if (strcmp(ptr, "No") == SAME) 172e21537dbSralph Notify[i] = NT_NO; 173e21537dbSralph else 174e21537dbSralph Notify[i] = NT_YES; 175e21537dbSralph } else 176e21537dbSralph Notify[i] = NT_YES; 177e21537dbSralph if ((Cmds[i] = malloc((unsigned)(strlen(xcmd)+1))) == NULL) { 178e21537dbSralph DEBUG(1, "MALLOC FAILED", CNULL); 179e21537dbSralph break; 180e21537dbSralph } 18152081424Ssam strcpy(Cmds[i], xcmd); 18252081424Ssam } 183e21537dbSralph Cmds[i] = CNULL; 18452081424Ssam fclose(fp); 18552081424Ssam 18652081424Ssam doprocess: 1872f96a7e7Sralph 1882f96a7e7Sralph (void) sprintf(HOME, "HOME=%s", Spool); 1892f96a7e7Sralph (void) sprintf(Shell, "SHELL=%s", SHELL); 1902f96a7e7Sralph environ = nenv; /* force use if our environment */ 1912f96a7e7Sralph 1922f96a7e7Sralph DEBUG(11,"path = %s\n", getenv("PATH")); 1932f96a7e7Sralph 194e21537dbSralph DEBUG(4, "process %s\n", CNULL); 1952bba3b8bSrick 1962f96a7e7Sralph time(&xstart); 19752081424Ssam while (gtxfile(xfile) > 0) { 198e21537dbSralph /* if /etc/nologin exists, exit cleanly */ 19998a5b756Sbloom #if defined(BSD4_2) || defined(USG) 20098a5b756Sbloom if (access(NOLOGIN) == 0) { 20198a5b756Sbloom #else !BSD4_2 && ! USG 20298a5b756Sbloom ultouch(); 203e21537dbSralph if (nologinflag) { 20498a5b756Sbloom #endif !BSD4_2 && !USG 205e21537dbSralph logent(NOLOGIN, "UUXQT SHUTDOWN"); 206e21537dbSralph if (Debug) 207e21537dbSralph logent("debugging", "continuing anyway"); 208e21537dbSralph else 209e21537dbSralph break; 210e21537dbSralph } 21152081424Ssam DEBUG(4, "xfile - %s\n", xfile); 21252081424Ssam 21352081424Ssam xfp = fopen(subfile(xfile), "r"); 2142cbba08fSrick if (xfp == NULL) { 2152cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", subfile(xfile)); 2162cbba08fSrick cleanup(1); 2172cbba08fSrick } 21852081424Ssam 21952081424Ssam /* initialize to default */ 22052081424Ssam strcpy(user, User); 221e21537dbSralph strcpy(fin, DEVNULL); 222e21537dbSralph strcpy(fout, DEVNULL); 2231a575e59Sbloom strcpy(sysout, Myname); 224e21537dbSralph badfiles = 0; 22552081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 2262bba3b8bSrick if(buf[0] != '\0' && buf[0] != '#' && 2272bba3b8bSrick buf[1] != ' ' && buf[1] != '\0' && buf[1] != '\n') { 2282bba3b8bSrick char *bnp, cfilename[BUFSIZ]; 2292bba3b8bSrick DEBUG(4, "uuxqt: buf = %s\n", buf); 2302bba3b8bSrick bnp = rindex(xfile, '/'); 2312bba3b8bSrick sprintf(cfilename, "%s/%s", CORRUPT, 2322bba3b8bSrick bnp ? bnp + 1 : xfile); 2332bba3b8bSrick DEBUG(4, "uuxqt: move %s to ", xfile); 2342bba3b8bSrick DEBUG(4, "%s\n", cfilename); 2352bba3b8bSrick xmv(xfile, cfilename); 236*a92c1dbeSrick syslog(LOG_WARNING, "%s: X. FILE CORRUPTED", 237*a92c1dbeSrick xfile); 2382bba3b8bSrick fclose(xfp); 2392bba3b8bSrick goto doprocess; 2402bba3b8bSrick } 24152081424Ssam switch (buf[0]) { 242*a92c1dbeSrick case X_USER: { 243*a92c1dbeSrick char ORmtname[MAXFULLNAME]; 244*a92c1dbeSrick strcpy(ORmtname, Rmtname); 24552081424Ssam sscanf(&buf[1], "%s %s", user, Rmtname); 2462cbba08fSrick sprintf(UU_MACHINE, "UU_MACHINE=%s", Rmtname); 247*a92c1dbeSrick if (strcmp(ORmtname, Rmtname) != 0) 248*a92c1dbeSrick logcls(); 249*a92c1dbeSrick break;} 250e21537dbSralph case X_RETURNTO: 251e21537dbSralph sscanf(&buf[1], "%s", user); 252e21537dbSralph break; 25352081424Ssam case X_STDIN: 25452081424Ssam sscanf(&buf[1], "%s", fin); 25552081424Ssam i = expfile(fin); 25652081424Ssam /* rti!trt: do not check permissions of 25752081424Ssam * vanilla spool file */ 25852081424Ssam if (i != 0 25952081424Ssam && (chkpth("", "", fin) || anyread(fin) != 0)) 26052081424Ssam badfiles = 1; 26152081424Ssam break; 26252081424Ssam case X_STDOUT: 26352081424Ssam sscanf(&buf[1], "%s%s", fout, sysout); 2641a575e59Sbloom sysout[MAXBASENAME] = '\0'; 26552081424Ssam /* rti!trt: do not check permissions of 26652081424Ssam * vanilla spool file. DO check permissions 26752081424Ssam * of writing on a non-vanilla file */ 26852081424Ssam i = 1; 26952081424Ssam if (fout[0] != '~' || prefix(sysout, Myname)) 27052081424Ssam i = expfile(fout); 27152081424Ssam if (i != 0 27252081424Ssam && (chkpth("", "", fout) 27352081424Ssam || chkperm(fout, (char *)1))) 27452081424Ssam badfiles = 1; 27552081424Ssam break; 27652081424Ssam case X_CMD: 27752081424Ssam strcpy(cmd, &buf[2]); 27852081424Ssam if (*(cmd + strlen(cmd) - 1) == '\n') 27952081424Ssam *(cmd + strlen(cmd) - 1) = '\0'; 28052081424Ssam break; 28152081424Ssam case X_NONOTI: 28252081424Ssam notiok = 0; 28352081424Ssam break; 28452081424Ssam case X_NONZERO: 28552081424Ssam nonzero = 1; 28652081424Ssam break; 28752081424Ssam default: 28852081424Ssam break; 28952081424Ssam } 29052081424Ssam } 29152081424Ssam 29252081424Ssam fclose(xfp); 29352081424Ssam DEBUG(4, "fin - %s, ", fin); 29452081424Ssam DEBUG(4, "fout - %s, ", fout); 29552081424Ssam DEBUG(4, "sysout - %s, ", sysout); 29652081424Ssam DEBUG(4, "user - %s\n", user); 29752081424Ssam DEBUG(4, "cmd - %s\n", cmd); 29852081424Ssam 29952081424Ssam /* command execution */ 300e21537dbSralph if (strcmp(fout, DEVNULL) == SAME) 301e21537dbSralph strcpy(dfile,DEVNULL); 30252081424Ssam else 30352081424Ssam gename(DATAPRE, sysout, 'O', dfile); 30452081424Ssam 30552081424Ssam /* expand file names where necessary */ 30652081424Ssam expfile(dfile); 3072f96a7e7Sralph cmdp = buf; 30852081424Ssam ptr = cmd; 30952081424Ssam xcmd[0] = '\0'; 31052081424Ssam argnok = 0; 31152081424Ssam while ((ptr = getprm(ptr, prm)) != NULL) { 31252081424Ssam if (prm[0] == ';' || prm[0] == '^' 31352081424Ssam || prm[0] == '&' || prm[0] == '|') { 31452081424Ssam xcmd[0] = '\0'; 31552081424Ssam APPCMD(prm); 31652081424Ssam continue; 31752081424Ssam } 31852081424Ssam 319e21537dbSralph if ((argnok = argok(xcmd, prm)) != SUCCESS) 32052081424Ssam /* command not valid */ 32152081424Ssam break; 32252081424Ssam 32352081424Ssam if (prm[0] == '~') 32452081424Ssam expfile(prm); 32552081424Ssam APPCMD(prm); 32652081424Ssam } 327e21537dbSralph /* 328e21537dbSralph * clean up trailing ' ' in command. 329e21537dbSralph */ 330e21537dbSralph if (cmdp > buf && cmdp[0] == '\0' && cmdp[-1] == ' ') 331e21537dbSralph *--cmdp = '\0'; 33252081424Ssam if (argnok || badfiles) { 33352081424Ssam sprintf(lbuf, "%s XQT DENIED", user); 33452081424Ssam logent(cmd, lbuf); 33552081424Ssam DEBUG(4, "bad command %s\n", prm); 33652081424Ssam notify(user, Rmtname, cmd, "DENIED"); 33752081424Ssam goto rmfiles; 33852081424Ssam } 33952081424Ssam sprintf(lbuf, "%s XQT", user); 34052081424Ssam logent(buf, lbuf); 34152081424Ssam DEBUG(4, "cmd %s\n", buf); 34252081424Ssam 34352081424Ssam mvxfiles(xfile); 3442cbba08fSrick if (subchdir(XQTDIR) < 0) { 3452cbba08fSrick syslog(LOG_ERR, "chdir(%s) failed: %m", XQTDIR); 3462cbba08fSrick cleanup(1); 3472cbba08fSrick } 3482f96a7e7Sralph ret = shio(buf, fin, dfile); 34952081424Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377, 35052081424Ssam (ret>>8) & 0377); 35152081424Ssam if (strcmp(xcmd, "rmail") == SAME) 35252081424Ssam notiok = 0; 35352081424Ssam if (strcmp(xcmd, "rnews") == SAME) 35452081424Ssam nonzero = 1; 355e21537dbSralph notiflg = chknotify(xcmd); 356e21537dbSralph if (notiok && notiflg != NT_NO && 357e21537dbSralph (ret != 0 || (!nonzero && notiflg == NT_YES))) 35852081424Ssam notify(user, Rmtname, cmd, retstat); 35952081424Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) { 36052081424Ssam /* mail failed - return letter to sender */ 361e21537dbSralph #ifdef DANGEROUS 362e21537dbSralph /* NOT GUARANTEED SAFE!!! */ 363e21537dbSralph if (!nonzero) 36452081424Ssam retosndr(user, Rmtname, fin); 365e21537dbSralph #else 366e21537dbSralph notify(user, Rmtname, cmd, retstat); 367e21537dbSralph #endif 368e21537dbSralph sprintf(buf, "%s (%s) from %s!%s", buf, retstat, Rmtname, user); 36952081424Ssam logent("MAIL FAIL", buf); 37052081424Ssam } 37152081424Ssam DEBUG(4, "exit cmd - %d\n", ret); 3722cbba08fSrick if (subchdir(Spool) < 0) { 3732cbba08fSrick syslog(LOG_ERR, "chdir(%s) failed: %m", Spool); 3742cbba08fSrick cleanup(1); 3752cbba08fSrick } 37652081424Ssam rmxfiles(xfile); 37752081424Ssam if (ret != 0) { 37852081424Ssam /* exit status not zero */ 37952081424Ssam dfp = fopen(subfile(dfile), "a"); 3802cbba08fSrick if (dfp == NULL) { 3812cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", 3822cbba08fSrick subfile(dfile)); 3832cbba08fSrick cleanup(1); 3842cbba08fSrick } 38552081424Ssam fprintf(dfp, "exit status %d", ret); 38652081424Ssam fclose(dfp); 38752081424Ssam } 388e21537dbSralph if (strcmp(fout, DEVNULL) != SAME) { 38952081424Ssam if (prefix(sysout, Myname)) { 39052081424Ssam xmv(dfile, fout); 39152081424Ssam chmod(fout, BASEMODE); 3922f96a7e7Sralph } else { 393e21537dbSralph char *cp = rindex(user, '!'); 39452081424Ssam gename(CMDPRE, sysout, 'O', cfile); 39552081424Ssam fp = fopen(subfile(cfile), "w"); 3962cbba08fSrick if (fp == NULL) { 3972cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", 3982cbba08fSrick subfile(cfile)); 3992cbba08fSrick cleanup(1); 4002cbba08fSrick } 401e21537dbSralph fprintf(fp, "S %s %s %s - %s 0666\n", dfile, 402e21537dbSralph fout, cp ? cp : user, lastpart(dfile)); 40352081424Ssam fclose(fp); 40452081424Ssam } 40552081424Ssam } 40652081424Ssam rmfiles: 40752081424Ssam xfp = fopen(subfile(xfile), "r"); 4082cbba08fSrick if (xfp == NULL) { 4092cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", 4102cbba08fSrick subfile(xfile)); 4112cbba08fSrick cleanup(1); 4122cbba08fSrick } 41352081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 41452081424Ssam if (buf[0] != X_RQDFILE) 41552081424Ssam continue; 41652081424Ssam sscanf(&buf[1], "%s", file); 41752081424Ssam unlink(subfile(file)); 41852081424Ssam } 41952081424Ssam unlink(subfile(xfile)); 42052081424Ssam fclose(xfp); 4212f96a7e7Sralph 4222f96a7e7Sralph /* rescan X. for new work every RECHECKTIME seconds */ 4232f96a7e7Sralph time(&xnow); 4242f96a7e7Sralph if (xnow > (xstart + RECHECKTIME)) { 4252f96a7e7Sralph extern int Nfiles; 4262f96a7e7Sralph Nfiles = 0; /*force rescan for new work */ 4272f96a7e7Sralph } 4282f96a7e7Sralph xstart = xnow; 42952081424Ssam } 43052081424Ssam 43152081424Ssam if (stcico) 43252081424Ssam xuucico(""); 43352081424Ssam cleanup(0); 43452081424Ssam } 43552081424Ssam 43652081424Ssam 43752081424Ssam cleanup(code) 43852081424Ssam int code; 43952081424Ssam { 44052081424Ssam logcls(); 44152081424Ssam rmlock(CNULL); 442e21537dbSralph #ifdef VMS 443e21537dbSralph /* 444e21537dbSralph * Since we run as a BATCH job we must wait for all processes to 445e21537dbSralph * to finish 446e21537dbSralph */ 4472f96a7e7Sralph while(wait(0) != -1) 4482f96a7e7Sralph ; 449e21537dbSralph #endif VMS 45052081424Ssam exit(code); 45152081424Ssam } 45252081424Ssam 45352081424Ssam 4542f96a7e7Sralph /* 4552f96a7e7Sralph * get a file to execute 45652081424Ssam * 45752081424Ssam * return codes: 0 - no file | 1 - file to execute 45852081424Ssam */ 45952081424Ssam 46052081424Ssam gtxfile(file) 46152081424Ssam register char *file; 46252081424Ssam { 46352081424Ssam char pre[3]; 4642bba3b8bSrick register int rechecked, i; 465e21537dbSralph time_t ystrdy; /* yesterday */ 466e21537dbSralph struct stat stbuf; /* for X file age */ 46752081424Ssam 46852081424Ssam pre[0] = XQTPRE; 46952081424Ssam pre[1] = '.'; 47052081424Ssam pre[2] = '\0'; 47152081424Ssam rechecked = 0; 47252081424Ssam retry: 4732bba3b8bSrick if (Nfiles-- <= 0) { 4742bba3b8bSrick Nfiles = 0; 47552081424Ssam if (rechecked) 476e21537dbSralph return 0; 47752081424Ssam rechecked = 1; 478e21537dbSralph DEBUG(4, "iswrk\n", CNULL); 4792bba3b8bSrick return iswrk(file, "get", Spool, pre); 48052081424Ssam } 4812bba3b8bSrick sprintf(file, "%s/%s", Spool, Filent[0]); 4822bba3b8bSrick for (i=0; i<Nfiles;i++) 4832bba3b8bSrick strcpy(Filent[i], Filent[i+1]); 4842bba3b8bSrick 48552081424Ssam DEBUG(4, "file - %s\n", file); 48652081424Ssam /* skip spurious subdirectories */ 48752081424Ssam if (strcmp(pre, file) == SAME) 48852081424Ssam goto retry; 48952081424Ssam if (gotfiles(file)) 490e21537dbSralph return 1; 491e21537dbSralph /* check for old X. file with no work files and remove them. */ 492e21537dbSralph if (Nfiles > LLEN/2) { 493e21537dbSralph time(&ystrdy); 494e21537dbSralph ystrdy -= (4 * 3600L); /* 4 hours ago */ 495e21537dbSralph DEBUG(4, "gtxfile: Nfiles > LLEN/2\n", CNULL); 4962bba3b8bSrick while (Nfiles-- > 0) { 4972bba3b8bSrick sprintf(file, "%s/%s", Spool, Filent[0]); 4982bba3b8bSrick for (i=0; i<Nfiles; i++) 4992bba3b8bSrick strcpy(Filent[i], Filent[i+1]); 5002bba3b8bSrick 5012bba3b8bSrick if (gotfiles(file)) 5022bba3b8bSrick return 1; 503e21537dbSralph if (stat(subfile(file), &stbuf) == 0) 504e21537dbSralph if (stbuf.st_mtime <= ystrdy) { 505e21537dbSralph char *bnp, cfilename[NAMESIZE]; 506e21537dbSralph DEBUG(4, "gtxfile: move %s to CORRUPT \n", file); 5072bba3b8bSrick bnp = rindex(file, '/'); 508e21537dbSralph sprintf(cfilename, "%s/%s", CORRUPT, 5092bba3b8bSrick bnp ? bnp + 1 : file); 5102bba3b8bSrick xmv(file, cfilename); 5112cbba08fSrick syslog(LOG_WARNING, "%s: X. FILE MISSING FILES", file); 512e21537dbSralph } 513e21537dbSralph } 5142bba3b8bSrick Nfiles = 0; 515e21537dbSralph DEBUG(4, "iswrk\n", CNULL); 516e21537dbSralph if (!iswrk(file, "get", Spool, pre)) 517e21537dbSralph return 0; 518e21537dbSralph } 51952081424Ssam goto retry; 52052081424Ssam } 52152081424Ssam 5222f96a7e7Sralph /* 5232f96a7e7Sralph * check for needed files 52452081424Ssam * 52552081424Ssam * return codes: 0 - not ready | 1 - all files ready 52652081424Ssam */ 52752081424Ssam 52852081424Ssam gotfiles(file) 52952081424Ssam register char *file; 53052081424Ssam { 53152081424Ssam struct stat stbuf; 53252081424Ssam register FILE *fp; 53352081424Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME]; 53452081424Ssam 53552081424Ssam fp = fopen(subfile(file), "r"); 53652081424Ssam if (fp == NULL) 537e21537dbSralph return 0; 53852081424Ssam 53952081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 54052081424Ssam DEBUG(4, "%s\n", buf); 54152081424Ssam if (buf[0] != X_RQDFILE) 54252081424Ssam continue; 54352081424Ssam sscanf(&buf[1], "%s", rqfile); 54452081424Ssam expfile(rqfile); 54552081424Ssam if (stat(subfile(rqfile), &stbuf) == -1) { 54652081424Ssam fclose(fp); 547e21537dbSralph return 0; 54852081424Ssam } 54952081424Ssam } 55052081424Ssam 55152081424Ssam fclose(fp); 552e21537dbSralph return 1; 55352081424Ssam } 55452081424Ssam 55552081424Ssam 5562f96a7e7Sralph /* 5572f96a7e7Sralph * remove execute files to x-directory 55852081424Ssam */ 55952081424Ssam 56052081424Ssam rmxfiles(xfile) 56152081424Ssam register char *xfile; 56252081424Ssam { 56352081424Ssam register FILE *fp; 56452081424Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; 56552081424Ssam char tfull[MAXFULLNAME]; 56652081424Ssam 56752081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 56852081424Ssam return; 56952081424Ssam 57052081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 57152081424Ssam if (buf[0] != X_RQDFILE) 57252081424Ssam continue; 57352081424Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2) 57452081424Ssam continue; 57552081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 57652081424Ssam unlink(subfile(tfull)); 57752081424Ssam } 57852081424Ssam fclose(fp); 57952081424Ssam return; 58052081424Ssam } 58152081424Ssam 58252081424Ssam 5832f96a7e7Sralph /* 5842f96a7e7Sralph * move execute files to x-directory 58552081424Ssam */ 58652081424Ssam 58752081424Ssam mvxfiles(xfile) 58852081424Ssam char *xfile; 58952081424Ssam { 59052081424Ssam register FILE *fp; 59152081424Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; 59252081424Ssam char tfull[MAXFULLNAME]; 59352081424Ssam 59452081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 59552081424Ssam return; 59652081424Ssam 59752081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 59852081424Ssam if (buf[0] != X_RQDFILE) 59952081424Ssam continue; 60052081424Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) 60152081424Ssam continue; 60252081424Ssam expfile(ffile); 60352081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 60452081424Ssam unlink(subfile(tfull)); 6052cbba08fSrick if (xmv(ffile, tfull) != 0) { 6062cbba08fSrick syslog(LOG_WARNING, "xmv(%s,%s) failed: %m", 6072cbba08fSrick ffile, tfull); 6082cbba08fSrick cleanup(1); 6092cbba08fSrick } 61052081424Ssam } 61152081424Ssam fclose(fp); 61252081424Ssam } 61352081424Ssam 6142f96a7e7Sralph /* 6152f96a7e7Sralph * check for valid command/argument 6162f96a7e7Sralph * *NOTE - side effect is to set xc to the command to be executed. 61752081424Ssam * 61852081424Ssam * return 0 - ok | 1 nok 61952081424Ssam */ 62052081424Ssam 62152081424Ssam argok(xc, cmd) 62252081424Ssam register char *xc, *cmd; 62352081424Ssam { 62452081424Ssam register char **ptr; 62552081424Ssam 62652081424Ssam #ifndef ALLOK 6272f96a7e7Sralph if (strpbrk(cmd, BADCHARS) != NULL) { 628e21537dbSralph DEBUG(1,"MAGIC CHARACTER FOUND\n", CNULL); 6292f96a7e7Sralph logent(cmd, "NASTY MAGIC CHARACTER FOUND"); 630e21537dbSralph return FAIL; 631e21537dbSralph } 632e21537dbSralph #endif !ALLOK 63352081424Ssam 63452081424Ssam if (xc[0] != '\0') 635e21537dbSralph return SUCCESS; 63652081424Ssam 63752081424Ssam #ifndef ALLOK 63852081424Ssam ptr = Cmds; 639e21537dbSralph DEBUG(9, "Compare %s and\n", cmd); 64052081424Ssam while(*ptr != NULL) { 641e21537dbSralph DEBUG(9, "\t%s\n", *ptr); 64252081424Ssam if (strcmp(cmd, *ptr) == SAME) 64352081424Ssam break; 64452081424Ssam ptr++; 64552081424Ssam } 646e21537dbSralph if (*ptr == NULL) { 647e21537dbSralph DEBUG(1,"COMMAND NOT FOUND\n", CNULL); 648e21537dbSralph return FAIL; 649e21537dbSralph } 65052081424Ssam #endif 65152081424Ssam strcpy(xc, cmd); 652e21537dbSralph DEBUG(9, "MATCHED %s\n", xc); 653e21537dbSralph return SUCCESS; 65452081424Ssam } 65552081424Ssam 65652081424Ssam 6572f96a7e7Sralph /* 6582f96a7e7Sralph * if notification should be sent for successful execution of cmd 659e21537dbSralph * 660e21537dbSralph * return NT_YES - do notification 661e21537dbSralph * NT_ERR - do notification if exit status != 0 662e21537dbSralph * NT_NO - don't do notification ever 663e21537dbSralph */ 664e21537dbSralph 665e21537dbSralph chknotify(cmd) 666e21537dbSralph char *cmd; 667e21537dbSralph { 668e21537dbSralph register char **ptr; 669e21537dbSralph register int *nptr; 670e21537dbSralph 671e21537dbSralph ptr = Cmds; 672e21537dbSralph nptr = Notify; 673e21537dbSralph while (*ptr != NULL) { 674e21537dbSralph if (strcmp(cmd, *ptr) == SAME) 675e21537dbSralph return *nptr; 676e21537dbSralph ptr++; 677e21537dbSralph nptr++; 678e21537dbSralph } 679e21537dbSralph return NT_YES; /* "shouldn't happen" */ 680e21537dbSralph } 681e21537dbSralph 682e21537dbSralph 683e21537dbSralph 6842f96a7e7Sralph /* 6852f96a7e7Sralph * send mail to user giving execution results 68652081424Ssam */ 68752081424Ssam 68852081424Ssam notify(user, rmt, cmd, str) 68952081424Ssam char *user, *rmt, *cmd, *str; 69052081424Ssam { 6912bba3b8bSrick char text[BUFSIZ*2]; 69252081424Ssam char ruser[MAXFULLNAME]; 69352081424Ssam 694bd1b9349Sbloom if (strpbrk(user, BADCHARS) != NULL) { 695bd1b9349Sbloom char lbuf[MAXFULLNAME]; 696bd1b9349Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user); 697bd1b9349Sbloom logent(cmd, lbuf); 698bd1b9349Sbloom strcpy(user, "postmaster"); 699bd1b9349Sbloom } 700e21537dbSralph sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str); 70152081424Ssam if (prefix(rmt, Myname)) 70252081424Ssam strcpy(ruser, user); 70352081424Ssam else 70452081424Ssam sprintf(ruser, "%s!%s", rmt, user); 705e21537dbSralph mailst(ruser, text, CNULL); 70652081424Ssam } 70752081424Ssam 7082f96a7e7Sralph /* 7092f96a7e7Sralph * return mail to sender 71052081424Ssam * 71152081424Ssam */ 71252081424Ssam retosndr(user, rmt, file) 71352081424Ssam char *user, *rmt, *file; 71452081424Ssam { 715e21537dbSralph char ruser[MAXFULLNAME]; 71652081424Ssam 717bd1b9349Sbloom if (strpbrk(user, BADCHARS) != NULL) { 718bd1b9349Sbloom char lbuf[MAXFULLNAME]; 719bd1b9349Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user); 720bd1b9349Sbloom logent(file, lbuf); 721bd1b9349Sbloom strcpy(user, "postmaster"); 722bd1b9349Sbloom } 72352081424Ssam if (strcmp(rmt, Myname) == SAME) 72452081424Ssam strcpy(ruser, user); 72552081424Ssam else 72652081424Ssam sprintf(ruser, "%s!%s", rmt, user); 72752081424Ssam 72852081424Ssam if (anyread(file) == 0) 72952081424Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file); 73052081424Ssam else 731e21537dbSralph mailst(ruser, "Mail failed. Letter returned to sender.\n", CNULL); 73252081424Ssam return; 73352081424Ssam } 734dbb6249cSralph 735dbb6249cSralph /* 7362f96a7e7Sralph * execute shell of command with fi and fo as standard input/output 7372f96a7e7Sralph */ 7382f96a7e7Sralph 7392f96a7e7Sralph shio(cmd, fi, fo) 7402f96a7e7Sralph char *cmd, *fi, *fo; 7412f96a7e7Sralph { 7422f96a7e7Sralph int status, f; 7432cbba08fSrick int pid, ret; 7442bba3b8bSrick char *args[256]; 7452f96a7e7Sralph extern int errno; 7462f96a7e7Sralph 7472f96a7e7Sralph if (fi == NULL) 7482f96a7e7Sralph fi = DEVNULL; 7492f96a7e7Sralph if (fo == NULL) 7502f96a7e7Sralph fo = DEVNULL; 7512f96a7e7Sralph 7522bba3b8bSrick getargs(cmd, args, 256); 7532f96a7e7Sralph DEBUG(3, "shio - %s\n", cmd); 7542f96a7e7Sralph #ifdef SIGCHLD 7552f96a7e7Sralph signal(SIGCHLD, SIG_IGN); 7562f96a7e7Sralph #endif SIGCHLD 7572f96a7e7Sralph if ((pid = fork()) == 0) { 7582f96a7e7Sralph signal(SIGINT, SIG_IGN); 7592f96a7e7Sralph signal(SIGHUP, SIG_IGN); 7602f96a7e7Sralph signal(SIGQUIT, SIG_IGN); 7612f96a7e7Sralph close(Ifn); 7622f96a7e7Sralph close(Ofn); 7632f96a7e7Sralph close(0); 7642f96a7e7Sralph setuid(getuid()); 7652f96a7e7Sralph f = open(subfile(fi), 0); 7662f96a7e7Sralph if (f != 0) { 7672f96a7e7Sralph logent(fi, "CAN'T READ"); 7682f96a7e7Sralph exit(-errno); 7692f96a7e7Sralph } 7702f96a7e7Sralph close(1); 7712f96a7e7Sralph f = creat(subfile(fo), 0666); 7722f96a7e7Sralph if (f != 1) { 7732f96a7e7Sralph logent(fo, "CAN'T WRITE"); 7742f96a7e7Sralph exit(-errno); 7752f96a7e7Sralph } 7762f96a7e7Sralph execvp(args[0], args); 7772f96a7e7Sralph exit(100+errno); 7782f96a7e7Sralph } 7792f96a7e7Sralph while ((ret = wait(&status)) != pid && ret != -1) 7802f96a7e7Sralph ; 7812f96a7e7Sralph DEBUG(3, "status %d\n", status); 7822f96a7e7Sralph return status; 7832f96a7e7Sralph } 784