Commit | Line | Data |
---|---|---|
f5c46f90 | 1 | #ifndef lint |
1a85e9d2 | 2 | static 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) {\ |
18 | char *p;\ | |
46b15d8a | 19 | for (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 |
27 | char *Cmds[NCMDS+1]; |
28 | int 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 | ||
33 | extern int Nfiles; | |
1a85e9d2 | 34 | char *strpbrk(); |
f5c46f90 | 35 | |
1a85e9d2 | 36 | int TransferSucceeded = 1; |
f5c46f90 SL |
37 | int notiok = 1; |
38 | int nonzero = 0; | |
39 | ||
1a85e9d2 RC |
40 | char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin:/usr/ucb"; |
41 | char Shell[MAXFULLNAME]; | |
42 | char HOME[MAXFULLNAME]; | |
46b15d8a | 43 | |
1a85e9d2 RC |
44 | extern char **environ; |
45 | char *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 |
58 | main(argc, argv) |
59 | char *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 | ||
170 | doprocess: | |
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 | ||
382 | cleanup(code) | |
383 | int 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 | ||
405 | gtxfile(file) | |
406 | register 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; | |
418 | retry: | |
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 | ||
464 | gotfiles(file) | |
465 | register 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 | ||
496 | rmxfiles(xfile) | |
497 | register 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 | ||
523 | mvxfiles(xfile) | |
524 | char *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 | ||
555 | argok(xc, cmd) | |
556 | register 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 | ||
599 | chknotify(cmd) | |
600 | char *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 | ||
622 | notify(user, rmt, cmd, str) | |
623 | char *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 | ||
642 | retosndr(user, rmt, file) | |
643 | char *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 | */ | |
662 | char * | |
1a85e9d2 | 663 | strpbrk(str, chars) |
cefa2bc1 RC |
664 | register 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 | ||
682 | shio(cmd, fi, fo) | |
683 | char *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 | } |