1*48671Sbostic /*- 2*48671Sbostic * Copyright (c) 1985, 1988 The Regents of the University of California. 3*48671Sbostic * All rights reserved. 4*48671Sbostic * 5*48671Sbostic * %sccs.include.proprietary.c% 6*48671Sbostic */ 7*48671Sbostic 813697Ssam #ifndef lint 9*48671Sbostic char copyright[] = 10*48671Sbostic "@(#) Copyright (c) 1985, 1988 The Regents of the University of California.\n\ 11*48671Sbostic All rights reserved.\n"; 12*48671Sbostic #endif /* not lint */ 1313697Ssam 14*48671Sbostic #ifndef lint 15*48671Sbostic static char sccsid[] = "@(#)uuxqt.c 5.14 (Berkeley) 04/24/91"; 16*48671Sbostic #endif /* not lint */ 17*48671Sbostic 1813697Ssam #include "uucp.h" 1913697Ssam #include <sys/stat.h> 2013697Ssam #ifdef NDIR 2113697Ssam #include "ndir.h" 2213697Ssam #else 2313702Ssam #include <sys/dir.h> 2413697Ssam #endif 2517846Sralph #include <signal.h> 2613697Ssam 2718628Sralph #define BADCHARS "&^|(`\\<>;\"{}\n'" 2818628Sralph #define RECHECKTIME 60*10 /* 10 minutes */ 2917870Sralph 3013697Ssam #define APPCMD(d) {\ 3113697Ssam char *p;\ 3217846Sralph for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';} 3313697Ssam 3433579Srick extern char Filent[LLEN][NAMESIZE]; 3533579Srick 3613697Ssam /* 3713697Ssam * uuxqt will execute commands set up by a uux command, 3813697Ssam * usually from a remote machine - set by uucp. 3913697Ssam */ 4013697Ssam 4113697Ssam #define NCMDS 50 4217846Sralph char *Cmds[NCMDS+1]; 4317846Sralph int Notify[NCMDS+1]; 4417846Sralph #define NT_YES 0 /* if should notify on execution */ 4517846Sralph #define NT_ERR 1 /* if should notify if non-zero exit status (-z equivalent) */ 4617846Sralph #define NT_NO 2 /* if should not notify ever (-n equivalent) */ 4713697Ssam 4817846Sralph extern int Nfiles; 4917846Sralph 5018628Sralph int TransferSucceeded = 1; 5113697Ssam int notiok = 1; 5213697Ssam int nonzero = 0; 5313697Ssam 5425147Sbloom struct timeb Now; 5525147Sbloom 5644709Strent char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin"; 5733966Srick char UU_MACHINE[MAXFULLNAME]; 5818628Sralph char Shell[MAXFULLNAME]; 5918628Sralph char HOME[MAXFULLNAME]; 6017846Sralph 6118628Sralph extern char **environ; 6218628Sralph char *nenv[] = { 6318628Sralph PATH, 6418628Sralph Shell, 6518628Sralph HOME, 6633966Srick UU_MACHINE, 6718628Sralph 0 6818628Sralph }; 6917846Sralph 7013697Ssam /* to remove restrictions from uuxqt 7113697Ssam * define ALLOK 1 7213697Ssam * 7313697Ssam * to add allowable commands, add to the file CMDFILE 7413697Ssam * A line of form "PATH=..." changes the search path 7513697Ssam */ 7613697Ssam main(argc, argv) 7713697Ssam char *argv[]; 7813697Ssam { 7933579Srick char xcmd[BUFSIZ*2]; 8013697Ssam int argnok; 8117846Sralph int notiflg; 8233579Srick char xfile[MAXFULLNAME], user[MAXFULLNAME], buf[BUFSIZ*2]; 8317846Sralph char lbuf[MAXFULLNAME]; 8413697Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME]; 8513697Ssam char file[NAMESIZE]; 8613697Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; 8713697Ssam register FILE *xfp, *fp; 8813697Ssam FILE *dfp; 8913697Ssam char path[MAXFULLNAME]; 9033579Srick char cmd[BUFSIZ*2]; 9113697Ssam char *cmdp, prm[1000], *ptr; 9213697Ssam char *getprm(), *lastpart(); 9333966Srick int uid, ret, badfiles; 9413697Ssam register int i; 9513697Ssam int stcico = 0; 9618628Sralph time_t xstart, xnow; 9713697Ssam char retstat[30]; 9833966Srick extern char *optarg; 9933966Srick extern int optind; 10013697Ssam 10113697Ssam strcpy(Progname, "uuxqt"); 10213697Ssam uucpname(Myname); 10334176Srick strcpy(Rmtname, Myname); 10413697Ssam 10513697Ssam umask(WFMASK); 10613697Ssam Ofn = 1; 10713697Ssam Ifn = 0; 10833966Srick while ((i = getopt(argc, argv, "x:S:")) != EOF) 10933966Srick switch(i) { 11013697Ssam case 'x': 11117846Sralph chkdebug(); 11233966Srick Debug = atoi(optarg); 11313697Ssam if (Debug <= 0) 11413697Ssam Debug = 1; 11513697Ssam break; 11633579Srick case 'S': 11733966Srick Spool = optarg; 11833579Srick DEBUG(1, "Spool set to %s", Spool); 11933579Srick break; 12033966Srick case '?': 12113697Ssam default: 12233966Srick fprintf(stderr, "unknown flag %s\n", argv[optind-1]); 12313697Ssam break; 12413697Ssam } 12513697Ssam 12618628Sralph DEBUG(4, "\n\n** START **\n", CNULL); 12733966Srick if (subchdir(Spool) < 0) { 12833966Srick syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool); 12933966Srick cleanup(1); 13033966Srick } 13113697Ssam strcpy(Wrkdir, Spool); 13213697Ssam uid = getuid(); 13333579Srick if (guinfo(uid, User, path) != SUCCESS) { 13433966Srick syslog(LOG_WARNING, "Can't find username for uid %d", uid); 13533579Srick DEBUG(1, "Using username", "uucp"); 13633579Srick strcpy(User, "uucp"); 13733579Srick } 13817846Sralph setgid(getegid()); 13917846Sralph setuid(geteuid()); 14017846Sralph 14113697Ssam DEBUG(4, "User - %s\n", User); 14223692Sbloom if (ulockf(X_LOCK, X_LOCKTIME) != 0) 14313697Ssam exit(0); 14413697Ssam 14513697Ssam fp = fopen(CMDFILE, "r"); 14613697Ssam if (fp == NULL) { 14717846Sralph logent(CANTOPEN, CMDFILE); 14813697Ssam Cmds[0] = "rmail"; 14913697Ssam Cmds[1] = "rnews"; 15013697Ssam Cmds[2] = "ruusend"; 15113697Ssam Cmds[3] = NULL; 15213697Ssam goto doprocess; 15313697Ssam } 15413697Ssam DEBUG(5, "%s opened\n", CMDFILE); 15517846Sralph for (i=0; i<NCMDS && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) { 15617846Sralph int j; 15717846Sralph /* strip trailing whitespace */ 15817846Sralph for (j = strlen(xcmd)-1; j >= 0; --j) 15917846Sralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t') 16017846Sralph xcmd[j] = '\0'; 16117846Sralph else 16217846Sralph break; 16317846Sralph /* look for imbedded whitespace */ 16417846Sralph for (; j >= 0; --j) 16517846Sralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t') 16617846Sralph break; 16717846Sralph /* skip this entry if it has embedded whitespace */ 16817846Sralph /* This defends against a bad PATH=, for example */ 16917846Sralph if (j >= 0) { 17017846Sralph logent(xcmd, "BAD WHITESPACE"); 17117846Sralph continue; 17217846Sralph } 17313697Ssam if (strncmp(xcmd, "PATH=", 5) == 0) { 17413697Ssam strcpy(PATH, xcmd); 17517846Sralph i--; /*kludge */ 17613697Ssam continue; 17713697Ssam } 17813697Ssam DEBUG(5, "xcmd = %s\n", xcmd); 17917846Sralph 18017846Sralph if ((ptr = index(xcmd, ',')) != NULL) { 18117846Sralph *ptr++ = '\0'; 18217846Sralph if (strncmp(ptr, "Err", 3) == SAME) 18317846Sralph Notify[i] = NT_ERR; 18417846Sralph else if (strcmp(ptr, "No") == SAME) 18517846Sralph Notify[i] = NT_NO; 18617846Sralph else 18717846Sralph Notify[i] = NT_YES; 18817846Sralph } else 18917846Sralph Notify[i] = NT_YES; 19017846Sralph if ((Cmds[i] = malloc((unsigned)(strlen(xcmd)+1))) == NULL) { 19117846Sralph DEBUG(1, "MALLOC FAILED", CNULL); 19217846Sralph break; 19317846Sralph } 19413697Ssam strcpy(Cmds[i], xcmd); 19513697Ssam } 19617846Sralph Cmds[i] = CNULL; 19713697Ssam fclose(fp); 19813697Ssam 19913697Ssam doprocess: 20018628Sralph 20118628Sralph (void) sprintf(HOME, "HOME=%s", Spool); 20218628Sralph (void) sprintf(Shell, "SHELL=%s", SHELL); 20318628Sralph environ = nenv; /* force use if our environment */ 20418628Sralph 20518628Sralph DEBUG(11,"path = %s\n", getenv("PATH")); 20618628Sralph 20717846Sralph DEBUG(4, "process %s\n", CNULL); 20833579Srick 20918628Sralph time(&xstart); 21013697Ssam while (gtxfile(xfile) > 0) { 21125147Sbloom /* if /etc/nologin exists, exit cleanly */ 21225147Sbloom #if defined(BSD4_2) || defined(USG) 21325147Sbloom if (access(NOLOGIN) == 0) { 21425147Sbloom #else !BSD4_2 && ! USG 21517846Sralph ultouch(); 21617846Sralph if (nologinflag) { 21725147Sbloom #endif !BSD4_2 && !USG 21817846Sralph logent(NOLOGIN, "UUXQT SHUTDOWN"); 21917846Sralph if (Debug) 22017846Sralph logent("debugging", "continuing anyway"); 22117846Sralph else 22217846Sralph break; 22317846Sralph } 22413697Ssam DEBUG(4, "xfile - %s\n", xfile); 22513697Ssam 22613697Ssam xfp = fopen(subfile(xfile), "r"); 22733966Srick if (xfp == NULL) { 22833966Srick syslog(LOG_ERR, "fopen(%s) failed: %m", subfile(xfile)); 22933966Srick cleanup(1); 23033966Srick } 23113697Ssam 23213697Ssam /* initialize to default */ 23313697Ssam strcpy(user, User); 23417846Sralph strcpy(fin, DEVNULL); 23517846Sralph strcpy(fout, DEVNULL); 23623692Sbloom strcpy(sysout, Myname); 23717846Sralph badfiles = 0; 23813697Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 23934267Srick if(buf[0] != '\0' && buf[0] != '#' && 24034267Srick buf[1] != ' ' && buf[1] != '\0' && buf[1] != '\n') { 24134267Srick char *bnp, cfilename[BUFSIZ]; 24234267Srick DEBUG(4, "uuxqt: buf = %s\n", buf); 24334267Srick bnp = rindex(xfile, '/'); 24434267Srick sprintf(cfilename, "%s/%s", CORRUPT, 24534267Srick bnp ? bnp + 1 : xfile); 24634267Srick DEBUG(4, "uuxqt: move %s to ", xfile); 24734267Srick DEBUG(4, "%s\n", cfilename); 24834267Srick xmv(xfile, cfilename); 24934267Srick syslog(LOG_WARNING, "%s: X. FILE CORRUPTED", 25034267Srick xfile); 25134267Srick fclose(xfp); 25234267Srick goto doprocess; 25334267Srick } 25413697Ssam switch (buf[0]) { 25534267Srick case X_USER: { 25634267Srick char ORmtname[MAXFULLNAME]; 25734267Srick strcpy(ORmtname, Rmtname); 25817846Sralph sscanf(&buf[1], "%s %s", user, Rmtname); 25933966Srick sprintf(UU_MACHINE, "UU_MACHINE=%s", Rmtname); 26034267Srick if (strcmp(ORmtname, Rmtname) != 0) 26134267Srick logcls(); 26234267Srick break;} 26317846Sralph case X_RETURNTO: 26417846Sralph sscanf(&buf[1], "%s", user); 26517846Sralph break; 26613697Ssam case X_STDIN: 26713697Ssam sscanf(&buf[1], "%s", fin); 26813697Ssam i = expfile(fin); 26913697Ssam /* rti!trt: do not check permissions of 27013697Ssam * vanilla spool file */ 27113697Ssam if (i != 0 27213697Ssam && (chkpth("", "", fin) || anyread(fin) != 0)) 27313697Ssam badfiles = 1; 27413697Ssam break; 27513697Ssam case X_STDOUT: 27613697Ssam sscanf(&buf[1], "%s%s", fout, sysout); 27723692Sbloom sysout[MAXBASENAME] = '\0'; 27813697Ssam /* rti!trt: do not check permissions of 27913697Ssam * vanilla spool file. DO check permissions 28013697Ssam * of writing on a non-vanilla file */ 28113697Ssam i = 1; 28213697Ssam if (fout[0] != '~' || prefix(sysout, Myname)) 28313697Ssam i = expfile(fout); 28413697Ssam if (i != 0 28513697Ssam && (chkpth("", "", fout) 28613697Ssam || chkperm(fout, (char *)1))) 28713697Ssam badfiles = 1; 28813697Ssam break; 28913697Ssam case X_CMD: 29013697Ssam strcpy(cmd, &buf[2]); 29113697Ssam if (*(cmd + strlen(cmd) - 1) == '\n') 29213697Ssam *(cmd + strlen(cmd) - 1) = '\0'; 29313697Ssam break; 29413697Ssam case X_NONOTI: 29513697Ssam notiok = 0; 29613697Ssam break; 29713697Ssam case X_NONZERO: 29813697Ssam nonzero = 1; 29913697Ssam break; 30013697Ssam default: 30113697Ssam break; 30213697Ssam } 30313697Ssam } 30413697Ssam 30513697Ssam fclose(xfp); 30613697Ssam DEBUG(4, "fin - %s, ", fin); 30713697Ssam DEBUG(4, "fout - %s, ", fout); 30813697Ssam DEBUG(4, "sysout - %s, ", sysout); 30913697Ssam DEBUG(4, "user - %s\n", user); 31013697Ssam DEBUG(4, "cmd - %s\n", cmd); 31113697Ssam 31213697Ssam /* command execution */ 31317846Sralph if (strcmp(fout, DEVNULL) == SAME) 31417846Sralph strcpy(dfile,DEVNULL); 31513697Ssam else 31613697Ssam gename(DATAPRE, sysout, 'O', dfile); 31713697Ssam 31813697Ssam /* expand file names where necessary */ 31913697Ssam expfile(dfile); 32018628Sralph cmdp = buf; 32113697Ssam ptr = cmd; 32213697Ssam xcmd[0] = '\0'; 32313697Ssam argnok = 0; 32413697Ssam while ((ptr = getprm(ptr, prm)) != NULL) { 32513697Ssam if (prm[0] == ';' || prm[0] == '^' 32613697Ssam || prm[0] == '&' || prm[0] == '|') { 32713697Ssam xcmd[0] = '\0'; 32813697Ssam APPCMD(prm); 32913697Ssam continue; 33013697Ssam } 33113697Ssam 33217846Sralph if ((argnok = argok(xcmd, prm)) != SUCCESS) 33313697Ssam /* command not valid */ 33413697Ssam break; 33513697Ssam 33613697Ssam if (prm[0] == '~') 33713697Ssam expfile(prm); 33813697Ssam APPCMD(prm); 33913697Ssam } 34017846Sralph /* 34117846Sralph * clean up trailing ' ' in command. 34217846Sralph */ 34317846Sralph if (cmdp > buf && cmdp[0] == '\0' && cmdp[-1] == ' ') 34417846Sralph *--cmdp = '\0'; 34513697Ssam if (argnok || badfiles) { 34613697Ssam sprintf(lbuf, "%s XQT DENIED", user); 34713697Ssam logent(cmd, lbuf); 34813697Ssam DEBUG(4, "bad command %s\n", prm); 34913697Ssam notify(user, Rmtname, cmd, "DENIED"); 35013697Ssam goto rmfiles; 35113697Ssam } 35213697Ssam sprintf(lbuf, "%s XQT", user); 35313697Ssam logent(buf, lbuf); 35413697Ssam DEBUG(4, "cmd %s\n", buf); 35513697Ssam 35613697Ssam mvxfiles(xfile); 35733966Srick if (subchdir(XQTDIR) < 0) { 35833966Srick syslog(LOG_ERR, "chdir(%s) failed: %m", XQTDIR); 35933966Srick cleanup(1); 36033966Srick } 36118628Sralph ret = shio(buf, fin, dfile); 36213697Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377, 36313697Ssam (ret>>8) & 0377); 36413697Ssam if (strcmp(xcmd, "rmail") == SAME) 36513697Ssam notiok = 0; 36613697Ssam if (strcmp(xcmd, "rnews") == SAME) 36713697Ssam nonzero = 1; 36817846Sralph notiflg = chknotify(xcmd); 36917846Sralph if (notiok && notiflg != NT_NO && 37017846Sralph (ret != 0 || (!nonzero && notiflg == NT_YES))) 37113697Ssam notify(user, Rmtname, cmd, retstat); 37213697Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) { 37313697Ssam /* mail failed - return letter to sender */ 37417846Sralph #ifdef DANGEROUS 37517846Sralph /* NOT GUARANTEED SAFE!!! */ 37617846Sralph if (!nonzero) 37717846Sralph retosndr(user, Rmtname, fin); 37817846Sralph #else 37917846Sralph notify(user, Rmtname, cmd, retstat); 38017846Sralph #endif 38117846Sralph sprintf(buf, "%s (%s) from %s!%s", buf, retstat, Rmtname, user); 38213697Ssam logent("MAIL FAIL", buf); 38313697Ssam } 38413697Ssam DEBUG(4, "exit cmd - %d\n", ret); 38533966Srick if (subchdir(Spool) < 0) { 38633966Srick syslog(LOG_ERR, "chdir(%s) failed: %m", Spool); 38733966Srick cleanup(1); 38833966Srick } 38913697Ssam rmxfiles(xfile); 39013697Ssam if (ret != 0) { 39113697Ssam /* exit status not zero */ 39213697Ssam dfp = fopen(subfile(dfile), "a"); 39333966Srick if (dfp == NULL) { 39433966Srick syslog(LOG_ERR, "fopen(%s) failed: %m", 39533966Srick subfile(dfile)); 39633966Srick cleanup(1); 39733966Srick } 39813697Ssam fprintf(dfp, "exit status %d", ret); 39913697Ssam fclose(dfp); 40013697Ssam } 40117846Sralph if (strcmp(fout, DEVNULL) != SAME) { 40213697Ssam if (prefix(sysout, Myname)) { 40313697Ssam xmv(dfile, fout); 40413697Ssam chmod(fout, BASEMODE); 40518628Sralph } else { 40617846Sralph char *cp = rindex(user, '!'); 40713697Ssam gename(CMDPRE, sysout, 'O', cfile); 40813697Ssam fp = fopen(subfile(cfile), "w"); 40933966Srick if (fp == NULL) { 41033966Srick syslog(LOG_ERR, "fopen(%s) failed: %m", 41133966Srick subfile(cfile)); 41233966Srick cleanup(1); 41333966Srick } 41417846Sralph fprintf(fp, "S %s %s %s - %s 0666\n", dfile, 41517846Sralph fout, cp ? cp : user, lastpart(dfile)); 41613697Ssam fclose(fp); 41713697Ssam } 41813697Ssam } 41913697Ssam rmfiles: 42013697Ssam xfp = fopen(subfile(xfile), "r"); 42133966Srick if (xfp == NULL) { 42233966Srick syslog(LOG_ERR, "fopen(%s) failed: %m", 42333966Srick subfile(xfile)); 42433966Srick cleanup(1); 42533966Srick } 42613697Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) { 42713697Ssam if (buf[0] != X_RQDFILE) 42813697Ssam continue; 42913697Ssam sscanf(&buf[1], "%s", file); 43013697Ssam unlink(subfile(file)); 43113697Ssam } 43213697Ssam unlink(subfile(xfile)); 43313697Ssam fclose(xfp); 43418628Sralph 43518628Sralph /* rescan X. for new work every RECHECKTIME seconds */ 43618628Sralph time(&xnow); 43718628Sralph if (xnow > (xstart + RECHECKTIME)) { 43818628Sralph extern int Nfiles; 43918628Sralph Nfiles = 0; /*force rescan for new work */ 44018628Sralph } 44118628Sralph xstart = xnow; 44213697Ssam } 44313697Ssam 44413697Ssam if (stcico) 44513697Ssam xuucico(""); 44613697Ssam cleanup(0); 44713697Ssam } 44813697Ssam 44913697Ssam 45013697Ssam cleanup(code) 45113697Ssam int code; 45213697Ssam { 45313697Ssam logcls(); 45413697Ssam rmlock(CNULL); 45517846Sralph #ifdef VMS 45617846Sralph /* 45717846Sralph * Since we run as a BATCH job we must wait for all processes to 45817846Sralph * to finish 45917846Sralph */ 46018628Sralph while(wait(0) != -1) 46118628Sralph ; 46217846Sralph #endif VMS 46313697Ssam exit(code); 46413697Ssam } 46513697Ssam 46613697Ssam 46718628Sralph /* 46818628Sralph * get a file to execute 46913697Ssam * 47013697Ssam * return codes: 0 - no file | 1 - file to execute 47113697Ssam */ 47213697Ssam 47313697Ssam gtxfile(file) 47413697Ssam register char *file; 47513697Ssam { 47613697Ssam char pre[3]; 47733579Srick register int rechecked, i; 47817846Sralph time_t ystrdy; /* yesterday */ 47917846Sralph struct stat stbuf; /* for X file age */ 48013697Ssam 48113697Ssam pre[0] = XQTPRE; 48213697Ssam pre[1] = '.'; 48313697Ssam pre[2] = '\0'; 48413697Ssam rechecked = 0; 48513697Ssam retry: 48633579Srick if (Nfiles-- <= 0) { 48733579Srick Nfiles = 0; 48813697Ssam if (rechecked) 48917846Sralph return 0; 49013697Ssam rechecked = 1; 49117846Sralph DEBUG(4, "iswrk\n", CNULL); 49233579Srick return iswrk(file, "get", Spool, pre); 49313697Ssam } 49433579Srick sprintf(file, "%s/%s", Spool, Filent[0]); 49533579Srick for (i=0; i<Nfiles;i++) 49633579Srick strcpy(Filent[i], Filent[i+1]); 49733579Srick 49813697Ssam DEBUG(4, "file - %s\n", file); 49913697Ssam /* skip spurious subdirectories */ 50013697Ssam if (strcmp(pre, file) == SAME) 50113697Ssam goto retry; 50213697Ssam if (gotfiles(file)) 50317846Sralph return 1; 50417846Sralph /* check for old X. file with no work files and remove them. */ 50517846Sralph if (Nfiles > LLEN/2) { 50617846Sralph time(&ystrdy); 50717846Sralph ystrdy -= (4 * 3600L); /* 4 hours ago */ 50817846Sralph DEBUG(4, "gtxfile: Nfiles > LLEN/2\n", CNULL); 50933579Srick while (Nfiles-- > 0) { 51033579Srick sprintf(file, "%s/%s", Spool, Filent[0]); 51133579Srick for (i=0; i<Nfiles; i++) 51233579Srick strcpy(Filent[i], Filent[i+1]); 51333579Srick 51433579Srick if (gotfiles(file)) 51533579Srick return 1; 51617846Sralph if (stat(subfile(file), &stbuf) == 0) 51717846Sralph if (stbuf.st_mtime <= ystrdy) { 51817846Sralph char *bnp, cfilename[NAMESIZE]; 51917846Sralph DEBUG(4, "gtxfile: move %s to CORRUPT \n", file); 52033579Srick bnp = rindex(file, '/'); 52117846Sralph sprintf(cfilename, "%s/%s", CORRUPT, 52233579Srick bnp ? bnp + 1 : file); 52333579Srick xmv(file, cfilename); 52433966Srick syslog(LOG_WARNING, "%s: X. FILE MISSING FILES", file); 52517846Sralph } 52617846Sralph } 52733579Srick Nfiles = 0; 52817846Sralph DEBUG(4, "iswrk\n", CNULL); 52917846Sralph if (!iswrk(file, "get", Spool, pre)) 53017846Sralph return 0; 53117846Sralph } 53213697Ssam goto retry; 53313697Ssam } 53413697Ssam 53518628Sralph /* 53618628Sralph * check for needed files 53713697Ssam * 53813697Ssam * return codes: 0 - not ready | 1 - all files ready 53913697Ssam */ 54013697Ssam 54113697Ssam gotfiles(file) 54213697Ssam register char *file; 54313697Ssam { 54413697Ssam struct stat stbuf; 54513697Ssam register FILE *fp; 54613697Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME]; 54713697Ssam 54813697Ssam fp = fopen(subfile(file), "r"); 54913697Ssam if (fp == NULL) 55017846Sralph return 0; 55113697Ssam 55213697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 55313697Ssam DEBUG(4, "%s\n", buf); 55413697Ssam if (buf[0] != X_RQDFILE) 55513697Ssam continue; 55613697Ssam sscanf(&buf[1], "%s", rqfile); 55713697Ssam expfile(rqfile); 55813697Ssam if (stat(subfile(rqfile), &stbuf) == -1) { 55913697Ssam fclose(fp); 56017846Sralph return 0; 56113697Ssam } 56213697Ssam } 56313697Ssam 56413697Ssam fclose(fp); 56517846Sralph return 1; 56613697Ssam } 56713697Ssam 56813697Ssam 56918628Sralph /* 57018628Sralph * remove execute files to x-directory 57113697Ssam */ 57213697Ssam 57313697Ssam rmxfiles(xfile) 57413697Ssam register char *xfile; 57513697Ssam { 57613697Ssam register FILE *fp; 57713697Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; 57813697Ssam char tfull[MAXFULLNAME]; 57913697Ssam 58013697Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 58113697Ssam return; 58213697Ssam 58313697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 58413697Ssam if (buf[0] != X_RQDFILE) 58513697Ssam continue; 58613697Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2) 58713697Ssam continue; 58813697Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 58913697Ssam unlink(subfile(tfull)); 59013697Ssam } 59113697Ssam fclose(fp); 59213697Ssam return; 59313697Ssam } 59413697Ssam 59513697Ssam 59618628Sralph /* 59718628Sralph * move execute files to x-directory 59813697Ssam */ 59913697Ssam 60013697Ssam mvxfiles(xfile) 60113697Ssam char *xfile; 60213697Ssam { 60313697Ssam register FILE *fp; 60413697Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE]; 60513697Ssam char tfull[MAXFULLNAME]; 60613697Ssam 60713697Ssam if((fp = fopen(subfile(xfile), "r")) == NULL) 60813697Ssam return; 60913697Ssam 61013697Ssam while (fgets(buf, BUFSIZ, fp) != NULL) { 61113697Ssam if (buf[0] != X_RQDFILE) 61213697Ssam continue; 61313697Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) 61413697Ssam continue; 61513697Ssam expfile(ffile); 61613697Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile); 61713697Ssam unlink(subfile(tfull)); 61833966Srick if (xmv(ffile, tfull) != 0) { 61933966Srick syslog(LOG_WARNING, "xmv(%s,%s) failed: %m", 62033966Srick ffile, tfull); 62133966Srick cleanup(1); 62233966Srick } 62313697Ssam } 62413697Ssam fclose(fp); 62513697Ssam } 62613697Ssam 62718628Sralph /* 62818628Sralph * check for valid command/argument 62918628Sralph * *NOTE - side effect is to set xc to the command to be executed. 63013697Ssam * 63113697Ssam * return 0 - ok | 1 nok 63213697Ssam */ 63313697Ssam 63413697Ssam argok(xc, cmd) 63513697Ssam register char *xc, *cmd; 63613697Ssam { 63713697Ssam register char **ptr; 63813697Ssam 63913697Ssam #ifndef ALLOK 64018628Sralph if (strpbrk(cmd, BADCHARS) != NULL) { 64117846Sralph DEBUG(1,"MAGIC CHARACTER FOUND\n", CNULL); 64218628Sralph logent(cmd, "NASTY MAGIC CHARACTER FOUND"); 64317846Sralph return FAIL; 64417846Sralph } 64517846Sralph #endif !ALLOK 64613697Ssam 64713697Ssam if (xc[0] != '\0') 64817846Sralph return SUCCESS; 64913697Ssam 65013697Ssam #ifndef ALLOK 65113697Ssam ptr = Cmds; 65217846Sralph DEBUG(9, "Compare %s and\n", cmd); 65313697Ssam while(*ptr != NULL) { 65417846Sralph DEBUG(9, "\t%s\n", *ptr); 65513697Ssam if (strcmp(cmd, *ptr) == SAME) 65613697Ssam break; 65717846Sralph ptr++; 65813697Ssam } 65917846Sralph if (*ptr == NULL) { 66017846Sralph DEBUG(1,"COMMAND NOT FOUND\n", CNULL); 66117846Sralph return FAIL; 66217846Sralph } 66313697Ssam #endif 66413697Ssam strcpy(xc, cmd); 66517846Sralph DEBUG(9, "MATCHED %s\n", xc); 66617846Sralph return SUCCESS; 66713697Ssam } 66813697Ssam 66913697Ssam 67018628Sralph /* 67118628Sralph * if notification should be sent for successful execution of cmd 67217846Sralph * 67317846Sralph * return NT_YES - do notification 67417846Sralph * NT_ERR - do notification if exit status != 0 67517846Sralph * NT_NO - don't do notification ever 67617846Sralph */ 67717846Sralph 67817846Sralph chknotify(cmd) 67917846Sralph char *cmd; 68017846Sralph { 68117846Sralph register char **ptr; 68217846Sralph register int *nptr; 68317846Sralph 68417846Sralph ptr = Cmds; 68517846Sralph nptr = Notify; 68617846Sralph while (*ptr != NULL) { 68717846Sralph if (strcmp(cmd, *ptr) == SAME) 68817846Sralph return *nptr; 68917846Sralph ptr++; 69017846Sralph nptr++; 69117846Sralph } 69217846Sralph return NT_YES; /* "shouldn't happen" */ 69317846Sralph } 69417846Sralph 69517846Sralph 69617846Sralph 69718628Sralph /* 69818628Sralph * send mail to user giving execution results 69913697Ssam */ 70013697Ssam 70113697Ssam notify(user, rmt, cmd, str) 70213697Ssam char *user, *rmt, *cmd, *str; 70313697Ssam { 70433579Srick char text[BUFSIZ*2]; 70513697Ssam char ruser[MAXFULLNAME]; 70613697Ssam 70725968Sbloom if (strpbrk(user, BADCHARS) != NULL) { 70825968Sbloom char lbuf[MAXFULLNAME]; 70925968Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user); 71025968Sbloom logent(cmd, lbuf); 71125968Sbloom strcpy(user, "postmaster"); 71225968Sbloom } 71317846Sralph sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str); 71413697Ssam if (prefix(rmt, Myname)) 71513697Ssam strcpy(ruser, user); 71613697Ssam else 71713697Ssam sprintf(ruser, "%s!%s", rmt, user); 71817846Sralph mailst(ruser, text, CNULL); 71913697Ssam } 72013697Ssam 72118628Sralph /* 72218628Sralph * return mail to sender 72313697Ssam * 72413697Ssam */ 72513697Ssam retosndr(user, rmt, file) 72613697Ssam char *user, *rmt, *file; 72713697Ssam { 72817846Sralph char ruser[MAXFULLNAME]; 72913697Ssam 73025968Sbloom if (strpbrk(user, BADCHARS) != NULL) { 73125968Sbloom char lbuf[MAXFULLNAME]; 73225968Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user); 73325968Sbloom logent(file, lbuf); 73425968Sbloom strcpy(user, "postmaster"); 73525968Sbloom } 73613697Ssam if (strcmp(rmt, Myname) == SAME) 73713697Ssam strcpy(ruser, user); 73813697Ssam else 73913697Ssam sprintf(ruser, "%s!%s", rmt, user); 74013697Ssam 74113697Ssam if (anyread(file) == 0) 74213697Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file); 74313697Ssam else 74417846Sralph mailst(ruser, "Mail failed. Letter returned to sender.\n", CNULL); 74513697Ssam return; 74613697Ssam } 74717870Sralph 74817870Sralph /* 74918628Sralph * execute shell of command with fi and fo as standard input/output 75018628Sralph */ 75118628Sralph 75218628Sralph shio(cmd, fi, fo) 75318628Sralph char *cmd, *fi, *fo; 75418628Sralph { 75518628Sralph int status, f; 75633966Srick int pid, ret; 75733579Srick char *args[256]; 75818628Sralph extern int errno; 75918628Sralph 76018628Sralph if (fi == NULL) 76118628Sralph fi = DEVNULL; 76218628Sralph if (fo == NULL) 76318628Sralph fo = DEVNULL; 76418628Sralph 76533579Srick getargs(cmd, args, 256); 76618628Sralph DEBUG(3, "shio - %s\n", cmd); 76718628Sralph #ifdef SIGCHLD 76818628Sralph signal(SIGCHLD, SIG_IGN); 76918628Sralph #endif SIGCHLD 77018628Sralph if ((pid = fork()) == 0) { 77118628Sralph signal(SIGINT, SIG_IGN); 77218628Sralph signal(SIGHUP, SIG_IGN); 77318628Sralph signal(SIGQUIT, SIG_IGN); 77418628Sralph close(Ifn); 77518628Sralph close(Ofn); 77618628Sralph close(0); 77718628Sralph setuid(getuid()); 77818628Sralph f = open(subfile(fi), 0); 77918628Sralph if (f != 0) { 78018628Sralph logent(fi, "CAN'T READ"); 78118628Sralph exit(-errno); 78218628Sralph } 78318628Sralph close(1); 78418628Sralph f = creat(subfile(fo), 0666); 78518628Sralph if (f != 1) { 78618628Sralph logent(fo, "CAN'T WRITE"); 78718628Sralph exit(-errno); 78818628Sralph } 78918628Sralph execvp(args[0], args); 79018628Sralph exit(100+errno); 79118628Sralph } 79218628Sralph while ((ret = wait(&status)) != pid && ret != -1) 79318628Sralph ; 79418628Sralph DEBUG(3, "status %d\n", status); 79518628Sralph return status; 79618628Sralph } 797