xref: /csrg-svn/usr.bin/uucp/uuxqt/uuxqt.c (revision 18628)
113697Ssam #ifndef lint
2*18628Sralph static char sccsid[] = "@(#)uuxqt.c	5.5 (Berkeley) 04/10/85";
313697Ssam #endif
413697Ssam 
513697Ssam #include "uucp.h"
613697Ssam #include <sys/stat.h>
713697Ssam #ifdef	NDIR
813697Ssam #include "ndir.h"
913697Ssam #else
1013702Ssam #include <sys/dir.h>
1113697Ssam #endif
1217846Sralph #include <signal.h>
1313697Ssam 
14*18628Sralph #define BADCHARS	"&^|(`\\<>;\"{}\n'"
15*18628Sralph #define RECHECKTIME	60*10	/* 10 minutes */
1617870Sralph 
1713697Ssam #define APPCMD(d) {\
1813697Ssam char *p;\
1917846Sralph for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';}
2013697Ssam 
2113697Ssam /*
2213697Ssam  *	uuxqt will execute commands set up by a uux command,
2313697Ssam  *	usually from a remote machine - set by uucp.
2413697Ssam  */
2513697Ssam 
2613697Ssam #define	NCMDS	50
2717846Sralph char *Cmds[NCMDS+1];
2817846Sralph int Notify[NCMDS+1];
2917846Sralph #define	NT_YES	0	/* if should notify on execution */
3017846Sralph #define	NT_ERR	1	/* if should notify if non-zero exit status (-z equivalent) */
3117846Sralph #define	NT_NO	2	/* if should not notify ever (-n equivalent) */
3213697Ssam 
3317846Sralph extern int Nfiles;
34*18628Sralph char *strpbrk();
3517846Sralph 
36*18628Sralph int TransferSucceeded = 1;
3713697Ssam int notiok = 1;
3813697Ssam int nonzero = 0;
3913697Ssam 
40*18628Sralph char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin:/usr/ucb";
41*18628Sralph char Shell[MAXFULLNAME];
42*18628Sralph char HOME[MAXFULLNAME];
4317846Sralph 
44*18628Sralph extern char **environ;
45*18628Sralph char *nenv[] = {
46*18628Sralph 	PATH,
47*18628Sralph 	Shell,
48*18628Sralph 	HOME,
49*18628Sralph 	0
50*18628Sralph };
5117846Sralph 
5213697Ssam /*  to remove restrictions from uuxqt
5313697Ssam  *  define ALLOK 1
5413697Ssam  *
5513697Ssam  *  to add allowable commands, add to the file CMDFILE
5613697Ssam  *  A line of form "PATH=..." changes the search path
5713697Ssam  */
5813697Ssam main(argc, argv)
5913697Ssam char *argv[];
6013697Ssam {
6113697Ssam 	char xcmd[MAXFULLNAME];
6213697Ssam 	int argnok;
6317846Sralph 	int notiflg;
6417846Sralph 	char xfile[MAXFULLNAME], user[MAXFULLNAME], buf[BUFSIZ];
6517846Sralph 	char lbuf[MAXFULLNAME];
6613697Ssam 	char cfile[NAMESIZE], dfile[MAXFULLNAME];
6713697Ssam 	char file[NAMESIZE];
6813697Ssam 	char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME];
6913697Ssam 	register FILE *xfp, *fp;
7013697Ssam 	FILE *dfp;
7113697Ssam 	char path[MAXFULLNAME];
7213697Ssam 	char cmd[BUFSIZ];
7313697Ssam 	char *cmdp, prm[1000], *ptr;
7413697Ssam 	char *getprm(), *lastpart();
7517846Sralph 	int uid, ret, ret2, badfiles;
7613697Ssam 	register int i;
7713697Ssam 	int stcico = 0;
78*18628Sralph 	time_t xstart, xnow;
7913697Ssam 	char retstat[30];
80*18628Sralph 	char **ep;
8113697Ssam 
8213697Ssam 	strcpy(Progname, "uuxqt");
8313697Ssam 	uucpname(Myname);
8413697Ssam 
8513697Ssam 	umask(WFMASK);
8613697Ssam 	Ofn = 1;
8713697Ssam 	Ifn = 0;
8813697Ssam 	while (argc>1 && argv[1][0] == '-') {
8913697Ssam 		switch(argv[1][1]){
9013697Ssam 		case 'x':
9117846Sralph 			chkdebug();
9213697Ssam 			Debug = atoi(&argv[1][2]);
9313697Ssam 			if (Debug <= 0)
9413697Ssam 				Debug = 1;
9513697Ssam 			break;
9613697Ssam 		default:
9713697Ssam 			fprintf(stderr, "unknown flag %s\n", argv[1]);
9813697Ssam 				break;
9913697Ssam 		}
10013697Ssam 		--argc;  argv++;
10113697Ssam 	}
10213697Ssam 
103*18628Sralph 	DEBUG(4, "\n\n** START **\n", CNULL);
10417846Sralph 	ret = subchdir(Spool);
10517846Sralph 	ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
10613697Ssam 	strcpy(Wrkdir, Spool);
10713697Ssam 	uid = getuid();
10813697Ssam 	guinfo(uid, User, path);
10917846Sralph 	setgid(getegid());
11017846Sralph 	setuid(geteuid());
11117846Sralph 
11213697Ssam 	DEBUG(4, "User - %s\n", User);
11313697Ssam 	if (ulockf(X_LOCK, (time_t)  X_LOCKTIME) != 0)
11413697Ssam 		exit(0);
11513697Ssam 
11613697Ssam 	fp = fopen(CMDFILE, "r");
11713697Ssam 	if (fp == NULL) {
11817846Sralph 		logent(CANTOPEN, CMDFILE);
11913697Ssam 		Cmds[0] = "rmail";
12013697Ssam 		Cmds[1] = "rnews";
12113697Ssam 		Cmds[2] = "ruusend";
12213697Ssam 		Cmds[3] = NULL;
12313697Ssam 		goto doprocess;
12413697Ssam 	}
12513697Ssam 	DEBUG(5, "%s opened\n", CMDFILE);
12617846Sralph 	for (i=0; i<NCMDS && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) {
12717846Sralph 		int j;
12817846Sralph 		/* strip trailing whitespace */
12917846Sralph 		for (j = strlen(xcmd)-1; j >= 0; --j)
13017846Sralph 			if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t')
13117846Sralph 				xcmd[j] = '\0';
13217846Sralph 			else
13317846Sralph 				break;
13417846Sralph 		/* look for imbedded whitespace */
13517846Sralph 		for (; j >= 0; --j)
13617846Sralph 			if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t')
13717846Sralph 				break;
13817846Sralph 		/* skip this entry if it has embedded whitespace */
13917846Sralph 		/* This defends against a bad PATH=, for example */
14017846Sralph 		if (j >= 0) {
14117846Sralph 			logent(xcmd, "BAD WHITESPACE");
14217846Sralph 			continue;
14317846Sralph 		}
14413697Ssam 		if (strncmp(xcmd, "PATH=", 5) == 0) {
14513697Ssam 			strcpy(PATH, xcmd);
14617846Sralph 			i--;	/*kludge */
14713697Ssam 			continue;
14813697Ssam 		}
14913697Ssam 		DEBUG(5, "xcmd = %s\n", xcmd);
15017846Sralph 
15117846Sralph 		if ((ptr = index(xcmd, ',')) != NULL) {
15217846Sralph 			*ptr++ = '\0';
15317846Sralph 			if (strncmp(ptr, "Err", 3) == SAME)
15417846Sralph 				Notify[i] = NT_ERR;
15517846Sralph 			else if (strcmp(ptr, "No") == SAME)
15617846Sralph 				Notify[i] = NT_NO;
15717846Sralph 			else
15817846Sralph 				Notify[i] = NT_YES;
15917846Sralph 		} else
16017846Sralph 			Notify[i] = NT_YES;
16117846Sralph 		if ((Cmds[i] = malloc((unsigned)(strlen(xcmd)+1))) == NULL) {
16217846Sralph 			DEBUG(1, "MALLOC FAILED", CNULL);
16317846Sralph 			break;
16417846Sralph 		}
16513697Ssam 		strcpy(Cmds[i], xcmd);
16613697Ssam 	}
16717846Sralph 	Cmds[i] = CNULL;
16813697Ssam 	fclose(fp);
16913697Ssam 
17013697Ssam doprocess:
171*18628Sralph 
172*18628Sralph 	(void) sprintf(HOME, "HOME=%s", Spool);
173*18628Sralph 	(void) sprintf(Shell, "SHELL=%s", SHELL);
174*18628Sralph 	environ = nenv; /* force use if our environment */
175*18628Sralph 
176*18628Sralph 	DEBUG(11,"path = %s\n", getenv("PATH"));
177*18628Sralph 
17817846Sralph 	DEBUG(4, "process %s\n", CNULL);
179*18628Sralph 	time(&xstart);
18013697Ssam 	while (gtxfile(xfile) > 0) {
18117846Sralph 		ultouch();
18217846Sralph 		/* if /etc/nologin exists, exit cleanly */
18317846Sralph 		if (nologinflag) {
18417846Sralph 			logent(NOLOGIN, "UUXQT SHUTDOWN");
18517846Sralph 			if (Debug)
18617846Sralph 				logent("debugging", "continuing anyway");
18717846Sralph 			else
18817846Sralph 				break;
18917846Sralph 		}
19013697Ssam 		DEBUG(4, "xfile - %s\n", xfile);
19113697Ssam 
19213697Ssam 		xfp = fopen(subfile(xfile), "r");
19317846Sralph 		ASSERT(xfp != NULL, CANTOPEN, xfile, 0);
19413697Ssam 
19513697Ssam 		/*  initialize to default  */
19613697Ssam 		strcpy(user, User);
19717846Sralph 		strcpy(fin, DEVNULL);
19817846Sralph 		strcpy(fout, DEVNULL);
19913697Ssam 		sprintf(sysout, "%.7s", Myname);
20017846Sralph 		badfiles = 0;
20113697Ssam 		while (fgets(buf, BUFSIZ, xfp) != NULL) {
20213697Ssam 			switch (buf[0]) {
20313697Ssam 			case X_USER:
20417846Sralph 				sscanf(&buf[1], "%s %s", user, Rmtname);
20513697Ssam 				break;
20617846Sralph 			case X_RETURNTO:
20717846Sralph 				sscanf(&buf[1], "%s", user);
20817846Sralph 				break;
20913697Ssam 			case X_STDIN:
21013697Ssam 				sscanf(&buf[1], "%s", fin);
21113697Ssam 				i = expfile(fin);
21213697Ssam 				/* rti!trt: do not check permissions of
21313697Ssam 				 * vanilla spool file */
21413697Ssam 				if (i != 0
21513697Ssam 				 && (chkpth("", "", fin) || anyread(fin) != 0))
21613697Ssam 					badfiles = 1;
21713697Ssam 				break;
21813697Ssam 			case X_STDOUT:
21913697Ssam 				sscanf(&buf[1], "%s%s", fout, sysout);
22013697Ssam 				sysout[7] = '\0';
22113697Ssam 				/* rti!trt: do not check permissions of
22213697Ssam 				 * vanilla spool file.  DO check permissions
22313697Ssam 				 * of writing on a non-vanilla file */
22413697Ssam 				i = 1;
22513697Ssam 				if (fout[0] != '~' || prefix(sysout, Myname))
22613697Ssam 					i = expfile(fout);
22713697Ssam 				if (i != 0
22813697Ssam 				 && (chkpth("", "", fout)
22913697Ssam 					|| chkperm(fout, (char *)1)))
23013697Ssam 					badfiles = 1;
23113697Ssam 				break;
23213697Ssam 			case X_CMD:
23313697Ssam 				strcpy(cmd, &buf[2]);
23413697Ssam 				if (*(cmd + strlen(cmd) - 1) == '\n')
23513697Ssam 					*(cmd + strlen(cmd) - 1) = '\0';
23613697Ssam 				break;
23713697Ssam 			case X_NONOTI:
23813697Ssam 				notiok = 0;
23913697Ssam 				break;
24013697Ssam 			case X_NONZERO:
24113697Ssam 				nonzero = 1;
24213697Ssam 				break;
24313697Ssam 			default:
24413697Ssam 				break;
24513697Ssam 			}
24613697Ssam 		}
24713697Ssam 
24813697Ssam 		fclose(xfp);
24913697Ssam 		DEBUG(4, "fin - %s, ", fin);
25013697Ssam 		DEBUG(4, "fout - %s, ", fout);
25113697Ssam 		DEBUG(4, "sysout - %s, ", sysout);
25213697Ssam 		DEBUG(4, "user - %s\n", user);
25313697Ssam 		DEBUG(4, "cmd - %s\n", cmd);
25413697Ssam 
25513697Ssam 		/*  command execution  */
25617846Sralph 		if (strcmp(fout, DEVNULL) == SAME)
25717846Sralph 			strcpy(dfile,DEVNULL);
25813697Ssam 		else
25913697Ssam 			gename(DATAPRE, sysout, 'O', dfile);
26013697Ssam 
26113697Ssam 		/* expand file names where necessary */
26213697Ssam 		expfile(dfile);
263*18628Sralph 		cmdp = buf;
26413697Ssam 		ptr = cmd;
26513697Ssam 		xcmd[0] = '\0';
26613697Ssam 		argnok = 0;
26713697Ssam 		while ((ptr = getprm(ptr, prm)) != NULL) {
26813697Ssam 			if (prm[0] == ';' || prm[0] == '^'
26913697Ssam 			  || prm[0] == '&'  || prm[0] == '|') {
27013697Ssam 				xcmd[0] = '\0';
27113697Ssam 				APPCMD(prm);
27213697Ssam 				continue;
27313697Ssam 			}
27413697Ssam 
27517846Sralph 			if ((argnok = argok(xcmd, prm)) != SUCCESS)
27613697Ssam 				/*  command not valid  */
27713697Ssam 				break;
27813697Ssam 
27913697Ssam 			if (prm[0] == '~')
28013697Ssam 				expfile(prm);
28113697Ssam 			APPCMD(prm);
28213697Ssam 		}
28317846Sralph 		/*
28417846Sralph 		 * clean up trailing ' ' in command.
28517846Sralph 		 */
28617846Sralph 		if (cmdp > buf && cmdp[0] == '\0' && cmdp[-1] == ' ')
28717846Sralph 			*--cmdp = '\0';
288*18628Sralph 		if (strpbrk(user, BADCHARS) != NULL) {
28917870Sralph 			sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user);
29017870Sralph 			logent(cmd, lbuf);
29117870Sralph 			strcpy(user, "postmaster");
29217870Sralph 		}
29313697Ssam 		if (argnok || badfiles) {
29413697Ssam 			sprintf(lbuf, "%s XQT DENIED", user);
29513697Ssam 			logent(cmd, lbuf);
29613697Ssam 			DEBUG(4, "bad command %s\n", prm);
29713697Ssam 			notify(user, Rmtname, cmd, "DENIED");
29813697Ssam 			goto rmfiles;
29913697Ssam 		}
30013697Ssam 		sprintf(lbuf, "%s XQT", user);
30113697Ssam 		logent(buf, lbuf);
30213697Ssam 		DEBUG(4, "cmd %s\n", buf);
30313697Ssam 
30413697Ssam 		mvxfiles(xfile);
30517846Sralph 		ret = subchdir(XQTDIR);
30617846Sralph 		ASSERT(ret >= 0, "CHDIR FAILED", XQTDIR, ret);
307*18628Sralph 		ret = shio(buf, fin, dfile);
30813697Ssam 		sprintf(retstat, "signal %d, exit %d", ret & 0377,
30913697Ssam 		  (ret>>8) & 0377);
31013697Ssam 		if (strcmp(xcmd, "rmail") == SAME)
31113697Ssam 			notiok = 0;
31213697Ssam 		if (strcmp(xcmd, "rnews") == SAME)
31313697Ssam 			nonzero = 1;
31417846Sralph 		notiflg = chknotify(xcmd);
31517846Sralph 		if (notiok && notiflg != NT_NO &&
31617846Sralph 		   (ret != 0 || (!nonzero && notiflg == NT_YES)))
31713697Ssam 			notify(user, Rmtname, cmd, retstat);
31813697Ssam 		else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) {
31913697Ssam 			/* mail failed - return letter to sender  */
32017846Sralph #ifdef	DANGEROUS
32117846Sralph 			/* NOT GUARANTEED SAFE!!! */
32217846Sralph 			if (!nonzero)
32317846Sralph 				retosndr(user, Rmtname, fin);
32417846Sralph #else
32517846Sralph 			notify(user, Rmtname, cmd, retstat);
32617846Sralph #endif
32717846Sralph 			sprintf(buf, "%s (%s) from %s!%s", buf, retstat, Rmtname, user);
32813697Ssam 			logent("MAIL FAIL", buf);
32913697Ssam 		}
33013697Ssam 		DEBUG(4, "exit cmd - %d\n", ret);
33117846Sralph 		ret2 = subchdir(Spool);
33217846Sralph 		ASSERT(ret2 >= 0, "CHDIR FAILED", Spool, ret);
33313697Ssam 		rmxfiles(xfile);
33413697Ssam 		if (ret != 0) {
33513697Ssam 			/*  exit status not zero */
33613697Ssam 			dfp = fopen(subfile(dfile), "a");
33717846Sralph 			ASSERT(dfp != NULL, CANTOPEN, dfile, 0);
33813697Ssam 			fprintf(dfp, "exit status %d", ret);
33913697Ssam 			fclose(dfp);
34013697Ssam 		}
34117846Sralph 		if (strcmp(fout, DEVNULL) != SAME) {
34213697Ssam 			if (prefix(sysout, Myname)) {
34313697Ssam 				xmv(dfile, fout);
34413697Ssam 				chmod(fout, BASEMODE);
345*18628Sralph 			} else {
34617846Sralph 				char *cp = rindex(user, '!');
34713697Ssam 				gename(CMDPRE, sysout, 'O', cfile);
34813697Ssam 				fp = fopen(subfile(cfile), "w");
34913697Ssam 				ASSERT(fp != NULL, "OPEN", cfile, 0);
35017846Sralph 				fprintf(fp, "S %s %s %s - %s 0666\n", dfile,
35117846Sralph 					fout, cp ? cp : user, lastpart(dfile));
35213697Ssam 				fclose(fp);
35313697Ssam 			}
35413697Ssam 		}
35513697Ssam 	rmfiles:
35613697Ssam 		xfp = fopen(subfile(xfile), "r");
35717846Sralph 		ASSERT(xfp != NULL, CANTOPEN, xfile, 0);
35813697Ssam 		while (fgets(buf, BUFSIZ, xfp) != NULL) {
35913697Ssam 			if (buf[0] != X_RQDFILE)
36013697Ssam 				continue;
36113697Ssam 			sscanf(&buf[1], "%s", file);
36213697Ssam 			unlink(subfile(file));
36313697Ssam 		}
36413697Ssam 		unlink(subfile(xfile));
36513697Ssam 		fclose(xfp);
366*18628Sralph 
367*18628Sralph 		/* rescan X. for new work every RECHECKTIME seconds */
368*18628Sralph 		time(&xnow);
369*18628Sralph 		if (xnow > (xstart + RECHECKTIME)) {
370*18628Sralph 			extern int Nfiles;
371*18628Sralph 			Nfiles = 0; 	/*force rescan for new work */
372*18628Sralph 		}
373*18628Sralph 		xstart = xnow;
37413697Ssam 	}
37513697Ssam 
37613697Ssam 	if (stcico)
37713697Ssam 		xuucico("");
37813697Ssam 	cleanup(0);
37913697Ssam }
38013697Ssam 
38113697Ssam 
38213697Ssam cleanup(code)
38313697Ssam int code;
38413697Ssam {
38513697Ssam 	logcls();
38613697Ssam 	rmlock(CNULL);
38717846Sralph #ifdef	VMS
38817846Sralph 	/*
38917846Sralph 	 *	Since we run as a BATCH job we must wait for all processes to
39017846Sralph 	 *	to finish
39117846Sralph 	 */
392*18628Sralph 	while(wait(0) != -1)
393*18628Sralph 		;
39417846Sralph #endif VMS
39513697Ssam 	exit(code);
39613697Ssam }
39713697Ssam 
39813697Ssam 
399*18628Sralph /*
400*18628Sralph  *	get a file to execute
40113697Ssam  *
40213697Ssam  *	return codes:  0 - no file  |  1 - file to execute
40313697Ssam  */
40413697Ssam 
40513697Ssam gtxfile(file)
40613697Ssam register char *file;
40713697Ssam {
40813697Ssam 	char pre[3];
40917846Sralph 	int rechecked;
41017846Sralph 	time_t ystrdy;		/* yesterday */
41117846Sralph 	extern time_t time();
41217846Sralph 	struct stat stbuf;	/* for X file age */
41313697Ssam 
41413697Ssam 	pre[0] = XQTPRE;
41513697Ssam 	pre[1] = '.';
41613697Ssam 	pre[2] = '\0';
41713697Ssam 	rechecked = 0;
41813697Ssam retry:
41913697Ssam 	if (!gtwrkf(Spool, file)) {
42013697Ssam 		if (rechecked)
42117846Sralph 			return 0;
42213697Ssam 		rechecked = 1;
42317846Sralph 		DEBUG(4, "iswrk\n", CNULL);
42413697Ssam 		if (!iswrk(file, "get", Spool, pre))
42517846Sralph 			return 0;
42613697Ssam 	}
42713697Ssam 	DEBUG(4, "file - %s\n", file);
42813697Ssam 	/* skip spurious subdirectories */
42913697Ssam 	if (strcmp(pre, file) == SAME)
43013697Ssam 		goto retry;
43113697Ssam 	if (gotfiles(file))
43217846Sralph 		return 1;
43317846Sralph 	/* check for old X. file with no work files and remove them. */
43417846Sralph 	if (Nfiles > LLEN/2) {
43517846Sralph 	    time(&ystrdy);
43617846Sralph 	    ystrdy -= (4 * 3600L);		/* 4 hours ago */
43717846Sralph 	    DEBUG(4, "gtxfile: Nfiles > LLEN/2\n", CNULL);
43817846Sralph 	    while (gtwrkf(Spool, file) && !gotfiles(file)) {
43917846Sralph 		if (stat(subfile(file), &stbuf) == 0)
44017846Sralph 		    if (stbuf.st_mtime <= ystrdy) {
44117846Sralph 			char *bnp, cfilename[NAMESIZE];
44217846Sralph 			DEBUG(4, "gtxfile: move %s to CORRUPT \n", file);
44317846Sralph 			unlink(subfile(file));
44417846Sralph 			bnp = rindex(subfile(file), '/');
44517846Sralph 			sprintf(cfilename, "%s/%s", CORRUPT,
44617846Sralph 				bnp ? bnp + 1 : subfile(file));
44717846Sralph 			xmv(subfile(file), cfilename);
44817846Sralph 			logent(file, "X. FILE CORRUPTED");
44917846Sralph 		    }
45017846Sralph 	    }
45117846Sralph 	    DEBUG(4, "iswrk\n", CNULL);
45217846Sralph 	    if (!iswrk(file, "get", Spool, pre))
45317846Sralph 		return 0;
45417846Sralph 	}
45513697Ssam 	goto retry;
45613697Ssam }
45713697Ssam 
458*18628Sralph /*
459*18628Sralph  *	check for needed files
46013697Ssam  *
46113697Ssam  *	return codes:  0 - not ready  |  1 - all files ready
46213697Ssam  */
46313697Ssam 
46413697Ssam gotfiles(file)
46513697Ssam register char *file;
46613697Ssam {
46713697Ssam 	struct stat stbuf;
46813697Ssam 	register FILE *fp;
46913697Ssam 	char buf[BUFSIZ], rqfile[MAXFULLNAME];
47013697Ssam 
47113697Ssam 	fp = fopen(subfile(file), "r");
47213697Ssam 	if (fp == NULL)
47317846Sralph 		return 0;
47413697Ssam 
47513697Ssam 	while (fgets(buf, BUFSIZ, fp) != NULL) {
47613697Ssam 		DEBUG(4, "%s\n", buf);
47713697Ssam 		if (buf[0] != X_RQDFILE)
47813697Ssam 			continue;
47913697Ssam 		sscanf(&buf[1], "%s", rqfile);
48013697Ssam 		expfile(rqfile);
48113697Ssam 		if (stat(subfile(rqfile), &stbuf) == -1) {
48213697Ssam 			fclose(fp);
48317846Sralph 			return 0;
48413697Ssam 		}
48513697Ssam 	}
48613697Ssam 
48713697Ssam 	fclose(fp);
48817846Sralph 	return 1;
48913697Ssam }
49013697Ssam 
49113697Ssam 
492*18628Sralph /*
493*18628Sralph  *	remove execute files to x-directory
49413697Ssam  */
49513697Ssam 
49613697Ssam rmxfiles(xfile)
49713697Ssam register char *xfile;
49813697Ssam {
49913697Ssam 	register FILE *fp;
50013697Ssam 	char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE];
50113697Ssam 	char tfull[MAXFULLNAME];
50213697Ssam 
50313697Ssam 	if((fp = fopen(subfile(xfile), "r")) == NULL)
50413697Ssam 		return;
50513697Ssam 
50613697Ssam 	while (fgets(buf, BUFSIZ, fp) != NULL) {
50713697Ssam 		if (buf[0] != X_RQDFILE)
50813697Ssam 			continue;
50913697Ssam 		if (sscanf(&buf[1], "%s%s", file, tfile) < 2)
51013697Ssam 			continue;
51113697Ssam 		sprintf(tfull, "%s/%s", XQTDIR, tfile);
51213697Ssam 		unlink(subfile(tfull));
51313697Ssam 	}
51413697Ssam 	fclose(fp);
51513697Ssam 	return;
51613697Ssam }
51713697Ssam 
51813697Ssam 
519*18628Sralph /*
520*18628Sralph  *	move execute files to x-directory
52113697Ssam  */
52213697Ssam 
52313697Ssam mvxfiles(xfile)
52413697Ssam char *xfile;
52513697Ssam {
52613697Ssam 	register FILE *fp;
52713697Ssam 	char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE];
52813697Ssam 	char tfull[MAXFULLNAME];
52913697Ssam 	int ret;
53013697Ssam 
53113697Ssam 	if((fp = fopen(subfile(xfile), "r")) == NULL)
53213697Ssam 		return;
53313697Ssam 
53413697Ssam 	while (fgets(buf, BUFSIZ, fp) != NULL) {
53513697Ssam 		if (buf[0] != X_RQDFILE)
53613697Ssam 			continue;
53713697Ssam 		if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2)
53813697Ssam 			continue;
53913697Ssam 		expfile(ffile);
54013697Ssam 		sprintf(tfull, "%s/%s", XQTDIR, tfile);
54113697Ssam 		unlink(subfile(tfull));
54213697Ssam 		ret = xmv(ffile, tfull);
54317846Sralph 		ASSERT(ret == 0, "XQTDIR ERROR", CNULL, ret);
54413697Ssam 	}
54513697Ssam 	fclose(fp);
54613697Ssam }
54713697Ssam 
548*18628Sralph /*
549*18628Sralph  *	check for valid command/argument
550*18628Sralph  *	*NOTE - side effect is to set xc to the	command to be executed.
55113697Ssam  *
55213697Ssam  *	return 0 - ok | 1 nok
55313697Ssam  */
55413697Ssam 
55513697Ssam argok(xc, cmd)
55613697Ssam register char *xc, *cmd;
55713697Ssam {
55813697Ssam 	register char **ptr;
55913697Ssam 
56013697Ssam #ifndef ALLOK
561*18628Sralph 	if (strpbrk(cmd, BADCHARS) != NULL) {
56217846Sralph 		DEBUG(1,"MAGIC CHARACTER FOUND\n", CNULL);
563*18628Sralph 		logent(cmd, "NASTY MAGIC CHARACTER FOUND");
56417846Sralph 		return FAIL;
56517846Sralph 	}
56617846Sralph #endif !ALLOK
56713697Ssam 
56813697Ssam 	if (xc[0] != '\0')
56917846Sralph 		return SUCCESS;
57013697Ssam 
57113697Ssam #ifndef ALLOK
57213697Ssam 	ptr = Cmds;
57317846Sralph 	DEBUG(9, "Compare %s and\n", cmd);
57413697Ssam 	while(*ptr != NULL) {
57517846Sralph 		DEBUG(9, "\t%s\n", *ptr);
57613697Ssam 		if (strcmp(cmd, *ptr) == SAME)
57713697Ssam 			break;
57817846Sralph 		ptr++;
57913697Ssam 	}
58017846Sralph 	if (*ptr == NULL) {
58117846Sralph 		DEBUG(1,"COMMAND NOT FOUND\n", CNULL);
58217846Sralph 		return FAIL;
58317846Sralph 	}
58413697Ssam #endif
58513697Ssam 	strcpy(xc, cmd);
58617846Sralph 	DEBUG(9, "MATCHED %s\n", xc);
58717846Sralph 	return SUCCESS;
58813697Ssam }
58913697Ssam 
59013697Ssam 
591*18628Sralph /*
592*18628Sralph  *	if notification should be sent for successful execution of cmd
59317846Sralph  *
59417846Sralph  *	return NT_YES - do notification
59517846Sralph  *	       NT_ERR - do notification if exit status != 0
59617846Sralph  *	       NT_NO  - don't do notification ever
59717846Sralph  */
59817846Sralph 
59917846Sralph chknotify(cmd)
60017846Sralph char *cmd;
60117846Sralph {
60217846Sralph 	register char **ptr;
60317846Sralph 	register int *nptr;
60417846Sralph 
60517846Sralph 	ptr = Cmds;
60617846Sralph 	nptr = Notify;
60717846Sralph 	while (*ptr != NULL) {
60817846Sralph 		if (strcmp(cmd, *ptr) == SAME)
60917846Sralph 			return *nptr;
61017846Sralph 		ptr++;
61117846Sralph 		nptr++;
61217846Sralph 	}
61317846Sralph 	return NT_YES;		/* "shouldn't happen" */
61417846Sralph }
61517846Sralph 
61617846Sralph 
61717846Sralph 
618*18628Sralph /*
619*18628Sralph  *	send mail to user giving execution results
62013697Ssam  */
62113697Ssam 
62213697Ssam notify(user, rmt, cmd, str)
62313697Ssam char *user, *rmt, *cmd, *str;
62413697Ssam {
62513697Ssam 	char text[MAXFULLNAME];
62613697Ssam 	char ruser[MAXFULLNAME];
62713697Ssam 
62817846Sralph 	sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str);
62913697Ssam 	if (prefix(rmt, Myname))
63013697Ssam 		strcpy(ruser, user);
63113697Ssam 	else
63213697Ssam 		sprintf(ruser, "%s!%s", rmt, user);
63317846Sralph 	mailst(ruser, text, CNULL);
63413697Ssam 	return;
63513697Ssam }
63613697Ssam 
637*18628Sralph /*
638*18628Sralph  *	return mail to sender
63913697Ssam  *
64013697Ssam  */
64113697Ssam 
64213697Ssam retosndr(user, rmt, file)
64313697Ssam char *user, *rmt, *file;
64413697Ssam {
64517846Sralph 	char ruser[MAXFULLNAME];
64613697Ssam 
64713697Ssam 	if (strcmp(rmt, Myname) == SAME)
64813697Ssam 		strcpy(ruser, user);
64913697Ssam 	else
65013697Ssam 		sprintf(ruser, "%s!%s", rmt, user);
65113697Ssam 
65213697Ssam 	if (anyread(file) == 0)
65313697Ssam 		mailst(ruser, "Mail failed.  Letter returned to sender.\n", file);
65413697Ssam 	else
65517846Sralph 		mailst(ruser, "Mail failed.  Letter returned to sender.\n", CNULL);
65613697Ssam 	return;
65713697Ssam }
65817870Sralph 
65917870Sralph /*
66017870Sralph  * this is like index, but takes a string as the second argument
66117870Sralph  */
66217870Sralph char *
663*18628Sralph strpbrk(str, chars)
66417870Sralph register char *str, *chars;
66517870Sralph {
66617870Sralph 	register char *cp;
66717870Sralph 
66817870Sralph 	do {
66917870Sralph 		cp = chars - 1;
67017870Sralph 		while (*++cp) {
67117870Sralph 			if (*str == *cp)
67217870Sralph 				return str;
67317870Sralph 		}
67417870Sralph 	} while (*str++);
67517870Sralph 	return NULL;
67617870Sralph }
677*18628Sralph 
678*18628Sralph /*
679*18628Sralph  *	execute shell of command with fi and fo as standard input/output
680*18628Sralph  */
681*18628Sralph 
682*18628Sralph shio(cmd, fi, fo)
683*18628Sralph char *cmd, *fi, *fo;
684*18628Sralph {
685*18628Sralph 	int status, f;
686*18628Sralph 	int uid, pid, ret;
687*18628Sralph 	char path[MAXFULLNAME];
688*18628Sralph 	char *args[20];
689*18628Sralph 	extern int errno;
690*18628Sralph 
691*18628Sralph 	if (fi == NULL)
692*18628Sralph 		fi = DEVNULL;
693*18628Sralph 	if (fo == NULL)
694*18628Sralph 		fo = DEVNULL;
695*18628Sralph 
696*18628Sralph 	getargs(cmd, args, 20);
697*18628Sralph 	DEBUG(3, "shio - %s\n", cmd);
698*18628Sralph #ifdef SIGCHLD
699*18628Sralph 	signal(SIGCHLD, SIG_IGN);
700*18628Sralph #endif SIGCHLD
701*18628Sralph 	if ((pid = fork()) == 0) {
702*18628Sralph 		signal(SIGINT, SIG_IGN);
703*18628Sralph 		signal(SIGHUP, SIG_IGN);
704*18628Sralph 		signal(SIGQUIT, SIG_IGN);
705*18628Sralph 		signal(SIGKILL, SIG_IGN);
706*18628Sralph 		close(Ifn);
707*18628Sralph 		close(Ofn);
708*18628Sralph 		close(0);
709*18628Sralph 		setuid(getuid());
710*18628Sralph 		f = open(subfile(fi), 0);
711*18628Sralph 		if (f != 0) {
712*18628Sralph 			logent(fi, "CAN'T READ");
713*18628Sralph 			exit(-errno);
714*18628Sralph 		}
715*18628Sralph 		close(1);
716*18628Sralph 		f = creat(subfile(fo), 0666);
717*18628Sralph 		if (f != 1) {
718*18628Sralph 			logent(fo, "CAN'T WRITE");
719*18628Sralph 			exit(-errno);
720*18628Sralph 		}
721*18628Sralph 		execvp(args[0], args);
722*18628Sralph 		exit(100+errno);
723*18628Sralph 	}
724*18628Sralph 	while ((ret = wait(&status)) != pid && ret != -1)
725*18628Sralph 		;
726*18628Sralph 	DEBUG(3, "status %d\n", status);
727*18628Sralph 	return status;
728*18628Sralph }
729