|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)uuxqt.c 5.12 (Berkeley) 5/13/88";
3: #endif
4:
5: #include "uucp.h"
6: #include <sys/stat.h>
7: #ifdef NDIR
8: #include "ndir.h"
9: #else
10: #include <sys/dir.h>
11: #endif
12: #include <signal.h>
13:
14: #define BADCHARS "&^|(`\\<>;\"{}\n'"
15: #define RECHECKTIME 60*10 /* 10 minutes */
16:
17: #define APPCMD(d) {\
18: char *p;\
19: for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';}
20:
21: extern char Filent[LLEN][NAMESIZE];
22:
23: /*
24: * uuxqt will execute commands set up by a uux command,
25: * usually from a remote machine - set by uucp.
26: */
27:
28: #define NCMDS 50
29: char *Cmds[NCMDS+1];
30: int Notify[NCMDS+1];
31: #define NT_YES 0 /* if should notify on execution */
32: #define NT_ERR 1 /* if should notify if non-zero exit status (-z equivalent) */
33: #define NT_NO 2 /* if should not notify ever (-n equivalent) */
34:
35: extern int Nfiles;
36:
37: int TransferSucceeded = 1;
38: int notiok = 1;
39: int nonzero = 0;
40:
41: struct timeb Now;
42:
43: char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin:/usr/ucb";
44: char UU_MACHINE[MAXFULLNAME];
45: char Shell[MAXFULLNAME];
46: char HOME[MAXFULLNAME];
47:
48: extern char **environ;
49: char *nenv[] = {
50: PATH,
51: Shell,
52: HOME,
53: UU_MACHINE,
54: 0
55: };
56:
57: /* to remove restrictions from uuxqt
58: * define ALLOK 1
59: *
60: * to add allowable commands, add to the file CMDFILE
61: * A line of form "PATH=..." changes the search path
62: */
63: main(argc, argv)
64: char *argv[];
65: {
66: char xcmd[BUFSIZ*2];
67: int argnok;
68: int notiflg;
69: char xfile[MAXFULLNAME], user[MAXFULLNAME], buf[BUFSIZ*2];
70: char lbuf[MAXFULLNAME];
71: char cfile[NAMESIZE], dfile[MAXFULLNAME];
72: char file[NAMESIZE];
73: char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME];
74: register FILE *xfp, *fp;
75: FILE *dfp;
76: char path[MAXFULLNAME];
77: char cmd[BUFSIZ*2];
78: char *cmdp, prm[1000], *ptr;
79: char *getprm(), *lastpart();
80: int uid, ret, badfiles;
81: register int i;
82: int stcico = 0;
83: time_t xstart, xnow;
84: char retstat[30];
85: extern char *optarg;
86: extern int optind;
87:
88: strcpy(Progname, "uuxqt");
89: uucpname(Myname);
90: strcpy(Rmtname, Myname);
91:
92: umask(WFMASK);
93: Ofn = 1;
94: Ifn = 0;
95: while ((i = getopt(argc, argv, "x:S:")) != EOF)
96: switch(i) {
97: case 'x':
98: chkdebug();
99: Debug = atoi(optarg);
100: if (Debug <= 0)
101: Debug = 1;
102: break;
103: case 'S':
104: Spool = optarg;
105: DEBUG(1, "Spool set to %s", Spool);
106: break;
107: case '?':
108: default:
109: fprintf(stderr, "unknown flag %s\n", argv[optind-1]);
110: break;
111: }
112:
113: DEBUG(4, "\n\n** START **\n", CNULL);
114: if (subchdir(Spool) < 0) {
115: syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool);
116: cleanup(1);
117: }
118: strcpy(Wrkdir, Spool);
119: uid = getuid();
120: if (guinfo(uid, User, path) != SUCCESS) {
121: syslog(LOG_WARNING, "Can't find username for uid %d", uid);
122: DEBUG(1, "Using username", "uucp");
123: strcpy(User, "uucp");
124: }
125: setgid(getegid());
126: setuid(geteuid());
127:
128: DEBUG(4, "User - %s\n", User);
129: if (ulockf(X_LOCK, X_LOCKTIME) != 0)
130: exit(0);
131:
132: fp = fopen(CMDFILE, "r");
133: if (fp == NULL) {
134: logent(CANTOPEN, CMDFILE);
135: Cmds[0] = "rmail";
136: Cmds[1] = "rnews";
137: Cmds[2] = "ruusend";
138: Cmds[3] = NULL;
139: goto doprocess;
140: }
141: DEBUG(5, "%s opened\n", CMDFILE);
142: for (i=0; i<NCMDS && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) {
143: int j;
144: /* strip trailing whitespace */
145: for (j = strlen(xcmd)-1; j >= 0; --j)
146: if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t')
147: xcmd[j] = '\0';
148: else
149: break;
150: /* look for imbedded whitespace */
151: for (; j >= 0; --j)
152: if (xcmd[j] == '\n' || xcmd[j] == ' ' || xcmd[j] == '\t')
153: break;
154: /* skip this entry if it has embedded whitespace */
155: /* This defends against a bad PATH=, for example */
156: if (j >= 0) {
157: logent(xcmd, "BAD WHITESPACE");
158: continue;
159: }
160: if (strncmp(xcmd, "PATH=", 5) == 0) {
161: strcpy(PATH, xcmd);
162: i--; /*kludge */
163: continue;
164: }
165: DEBUG(5, "xcmd = %s\n", xcmd);
166:
167: if ((ptr = index(xcmd, ',')) != NULL) {
168: *ptr++ = '\0';
169: if (strncmp(ptr, "Err", 3) == SAME)
170: Notify[i] = NT_ERR;
171: else if (strcmp(ptr, "No") == SAME)
172: Notify[i] = NT_NO;
173: else
174: Notify[i] = NT_YES;
175: } else
176: Notify[i] = NT_YES;
177: if ((Cmds[i] = malloc((unsigned)(strlen(xcmd)+1))) == NULL) {
178: DEBUG(1, "MALLOC FAILED", CNULL);
179: break;
180: }
181: strcpy(Cmds[i], xcmd);
182: }
183: Cmds[i] = CNULL;
184: fclose(fp);
185:
186: doprocess:
187:
188: (void) sprintf(HOME, "HOME=%s", Spool);
189: (void) sprintf(Shell, "SHELL=%s", SHELL);
190: environ = nenv; /* force use if our environment */
191:
192: DEBUG(11,"path = %s\n", getenv("PATH"));
193:
194: DEBUG(4, "process %s\n", CNULL);
195:
196: time(&xstart);
197: while (gtxfile(xfile) > 0) {
198: /* if /etc/nologin exists, exit cleanly */
199: #if defined(BSD4_2) || defined(USG)
200: if (access(NOLOGIN) == 0) {
201: #else !BSD4_2 && ! USG
202: ultouch();
203: if (nologinflag) {
204: #endif !BSD4_2 && !USG
205: logent(NOLOGIN, "UUXQT SHUTDOWN");
206: if (Debug)
207: logent("debugging", "continuing anyway");
208: else
209: break;
210: }
211: DEBUG(4, "xfile - %s\n", xfile);
212:
213: xfp = fopen(subfile(xfile), "r");
214: if (xfp == NULL) {
215: syslog(LOG_ERR, "fopen(%s) failed: %m", subfile(xfile));
216: cleanup(1);
217: }
218:
219: /* initialize to default */
220: strcpy(user, User);
221: strcpy(fin, DEVNULL);
222: strcpy(fout, DEVNULL);
223: strcpy(sysout, Myname);
224: badfiles = 0;
225: while (fgets(buf, BUFSIZ, xfp) != NULL) {
226: if(buf[0] != '\0' && buf[0] != '#' &&
227: buf[1] != ' ' && buf[1] != '\0' && buf[1] != '\n') {
228: char *bnp, cfilename[BUFSIZ];
229: DEBUG(4, "uuxqt: buf = %s\n", buf);
230: bnp = rindex(xfile, '/');
231: sprintf(cfilename, "%s/%s", CORRUPT,
232: bnp ? bnp + 1 : xfile);
233: DEBUG(4, "uuxqt: move %s to ", xfile);
234: DEBUG(4, "%s\n", cfilename);
235: xmv(xfile, cfilename);
236: syslog(LOG_WARNING, "%s: X. FILE CORRUPTED",
237: xfile);
238: fclose(xfp);
239: goto doprocess;
240: }
241: switch (buf[0]) {
242: case X_USER: {
243: char ORmtname[MAXFULLNAME];
244: strcpy(ORmtname, Rmtname);
245: sscanf(&buf[1], "%s %s", user, Rmtname);
246: sprintf(UU_MACHINE, "UU_MACHINE=%s", Rmtname);
247: if (strcmp(ORmtname, Rmtname) != 0)
248: logcls();
249: break;}
250: case X_RETURNTO:
251: sscanf(&buf[1], "%s", user);
252: break;
253: case X_STDIN:
254: sscanf(&buf[1], "%s", fin);
255: i = expfile(fin);
256: /* rti!trt: do not check permissions of
257: * vanilla spool file */
258: if (i != 0
259: && (chkpth("", "", fin) || anyread(fin) != 0))
260: badfiles = 1;
261: break;
262: case X_STDOUT:
263: sscanf(&buf[1], "%s%s", fout, sysout);
264: sysout[MAXBASENAME] = '\0';
265: /* rti!trt: do not check permissions of
266: * vanilla spool file. DO check permissions
267: * of writing on a non-vanilla file */
268: i = 1;
269: if (fout[0] != '~' || prefix(sysout, Myname))
270: i = expfile(fout);
271: if (i != 0
272: && (chkpth("", "", fout)
273: || chkperm(fout, (char *)1)))
274: badfiles = 1;
275: break;
276: case X_CMD:
277: strcpy(cmd, &buf[2]);
278: if (*(cmd + strlen(cmd) - 1) == '\n')
279: *(cmd + strlen(cmd) - 1) = '\0';
280: break;
281: case X_NONOTI:
282: notiok = 0;
283: break;
284: case X_NONZERO:
285: nonzero = 1;
286: break;
287: default:
288: break;
289: }
290: }
291:
292: fclose(xfp);
293: DEBUG(4, "fin - %s, ", fin);
294: DEBUG(4, "fout - %s, ", fout);
295: DEBUG(4, "sysout - %s, ", sysout);
296: DEBUG(4, "user - %s\n", user);
297: DEBUG(4, "cmd - %s\n", cmd);
298:
299: /* command execution */
300: if (strcmp(fout, DEVNULL) == SAME)
301: strcpy(dfile,DEVNULL);
302: else
303: gename(DATAPRE, sysout, 'O', dfile);
304:
305: /* expand file names where necessary */
306: expfile(dfile);
307: cmdp = buf;
308: ptr = cmd;
309: xcmd[0] = '\0';
310: argnok = 0;
311: while ((ptr = getprm(ptr, prm)) != NULL) {
312: if (prm[0] == ';' || prm[0] == '^'
313: || prm[0] == '&' || prm[0] == '|') {
314: xcmd[0] = '\0';
315: APPCMD(prm);
316: continue;
317: }
318:
319: if ((argnok = argok(xcmd, prm)) != SUCCESS)
320: /* command not valid */
321: break;
322:
323: if (prm[0] == '~')
324: expfile(prm);
325: APPCMD(prm);
326: }
327: /*
328: * clean up trailing ' ' in command.
329: */
330: if (cmdp > buf && cmdp[0] == '\0' && cmdp[-1] == ' ')
331: *--cmdp = '\0';
332: if (argnok || badfiles) {
333: sprintf(lbuf, "%s XQT DENIED", user);
334: logent(cmd, lbuf);
335: DEBUG(4, "bad command %s\n", prm);
336: notify(user, Rmtname, cmd, "DENIED");
337: goto rmfiles;
338: }
339: sprintf(lbuf, "%s XQT", user);
340: logent(buf, lbuf);
341: DEBUG(4, "cmd %s\n", buf);
342:
343: mvxfiles(xfile);
344: if (subchdir(XQTDIR) < 0) {
345: syslog(LOG_ERR, "chdir(%s) failed: %m", XQTDIR);
346: cleanup(1);
347: }
348: ret = shio(buf, fin, dfile);
349: sprintf(retstat, "signal %d, exit %d", ret & 0377,
350: (ret>>8) & 0377);
351: if (strcmp(xcmd, "rmail") == SAME)
352: notiok = 0;
353: if (strcmp(xcmd, "rnews") == SAME)
354: nonzero = 1;
355: notiflg = chknotify(xcmd);
356: if (notiok && notiflg != NT_NO &&
357: (ret != 0 || (!nonzero && notiflg == NT_YES)))
358: notify(user, Rmtname, cmd, retstat);
359: else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) {
360: /* mail failed - return letter to sender */
361: #ifdef DANGEROUS
362: /* NOT GUARANTEED SAFE!!! */
363: if (!nonzero)
364: retosndr(user, Rmtname, fin);
365: #else
366: notify(user, Rmtname, cmd, retstat);
367: #endif
368: sprintf(buf, "%s (%s) from %s!%s", buf, retstat, Rmtname, user);
369: logent("MAIL FAIL", buf);
370: }
371: DEBUG(4, "exit cmd - %d\n", ret);
372: if (subchdir(Spool) < 0) {
373: syslog(LOG_ERR, "chdir(%s) failed: %m", Spool);
374: cleanup(1);
375: }
376: rmxfiles(xfile);
377: if (ret != 0) {
378: /* exit status not zero */
379: dfp = fopen(subfile(dfile), "a");
380: if (dfp == NULL) {
381: syslog(LOG_ERR, "fopen(%s) failed: %m",
382: subfile(dfile));
383: cleanup(1);
384: }
385: fprintf(dfp, "exit status %d", ret);
386: fclose(dfp);
387: }
388: if (strcmp(fout, DEVNULL) != SAME) {
389: if (prefix(sysout, Myname)) {
390: xmv(dfile, fout);
391: chmod(fout, BASEMODE);
392: } else {
393: char *cp = rindex(user, '!');
394: gename(CMDPRE, sysout, 'O', cfile);
395: fp = fopen(subfile(cfile), "w");
396: if (fp == NULL) {
397: syslog(LOG_ERR, "fopen(%s) failed: %m",
398: subfile(cfile));
399: cleanup(1);
400: }
401: fprintf(fp, "S %s %s %s - %s 0666\n", dfile,
402: fout, cp ? cp : user, lastpart(dfile));
403: fclose(fp);
404: }
405: }
406: rmfiles:
407: xfp = fopen(subfile(xfile), "r");
408: if (xfp == NULL) {
409: syslog(LOG_ERR, "fopen(%s) failed: %m",
410: subfile(xfile));
411: cleanup(1);
412: }
413: while (fgets(buf, BUFSIZ, xfp) != NULL) {
414: if (buf[0] != X_RQDFILE)
415: continue;
416: sscanf(&buf[1], "%s", file);
417: unlink(subfile(file));
418: }
419: unlink(subfile(xfile));
420: fclose(xfp);
421:
422: /* rescan X. for new work every RECHECKTIME seconds */
423: time(&xnow);
424: if (xnow > (xstart + RECHECKTIME)) {
425: extern int Nfiles;
426: Nfiles = 0; /*force rescan for new work */
427: }
428: xstart = xnow;
429: }
430:
431: if (stcico)
432: xuucico("");
433: cleanup(0);
434: }
435:
436:
437: cleanup(code)
438: int code;
439: {
440: logcls();
441: rmlock(CNULL);
442: #ifdef VMS
443: /*
444: * Since we run as a BATCH job we must wait for all processes to
445: * to finish
446: */
447: while(wait(0) != -1)
448: ;
449: #endif VMS
450: exit(code);
451: }
452:
453:
454: /*
455: * get a file to execute
456: *
457: * return codes: 0 - no file | 1 - file to execute
458: */
459:
460: gtxfile(file)
461: register char *file;
462: {
463: char pre[3];
464: register int rechecked, i;
465: time_t ystrdy; /* yesterday */
466: struct stat stbuf; /* for X file age */
467:
468: pre[0] = XQTPRE;
469: pre[1] = '.';
470: pre[2] = '\0';
471: rechecked = 0;
472: retry:
473: if (Nfiles-- <= 0) {
474: Nfiles = 0;
475: if (rechecked)
476: return 0;
477: rechecked = 1;
478: DEBUG(4, "iswrk\n", CNULL);
479: return iswrk(file, "get", Spool, pre);
480: }
481: sprintf(file, "%s/%s", Spool, Filent[0]);
482: for (i=0; i<Nfiles;i++)
483: strcpy(Filent[i], Filent[i+1]);
484:
485: DEBUG(4, "file - %s\n", file);
486: /* skip spurious subdirectories */
487: if (strcmp(pre, file) == SAME)
488: goto retry;
489: if (gotfiles(file))
490: return 1;
491: /* check for old X. file with no work files and remove them. */
492: if (Nfiles > LLEN/2) {
493: time(&ystrdy);
494: ystrdy -= (4 * 3600L); /* 4 hours ago */
495: DEBUG(4, "gtxfile: Nfiles > LLEN/2\n", CNULL);
496: while (Nfiles-- > 0) {
497: sprintf(file, "%s/%s", Spool, Filent[0]);
498: for (i=0; i<Nfiles; i++)
499: strcpy(Filent[i], Filent[i+1]);
500:
501: if (gotfiles(file))
502: return 1;
503: if (stat(subfile(file), &stbuf) == 0)
504: if (stbuf.st_mtime <= ystrdy) {
505: char *bnp, cfilename[NAMESIZE];
506: DEBUG(4, "gtxfile: move %s to CORRUPT \n", file);
507: bnp = rindex(file, '/');
508: sprintf(cfilename, "%s/%s", CORRUPT,
509: bnp ? bnp + 1 : file);
510: xmv(file, cfilename);
511: syslog(LOG_WARNING, "%s: X. FILE MISSING FILES", file);
512: }
513: }
514: Nfiles = 0;
515: DEBUG(4, "iswrk\n", CNULL);
516: if (!iswrk(file, "get", Spool, pre))
517: return 0;
518: }
519: goto retry;
520: }
521:
522: /*
523: * check for needed files
524: *
525: * return codes: 0 - not ready | 1 - all files ready
526: */
527:
528: gotfiles(file)
529: register char *file;
530: {
531: struct stat stbuf;
532: register FILE *fp;
533: char buf[BUFSIZ], rqfile[MAXFULLNAME];
534:
535: fp = fopen(subfile(file), "r");
536: if (fp == NULL)
537: return 0;
538:
539: while (fgets(buf, BUFSIZ, fp) != NULL) {
540: DEBUG(4, "%s\n", buf);
541: if (buf[0] != X_RQDFILE)
542: continue;
543: sscanf(&buf[1], "%s", rqfile);
544: expfile(rqfile);
545: if (stat(subfile(rqfile), &stbuf) == -1) {
546: fclose(fp);
547: return 0;
548: }
549: }
550:
551: fclose(fp);
552: return 1;
553: }
554:
555:
556: /*
557: * remove execute files to x-directory
558: */
559:
560: rmxfiles(xfile)
561: register char *xfile;
562: {
563: register FILE *fp;
564: char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE];
565: char tfull[MAXFULLNAME];
566:
567: if((fp = fopen(subfile(xfile), "r")) == NULL)
568: return;
569:
570: while (fgets(buf, BUFSIZ, fp) != NULL) {
571: if (buf[0] != X_RQDFILE)
572: continue;
573: if (sscanf(&buf[1], "%s%s", file, tfile) < 2)
574: continue;
575: sprintf(tfull, "%s/%s", XQTDIR, tfile);
576: unlink(subfile(tfull));
577: }
578: fclose(fp);
579: return;
580: }
581:
582:
583: /*
584: * move execute files to x-directory
585: */
586:
587: mvxfiles(xfile)
588: char *xfile;
589: {
590: register FILE *fp;
591: char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE];
592: char tfull[MAXFULLNAME];
593:
594: if((fp = fopen(subfile(xfile), "r")) == NULL)
595: return;
596:
597: while (fgets(buf, BUFSIZ, fp) != NULL) {
598: if (buf[0] != X_RQDFILE)
599: continue;
600: if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2)
601: continue;
602: expfile(ffile);
603: sprintf(tfull, "%s/%s", XQTDIR, tfile);
604: unlink(subfile(tfull));
605: if (xmv(ffile, tfull) != 0) {
606: syslog(LOG_WARNING, "xmv(%s,%s) failed: %m",
607: ffile, tfull);
608: cleanup(1);
609: }
610: }
611: fclose(fp);
612: }
613:
614: /*
615: * check for valid command/argument
616: * *NOTE - side effect is to set xc to the command to be executed.
617: *
618: * return 0 - ok | 1 nok
619: */
620:
621: argok(xc, cmd)
622: register char *xc, *cmd;
623: {
624: register char **ptr;
625:
626: #ifndef ALLOK
627: if (strpbrk(cmd, BADCHARS) != NULL) {
628: DEBUG(1,"MAGIC CHARACTER FOUND\n", CNULL);
629: logent(cmd, "NASTY MAGIC CHARACTER FOUND");
630: return FAIL;
631: }
632: #endif !ALLOK
633:
634: if (xc[0] != '\0')
635: return SUCCESS;
636:
637: #ifndef ALLOK
638: ptr = Cmds;
639: DEBUG(9, "Compare %s and\n", cmd);
640: while(*ptr != NULL) {
641: DEBUG(9, "\t%s\n", *ptr);
642: if (strcmp(cmd, *ptr) == SAME)
643: break;
644: ptr++;
645: }
646: if (*ptr == NULL) {
647: DEBUG(1,"COMMAND NOT FOUND\n", CNULL);
648: return FAIL;
649: }
650: #endif
651: strcpy(xc, cmd);
652: DEBUG(9, "MATCHED %s\n", xc);
653: return SUCCESS;
654: }
655:
656:
657: /*
658: * if notification should be sent for successful execution of cmd
659: *
660: * return NT_YES - do notification
661: * NT_ERR - do notification if exit status != 0
662: * NT_NO - don't do notification ever
663: */
664:
665: chknotify(cmd)
666: char *cmd;
667: {
668: register char **ptr;
669: register int *nptr;
670:
671: ptr = Cmds;
672: nptr = Notify;
673: while (*ptr != NULL) {
674: if (strcmp(cmd, *ptr) == SAME)
675: return *nptr;
676: ptr++;
677: nptr++;
678: }
679: return NT_YES; /* "shouldn't happen" */
680: }
681:
682:
683:
684: /*
685: * send mail to user giving execution results
686: */
687:
688: notify(user, rmt, cmd, str)
689: char *user, *rmt, *cmd, *str;
690: {
691: char text[BUFSIZ*2];
692: char ruser[MAXFULLNAME];
693:
694: if (strpbrk(user, BADCHARS) != NULL) {
695: char lbuf[MAXFULLNAME];
696: sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user);
697: logent(cmd, lbuf);
698: strcpy(user, "postmaster");
699: }
700: sprintf(text, "uuxqt cmd (%s) status (%s)", cmd, str);
701: if (prefix(rmt, Myname))
702: strcpy(ruser, user);
703: else
704: sprintf(ruser, "%s!%s", rmt, user);
705: mailst(ruser, text, CNULL);
706: }
707:
708: /*
709: * return mail to sender
710: *
711: */
712: retosndr(user, rmt, file)
713: char *user, *rmt, *file;
714: {
715: char ruser[MAXFULLNAME];
716:
717: if (strpbrk(user, BADCHARS) != NULL) {
718: char lbuf[MAXFULLNAME];
719: sprintf(lbuf, "%s INVALID CHARACTER IN USERNAME", user);
720: logent(file, lbuf);
721: strcpy(user, "postmaster");
722: }
723: if (strcmp(rmt, Myname) == SAME)
724: strcpy(ruser, user);
725: else
726: sprintf(ruser, "%s!%s", rmt, user);
727:
728: if (anyread(file) == 0)
729: mailst(ruser, "Mail failed. Letter returned to sender.\n", file);
730: else
731: mailst(ruser, "Mail failed. Letter returned to sender.\n", CNULL);
732: return;
733: }
734:
735: /*
736: * execute shell of command with fi and fo as standard input/output
737: */
738:
739: shio(cmd, fi, fo)
740: char *cmd, *fi, *fo;
741: {
742: int status, f;
743: int pid, ret;
744: char *args[256];
745: extern int errno;
746:
747: if (fi == NULL)
748: fi = DEVNULL;
749: if (fo == NULL)
750: fo = DEVNULL;
751:
752: getargs(cmd, args, 256);
753: DEBUG(3, "shio - %s\n", cmd);
754: #ifdef SIGCHLD
755: signal(SIGCHLD, SIG_IGN);
756: #endif SIGCHLD
757: if ((pid = fork()) == 0) {
758: signal(SIGINT, SIG_IGN);
759: signal(SIGHUP, SIG_IGN);
760: signal(SIGQUIT, SIG_IGN);
761: close(Ifn);
762: close(Ofn);
763: close(0);
764: setuid(getuid());
765: f = open(subfile(fi), 0);
766: if (f != 0) {
767: logent(fi, "CAN'T READ");
768: exit(-errno);
769: }
770: close(1);
771: f = creat(subfile(fo), 0666);
772: if (f != 1) {
773: logent(fo, "CAN'T WRITE");
774: exit(-errno);
775: }
776: execvp(args[0], args);
777: exit(100+errno);
778: }
779: while ((ret = wait(&status)) != pid && ret != -1)
780: ;
781: DEBUG(3, "status %d\n", status);
782: return status;
783: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.