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