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