|
|
1.1 root 1: /*
2: * uuxqt.c
3: *
4: * Execute local commands spooled by remote sites.
5: *
6: * copyright (x) richard h. lamb 1985, 1986, 1987
7: * changes (massive) copyright (c) 1989-1991 by Mark Williams Company
8: */
9:
10: #include <stdio.h>
11: #include <signal.h>
12: #include <access.h>
13: #include <sys/param.h>
14: #include <sys/stat.h>
15: #include "dirent.h"
16: #include "dcp.h"
17: #include "perm.h"
18:
19: /*
20: * Global Variables Definitions
21: */
22:
23: char directory[CTLFLEN]; /* directory for control files */
24: char xfile[CTLFLEN]; /* "X.*" control file name */
25: FILE *xfp = NULL; /* Opened "X.*" FILE pointer */
26: int processid; /* process id of this uuxqt */
27: char line[BUFSIZ]; /* Reading a text line */
28:
29: static char command[BUFSIZ], input[60], output[60];
30: static char orig_user[128];
31: static char orig_system[SITELEN+1];
32: static char notifywho[BUFSIZ];
33: static char *allowed;
34:
35: static int failstatus_req;
36: static int succstatus_req;
37: static char errbuf1[BUFSIZ];
38: static char errbuf2[BUFSIZ];
39: static char errbuf3[BUFSIZ];
40: static char reason[80];
41:
42: static char *sep = " \t\n";
43:
44: char *rmtname = NULL;
45: char **zenvp; /* Globally Available envp */
46:
47: extern int optind;
48: extern int optopt;
49: extern char *optarg;
50:
51: /*
52: * Extern Function Declarations
53: */
54:
55: extern char *strtok();
56: extern char *index();
57:
58: catchsegv()
59: {
60: fatal("Segmentation violation -- uuxqt aborted");
61: }
62:
63: catchterm()
64: {
65: fatal("Local signal -- uuxqt aborted");
66: }
67:
68: main(argc, argv, envp)
69: int argc;
70: char *argv[], *envp[];
71: {
72: char xqtdir[LOGFLEN];
73: char ch;
74:
75: umask(077);
76: while ( (ch=getopt(argc, argv, "x:vV")) != EOF ) {
77: switch (ch) {
78: case 'x':
79: debuglevel = atoi(optarg);
80: break;
81: case 'v':
82: case 'V':
83: fatal("uuxqt: Version %s", VERSION);
84: case '?':
85: default:
86: fatal("Improper option usage: %c", optopt);
87: }
88: }
89:
90: bedaemon(); /* detach from controlling terminal */
91:
92: zenvp = envp;
93: processid = getpid();
94: signal(SIGINT, SIG_IGN);
95: signal(SIGHUP, SIG_IGN);
96: signal(SIGQUIT, SIG_IGN);
97: signal(SIGTERM, catchterm);
98: signal(SIGSEGV, catchsegv);
99: open_debug("uuxqt", 0);
100: sprintf(xqtdir, "%s/.Xqtdir", SPOOLDIR);
101: if (chdir(xqtdir) != 0)
102: fatal("can't chdir to: %s", xqtdir);
103: dcxqt();
104: close_debug();
105: exit(0);
106: }
107:
108: dcxqt()
109: {
110: if ( lockexist("uuxqt") )
111: return;
112:
113: if ( lockit("uuxqt") < 0 )
114: fatal("Can't lock uuxqt");
115:
116: if ( dscan_start() ) {
117: while ( dscan() ) {
118: if ( xscan_start() ) {
119: while ( xscan() )
120: dcxqt_work();
121: xscan_done();
122: }
123: }
124: dscan_done();
125: }
126: if ( lockrm("uuxqt") < 0 )
127: printmsg(M_LOG, "error unlocking uuxqt");
128: }
129:
130: /*
131: * Perform the work specified in the "X.*" control file: "xfile"
132: */
133:
134: dcxqt_work()
135: {
136: static char lastsite[SITELEN] = "\0";
137: int filewait = 0;
138: int removethis = 0;
139: int did_work = 0;
140: int fnd;
141: int execval;
142: char *sp, *osp;
143:
144: if ( (xfp=fopen(xfile, "r")) == NULL )
145: return;
146:
147: reason[0] = input[0] = output[0] = command[0] =
148: notifywho[0] = orig_user[0] = orig_system[0] =
149: errbuf1[0] = errbuf2[0] = errbuf3[0] = '\0';
150: failstatus_req = succstatus_req = fnd = 0;
151:
152: while ( fgets(line, BUFSIZ, xfp) != NULL ) {
153: sp = strtok(line, sep);
154: switch(line[0]) {
155: case 'C':
156: sp = strtok(NULL, "#\n");
157: strcpy(command, sp);
158: break;
159: case 'F':
160: sp = strtok(NULL, sep);
161: osp = strtok(NULL, sep);
162: sprintf(input,"%s/%s", directory, sp);
163: filewait |= isfileabsent(input);
164:
165: if (filewait == 0 && osp != NULL) {
166: if (link(input, osp) == -1) {
167: sprintf(errbuf1,
168: "Cannot link %s to %s.\n",
169: input, osp);
170: removethis = 1;
171: }
172: ul(input);
173: input[0] = '\0';
174: }
175: break;
176: case 'I':
177: sp = strtok(NULL, sep);
178: sprintf(input, "%s/%s", directory, sp);
179: break;
180: case 'M':
181: strcpy(errbuf2,
182: "Execute M record not supported");
183: break;
184: case 'O':
185: sp = strtok(NULL, sep);
186: sprintf(output, "%s/%s", directory, sp);
187: break;
188: case 'R':
189: strcpy (notifywho, sp = strtok(NULL, sep));
190: break;
191: case 'U':
192: strcpy(orig_user, sp = strtok(NULL, sep));
193: strncpy(orig_system,sp=strtok(NULL, sep), SITELEN);
194: if ( strncmp(orig_system, lastsite, SITELEN) != 0) {
195: strncpy(lastsite, orig_system, SITELEN);
196: rmtname = &lastsite[0];
197: open_the_logfile("uuxqt");
198: plog(M_INFO, "Starting Xqt {%d} (V%s)",
199: processid, VERSION);
200: perm_get(orig_system, NULL);
201: allowed = perm_value(commands_e);
202: }
203: break;
204: case 'Z':
205: failstatus_req = 1;
206: break;
207: case 'n':
208: succstatus_req = 1;
209: break;
210: case '#':
211: break;
212: default:
213: sprintf(errbuf3, "Unknown command %s", sp);
214: break;
215: }
216: }
217:
218: if (strlen(notifywho) < 1)
219: strcpy (notifywho, orig_user);
220: if (strlen(errbuf1) > 0)
221: plog(M_INFO, errbuf1);
222: if (strlen(errbuf2) > 0)
223: plog(M_INFO, errbuf2);
224: if (strlen(errbuf3) > 0)
225: plog(M_INFO, errbuf3);
226:
227: plog(M_INFO, "%s (<%s >%s)", command, input, output);
228: if (removethis) {
229: unlinkfiles();
230: } else if (filewait)
231: plog(M_INFO, "Waiting for files");
232: else {
233: did_work ++;
234: if ( (execval=shell2(command, input, output)) != 0 ) {
235: plog(M_INFO, "Command failed, status %d (0x%04x)",
236: execval, execval);
237: strcpy(reason, "Exit status not zero");
238: }
239: if (succstatus_req || (failstatus_req && (execval != 0)))
240: remote_status(execval);
241: unlinkfiles();
242: }
243: if (did_work > 0) {
244: plog(M_INFO, "Finished {%d}", processid);
245: }
246: fclose(xfp);
247: }
248:
249: unlinkfiles()
250: {
251: char *osp, *sp;
252:
253: rewind(xfp);
254: while(fgets(line, BUFSIZ, xfp) != NULL) {
255: sp = strtok(line, sep);
256: switch(line[0]) {
257: case 'C':
258: break;
259: case 'F':
260: sp = strtok(NULL, sep);
261: osp = strtok(NULL, sep);
262: ul(sp);
263: if (osp != NULL)
264: ul(osp);
265: break;
266: case 'I':case 'M':case 'O':
267: case 'U':case 'Z':case 'n':
268: default:
269: break;
270:
271: }
272: }
273: ul(xfile);
274: ul(input);
275: ul(output);
276: }
277:
278: static
279: ul(fn)
280: char *fn;
281: {
282: int status;
283: if (strlen(fn) < 1)
284: return;
285: status = unlink(fn);
286: }
287:
288: remote_status(val)
289: int val;
290: {
291: static char pbuf[BUFSIZ];
292:
293: FILE *fmp;
294: (void) signal(SIGPIPE, SIG_IGN);
295: sprintf(pbuf, "mail -auucp %s!%s ", orig_system, notifywho);
296: if ((fmp = popen(pbuf, "w")) == NULL)
297: plog(M_INFO, "Cannot send remote status mail");
298: else {
299: fprintf(fmp, "From: UUXQT V%s\n", VERSION);
300: fprintf(fmp, "Subject: UUXQT remote execution status\n\n");
301: fprintf(fmp,
302: "Command \"%s\" %s.\n\tStatus %d (0x%04x)",
303: command, val ? "failed" : "succeeded", val, val);
304: if (strlen(reason) > 0)
305: fprintf(fmp, "\nReason: %s", reason);
306: fprintf(fmp, "\n");
307: if (pclose(fmp) != 0)
308: plog(M_INFO, "Remote status mail failed");
309: plog(M_INFO, "Remote status mail posted to %s!%s",
310: orig_system, notifywho);
311: }
312: }
313:
314: isfileabsent(fn)
315: char *fn;
316: {
317: return access(fn, AREAD);
318: }
319:
320: #define MAXENVS 200
321: static char *uuenvp[MAXENVS];
322: static char uu_user[BUFSIZ];
323: static char uu_mach[BUFSIZ];
324:
325: shell2(command, inname, outname)
326: char *command;
327: char *inname;
328: char *outname;
329: {
330: int waitstat;
331: int fd, i;
332: int waitpid, cpid;
333:
334: if ( !permission(command) ) {
335: strcpy(reason, "No permission to execute command");
336: plog(M_INFO, "No permission to execute: %s", command);
337: if (failstatus_req)
338: remote_status(-1);
339: return 0;
340: }
341:
342: sprintf(uu_user, "UU_USER=%s", notifywho);
343: sprintf(uu_mach, "UU_MACHINE=%s", orig_system);
344: uuenvp[0] = uu_user;
345: uuenvp[1] = uu_mach;
346: for (i=2; (zenvp[i]!=NULL) && (i<MAXENVS); i++)
347: uuenvp[i] = zenvp[i-2];
348: if ((cpid = fork()) < 0) {
349: plog(M_INFO, "couldn't fork");
350: return -1;
351: }
352: if (cpid == 0) {
353: if (strlen(inname) != 0) {
354: fd = open(inname, 0);
355: dup2(fd, 0);
356: if (fd > 0)
357: close(fd);
358: }
359: if (strlen(outname) != 0) {
360: fd = creat(outname, 0644);
361: dup2(fd, 1);
362: if (fd > 1)
363: close(fd);
364: }
365: execle("/bin/sh", "sh", "-c", command, (char *)0, uuenvp);
366: plog(M_INFO, "Could not exec /bin/sh");
367: exit(0177);
368: }
369: while (((waitpid = wait(&waitstat)) != cpid) && (waitpid > 0))
370: ;
371: return waitstat;
372: }
373:
374: permission(command)
375: char *command;
376: {
377: char *sp, *cp, *spcp;
378: int ok;
379:
380: if ( (spcp=index(command, ' ')) != NULL )
381: *spcp = '\0';
382:
383: sp = allowed;
384: ok = 0;
385: do {
386: if ( (cp=index(sp, ':')) != NULL )
387: *cp = '\0';
388: if ( strcmp(command, sp) == 0 )
389: ok = 1;
390: if ( cp != NULL )
391: *cp++ = ':';
392: } while ( !ok && ((sp=cp) != NULL) );
393:
394: if ( spcp != NULL )
395: *spcp = ' ';
396: return(ok);
397: }
398:
399: /*
400: * Directory Scan Functions:
401: *
402: * dscan_start() : Opens SPOOLDIR to scan for sitename subdirectories
403: * : Returns: (1) opened ok, (0) error
404: * dscan() : Sets variable "directory" to next directory
405: * : Returns: (1) found directory, (0) no directory
406: * dscan_done() : Done scanning SPOOLDIR for directories
407: *
408: * xscan_start() : Opens "directory" to scan for "X.*" control files
409: * : Returns: (1) opened ok, (0) error
410: * xscan() : Sets variable "xfile" to next such "X.*" control file
411: * : Returns: (1) found file, (0) no file
412: * xscan_done() : Done scanning "directory" for "X.*" control files
413: */
414:
415: static DIR *sdirp, *xdirp;
416: extern DIR *opendir();
417: extern struct direct *readdir();
418:
419: dscan_start()
420: {
421: if ( (sdirp=opendir(SPOOLDIR)) == NULL ) {
422: printmsg(M_LOG, "Cannot open spool directory: %s", SPOOLDIR);
423: return(0);
424: }
425: return(1);
426: }
427:
428: dscan()
429: {
430: struct stat statbuf;
431: struct dirent *mdp;
432:
433: while( (mdp=readdir(sdirp)) != NULL ) {
434: if ( mdp->d_name[0] == '.' )
435: continue;
436: sprintf(directory, "%s/%s", SPOOLDIR, mdp->d_name);
437: stat(directory, &statbuf);
438: if ( statbuf.st_mode & S_IFDIR )
439: return(1);
440: }
441: return(0);
442: }
443:
444: dscan_done()
445: {
446: closedir(sdirp);
447: }
448:
449: xscan_start()
450: {
451: if ( (xdirp=opendir(directory)) == NULL ) {
452: printmsg(M_LOG, "Cannot open spool directory: %s", directory);
453: return(0);
454: }
455: return(1);
456: }
457:
458: xscan()
459: {
460: struct stat statbuf;
461: struct dirent *xdp;
462:
463: while( (xdp=readdir(xdirp)) != NULL ) {
464: if ( strncmp(xdp->d_name, "X.", 2) == 0 ) {
465: sprintf(xfile, "%s/%s", directory, xdp->d_name);
466: stat(xfile, &statbuf);
467: if ( statbuf.st_mode & S_IFDIR )
468: continue;
469: return(1);
470: }
471: }
472: return(0);
473: }
474:
475: xscan_done()
476: {
477: closedir(xdirp);
478: }
479:
480: fatal(x)
481: {
482: printmsg(M_FATAL, "%r", &x);
483: if ( lockexist("uuxqt") )
484: lockrm("uuxqt");
485: close_logfile();
486: close_debug();
487: exit(1);
488: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.