|
|
1.1 ! root 1: /* @(#)uuxqt.c 1.13 */ ! 2: ! 3: #include "uucp.h" ! 4: VERSION(@(#)uuxqt.c 1.13); ! 5: ! 6: /* ! 7: * execute commands set up by a uux command, ! 8: * usually from a remote machine - set by uucp. ! 9: */ ! 10: ! 11: #ifndef V7 ! 12: #define LOGNAME "LOGNAME=uucp" ! 13: #else ! 14: #define LOGNAME "USER=uucp" ! 15: #endif ! 16: ! 17: #define C_COMMAND 1 ! 18: #define C_FILE 2 ! 19: #define BAD_COMMAND 1 ! 20: #define BAD_FILE 2 ! 21: #define USAGE "[-xDEGUG] [-sSYSTEM]" ! 22: #define APPCMD(p) {(void) strcat(_Cmd, p); (void) strcat(_Cmd, " ");} ! 23: #define APPCMDNS(p) {(void) strcat(_Cmd, p);} ! 24: ! 25: char _Xfile[MAXFULLNAME]; ! 26: char _Cmd[2 * BUFSIZ]; /* build up command buffer */ ! 27: int _CargType; /* argument type of next C argument */ ! 28: char frogs[] = ";&|<>^`\\('\""; ! 29: ! 30: static void retosndr(), uucpst(); ! 31: static int chkFile(); ! 32: static int doFileChk(); ! 33: ! 34: main(argc, argv, envp) ! 35: char *argv[], *envp[]; ! 36: { ! 37: DIR *fp1; ! 38: int ret, maxnumb; ! 39: char dirname[MAXFULLNAME], lockname[MAXFULLNAME]; ! 40: extern onintr(); ! 41: FILE *fp; ! 42: ! 43: (void) signal(SIGILL, onintr); ! 44: (void) signal(SIGTRAP, onintr); ! 45: (void) signal(SIGIOT, onintr); ! 46: (void) signal(SIGEMT, onintr); ! 47: (void) signal(SIGFPE, onintr); ! 48: (void) signal(SIGBUS, onintr); ! 49: (void) signal(SIGSEGV, onintr); ! 50: (void) signal(SIGSYS, onintr); ! 51: (void) signal(SIGPIPE, onintr); ! 52: (void) signal(SIGTERM, SIG_IGN); ! 53: ! 54: /* choose LOGFILE */ ! 55: (void) strcpy(Logfile, LOGUUXQT); ! 56: ! 57: /* ! 58: * get local system name ! 59: */ ! 60: Env = envp; ! 61: Nstat.t_qtime = time((time_t *)0); ! 62: (void) strcpy(Progname, "uuxqt"); ! 63: Pchar = 'Q'; ! 64: uucpname(Myname); ! 65: Ofn = 1; ! 66: Ifn = 0; ! 67: dirname[0] = NULLCHAR; ! 68: while ((ret = getopt(argc, argv, "s:x:")) != EOF) { ! 69: switch(ret){ ! 70: ! 71: /* ! 72: * debugging level ! 73: */ ! 74: case 'x': ! 75: Debug = atoi(optarg); ! 76: if (Debug <= 0) ! 77: Debug = 1; ! 78: break; ! 79: ! 80: case 's': ! 81: /* fake out uuxqt and use the argument as if ! 82: * it were the spool directory for the purpose ! 83: * of determining what subdirectories to search ! 84: * EX: mkdir /tmp/foo; touch /tmp/foo/{baz,gorp} ! 85: * uuxqt -s/tmp/foo ! 86: * this will cause uuxqt to only run on the sub ! 87: * baz and gorp in the Spool directory. Trust me. ! 88: */ ! 89: (void) strncpy(dirname, optarg, MAXFULLNAME); ! 90: break; ! 91: ! 92: default: ! 93: (void) fprintf(stderr, "\tusage: %s %s\n", ! 94: Progname, USAGE); ! 95: exit(1); ! 96: } ! 97: } ! 98: if (argc != optind) { ! 99: (void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE); ! 100: exit(1); ! 101: } ! 102: ! 103: DEBUG(4, "\n\n** START **\n", ""); ! 104: fp = fopen(LMTUUXQT, "r"); ! 105: if (fp == NULL) { ! 106: DEBUG(1, "No limitfile - %s\n", LMTUUXQT); ! 107: } else { ! 108: (void) fscanf(fp, "%d", &maxnumb); ! 109: (void) fclose(fp); ! 110: DEBUG(4, "Uuxqt limit %d -- ", maxnumb); ! 111: ret = cuantos(X_LOCKPRE, X_LOCKDIR); ! 112: DEBUG(4, "found %d -- ", ret); ! 113: if (maxnumb >= 0 && ret >= maxnumb) { ! 114: DEBUG(4, "exiting\n", maxnumb); ! 115: exit(0); ! 116: } ! 117: DEBUG(4, "continuing\n", maxnumb); ! 118: } ! 119: ! 120: /* ! 121: * determine user who started uuxqt (in principle) ! 122: */ ! 123: strcpy(User, "uucp"); /* in case all else fails (can't happen) */ ! 124: Uid = getuid(); ! 125: Euid = geteuid(); /* this should be UUCPUID */ ! 126: guinfo(Euid, User); ! 127: setuucp(User); ! 128: DEBUG(4, "User - %s\n", User); ! 129: guinfo(Uid, Loginuser); ! 130: ! 131: DEBUG(4, "process %s\n", ""); ! 132: ! 133: fp1 = opendir(Spool); ! 134: ASSERT(fp1 != NULL, Ct_OPEN, Spool, errno); ! 135: ! 136: if (dirname[0] != NULLCHAR) { ! 137: (void) sprintf(lockname, "%s.%s", X_LOCK, dirname); ! 138: if (ulockf(lockname, (time_t) X_LOCKTIME) == 0) { ! 139: xprocess(dirname); ! 140: rmlock(CNULL); ! 141: } ! 142: } ! 143: else { ! 144: while (gdirf(fp1, dirname, Spool) == TRUE) { ! 145: if (strpbrk(dirname, frogs) != NULL) /* skip naughty names */ ! 146: continue; ! 147: (void) sprintf(lockname, "%s.%s", X_LOCK, dirname); ! 148: if (ulockf(lockname, (time_t) X_LOCKTIME) != 0) ! 149: continue; ! 150: xprocess(dirname); ! 151: rmlock(CNULL); ! 152: } ! 153: } ! 154: ! 155: closedir(fp1); ! 156: cleanup(0); ! 157: } ! 158: ! 159: cleanup(code) ! 160: int code; ! 161: { ! 162: rmlock(CNULL); ! 163: exit(code); ! 164: } ! 165: ! 166: /* ! 167: * catch signal then cleanup and exit ! 168: */ ! 169: onintr(inter) ! 170: register int inter; ! 171: { ! 172: char str[30]; ! 173: (void) signal(inter, SIG_IGN); ! 174: (void) sprintf(str, "QSIGNAL %d", inter); ! 175: logent(str, "QCAUGHT"); ! 176: cleanup(-inter); ! 177: } ! 178: ! 179: #define XCACHESIZE (4096 / (MAXBASENAME + 1)) ! 180: static char xcache[XCACHESIZE][MAXBASENAME + 1]; /* cache for X. files */ ! 181: static int xcachesize = 0; /* how many left? */ ! 182: ! 183: /* ! 184: * stash an X. file so we can process them sorted first by grade, then by ! 185: * sequence number ! 186: */ ! 187: static int ! 188: xstash(file) ! 189: char *file; ! 190: { ! 191: DEBUG(4, "stashing %s\n", file); ! 192: strcpy(xcache[xcachesize++], file); ! 193: } ! 194: ! 195: /* ! 196: * xcompare ! 197: * comparison routine for for qsort() ! 198: */ ! 199: static int ! 200: xcompare(f1, f2) ! 201: register char *f1, *f2; ! 202: { ! 203: /* assumes file name is X.siteG1234 */ ! 204: /* use -strcmp() so that xstash is sorted largest first */ ! 205: /* pull files out of the stash from largest index to smallest */ ! 206: ! 207: return(-strcmp(f1 + strlen(f1) - 5, f2 + strlen(f2) - 5)); ! 208: } ! 209: ! 210: /* ! 211: * xsort ! 212: * sort the cached X. files, ! 213: * largest (last) to smallest (next to be processed) ! 214: */ ! 215: static int ! 216: xsort() ! 217: { ! 218: DEBUG(4, "xsort: first was %s\n", xcache[0]); ! 219: qsort(xcache, xcachesize, MAXBASENAME + 1, xcompare); ! 220: DEBUG(4, "xsort: first is %s\n", xcache[0]); ! 221: } ! 222: ! 223: /* ! 224: * xget ! 225: * return smallest X. file in cache ! 226: * (hint: it's the last one in the array) ! 227: */ ! 228: static int ! 229: xget(file) ! 230: char *file; ! 231: { ! 232: if (xcachesize > 0) { ! 233: strcpy(file, xcache[--xcachesize]); ! 234: DEBUG(4, "xget: returning %s\n", file); ! 235: return(1); ! 236: } else { ! 237: /* avoid horror of xcachesize < 0 (impossible, you say?)! */ ! 238: xcachesize = 0; ! 239: return(0); ! 240: } ! 241: } ! 242: ! 243: ! 244: /* ! 245: * get a file to execute ! 246: * file -> a read to return filename in ! 247: * returns: ! 248: * 0 -> no file ! 249: * 1 -> file to execute ! 250: */ ! 251: gt_Xfile(file, dir) ! 252: register char *file, *dir; ! 253: { ! 254: DIR *pdir; ! 255: ! 256: if (xcachesize == 0) { ! 257: /* open spool directory */ ! 258: pdir = opendir(dir); ! 259: /* this was an ASSERT, but it's not so bad as all that */ ! 260: if (pdir == NULL) ! 261: return(0); ! 262: ! 263: /* scan spool directory looking for X. files to stash */ ! 264: while (gnamef(pdir, file) == TRUE) { ! 265: DEBUG(4, "gt_Xfile got %s\n", file); ! 266: /* look for x prefix */ ! 267: if (file[0] != XQTPRE) ! 268: continue; ! 269: ! 270: /* check to see if required files have arrived */ ! 271: if (gotfiles(file)) ! 272: xstash(file); ! 273: if (xcachesize >= XCACHESIZE) ! 274: break; ! 275: } ! 276: closedir(pdir); ! 277: xsort(); ! 278: } ! 279: ! 280: return(xget(file)); ! 281: } ! 282: ! 283: /* ! 284: * check for needed files ! 285: * file -> name of file to check ! 286: * return: ! 287: * 0 -> not ready ! 288: * 1 -> all files ready ! 289: */ ! 290: gotfiles(file) ! 291: register char *file; ! 292: { ! 293: register FILE *fp; ! 294: struct stat stbuf; ! 295: char buf[BUFSIZ], rqfile[MAXFULLNAME]; ! 296: ! 297: fp = fopen(file, "r"); ! 298: if (fp == NULL) ! 299: return(FALSE); ! 300: ! 301: while (fgets(buf, BUFSIZ, fp) != NULL) { ! 302: DEBUG(4, "%s\n", buf); ! 303: ! 304: /* ! 305: * look at required files ! 306: */ ! 307: if (buf[0] != X_RQDFILE) ! 308: continue; ! 309: (void) sscanf(&buf[1], "%s", rqfile); ! 310: ! 311: /* ! 312: * expand file name ! 313: */ ! 314: expfile(rqfile); ! 315: ! 316: /* ! 317: * see if file exists ! 318: */ ! 319: if (stat(rqfile, &stbuf) == -1) { ! 320: fclose(fp); ! 321: return(FALSE); ! 322: } ! 323: } ! 324: ! 325: fclose(fp); ! 326: return(TRUE); ! 327: } ! 328: ! 329: /* ! 330: * remove execute files to x-directory ! 331: * ! 332: * _Xfile is a global ! 333: * return: ! 334: * none ! 335: */ ! 336: rm_Xfiles() ! 337: { ! 338: register FILE *fp; ! 339: char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE]; ! 340: char tfull[MAXFULLNAME]; ! 341: ! 342: if ((fp = fopen(_Xfile, "r")) == NULL) { ! 343: DEBUG(4, "rm_Xfiles: can't read %s\n", _Xfile); ! 344: return; ! 345: } ! 346: ! 347: /* ! 348: * (void) unlink each file belonging to job ! 349: */ ! 350: while (fgets(buf, BUFSIZ, fp) != NULL) { ! 351: if (buf[0] != X_RQDFILE) ! 352: continue; ! 353: if (sscanf(&buf[1], "%s%s", file, tfile) < 2) ! 354: continue; ! 355: (void) sprintf(tfull, "%s/%s", XQTDIR, tfile); ! 356: (void) unlink(tfull); ! 357: } ! 358: fclose(fp); ! 359: return; ! 360: } ! 361: ! 362: /* ! 363: * move execute files to x-directory ! 364: * _Xfile is a global ! 365: * return: ! 366: * none ! 367: */ ! 368: mv_Xfiles() ! 369: { ! 370: register FILE *fp; ! 371: char buf[BUFSIZ], ffile[MAXNAMESIZE], tfile[MAXNAMESIZE]; ! 372: char tfull[MAXNAMESIZE]; ! 373: ! 374: if ((fp = fopen(_Xfile, "r")) == NULL) { ! 375: DEBUG(4, "mv_Xfiles: can't read %s\n", _Xfile); ! 376: return; ! 377: } ! 378: ! 379: while (fgets(buf, BUFSIZ, fp) != NULL) { ! 380: if (buf[0] != X_RQDFILE) ! 381: continue; ! 382: if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) ! 383: continue; ! 384: ! 385: /* ! 386: * expand file names and move to ! 387: * execute directory ! 388: * Make files readable by anyone ! 389: */ ! 390: expfile(ffile); ! 391: (void) sprintf(tfull, "%s/%s", XQTDIR, tfile); ! 392: ! 393: ASSERT(xmv(ffile, tfull) == 0, "XMV ERROR", tfull, errno); ! 394: chmod(tfull, 0666); ! 395: } ! 396: fclose(fp); ! 397: return; ! 398: } ! 399: ! 400: /* ! 401: * undo what mv_Xfiles did ! 402: * _Xfile is a global ! 403: * return: ! 404: * none ! 405: */ ! 406: unmv_Xfiles() ! 407: { ! 408: FILE *fp; ! 409: char buf[BUFSIZ], ffile[MAXNAMESIZE], tfile[MAXNAMESIZE]; ! 410: char tfull[MAXNAMESIZE], ffull[MAXNAMESIZE], xfull[MAXNAMESIZE]; ! 411: ! 412: (void) sprintf(xfull, "%s/%s", RemSpool, _Xfile); ! 413: if ((fp = fopen(xfull, "r")) == NULL) { ! 414: DEBUG(4, "unmv_Xfiles: can't read %s\n", xfull); ! 415: return; ! 416: } ! 417: ! 418: while (fgets(buf, BUFSIZ, fp) != NULL) { ! 419: if (buf[0] != X_RQDFILE) ! 420: continue; ! 421: if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2) ! 422: continue; ! 423: ! 424: /* ! 425: * expand file names and move back to ! 426: * spool directory ! 427: * Make files readable by uucp ! 428: */ ! 429: (void) sprintf(ffull, "%s/%s", RemSpool, ffile); ! 430: /* i know we're in .Xqtdir, but what the hell ... */ ! 431: (void) sprintf(tfull, "%s/%s", XQTDIR, tfile); ! 432: ! 433: ASSERT(xmv(tfull, ffull) == 0, "XMV ERROR", ffull, errno); ! 434: (void) chmod(ffull, 0600); ! 435: } ! 436: fclose(fp); ! 437: return; ! 438: } ! 439: ! 440: /* chkpart - checks the string (ptr points to it) for illegal command or ! 441: * file permission restriction - called recursively ! 442: * to check lines that have `string` or (string) form. ! 443: * _Cmd is the buffer where the command is built up. ! 444: * _CargType is the type of the next C line argument ! 445: * ! 446: * Return: ! 447: * BAD_FILE if a non permitted file is found ! 448: * BAD_COMMAND if non permitted command is found ! 449: * 0 - ok ! 450: */ ! 451: ! 452: static ! 453: int ! 454: chkpart(ptr) ! 455: char *ptr; ! 456: { ! 457: char prm[BUFSIZ], xcmd[BUFSIZ]; ! 458: char savechar[2]; /* one character string with NULL */ ! 459: int ret; ! 460: ! 461: /* _CargType is the arg type for this iteration (cmd or file) */ ! 462: while ((ptr = getprm(ptr, prm)) != NULL) { ! 463: DEBUG(4, "prm='%s'\n", prm); ! 464: switch(*prm) { ! 465: ! 466: /* End of command delimiter */ ! 467: case ';': ! 468: case '^': ! 469: case '&': ! 470: case '|': ! 471: APPCMDNS(prm); ! 472: _CargType = C_COMMAND; ! 473: continue; ! 474: ! 475: /* Other delimiter */ ! 476: case '>': ! 477: case '<': ! 478: APPCMDNS(prm); ! 479: continue; ! 480: ! 481: case '`': /* don't allow any ` commands */ ! 482: case '\\': ! 483: return(BAD_COMMAND); ! 484: ! 485: /* Some allowable quoted string */ ! 486: case '(': ! 487: case '"': ! 488: case '\'': ! 489: /* must recurse */ ! 490: savechar[0] = *prm; ! 491: savechar[1] = NULLCHAR; ! 492: APPCMD(savechar); /* put first char into command */ ! 493: savechar[0] = prm[strlen(prm)-1]; ! 494: prm[strlen(prm)-1] = NULLCHAR; /* delete last character */ ! 495: ! 496: /* recurse */ ! 497: if (ret = chkpart(prm+1)) { /* failed */ ! 498: return(ret); ! 499: } ! 500: APPCMD(savechar); /* put last char into command */ ! 501: continue; ! 502: ! 503: default: /* check for command or file */ ! 504: break; ! 505: } ! 506: ! 507: if (_CargType == C_COMMAND) { ! 508: if ( (cmdOK(prm, xcmd)) == FALSE) ! 509: return(BAD_COMMAND); ! 510: APPCMD(xcmd); ! 511: _CargType = C_FILE; ! 512: continue; ! 513: } ! 514: ! 515: #if NOTDEF ! 516: if (chkFile(prm)) ! 517: return(BAD_FILE); ! 518: else ! 519: #endif ! 520: APPCMD(prm); ! 521: } ! 522: return(0); /* all ok */ ! 523: } ! 524: ! 525: /* chkFile - try to find a path name in the prm. ! 526: * if found, check it for access permission. ! 527: * ! 528: * check file access permissions ! 529: * if ! in name assume that access on local machine is required ! 530: * ! 531: * Return: ! 532: * BAD_FILE - not permitted ! 533: * 0 - ok ! 534: */ ! 535: ! 536: static ! 537: int ! 538: chkFile(prm) ! 539: char *prm; ! 540: { ! 541: char *p, buf[BUFSIZ]; ! 542: ! 543: (void) strcpy(buf, prm); ! 544: switch(*prm) { ! 545: case '~': ! 546: case '/': ! 547: if (doFileChk(buf)) ! 548: return(BAD_FILE); ! 549: else ! 550: return(0); ! 551: /*NOTREACHED*/ ! 552: ! 553: case '!': ! 554: return(chkFile(buf+1)); ! 555: /*NOTREACHED*/ ! 556: ! 557: default: ! 558: break; ! 559: } ! 560: ! 561: if ( (p =strchr(buf, '!')) == NULL) { /* no "!", look for "/" */ ! 562: if ( (p = strchr(buf, '/')) == NULL) { /* ok */ ! 563: return(0); ! 564: } ! 565: if (doFileChk(p)) ! 566: return(BAD_FILE); ! 567: else ! 568: return(0); ! 569: } ! 570: ! 571: /* there is at least one '!' - see if it refers to my system */ ! 572: if (PREFIX(Myname, buf)) /* my system so far, check further */ ! 573: return(chkFile(p+1)); /* recurse with thing after '!' */ ! 574: else /* not my system - not my worry */ ! 575: return(0); ! 576: } ! 577: ! 578: /* doFileChk - check file path permission ! 579: * NOTE: file is assumed to be a buffer that expfile an ! 580: * write into. ! 581: * Return ! 582: * BAD_FILE - not allowed ! 583: * 0 - ok ! 584: */ ! 585: ! 586: static ! 587: int ! 588: doFileChk(file) ! 589: char *file; ! 590: { ! 591: expfile(file); ! 592: DEBUG(7, "fullname: %s\n", file); ! 593: if (chkpth(file, CK_READ) == FAIL ! 594: || chkpth(file, CK_WRITE) == FAIL ) ! 595: return(BAD_FILE); ! 596: else ! 597: return(0); ! 598: } ! 599: ! 600: ! 601: /* ! 602: * return stuff to user ! 603: * user -> user to notify ! 604: * rmt -> system name where user resides ! 605: * file -> file to return (generally contains input) ! 606: * cmd -> command that was to be executed ! 607: * buf -> user friendly face saving uplifting edifying missive ! 608: * errfile -> stderr output from cmd xeqn ! 609: * return: ! 610: * none ! 611: */ ! 612: static void ! 613: retosndr(user, rmt, file, cmd, buf, errfile) ! 614: char *user, *rmt, *file, *cmd, *buf, *errfile; ! 615: { ! 616: char ruser[BUFSIZ], msg[BUFSIZ]; ! 617: ! 618: (void) sprintf(msg, ! 619: "remote execution\t[uucp job %s (%s)]\n\t%s\n%s\n", ! 620: &_Xfile[2], timeStamp(), cmd, buf); ! 621: ! 622: DEBUG(5, "retosndr %s, ", msg); ! 623: ! 624: if (EQUALS(rmt, Myname)) ! 625: (void) strcpy(ruser, user); ! 626: else ! 627: (void) sprintf(ruser, "%s!%s", rmt, user); ! 628: ! 629: mailst(ruser, msg, file, errfile); ! 630: } ! 631: ! 632: ! 633: /* ! 634: * uucpst - send the status message back using a uucp command ! 635: * NOTE - this would be better if the file could be appended. ! 636: * - suggestion for the future - if rmail would take a file name ! 637: * instead of just person, then that facility would be correct, ! 638: * and this routine would not be needed. ! 639: */ ! 640: ! 641: static ! 642: void ! 643: uucpst(rmt, tofile, errfile, cmd, buf) ! 644: char *rmt, *tofile, *errfile, *cmd, *buf; ! 645: { ! 646: char arg[MAXFULLNAME], tmp[MAXBASENAME], msg[BUFSIZ]; ! 647: int ret; ! 648: FILE *fp, *fi; ! 649: int pid, rpid; ! 650: ! 651: (void) sprintf(msg, ! 652: "uucp job %s (%s) remote execution\n\t%s\n%s\n", ! 653: &_Xfile[2], timeStamp(), cmd, buf); ! 654: ! 655: (void) sprintf(tmp, "%s.%d", rmt, getpid()); ! 656: if ((fp = fopen(tmp, "w")) == NULL) ! 657: return; ! 658: (void) fprintf(fp, "%s\n", msg); ! 659: ! 660: /* copy back stderr */ ! 661: if (*errfile != '\0' && NOTEMPTY(errfile) ! 662: && (fi = fopen(errfile, "r")) != NULL) { ! 663: fputs("\n\t===== stderr was =====\n", fp); ! 664: if (xfappend(fi, fp) != SUCCESS) ! 665: fputs("\n\t===== well, i tried =====\n", fp); ! 666: (void) fclose(fi); ! 667: fputc('\n', fp); ! 668: } ! 669: ! 670: ! 671: (void) fclose(fp); ! 672: (void) sprintf(arg, "%s!%s", rmt, tofile); ! 673: ! 674: /* start uucp */ ! 675: ! 676: if ((pid = fork()) == 0) { ! 677: (void) close(0); ! 678: (void) close(1); ! 679: (void) close(2); ! 680: (void) open("/dev/null", 2); ! 681: (void) open("/dev/null", 2); ! 682: (void) open("/dev/null", 2); ! 683: #ifdef V8 ! 684: (void) close(3); ! 685: (void) open("/dev/null", 2); ! 686: #endif ! 687: (void) signal(SIGINT, SIG_IGN); ! 688: (void) signal(SIGHUP, SIG_IGN); ! 689: (void) signal(SIGQUIT, SIG_IGN); ! 690: closelog(); ! 691: ! 692: (void) execle("/usr/bin/uucp", "UUCP", ! 693: "-C", tmp, arg, 0, Env); ! 694: (void) _exit(100); ! 695: } ! 696: ! 697: while ((rpid = wait(&ret)) > 0 && rpid != pid) ! 698: ; ! 699: (void) unlink(tmp); ! 700: return; ! 701: } ! 702: ! 703: static ! 704: xprocess(dirname) ! 705: char *dirname; ! 706: { ! 707: int return_stdin; /* return stdin for failed commands */ ! 708: int cmdok, mask, ret, badfiles; ! 709: int send_zero; /* return successful completion status */ ! 710: int send_nonzero; /* return unsuccessful completion status */ ! 711: int send_nothing; /* request for no exit status */ ! 712: int store_status; /* store status of command in local file */ ! 713: char lbuf[BUFSIZ]; ! 714: char *p; ! 715: char dfile[MAXFULLNAME], cfile[MAXFULLNAME], incmd[BUFSIZ]; ! 716: char errDfile[BUFSIZ]; ! 717: char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME]; ! 718: char file[MAXNAMESIZE], tempname[NAMESIZE]; ! 719: char _Sfile[MAXFULLNAME]; /* name of local file for status */ ! 720: FILE *xfp, *dfp, *fp, *errdfp; ! 721: struct stat sb; ! 722: char buf[BUFSIZ], user[BUFSIZ], retaddr[BUFSIZ], msgbuf[BUFSIZ]; ! 723: ! 724: (void) strcpy(Rmtname, dirname); ! 725: chremdir(Rmtname); ! 726: (void) mchFind(Rmtname); ! 727: while (gt_Xfile(_Xfile, RemSpool) > 0) { ! 728: DEBUG(4, "_Xfile - %s\n", _Xfile); ! 729: ! 730: if ( (xfp = fopen(_Xfile, "r")) == NULL) { ! 731: toCorrupt(_Xfile); ! 732: continue; ! 733: } ! 734: ASSERT(xfp != NULL, Ct_OPEN, _Xfile, errno); ! 735: ! 736: if (stat(_Xfile, &sb) != -1) ! 737: Nstat.t_qtime = sb.st_mtime; ! 738: /* ! 739: * initialize to defaults ! 740: */ ! 741: (void) strcpy(user, User); ! 742: (void) strcpy(fin, "/dev/null"); ! 743: (void) strcpy(fout, "/dev/null"); ! 744: (void) sprintf(sysout, "%.*s", MAXBASENAME, Myname); ! 745: badfiles = 0; ! 746: *incmd = *retaddr = NULLCHAR; ! 747: (void) initSeq(); ! 748: send_zero = send_nonzero = send_nothing = store_status = return_stdin = 0; ! 749: ! 750: while (fgets(buf, BUFSIZ, xfp) != NULL) { ! 751: /* ! 752: * interpret JCL card ! 753: */ ! 754: switch (buf[0]) { ! 755: case X_USER: /* user name */ ! 756: /* ignore Rmtname -- i don't believe it */ ! 757: (void) sscanf(&buf[1], "%s", user); ! 758: break; ! 759: ! 760: case X_STDIN: /* standard input */ ! 761: (void) sscanf(&buf[1], "%s", fin); ! 762: expfile(fin); ! 763: if (chkpth(fin, CK_READ)) { ! 764: DEBUG(4, "badfile - in: %s\n", fin); ! 765: badfiles = 1; ! 766: } ! 767: break; ! 768: ! 769: case X_STDOUT: /* standard output */ ! 770: (void) sscanf(&buf[1], "%s%s", fout, sysout); ! 771: if ((p = strpbrk(sysout, "!/")) != NULL) ! 772: *p = NULLCHAR; /* these can hurt! */ ! 773: if (*sysout != NULLCHAR && !EQUALS(sysout, Myname)) ! 774: break; ! 775: ! 776: expfile(fout); ! 777: if (chkpth(fout, CK_WRITE)) { ! 778: badfiles = 1; ! 779: DEBUG(4, "badfile - out: %s\n", fout); ! 780: } ! 781: break; ! 782: ! 783: ! 784: case X_CMD: /* command to execute */ ! 785: (void) strcpy(incmd, &buf[2]); ! 786: if (*(incmd + strlen(incmd) - 1) == '\n') ! 787: *(incmd + strlen(incmd) - 1) = NULLCHAR; ! 788: break; ! 789: ! 790: case X_MAILF: /* put status in _Sfile */ ! 791: store_status = 1; ! 792: (void) sscanf(&buf[1], "%s", _Sfile); ! 793: break; ! 794: ! 795: case X_SENDNOTHING: /* no failure notification */ ! 796: send_nothing++; ! 797: break; ! 798: ! 799: case X_SENDZERO: /* success notification */ ! 800: send_zero++; ! 801: break; ! 802: ! 803: case X_NONZERO: /* failure notification */ ! 804: send_nonzero++; ! 805: break; ! 806: ! 807: case X_BRINGBACK: /* return stdin on command failure */ ! 808: return_stdin = 1; ! 809: break; ! 810: ! 811: ! 812: case X_RETADDR: /* return address */ ! 813: (void) sscanf(&buf[1], "%s", retaddr); ! 814: break; ! 815: ! 816: default: ! 817: break; ! 818: } ! 819: } ! 820: ! 821: fclose(xfp); ! 822: DEBUG(4, "fin - %s, ", fin); ! 823: DEBUG(4, "fout - %s, ", fout); ! 824: DEBUG(4, "sysout - %s, ", sysout); ! 825: DEBUG(4, "user - %s\n", user); ! 826: DEBUG(4, "incmd - %s\n", incmd); ! 827: ! 828: if (retaddr[0] != NULLCHAR) ! 829: (void) strcpy(user, retaddr); /* pick on this guy */ ! 830: ! 831: /* get rid of stuff that can hurt */ ! 832: if ( (p = strpbrk(user, frogs)) != NULL) ! 833: *p = NULLCHAR; ! 834: if (incmd[0] == NULLCHAR) { ! 835: /* this is a bad X. file - just get rid of it */ ! 836: toCorrupt(_Xfile); ! 837: continue; ! 838: } ! 839: ! 840: /* ! 841: * send_nothing must be explicitly requested to avert failure status ! 842: * send_zero must be explicitly requested for success notification ! 843: */ ! 844: if (!send_nothing) ! 845: send_nonzero++; ! 846: ! 847: /* ! 848: * command execution ! 849: * generate a temporary file (if necessary) ! 850: * to hold output to be shipped back ! 851: */ ! 852: if (EQUALS(fout, "/dev/null")) ! 853: (void) strcpy(dfile, "/dev/null"); ! 854: else { ! 855: gename(DATAPRE, sysout, 'O', tempname); ! 856: (void) sprintf(dfile, "%s/%s", WORKSPACE, tempname); ! 857: } ! 858: ! 859: /* initialize command line */ ! 860: /* set up two environment variables, remote machine name */ ! 861: /* and remote user name if available from R line */ ! 862: (void) sprintf(_Cmd, ! 863: "%s %s UU_MACHINE=%s UU_USER=%s export UU_MACHINE UU_USER PATH; exec ", ! 864: PATH, LOGNAME, Rmtname, user); ! 865: ! 866: /* ! 867: * check to see if command can be executed ! 868: */ ! 869: _CargType = C_COMMAND; /* the first thing is a command */ ! 870: cmdok = chkpart(incmd); ! 871: ! 872: if (badfiles || (cmdok == BAD_COMMAND) || cmdok == BAD_FILE) { ! 873: if (cmdok == BAD_COMMAND) { ! 874: (void) sprintf(lbuf, "%s XQT DENIED", user); ! 875: (void) sprintf(msgbuf, "execution permission denied to %s", user); ! 876: } else { ! 877: (void) sprintf(lbuf, ! 878: "%s XQT- STDIN(%s)/STDOUT/FILE ACCESS DENIED", user, fin); ! 879: (void) sprintf(msgbuf, "file access denied to %s", user); ! 880: } ! 881: return_stdin = 0; /* it might not be his data */ ! 882: logent(incmd, lbuf); ! 883: DEBUG(4, "bad command %s\n", incmd); ! 884: ! 885: if (send_nonzero) ! 886: retosndr(user, Rmtname, return_stdin ? fin : "", incmd, msgbuf, ""); ! 887: if (store_status) ! 888: uucpst(Rmtname, _Sfile, "", incmd, msgbuf); ! 889: goto rmfiles; ! 890: } ! 891: ! 892: (void) sprintf(lbuf, "%s XQT <%s >%s", user, fin, fout); ! 893: logent(_Cmd, lbuf); ! 894: DEBUG(4, "cmd %s\n", _Cmd); ! 895: ! 896: /* move files to execute directory and change to that directory */ ! 897: ! 898: mv_Xfiles(); ! 899: ! 900: ASSERT(chdir(XQTDIR) == 0, Ct_CHDIR, XQTDIR, errno); ! 901: ! 902: /* invoke shell to execute command */ ! 903: ! 904: mask = umask(0); ! 905: DEBUG(7, "full cmd: %s\n", _Cmd); ! 906: ! 907: /* temp file to capture error output */ ! 908: gename(DATAPRE, sysout, 'E', tempname); ! 909: (void) sprintf(errDfile, "%s/%s", WORKSPACE, tempname); ! 910: ret = shio(_Cmd, fin, dfile, errDfile); ! 911: umask(mask); ! 912: if (ret == -1) { /* -1 means the fork() failed */ ! 913: unmv_Xfiles(); /* put things back */ ! 914: errent(Ct_FORK, buf, errno, sccsid, __FILE__, __LINE__); ! 915: cleanup(1); /* g'nite! */ ! 916: } ! 917: ! 918: if (ret == 0) { /* exit == signal == 0 */ ! 919: (void) strcpy(msgbuf, "exited normally"); ! 920: if (send_zero) ! 921: retosndr(user, Rmtname, "", incmd, msgbuf, ""); ! 922: if (store_status) ! 923: uucpst(Rmtname, _Sfile, "", incmd, msgbuf); ! 924: } else { /* exit != 0 */ ! 925: int exitcode = (ret >> 8) & 0377; ! 926: ! 927: if (exitcode) /* exit != 0 */ ! 928: (void) sprintf(msgbuf, "exited with status %d", exitcode); ! 929: else /* signal != 0 */ ! 930: (void) sprintf(msgbuf, "terminated by signal %d", ret & 0177); ! 931: DEBUG(5, "%s\n", msgbuf); ! 932: ! 933: if (send_nonzero) ! 934: retosndr(user, Rmtname, return_stdin ? fin : "", incmd, msgbuf, errDfile); ! 935: if (store_status) ! 936: uucpst(Rmtname, _Sfile, errDfile, incmd, msgbuf); ! 937: ! 938: (void) sprintf(lbuf, "%s - %s", incmd, msgbuf); ! 939: logent(lbuf, "COMMAND FAIL"); ! 940: } ! 941: ! 942: /* change back to spool directory */ ! 943: ! 944: chremdir(Rmtname); ! 945: ! 946: /* remove file */ ! 947: ! 948: rm_Xfiles(); ! 949: ! 950: if (ret != 0) { ! 951: /* ! 952: * exit status not zero, ! 953: * so append bad news message and stderr to returned data ! 954: */ ! 955: if (access(dfile, 0) != 0) ! 956: close(creat(dfile, DFILEMODE)); ! 957: dfp = fopen(dfile, "a"); ! 958: ASSERT(dfp != NULL, Ct_OPEN, dfile, errno); ! 959: if (NOTEMPTY(errDfile) && (errdfp = fopen(errDfile, "r")) != NULL) { ! 960: (void) fprintf(dfp, "%s\n\t===== error output =====\n", msgbuf); ! 961: (void) xfappend(errdfp, dfp); /* who cares if it fails? */ ! 962: (void) fclose(errdfp); ! 963: } ! 964: (void) fclose(dfp); ! 965: } ! 966: ! 967: if (!EQUALS(fout, "/dev/null")) { ! 968: /* ! 969: * if output is on this machine copy output ! 970: * there, otherwise spawn job to send to send ! 971: * output elsewhere. ! 972: */ ! 973: ! 974: if (EQUALS(sysout, Myname)) { ! 975: xmv(dfile, fout); ! 976: } ! 977: else { ! 978: gename(CMDPRE, sysout, 'O', tempname); ! 979: (void) sprintf(cfile, "%s/%s", WORKSPACE, tempname); ! 980: fp = fdopen(ret = creat(cfile, CFILEMODE), "w"); ! 981: ASSERT(ret >= 0 && fp != NULL, Ct_OPEN, cfile, errno); ! 982: (void) fprintf(fp, "S %s %s %s -d %s 0666\n", ! 983: BASENAME(dfile, '/'), fout, user, BASENAME(dfile, '/')); ! 984: fclose(fp); ! 985: wfcommit(dfile, BASENAME(dfile, '/'), sysout); ! 986: wfcommit(cfile, BASENAME(cfile, '/'), sysout); ! 987: } ! 988: } ! 989: rmfiles: ! 990: ! 991: /* delete job files in spool directory */ ! 992: xfp = fopen(_Xfile, "r"); ! 993: ASSERT(xfp != NULL, Ct_OPEN, _Xfile, errno); ! 994: while (fgets(buf, BUFSIZ, xfp) != NULL) { ! 995: if (buf[0] != X_RQDFILE) ! 996: continue; ! 997: (void) sscanf(&buf[1], "%s", file); ! 998: (void) unlink(file); ! 999: } ! 1000: (void) unlink(_Xfile); ! 1001: fclose(xfp); ! 1002: unlink(errDfile); ! 1003: } ! 1004: } ! 1005: ! 1006: ! 1007: /* ! 1008: * return the number of files in directory <dir> who's names ! 1009: * begin with <prefix> ! 1010: * This is used to count the number of uuxqts currently running. ! 1011: * ! 1012: */ ! 1013: ! 1014: cuantos(prefix, dir) ! 1015: char *prefix, *dir; ! 1016: { ! 1017: int i = 0; ! 1018: DIR *pdir; ! 1019: char fullname[MAXNAMESIZE], file[MAXNAMESIZE]; ! 1020: ! 1021: pdir = opendir(dir); ! 1022: ASSERT(pdir != NULL, Ct_OPEN, dir, errno); ! 1023: ! 1024: while (gnamef(pdir, file) == TRUE) ! 1025: if (PREFIX(prefix, file)) { ! 1026: (void) sprintf(fullname, "%s/%s", dir, file); ! 1027: if (checkLock(fullname)) ! 1028: i++; ! 1029: } ! 1030: closedir(pdir); ! 1031: return(i); ! 1032: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.