|
|
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.