xref: /original-bsd/usr.bin/uucp/uuxqt/uuxqt.c (revision a92c1dbe)
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