144e19819Sbostic /*-
2*ec71041fSbostic * Copyright (c) 1985, 1988, 1993
3*ec71041fSbostic * The Regents of the University of California. All rights reserved.
444e19819Sbostic *
544e19819Sbostic * %sccs.include.proprietary.c%
644e19819Sbostic */
744e19819Sbostic
852081424Ssam #ifndef lint
9*ec71041fSbostic static char copyright[] =
10*ec71041fSbostic "@(#) Copyright (c) 1985, 1988, 1993\n\
11*ec71041fSbostic The Regents of the University of California. All rights reserved.\n";
1244e19819Sbostic #endif /* not lint */
1344e19819Sbostic
1444e19819Sbostic #ifndef lint
15*ec71041fSbostic static char sccsid[] = "@(#)uuxqt.c 8.1 (Berkeley) 06/06/93";
1644e19819Sbostic #endif /* not lint */
1752081424Ssam
1852081424Ssam #include "uucp.h"
1952081424Ssam #include <sys/stat.h>
2052081424Ssam #ifdef NDIR
2152081424Ssam #include "ndir.h"
2252081424Ssam #else
23109b7051Ssam #include <sys/dir.h>
2452081424Ssam #endif
25e21537dbSralph #include <signal.h>
2652081424Ssam
272f96a7e7Sralph #define BADCHARS "&^|(`\\<>;\"{}\n'"
282f96a7e7Sralph #define RECHECKTIME 60*10 /* 10 minutes */
29dbb6249cSralph
3052081424Ssam #define APPCMD(d) {\
3152081424Ssam char *p;\
32e21537dbSralph for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';}
3352081424Ssam
342bba3b8bSrick extern char Filent[LLEN][NAMESIZE];
352bba3b8bSrick
3652081424Ssam /*
3752081424Ssam * uuxqt will execute commands set up by a uux command,
3852081424Ssam * usually from a remote machine - set by uucp.
3952081424Ssam */
4052081424Ssam
4152081424Ssam #define NCMDS 50
42e21537dbSralph char *Cmds[NCMDS+1];
43e21537dbSralph int Notify[NCMDS+1];
44e21537dbSralph #define NT_YES 0 /* if should notify on execution */
45e21537dbSralph #define NT_ERR 1 /* if should notify if non-zero exit status (-z equivalent) */
46e21537dbSralph #define NT_NO 2 /* if should not notify ever (-n equivalent) */
47e21537dbSralph
48e21537dbSralph extern int Nfiles;
4952081424Ssam
502f96a7e7Sralph int TransferSucceeded = 1;
5152081424Ssam int notiok = 1;
5252081424Ssam int nonzero = 0;
5352081424Ssam
5498a5b756Sbloom struct timeb Now;
5598a5b756Sbloom
56290a350eStrent char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin";
572cbba08fSrick char UU_MACHINE[MAXFULLNAME];
582f96a7e7Sralph char Shell[MAXFULLNAME];
592f96a7e7Sralph char HOME[MAXFULLNAME];
602f96a7e7Sralph
612f96a7e7Sralph extern char **environ;
622f96a7e7Sralph char *nenv[] = {
632f96a7e7Sralph PATH,
642f96a7e7Sralph Shell,
652f96a7e7Sralph HOME,
662cbba08fSrick UU_MACHINE,
672f96a7e7Sralph 0
682f96a7e7Sralph };
692f96a7e7Sralph
7052081424Ssam /* to remove restrictions from uuxqt
7152081424Ssam * define ALLOK 1
7252081424Ssam *
7352081424Ssam * to add allowable commands, add to the file CMDFILE
7452081424Ssam * A line of form "PATH=..." changes the search path
7552081424Ssam */
main(argc,argv)7652081424Ssam main(argc, argv)
7752081424Ssam char *argv[];
7852081424Ssam {
792bba3b8bSrick char xcmd[BUFSIZ*2];
8052081424Ssam int argnok;
81e21537dbSralph int notiflg;
822bba3b8bSrick char xfile[MAXFULLNAME], user[MAXFULLNAME], buf[BUFSIZ*2];
83e21537dbSralph char lbuf[MAXFULLNAME];
8452081424Ssam char cfile[NAMESIZE], dfile[MAXFULLNAME];
8552081424Ssam char file[NAMESIZE];
8652081424Ssam char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME];
8752081424Ssam register FILE *xfp, *fp;
8852081424Ssam FILE *dfp;
8952081424Ssam char path[MAXFULLNAME];
902bba3b8bSrick char cmd[BUFSIZ*2];
9152081424Ssam char *cmdp, prm[1000], *ptr;
9252081424Ssam char *getprm(), *lastpart();
932cbba08fSrick int uid, ret, badfiles;
9452081424Ssam register int i;
9552081424Ssam int stcico = 0;
962f96a7e7Sralph time_t xstart, xnow;
9752081424Ssam char retstat[30];
982cbba08fSrick extern char *optarg;
992cbba08fSrick extern int optind;
10052081424Ssam
10152081424Ssam strcpy(Progname, "uuxqt");
10252081424Ssam uucpname(Myname);
103f2386554Srick strcpy(Rmtname, Myname);
10452081424Ssam
10552081424Ssam umask(WFMASK);
10652081424Ssam Ofn = 1;
10752081424Ssam Ifn = 0;
1082cbba08fSrick while ((i = getopt(argc, argv, "x:S:")) != EOF)
1092cbba08fSrick switch(i) {
11052081424Ssam case 'x':
111e21537dbSralph chkdebug();
1122cbba08fSrick Debug = atoi(optarg);
11352081424Ssam if (Debug <= 0)
11452081424Ssam Debug = 1;
11552081424Ssam break;
1162bba3b8bSrick case 'S':
1172cbba08fSrick Spool = optarg;
1182bba3b8bSrick DEBUG(1, "Spool set to %s", Spool);
1192bba3b8bSrick break;
1202cbba08fSrick case '?':
12152081424Ssam default:
1222cbba08fSrick fprintf(stderr, "unknown flag %s\n", argv[optind-1]);
12352081424Ssam break;
12452081424Ssam }
12552081424Ssam
1262f96a7e7Sralph DEBUG(4, "\n\n** START **\n", CNULL);
1272cbba08fSrick if (subchdir(Spool) < 0) {
1282cbba08fSrick syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool);
1292cbba08fSrick cleanup(1);
1302cbba08fSrick }
13152081424Ssam strcpy(Wrkdir, Spool);
13252081424Ssam uid = getuid();
1332bba3b8bSrick if (guinfo(uid, User, path) != SUCCESS) {
1342cbba08fSrick syslog(LOG_WARNING, "Can't find username for uid %d", uid);
1352bba3b8bSrick DEBUG(1, "Using username", "uucp");
1362bba3b8bSrick strcpy(User, "uucp");
1372bba3b8bSrick }
138e21537dbSralph setgid(getegid());
139e21537dbSralph setuid(geteuid());
140e21537dbSralph
14152081424Ssam DEBUG(4, "User - %s\n", User);
1421a575e59Sbloom if (ulockf(X_LOCK, X_LOCKTIME) != 0)
14352081424Ssam exit(0);
14452081424Ssam
14552081424Ssam fp = fopen(CMDFILE, "r");
14652081424Ssam if (fp == NULL) {
147e21537dbSralph logent(CANTOPEN, CMDFILE);
14852081424Ssam Cmds[0] = "rmail";
14952081424Ssam Cmds[1] = "rnews";
15052081424Ssam Cmds[2] = "ruusend";
15152081424Ssam Cmds[3] = NULL;
15252081424Ssam goto doprocess;
15352081424Ssam }
15452081424Ssam DEBUG(5, "%s opened\n", CMDFILE);
155e21537dbSralph for (i=0; i<NCMDS && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) {
156e21537dbSralph int j;
157e21537dbSralph /* strip trailing whitespace */
158e21537dbSralph for (j = strlen(xcmd)-1; j >= 0; --j)
159e21537dbSralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t')
160e21537dbSralph xcmd[j] = '\0';
161e21537dbSralph else
162e21537dbSralph break;
163e21537dbSralph /* look for imbedded whitespace */
164e21537dbSralph for (; j >= 0; --j)
165e21537dbSralph if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t')
166e21537dbSralph break;
167e21537dbSralph /* skip this entry if it has embedded whitespace */
168e21537dbSralph /* This defends against a bad PATH=, for example */
169e21537dbSralph if (j >= 0) {
170e21537dbSralph logent(xcmd, "BAD WHITESPACE");
171e21537dbSralph continue;
172e21537dbSralph }
17352081424Ssam if (strncmp(xcmd, "PATH=", 5) == 0) {
17452081424Ssam strcpy(PATH, xcmd);
17552081424Ssam i--; /*kludge */
17652081424Ssam continue;
17752081424Ssam }
17852081424Ssam DEBUG(5, "xcmd = %s\n", xcmd);
179e21537dbSralph
180e21537dbSralph if ((ptr = index(xcmd, ',')) != NULL) {
181e21537dbSralph *ptr++ = '\0';
182e21537dbSralph if (strncmp(ptr, "Err", 3) == SAME)
183e21537dbSralph Notify[i] = NT_ERR;
184e21537dbSralph else if (strcmp(ptr, "No") == SAME)
185e21537dbSralph Notify[i] = NT_NO;
186e21537dbSralph else
187e21537dbSralph Notify[i] = NT_YES;
188e21537dbSralph } else
189e21537dbSralph Notify[i] = NT_YES;
190e21537dbSralph if ((Cmds[i] = malloc((unsigned)(strlen(xcmd)+1))) == NULL) {
191e21537dbSralph DEBUG(1, "MALLOC FAILED", CNULL);
192e21537dbSralph break;
193e21537dbSralph }
19452081424Ssam strcpy(Cmds[i], xcmd);
19552081424Ssam }
196e21537dbSralph Cmds[i] = CNULL;
19752081424Ssam fclose(fp);
19852081424Ssam
19952081424Ssam doprocess:
2002f96a7e7Sralph
2012f96a7e7Sralph (void) sprintf(HOME, "HOME=%s", Spool);
2022f96a7e7Sralph (void) sprintf(Shell, "SHELL=%s", SHELL);
2032f96a7e7Sralph environ = nenv; /* force use if our environment */
2042f96a7e7Sralph
2052f96a7e7Sralph DEBUG(11,"path = %s\n", getenv("PATH"));
2062f96a7e7Sralph
207e21537dbSralph DEBUG(4, "process %s\n", CNULL);
2082bba3b8bSrick
2092f96a7e7Sralph time(&xstart);
21052081424Ssam while (gtxfile(xfile) > 0) {
211e21537dbSralph /* if /etc/nologin exists, exit cleanly */
21298a5b756Sbloom #if defined(BSD4_2) || defined(USG)
21398a5b756Sbloom if (access(NOLOGIN) == 0) {
21498a5b756Sbloom #else !BSD4_2 && ! USG
21598a5b756Sbloom ultouch();
216e21537dbSralph if (nologinflag) {
21798a5b756Sbloom #endif !BSD4_2 && !USG
218e21537dbSralph logent(NOLOGIN, "UUXQT SHUTDOWN");
219e21537dbSralph if (Debug)
220e21537dbSralph logent("debugging", "continuing anyway");
221e21537dbSralph else
222e21537dbSralph break;
223e21537dbSralph }
22452081424Ssam DEBUG(4, "xfile - %s\n", xfile);
22552081424Ssam
22652081424Ssam xfp = fopen(subfile(xfile), "r");
2272cbba08fSrick if (xfp == NULL) {
2282cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m", subfile(xfile));
2292cbba08fSrick cleanup(1);
2302cbba08fSrick }
23152081424Ssam
23252081424Ssam /* initialize to default */
23352081424Ssam strcpy(user, User);
234e21537dbSralph strcpy(fin, DEVNULL);
235e21537dbSralph strcpy(fout, DEVNULL);
2361a575e59Sbloom strcpy(sysout, Myname);
237e21537dbSralph badfiles = 0;
23852081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) {
2392bba3b8bSrick if(buf[0] != '\0' && buf[0] != '#' &&
2402bba3b8bSrick buf[1] != ' ' && buf[1] != '\0' && buf[1] != '\n') {
2412bba3b8bSrick char *bnp, cfilename[BUFSIZ];
2422bba3b8bSrick DEBUG(4, "uuxqt: buf = %s\n", buf);
2432bba3b8bSrick bnp = rindex(xfile, '/');
2442bba3b8bSrick sprintf(cfilename, "%s/%s", CORRUPT,
2452bba3b8bSrick bnp ? bnp + 1 : xfile);
2462bba3b8bSrick DEBUG(4, "uuxqt: move %s to ", xfile);
2472bba3b8bSrick DEBUG(4, "%s\n", cfilename);
2482bba3b8bSrick xmv(xfile, cfilename);
249a92c1dbeSrick syslog(LOG_WARNING, "%s: X. FILE CORRUPTED",
250a92c1dbeSrick xfile);
2512bba3b8bSrick fclose(xfp);
2522bba3b8bSrick goto doprocess;
2532bba3b8bSrick }
25452081424Ssam switch (buf[0]) {
255a92c1dbeSrick case X_USER: {
256a92c1dbeSrick char ORmtname[MAXFULLNAME];
257a92c1dbeSrick strcpy(ORmtname, Rmtname);
25852081424Ssam sscanf(&buf[1], "%s %s", user, Rmtname);
2592cbba08fSrick sprintf(UU_MACHINE, "UU_MACHINE=%s", Rmtname);
260a92c1dbeSrick if (strcmp(ORmtname, Rmtname) != 0)
261a92c1dbeSrick logcls();
262a92c1dbeSrick break;}
263e21537dbSralph case X_RETURNTO:
264e21537dbSralph sscanf(&buf[1], "%s", user);
265e21537dbSralph break;
26652081424Ssam case X_STDIN:
26752081424Ssam sscanf(&buf[1], "%s", fin);
26852081424Ssam i = expfile(fin);
26952081424Ssam /* rti!trt: do not check permissions of
27052081424Ssam * vanilla spool file */
27152081424Ssam if (i != 0
27252081424Ssam && (chkpth("", "", fin) || anyread(fin) != 0))
27352081424Ssam badfiles = 1;
27452081424Ssam break;
27552081424Ssam case X_STDOUT:
27652081424Ssam sscanf(&buf[1], "%s%s", fout, sysout);
2771a575e59Sbloom sysout[MAXBASENAME] = '\0';
27852081424Ssam /* rti!trt: do not check permissions of
27952081424Ssam * vanilla spool file. DO check permissions
28052081424Ssam * of writing on a non-vanilla file */
28152081424Ssam i = 1;
28252081424Ssam if (fout[0] != '~' || prefix(sysout, Myname))
28352081424Ssam i = expfile(fout);
28452081424Ssam if (i != 0
28552081424Ssam && (chkpth("", "", fout)
28652081424Ssam || chkperm(fout, (char *)1)))
28752081424Ssam badfiles = 1;
28852081424Ssam break;
28952081424Ssam case X_CMD:
29052081424Ssam strcpy(cmd, &buf[2]);
29152081424Ssam if (*(cmd + strlen(cmd) - 1) == '\n')
29252081424Ssam *(cmd + strlen(cmd) - 1) = '\0';
29352081424Ssam break;
29452081424Ssam case X_NONOTI:
29552081424Ssam notiok = 0;
29652081424Ssam break;
29752081424Ssam case X_NONZERO:
29852081424Ssam nonzero = 1;
29952081424Ssam break;
30052081424Ssam default:
30152081424Ssam break;
30252081424Ssam }
30352081424Ssam }
30452081424Ssam
30552081424Ssam fclose(xfp);
30652081424Ssam DEBUG(4, "fin - %s, ", fin);
30752081424Ssam DEBUG(4, "fout - %s, ", fout);
30852081424Ssam DEBUG(4, "sysout - %s, ", sysout);
30952081424Ssam DEBUG(4, "user - %s\n", user);
31052081424Ssam DEBUG(4, "cmd - %s\n", cmd);
31152081424Ssam
31252081424Ssam /* command execution */
313e21537dbSralph if (strcmp(fout, DEVNULL) == SAME)
314e21537dbSralph strcpy(dfile,DEVNULL);
31552081424Ssam else
31652081424Ssam gename(DATAPRE, sysout, 'O', dfile);
31752081424Ssam
31852081424Ssam /* expand file names where necessary */
31952081424Ssam expfile(dfile);
3202f96a7e7Sralph cmdp = buf;
32152081424Ssam ptr = cmd;
32252081424Ssam xcmd[0] = '\0';
32352081424Ssam argnok = 0;
32452081424Ssam while ((ptr = getprm(ptr, prm)) != NULL) {
32552081424Ssam if (prm[0] == ';' || prm[0] == '^'
32652081424Ssam || prm[0] == '&' || prm[0] == '|') {
32752081424Ssam xcmd[0] = '\0';
32852081424Ssam APPCMD(prm);
32952081424Ssam continue;
33052081424Ssam }
33152081424Ssam
332e21537dbSralph if ((argnok = argok(xcmd, prm)) != SUCCESS)
33352081424Ssam /* command not valid */
33452081424Ssam break;
33552081424Ssam
33652081424Ssam if (prm[0] == '~')
33752081424Ssam expfile(prm);
33852081424Ssam APPCMD(prm);
33952081424Ssam }
340e21537dbSralph /*
341e21537dbSralph * clean up trailing ' ' in command.
342e21537dbSralph */
343e21537dbSralph if (cmdp > buf && cmdp[0] == '\0' && cmdp[-1] == ' ')
344e21537dbSralph *--cmdp = '\0';
34552081424Ssam if (argnok || badfiles) {
34652081424Ssam sprintf(lbuf, "%s XQT DENIED", user);
34752081424Ssam logent(cmd, lbuf);
34852081424Ssam DEBUG(4, "bad command %s\n", prm);
34952081424Ssam notify(user, Rmtname, cmd, "DENIED");
35052081424Ssam goto rmfiles;
35152081424Ssam }
35252081424Ssam sprintf(lbuf, "%s XQT", user);
35352081424Ssam logent(buf, lbuf);
35452081424Ssam DEBUG(4, "cmd %s\n", buf);
35552081424Ssam
35652081424Ssam mvxfiles(xfile);
3572cbba08fSrick if (subchdir(XQTDIR) < 0) {
3582cbba08fSrick syslog(LOG_ERR, "chdir(%s) failed: %m", XQTDIR);
3592cbba08fSrick cleanup(1);
3602cbba08fSrick }
3612f96a7e7Sralph ret = shio(buf, fin, dfile);
36252081424Ssam sprintf(retstat, "signal %d, exit %d", ret & 0377,
36352081424Ssam (ret>>8) & 0377);
36452081424Ssam if (strcmp(xcmd, "rmail") == SAME)
36552081424Ssam notiok = 0;
36652081424Ssam if (strcmp(xcmd, "rnews") == SAME)
36752081424Ssam nonzero = 1;
368e21537dbSralph notiflg = chknotify(xcmd);
369e21537dbSralph if (notiok && notiflg != NT_NO &&
370e21537dbSralph (ret != 0 || (!nonzero && notiflg == NT_YES)))
37152081424Ssam notify(user, Rmtname, cmd, retstat);
37252081424Ssam else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) {
37352081424Ssam /* mail failed - return letter to sender */
374e21537dbSralph #ifdef DANGEROUS
375e21537dbSralph /* NOT GUARANTEED SAFE!!! */
376e21537dbSralph if (!nonzero)
37752081424Ssam retosndr(user, Rmtname, fin);
378e21537dbSralph #else
379e21537dbSralph notify(user, Rmtname, cmd, retstat);
380e21537dbSralph #endif
381e21537dbSralph sprintf(buf, "%s (%s) from %s!%s", buf, retstat, Rmtname, user);
38252081424Ssam logent("MAIL FAIL", buf);
38352081424Ssam }
38452081424Ssam DEBUG(4, "exit cmd - %d\n", ret);
3852cbba08fSrick if (subchdir(Spool) < 0) {
3862cbba08fSrick syslog(LOG_ERR, "chdir(%s) failed: %m", Spool);
3872cbba08fSrick cleanup(1);
3882cbba08fSrick }
38952081424Ssam rmxfiles(xfile);
39052081424Ssam if (ret != 0) {
39152081424Ssam /* exit status not zero */
39252081424Ssam dfp = fopen(subfile(dfile), "a");
3932cbba08fSrick if (dfp == NULL) {
3942cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m",
3952cbba08fSrick subfile(dfile));
3962cbba08fSrick cleanup(1);
3972cbba08fSrick }
39852081424Ssam fprintf(dfp, "exit status %d", ret);
39952081424Ssam fclose(dfp);
40052081424Ssam }
401e21537dbSralph if (strcmp(fout, DEVNULL) != SAME) {
40252081424Ssam if (prefix(sysout, Myname)) {
40352081424Ssam xmv(dfile, fout);
40452081424Ssam chmod(fout, BASEMODE);
4052f96a7e7Sralph } else {
406e21537dbSralph char *cp = rindex(user, '!');
40752081424Ssam gename(CMDPRE, sysout, 'O', cfile);
40852081424Ssam fp = fopen(subfile(cfile), "w");
4092cbba08fSrick if (fp == NULL) {
4102cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m",
4112cbba08fSrick subfile(cfile));
4122cbba08fSrick cleanup(1);
4132cbba08fSrick }
414e21537dbSralph fprintf(fp, "S %s %s %s - %s 0666\n", dfile,
415e21537dbSralph fout, cp ? cp : user, lastpart(dfile));
41652081424Ssam fclose(fp);
41752081424Ssam }
41852081424Ssam }
41952081424Ssam rmfiles:
42052081424Ssam xfp = fopen(subfile(xfile), "r");
4212cbba08fSrick if (xfp == NULL) {
4222cbba08fSrick syslog(LOG_ERR, "fopen(%s) failed: %m",
4232cbba08fSrick subfile(xfile));
4242cbba08fSrick cleanup(1);
4252cbba08fSrick }
42652081424Ssam while (fgets(buf, BUFSIZ, xfp) != NULL) {
42752081424Ssam if (buf[0] != X_RQDFILE)
42852081424Ssam continue;
42952081424Ssam sscanf(&buf[1], "%s", file);
43052081424Ssam unlink(subfile(file));
43152081424Ssam }
43252081424Ssam unlink(subfile(xfile));
43352081424Ssam fclose(xfp);
4342f96a7e7Sralph
4352f96a7e7Sralph /* rescan X. for new work every RECHECKTIME seconds */
4362f96a7e7Sralph time(&xnow);
4372f96a7e7Sralph if (xnow > (xstart + RECHECKTIME)) {
4382f96a7e7Sralph extern int Nfiles;
4392f96a7e7Sralph Nfiles = 0; /*force rescan for new work */
4402f96a7e7Sralph }
4412f96a7e7Sralph xstart = xnow;
44252081424Ssam }
44352081424Ssam
44452081424Ssam if (stcico)
44552081424Ssam xuucico("");
44652081424Ssam cleanup(0);
44752081424Ssam }
44852081424Ssam
44952081424Ssam
cleanup(code)45052081424Ssam cleanup(code)
45152081424Ssam int code;
45252081424Ssam {
45352081424Ssam logcls();
45452081424Ssam rmlock(CNULL);
455e21537dbSralph #ifdef VMS
456e21537dbSralph /*
457e21537dbSralph * Since we run as a BATCH job we must wait for all processes to
458e21537dbSralph * to finish
459e21537dbSralph */
4602f96a7e7Sralph while(wait(0) != -1)
4612f96a7e7Sralph ;
462e21537dbSralph #endif VMS
46352081424Ssam exit(code);
46452081424Ssam }
46552081424Ssam
46652081424Ssam
4672f96a7e7Sralph /*
4682f96a7e7Sralph * get a file to execute
46952081424Ssam *
47052081424Ssam * return codes: 0 - no file | 1 - file to execute
47152081424Ssam */
47252081424Ssam
gtxfile(file)47352081424Ssam gtxfile(file)
47452081424Ssam register char *file;
47552081424Ssam {
47652081424Ssam char pre[3];
4772bba3b8bSrick register int rechecked, i;
478e21537dbSralph time_t ystrdy; /* yesterday */
479e21537dbSralph struct stat stbuf; /* for X file age */
48052081424Ssam
48152081424Ssam pre[0] = XQTPRE;
48252081424Ssam pre[1] = '.';
48352081424Ssam pre[2] = '\0';
48452081424Ssam rechecked = 0;
48552081424Ssam retry:
4862bba3b8bSrick if (Nfiles-- <= 0) {
4872bba3b8bSrick Nfiles = 0;
48852081424Ssam if (rechecked)
489e21537dbSralph return 0;
49052081424Ssam rechecked = 1;
491e21537dbSralph DEBUG(4, "iswrk\n", CNULL);
4922bba3b8bSrick return iswrk(file, "get", Spool, pre);
49352081424Ssam }
4942bba3b8bSrick sprintf(file, "%s/%s", Spool, Filent[0]);
4952bba3b8bSrick for (i=0; i<Nfiles;i++)
4962bba3b8bSrick strcpy(Filent[i], Filent[i+1]);
4972bba3b8bSrick
49852081424Ssam DEBUG(4, "file - %s\n", file);
49952081424Ssam /* skip spurious subdirectories */
50052081424Ssam if (strcmp(pre, file) == SAME)
50152081424Ssam goto retry;
50252081424Ssam if (gotfiles(file))
503e21537dbSralph return 1;
504e21537dbSralph /* check for old X. file with no work files and remove them. */
505e21537dbSralph if (Nfiles > LLEN/2) {
506e21537dbSralph time(&ystrdy);
507e21537dbSralph ystrdy -= (4 * 3600L); /* 4 hours ago */
508e21537dbSralph DEBUG(4, "gtxfile: Nfiles > LLEN/2\n", CNULL);
5092bba3b8bSrick while (Nfiles-- > 0) {
5102bba3b8bSrick sprintf(file, "%s/%s", Spool, Filent[0]);
5112bba3b8bSrick for (i=0; i<Nfiles; i++)
5122bba3b8bSrick strcpy(Filent[i], Filent[i+1]);
5132bba3b8bSrick
5142bba3b8bSrick if (gotfiles(file))
5152bba3b8bSrick return 1;
516e21537dbSralph if (stat(subfile(file), &stbuf) == 0)
517e21537dbSralph if (stbuf.st_mtime <= ystrdy) {
518e21537dbSralph char *bnp, cfilename[NAMESIZE];
519e21537dbSralph DEBUG(4, "gtxfile: move %s to CORRUPT \n", file);
5202bba3b8bSrick bnp = rindex(file, '/');
521e21537dbSralph sprintf(cfilename, "%s/%s", CORRUPT,
5222bba3b8bSrick bnp ? bnp + 1 : file);
5232bba3b8bSrick xmv(file, cfilename);
5242cbba08fSrick syslog(LOG_WARNING, "%s: X. FILE MISSING FILES", file);
525e21537dbSralph }
526e21537dbSralph }
5272bba3b8bSrick Nfiles = 0;
528e21537dbSralph DEBUG(4, "iswrk\n", CNULL);
529e21537dbSralph if (!iswrk(file, "get", Spool, pre))
530e21537dbSralph return 0;
531e21537dbSralph }
53252081424Ssam goto retry;
53352081424Ssam }
53452081424Ssam
5352f96a7e7Sralph /*
5362f96a7e7Sralph * check for needed files
53752081424Ssam *
53852081424Ssam * return codes: 0 - not ready | 1 - all files ready
53952081424Ssam */
54052081424Ssam
gotfiles(file)54152081424Ssam gotfiles(file)
54252081424Ssam register char *file;
54352081424Ssam {
54452081424Ssam struct stat stbuf;
54552081424Ssam register FILE *fp;
54652081424Ssam char buf[BUFSIZ], rqfile[MAXFULLNAME];
54752081424Ssam
54852081424Ssam fp = fopen(subfile(file), "r");
54952081424Ssam if (fp == NULL)
550e21537dbSralph return 0;
55152081424Ssam
55252081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) {
55352081424Ssam DEBUG(4, "%s\n", buf);
55452081424Ssam if (buf[0] != X_RQDFILE)
55552081424Ssam continue;
55652081424Ssam sscanf(&buf[1], "%s", rqfile);
55752081424Ssam expfile(rqfile);
55852081424Ssam if (stat(subfile(rqfile), &stbuf) == -1) {
55952081424Ssam fclose(fp);
560e21537dbSralph return 0;
56152081424Ssam }
56252081424Ssam }
56352081424Ssam
56452081424Ssam fclose(fp);
565e21537dbSralph return 1;
56652081424Ssam }
56752081424Ssam
56852081424Ssam
5692f96a7e7Sralph /*
5702f96a7e7Sralph * remove execute files to x-directory
57152081424Ssam */
57252081424Ssam
rmxfiles(xfile)57352081424Ssam rmxfiles(xfile)
57452081424Ssam register char *xfile;
57552081424Ssam {
57652081424Ssam register FILE *fp;
57752081424Ssam char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE];
57852081424Ssam char tfull[MAXFULLNAME];
57952081424Ssam
58052081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL)
58152081424Ssam return;
58252081424Ssam
58352081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) {
58452081424Ssam if (buf[0] != X_RQDFILE)
58552081424Ssam continue;
58652081424Ssam if (sscanf(&buf[1], "%s%s", file, tfile) < 2)
58752081424Ssam continue;
58852081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile);
58952081424Ssam unlink(subfile(tfull));
59052081424Ssam }
59152081424Ssam fclose(fp);
59252081424Ssam return;
59352081424Ssam }
59452081424Ssam
59552081424Ssam
5962f96a7e7Sralph /*
5972f96a7e7Sralph * move execute files to x-directory
59852081424Ssam */
59952081424Ssam
mvxfiles(xfile)60052081424Ssam mvxfiles(xfile)
60152081424Ssam char *xfile;
60252081424Ssam {
60352081424Ssam register FILE *fp;
60452081424Ssam char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE];
60552081424Ssam char tfull[MAXFULLNAME];
60652081424Ssam
60752081424Ssam if((fp = fopen(subfile(xfile), "r")) == NULL)
60852081424Ssam return;
60952081424Ssam
61052081424Ssam while (fgets(buf, BUFSIZ, fp) != NULL) {
61152081424Ssam if (buf[0] != X_RQDFILE)
61252081424Ssam continue;
61352081424Ssam if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2)
61452081424Ssam continue;
61552081424Ssam expfile(ffile);
61652081424Ssam sprintf(tfull, "%s/%s", XQTDIR, tfile);
61752081424Ssam unlink(subfile(tfull));
6182cbba08fSrick if (xmv(ffile, tfull) != 0) {
6192cbba08fSrick syslog(LOG_WARNING, "xmv(%s,%s) failed: %m",
6202cbba08fSrick ffile, tfull);
6212cbba08fSrick cleanup(1);
6222cbba08fSrick }
62352081424Ssam }
62452081424Ssam fclose(fp);
62552081424Ssam }
62652081424Ssam
6272f96a7e7Sralph /*
6282f96a7e7Sralph * check for valid command/argument
6292f96a7e7Sralph * *NOTE - side effect is to set xc to the command to be executed.
63052081424Ssam *
63152081424Ssam * return 0 - ok | 1 nok
63252081424Ssam */
63352081424Ssam
argok(xc,cmd)63452081424Ssam argok(xc, cmd)
63552081424Ssam register char *xc, *cmd;
63652081424Ssam {
63752081424Ssam register char **ptr;
63852081424Ssam
63952081424Ssam #ifndef ALLOK
6402f96a7e7Sralph if (strpbrk(cmd, BADCHARS) != NULL) {
641e21537dbSralph DEBUG(1,"MAGIC CHARACTER FOUND\n", CNULL);
6422f96a7e7Sralph logent(cmd, "NASTY MAGIC CHARACTER FOUND");
643e21537dbSralph return FAIL;
644e21537dbSralph }
645e21537dbSralph #endif !ALLOK
64652081424Ssam
64752081424Ssam if (xc[0] != '\0')
648e21537dbSralph return SUCCESS;
64952081424Ssam
65052081424Ssam #ifndef ALLOK
65152081424Ssam ptr = Cmds;
652e21537dbSralph DEBUG(9, "Compare %s and\n", cmd);
65352081424Ssam while(*ptr != NULL) {
654e21537dbSralph DEBUG(9, "\t%s\n", *ptr);
65552081424Ssam if (strcmp(cmd, *ptr) == SAME)
65652081424Ssam break;
65752081424Ssam ptr++;
65852081424Ssam }
659e21537dbSralph if (*ptr == NULL) {
660e21537dbSralph DEBUG(1,"COMMAND NOT FOUND\n", CNULL);
661e21537dbSralph return FAIL;
662e21537dbSralph }
66352081424Ssam #endif
66452081424Ssam strcpy(xc, cmd);
665e21537dbSralph DEBUG(9, "MATCHED %s\n", xc);
666e21537dbSralph return SUCCESS;
66752081424Ssam }
66852081424Ssam
66952081424Ssam
6702f96a7e7Sralph /*
6712f96a7e7Sralph * if notification should be sent for successful execution of cmd
672e21537dbSralph *
673e21537dbSralph * return NT_YES - do notification
674e21537dbSralph * NT_ERR - do notification if exit status != 0
675e21537dbSralph * NT_NO - don't do notification ever
676e21537dbSralph */
677e21537dbSralph
chknotify(cmd)678e21537dbSralph chknotify(cmd)
679e21537dbSralph char *cmd;
680e21537dbSralph {
681e21537dbSralph register char **ptr;
682e21537dbSralph register int *nptr;
683e21537dbSralph
684e21537dbSralph ptr = Cmds;
685e21537dbSralph nptr = Notify;
686e21537dbSralph while (*ptr != NULL) {
687e21537dbSralph if (strcmp(cmd, *ptr) == SAME)
688e21537dbSralph return *nptr;
689e21537dbSralph ptr++;
690e21537dbSralph nptr++;
691e21537dbSralph }
692e21537dbSralph return NT_YES; /* "shouldn't happen" */
693e21537dbSralph }
694e21537dbSralph
695e21537dbSralph
696e21537dbSralph
6972f96a7e7Sralph /*
6982f96a7e7Sralph * send mail to user giving execution results
69952081424Ssam */
70052081424Ssam
notify(user,rmt,cmd,str)70152081424Ssam notify(user, rmt, cmd, str)
70252081424Ssam char *user, *rmt, *cmd, *str;
70352081424Ssam {
7042bba3b8bSrick char text[BUFSIZ*2];
70552081424Ssam char ruser[MAXFULLNAME];
70652081424Ssam
707bd1b9349Sbloom if (strpbrk(user, BADCHARS) != NULL) {
708bd1b9349Sbloom char lbuf[MAXFULLNAME];
709bd1b9349Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user);
710bd1b9349Sbloom logent(cmd, lbuf);
711bd1b9349Sbloom strcpy(user, "postmaster");
712bd1b9349Sbloom }
713e21537dbSralph sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str);
71452081424Ssam if (prefix(rmt, Myname))
71552081424Ssam strcpy(ruser, user);
71652081424Ssam else
71752081424Ssam sprintf(ruser, "%s!%s", rmt, user);
718e21537dbSralph mailst(ruser, text, CNULL);
71952081424Ssam }
72052081424Ssam
7212f96a7e7Sralph /*
7222f96a7e7Sralph * return mail to sender
72352081424Ssam *
72452081424Ssam */
retosndr(user,rmt,file)72552081424Ssam retosndr(user, rmt, file)
72652081424Ssam char *user, *rmt, *file;
72752081424Ssam {
728e21537dbSralph char ruser[MAXFULLNAME];
72952081424Ssam
730bd1b9349Sbloom if (strpbrk(user, BADCHARS) != NULL) {
731bd1b9349Sbloom char lbuf[MAXFULLNAME];
732bd1b9349Sbloom sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user);
733bd1b9349Sbloom logent(file, lbuf);
734bd1b9349Sbloom strcpy(user, "postmaster");
735bd1b9349Sbloom }
73652081424Ssam if (strcmp(rmt, Myname) == SAME)
73752081424Ssam strcpy(ruser, user);
73852081424Ssam else
73952081424Ssam sprintf(ruser, "%s!%s", rmt, user);
74052081424Ssam
74152081424Ssam if (anyread(file) == 0)
74252081424Ssam mailst(ruser, "Mail failed. Letter returned to sender.\n", file);
74352081424Ssam else
744e21537dbSralph mailst(ruser, "Mail failed. Letter returned to sender.\n", CNULL);
74552081424Ssam return;
74652081424Ssam }
747dbb6249cSralph
748dbb6249cSralph /*
7492f96a7e7Sralph * execute shell of command with fi and fo as standard input/output
7502f96a7e7Sralph */
7512f96a7e7Sralph
shio(cmd,fi,fo)7522f96a7e7Sralph shio(cmd, fi, fo)
7532f96a7e7Sralph char *cmd, *fi, *fo;
7542f96a7e7Sralph {
7552f96a7e7Sralph int status, f;
7562cbba08fSrick int pid, ret;
7572bba3b8bSrick char *args[256];
7582f96a7e7Sralph extern int errno;
7592f96a7e7Sralph
7602f96a7e7Sralph if (fi == NULL)
7612f96a7e7Sralph fi = DEVNULL;
7622f96a7e7Sralph if (fo == NULL)
7632f96a7e7Sralph fo = DEVNULL;
7642f96a7e7Sralph
7652bba3b8bSrick getargs(cmd, args, 256);
7662f96a7e7Sralph DEBUG(3, "shio - %s\n", cmd);
7672f96a7e7Sralph #ifdef SIGCHLD
7682f96a7e7Sralph signal(SIGCHLD, SIG_IGN);
7692f96a7e7Sralph #endif SIGCHLD
7702f96a7e7Sralph if ((pid = fork()) == 0) {
7712f96a7e7Sralph signal(SIGINT, SIG_IGN);
7722f96a7e7Sralph signal(SIGHUP, SIG_IGN);
7732f96a7e7Sralph signal(SIGQUIT, SIG_IGN);
7742f96a7e7Sralph close(Ifn);
7752f96a7e7Sralph close(Ofn);
7762f96a7e7Sralph close(0);
7772f96a7e7Sralph setuid(getuid());
7782f96a7e7Sralph f = open(subfile(fi), 0);
7792f96a7e7Sralph if (f != 0) {
7802f96a7e7Sralph logent(fi, "CAN'T READ");
7812f96a7e7Sralph exit(-errno);
7822f96a7e7Sralph }
7832f96a7e7Sralph close(1);
7842f96a7e7Sralph f = creat(subfile(fo), 0666);
7852f96a7e7Sralph if (f != 1) {
7862f96a7e7Sralph logent(fo, "CAN'T WRITE");
7872f96a7e7Sralph exit(-errno);
7882f96a7e7Sralph }
7892f96a7e7Sralph execvp(args[0], args);
7902f96a7e7Sralph exit(100+errno);
7912f96a7e7Sralph }
7922f96a7e7Sralph while ((ret = wait(&status)) != pid && ret != -1)
7932f96a7e7Sralph ;
7942f96a7e7Sralph DEBUG(3, "status %d\n", status);
7952f96a7e7Sralph return status;
7962f96a7e7Sralph }
797