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