1: #ifndef lint 2: static char sccsid[] = "@(#)cico.c 5.14 (Berkeley) 4/14/86"; 3: #endif 4: 5: #include <signal.h> 6: #include "uucp.h" 7: #include <setjmp.h> 8: #ifdef USG 9: #include <termio.h> 10: #endif 11: #ifndef USG 12: #include <sgtty.h> 13: #endif 14: #ifdef BSDTCP 15: #include <netdb.h> 16: #include <netinet/in.h> 17: #include <sys/socket.h> 18: #endif BSDTCP 19: #include <sys/stat.h> 20: #include "uust.h" 21: #include "uusub.h" 22: 23: #if defined(VMS) && defined(BSDTCP) 24: #define NOGETPEER 25: #endif 26: 27: #ifdef BSD2_9 28: #define NOGETPEER 29: #endif 30: 31: jmp_buf Sjbuf; 32: jmp_buf Pipebuf; 33: 34: /* call fail text */ 35: char *Stattext[] = { 36: "", 37: "BAD SYSTEM", 38: "WRONG TIME TO CALL", 39: "SYSTEM LOCKED", 40: "NO DEVICE", 41: "CALL FAILED", 42: "LOGIN FAILED", 43: "BAD SEQUENCE" 44: }; 45: 46: /* call fail codes */ 47: int Stattype[] = { 48: 0, 49: 0, 50: SS_WRONGTIME, 51: 0, 52: SS_NODEVICE, 53: SS_FAIL, 54: SS_FAIL, 55: SS_BADSEQ 56: }; 57: 58: /* Arguments to setdebug(): */ 59: #define DBG_TEMP 0 /* Create a temporary audit file */ 60: #define DBG_PERM 1 /* Create a permanent audit file */ 61: #define DBG_CLEAN 2 /* Cleanup, discard temp file */ 62: 63: int ReverseRole = 0; 64: int Role = SLAVE; 65: int onesys = 0; 66: int turntime = 30 * 60; /* 30 minutes expressed in seconds */ 67: char *ttyn = NULL; 68: extern int LocalOnly; 69: extern int errno; 70: extern char MaxGrade, DefMaxGrade; 71: extern char Myfullname[]; 72: 73: #ifdef USG 74: struct termio Savettyb; 75: #endif 76: #ifndef USG 77: struct sgttyb Savettyb; 78: #endif 79: 80: /* 81: * this program is used to place a call to a 82: * remote machine, login, and copy files between the two machines. 83: */ 84: main(argc, argv) 85: int argc; 86: register char *argv[]; 87: { 88: register int ret; 89: int seq; 90: char wkpre[NAMESIZE], file[NAMESIZE]; 91: char msg[MAXFULLNAME], *q; 92: register char *p; 93: extern onintr(), timeout(), dbg_signal(); 94: extern char *pskip(); 95: char rflags[MAXFULLNAME]; 96: #ifdef NOGETPEER 97: u_long Hostnumber = 0; 98: #endif NOGETPEER 99: 100: strcpy(Progname, "uucico"); 101: 102: #ifdef BSD4_2 103: sigsetmask(0); /* in case we inherit blocked signals */ 104: #endif BSD4_2 105: signal(SIGINT, onintr); 106: signal(SIGHUP, onintr); 107: signal(SIGQUIT, onintr); 108: signal(SIGTERM, onintr); 109: signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */ 110: signal(SIGFPE, dbg_signal); 111: ret = guinfo(getuid(), User, msg); 112: strcpy(Loginuser, User); 113: uucpname(Myname); 114: ASSERT(ret == 0, "BAD UID", CNULL, ret); 115: 116: setbuf (stderr, CNULL); 117: 118: rflags[0] = '\0'; 119: umask(WFMASK); 120: strcpy(Rmtname, Myname); 121: Ifn = Ofn = -1; 122: while(argc>1 && argv[1][0] == '-'){ 123: switch(argv[1][1]){ 124: case 'd': 125: Spool = &argv[1][2]; 126: break; 127: case 'g': 128: case 'p': 129: MaxGrade = DefMaxGrade = argv[1][2]; 130: break; 131: case 'r': 132: Role = atoi(&argv[1][2]); 133: break; 134: case 'R': 135: ReverseRole++; 136: Role = MASTER; 137: break; 138: case 's': 139: strncpy(Rmtname, &argv[1][2], MAXBASENAME); 140: Rmtname[MAXBASENAME] = '\0'; 141: if (Rmtname[0] != '\0') 142: onesys = 1; 143: break; 144: case 'x': 145: Debug = atoi(&argv[1][2]); 146: if (Debug <= 0) 147: Debug = 1; 148: strcat(rflags, argv[1]); 149: break; 150: case 't': 151: turntime = atoi(&argv[1][2])*60;/* minutes to seconds */ 152: break; 153: case 'L': /* local calls only */ 154: LocalOnly++; 155: break; 156: #ifdef NOGETPEER 157: case 'h': 158: Hostnumber = inet_addr(&argv[1][2]); 159: break; 160: #endif NOGETPEER 161: default: 162: printf("unknown flag %s (ignored)\n", argv[1]); 163: break; 164: } 165: --argc; argv++; 166: } 167: 168: while (argc > 1) { 169: fprintf(stderr, "unknown argument %s (ignored)\n", argv[1]); 170: --argc; argv++; 171: } 172: 173: if (Debug && Role == MASTER) 174: chkdebug(); 175: 176: /* Try to run as uucp */ 177: setgid(getegid()); 178: setuid(geteuid()); 179: #ifdef TIOCNOTTY 180: /* 181: * detach uucico from controlling terminal 182: * to defend against rlogind sending us a SIGKILL (!!!) 183: */ 184: if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) { 185: ioctl(ret, TIOCNOTTY, STBNULL); 186: close(ret); 187: } 188: #endif TIOCNOTTY 189: #ifdef BSD4_2 190: if (getpgrp(0) == 0) { /* We have no controlling terminal */ 191: setpgrp(0, getpid()); 192: } 193: #endif BSD4_2 194: 195: ret = subchdir(Spool); 196: ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret); 197: strcpy(Wrkdir, Spool); 198: 199: if (Debug) { 200: setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM); 201: if (Debug > 0) 202: logent ("Local Enabled", "DEBUG"); 203: } 204: 205: /* 206: * First time through: If we're the slave, do initial checking. 207: */ 208: if (Role == SLAVE) { 209: /* check for /etc/nologin */ 210: if (access(NOLOGIN, 0) == 0) { 211: logent(NOLOGIN, "UUCICO SHUTDOWN"); 212: if (Debug > 4) 213: logent("DEBUGGING", "continuing anyway"); 214: else 215: cleanup(1); 216: } 217: Ifn = 0; 218: Ofn = 1; 219: #ifdef TCPIP 220: /* 221: * Determine if we are on TCPIP 222: */ 223: if (isatty(Ifn) < 0) { 224: IsTcpIp = 1; 225: DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); 226: } else 227: IsTcpIp = 0; 228: #endif TCPIP 229: /* initial handshake */ 230: onesys = 1; 231: if (!IsTcpIp) { 232: #ifdef USG 233: ret = ioctl(Ifn, TCGETA, &Savettyb); 234: Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7; 235: Savettyb.c_oflag |= OPOST; 236: Savettyb.c_lflag |= (ISIG|ICANON|ECHO); 237: #else !USG 238: ret = ioctl(Ifn, TIOCGETP, &Savettyb); 239: Savettyb.sg_flags |= ECHO; 240: Savettyb.sg_flags &= ~RAW; 241: #endif !USG 242: ttyn = ttyname(Ifn); 243: } 244: fixmode(Ifn); 245: 246: /* 247: * Initial Message -- tell them we're here, and who we are. 248: */ 249: sprintf(msg, "here=%s", Myfullname); 250: omsg('S', msg, Ofn); 251: signal(SIGALRM, timeout); 252: alarm(MAXMSGTIME); 253: if (setjmp(Sjbuf)) { 254: /* timed out */ 255: if (!IsTcpIp) { 256: #ifdef USG 257: ret = ioctl(Ifn, TCSETA, &Savettyb); 258: 259: #else !USG 260: ret = ioctl(Ifn, TIOCSETP, &Savettyb); 261: #endif !USG 262: } 263: cleanup(0); 264: } 265: for (;;) { 266: ret = imsg(msg, Ifn); 267: if (ret != SUCCESS) { 268: alarm(0); 269: if (!IsTcpIp) { 270: #ifdef USG 271: ret = ioctl(Ifn, TCSETA, &Savettyb); 272: #else !USG 273: ret = ioctl(Ifn, TIOCSETP, &Savettyb); 274: #endif !USG 275: } 276: cleanup(0); 277: } 278: if (msg[0] == 'S') 279: break; 280: } 281: alarm(0); 282: q = &msg[1]; 283: p = pskip(q); 284: strncpy(Rmtname, q, MAXBASENAME); 285: Rmtname[MAXBASENAME] = '\0'; 286: 287: /* 288: * Now that we know who they are, give the audit file the right 289: * name. 290: */ 291: setdebug (DBG_PERM); 292: DEBUG(4, "sys-%s\n", Rmtname); 293: /* The versys will also do an alias on the incoming name */ 294: if (versys(&Rmtname)) { 295: /* If we don't know them, we won't talk to them... */ 296: #ifdef NOSTRANGERS 297: logent(Rmtname, "UNKNOWN HOST"); 298: omsg('R', "You are unknown to me", Ofn); 299: cleanup(0); 300: #endif NOSTRANGERS 301: } 302: #ifdef BSDTCP 303: /* we must make sure they are really who they say they 304: * are. We compare the hostnumber with the number in the hosts 305: * table for the site they claim to be. 306: */ 307: if (IsTcpIp) { 308: struct hostent *hp; 309: char *cpnt, *inet_ntoa(); 310: int fromlen; 311: struct sockaddr_in from; 312: extern char PhoneNumber[]; 313: 314: #ifdef NOGETPEER 315: from.sin_addr.s_addr = Hostnumber; 316: from.sin_family = AF_INET; 317: #else !NOGETPEER 318: fromlen = sizeof(from); 319: if (getpeername(Ifn, &from, &fromlen) < 0) { 320: logent(Rmtname, "NOT A TCP CONNECTION"); 321: omsg('R', "NOT TCP", Ofn); 322: cleanup(0); 323: } 324: #endif !NOGETPEER 325: hp = gethostbyaddr(&from.sin_addr, 326: sizeof (struct in_addr), from.sin_family); 327: if (hp == NULL) { 328: /* security break or just old host table? */ 329: logent(Rmtname, "UNKNOWN IP-HOST Name ="); 330: cpnt = inet_ntoa(from.sin_addr), 331: logent(cpnt, "UNKNOWN IP-HOST Number ="); 332: sprintf(wkpre, "%s/%s isn't in my host table", 333: Rmtname, cpnt); 334: omsg('R' ,wkpre ,Ofn); 335: cleanup(0); 336: } 337: if (Debug > 99) 338: logent(Rmtname,"Request from IP-Host name ="); 339: /* 340: * The following is to determine if the name given us by 341: * the Remote uucico matches any of the names 342: * given its network number (remote machine) in our 343: * host table. 344: * We could check the aliases, but that won't work in 345: * all cases (like if you are running the domain 346: * server, where you don't get any aliases). The only 347: * reliable way I can think of that works in ALL cases 348: * is too look up the site in L.sys and see if the 349: * sitename matches what we would call him if we 350: * originated the call. 351: */ 352: /* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */ 353: if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) { 354: if (Debug > 99) 355: logent(q,"Found in host Tables"); 356: } else { 357: logent(hp->h_name, "FORGED HOSTNAME"); 358: logent(inet_ntoa(from.sin_addr), "ORIGINATED AT"); 359: logent(PhoneNumber, "SHOULD BE"); 360: sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber); 361: omsg('R', wkpre, Ofn); 362: cleanup(0); 363: } 364: } 365: #endif BSDTCP 366: 367: if (mlock(Rmtname)) { 368: omsg('R', "LCK", Ofn); 369: cleanup(0); 370: } 371: else if (callback(Loginuser)) { 372: signal(SIGINT, SIG_IGN); 373: signal(SIGHUP, SIG_IGN); 374: omsg('R', "CB", Ofn); 375: logent("CALLBACK", "REQUIRED"); 376: /* set up for call back */ 377: systat(Rmtname, SS_CALLBACK, "CALLING BACK"); 378: gename(CMDPRE, Rmtname, 'C', file); 379: close(creat(subfile(file), 0666)); 380: xuucico(Rmtname); 381: cleanup(0); 382: } 383: seq = 0; 384: while (*p == '-') { 385: q = pskip(p); 386: switch(*(++p)) { 387: case 'x': 388: if (Debug == 0) { 389: Debug = atoi(++p); 390: if (Debug <= 0) 391: Debug = 1; 392: setdebug(DBG_PERM); 393: if (Debug > 0) 394: logent("Remote Enabled", "DEBUG"); 395: } else { 396: DEBUG(1, "Remote debug request ignored\n", 397: CNULL); 398: } 399: break; 400: case 'Q': 401: seq = atoi(++p); 402: break; 403: case 'p': 404: MaxGrade = DefMaxGrade = *++p; 405: DEBUG(4, "MaxGrade set to %c\n", MaxGrade); 406: break; 407: case 'v': 408: if (strncmp(p, "grade", 5) == 0) { 409: p += 6; 410: MaxGrade = DefMaxGrade = *p++; 411: DEBUG(4, "MaxGrade set to %c\n", MaxGrade); 412: } 413: break; 414: default: 415: break; 416: } 417: p = q; 418: } 419: if (callok(Rmtname) == SS_BADSEQ) { 420: logent("BADSEQ", "PREVIOUS"); 421: omsg('R', "BADSEQ", Ofn); 422: cleanup(0); 423: } 424: #ifdef GNXSEQ 425: if ((ret = gnxseq(Rmtname)) == seq) { 426: omsg('R', "OK", Ofn); 427: cmtseq(); 428: } else { 429: #else !GNXSEQ 430: if (seq == 0) 431: omsg('R', "OK", Ofn); 432: else { 433: #endif !GNXSEQ 434: systat(Rmtname, Stattype[7], Stattext[7]); 435: logent("BAD SEQ", "FAILED HANDSHAKE"); 436: #ifdef GNXSEQ 437: ulkseq(); 438: #endif GNXSEQ 439: omsg('R', "BADSEQ", Ofn); 440: cleanup(0); 441: } 442: if (ttyn != NULL) 443: chmod(ttyn, 0600); 444: } 445: 446: loop: 447: if(setjmp(Pipebuf)) { /* come here on SIGPIPE */ 448: clsacu(); 449: close(Ofn); 450: close(Ifn); 451: Ifn = Ofn = -1; 452: rmlock(CNULL); 453: sleep(3); 454: } 455: if (!onesys) { 456: ret = gnsys(Rmtname, Spool, CMDPRE); 457: setdebug(DBG_PERM); 458: if (ret == FAIL) 459: cleanup(100); 460: if (ret == SUCCESS) 461: cleanup(0); 462: } else if (Role == MASTER && callok(Rmtname) != 0) { 463: logent("SYSTEM STATUS", "CAN NOT CALL"); 464: cleanup(0); 465: } 466: 467: sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); 468: 469: signal(SIGINT, SIG_IGN); 470: signal(SIGQUIT, SIG_IGN); 471: if (Role == MASTER) { 472: /* check for /etc/nologin */ 473: if (access(NOLOGIN, 0) == 0) { 474: logent(NOLOGIN, "UUCICO SHUTDOWN"); 475: if (Debug > 4) 476: logent("DEBUGGING", "continuing anyway"); 477: else 478: cleanup(1); 479: } 480: /* master part */ 481: signal(SIGHUP, SIG_IGN); 482: if (Ifn != -1 && Role == MASTER) { 483: write(Ofn, EOTMSG, strlen(EOTMSG)); 484: clsacu(); 485: close(Ofn); 486: close(Ifn); 487: Ifn = Ofn = -1; 488: rmlock(CNULL); 489: sleep(3); 490: } 491: sprintf(msg, "call to %s ", Rmtname); 492: if (mlock(Rmtname) != SUCCESS) { 493: logent(msg, "LOCKED"); 494: US_SST(us_s_lock); 495: goto next; 496: } 497: Ofn = Ifn = conn(Rmtname); 498: if (Ofn < 0) { 499: if (Ofn != CF_TIME) 500: logent(msg, _FAILED); 501: /* avoid excessive 'wrong time' info */ 502: if (Stattype[-Ofn] != SS_WRONGTIME){ 503: systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]); 504: US_SST(-Ofn); 505: UB_SST(-Ofn); 506: } 507: goto next; 508: } else { 509: logent(msg, "SUCCEEDED"); 510: US_SST(us_s_cok); 511: UB_SST(ub_ok); 512: } 513: #ifdef TCPIP 514: /* 515: * Determine if we are on TCPIP 516: */ 517: if (isatty(Ifn) == 0) { 518: IsTcpIp = 1; 519: DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); 520: } else 521: IsTcpIp = 0; 522: #endif 523: 524: if (setjmp(Sjbuf)) 525: goto next; 526: signal(SIGALRM, timeout); 527: alarm(2 * MAXMSGTIME); 528: for (;;) { 529: ret = imsg(msg, Ifn); 530: if (ret != 0) { 531: alarm(0); 532: logent("imsg 1", _FAILED); 533: goto Failure; 534: } 535: if (msg[0] == 'S') 536: break; 537: } 538: alarm(MAXMSGTIME); 539: #ifdef GNXSEQ 540: seq = gnxseq(Rmtname); 541: #else !GNXSEQ 542: seq = 0; 543: #endif !GNXSEQ 544: if (MaxGrade != '\177') { 545: DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade); 546: sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s", 547: Myname, seq, MaxGrade, MaxGrade, rflags); 548: } else 549: sprintf(msg, "%s -Q%d %s", Myname, seq, rflags); 550: omsg('S', msg, Ofn); 551: for (;;) { 552: ret = imsg(msg, Ifn); 553: DEBUG(4, "msg-%s\n", msg); 554: if (ret != SUCCESS) { 555: alarm(0); 556: #ifdef GNXSEQ 557: ulkseq(); 558: #endif GNXSEQ 559: logent("imsg 2", _FAILED); 560: goto Failure; 561: } 562: if (msg[0] == 'R') 563: break; 564: } 565: alarm(0); 566: if (msg[1] == 'B') { 567: /* bad sequence */ 568: logent("BAD SEQ", "FAILED HANDSHAKE"); 569: US_SST(us_s_hand); 570: systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]); 571: #ifdef GNXSEQ 572: ulkseq(); 573: #endif GNXSEQ 574: goto next; 575: } 576: if (strcmp(&msg[1], "OK") != SAME) { 577: logent(&msg[1], "FAILED HANDSHAKE"); 578: US_SST(us_s_hand); 579: #ifdef GNXSEQ 580: ulkseq(); 581: #endif GNXSEQ 582: systat(Rmtname, SS_INPROGRESS, 583: strcmp(&msg[1], "CB") == SAME? 584: "AWAITING CALLBACK": "FAILED HANDSHAKE"); 585: goto next; 586: } 587: #ifdef GNXSEQ 588: cmtseq(); 589: #endif GNXSEQ 590: } 591: DEBUG(1, "Rmtname %s, ", Rmtname); 592: DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE"); 593: DEBUG(1, "Ifn - %d, ", Ifn); 594: DEBUG(1, "Loginuser - %s\n", Loginuser); 595: 596: ttyn = ttyname(Ifn); 597: 598: alarm(MAXMSGTIME); 599: if (ret=setjmp(Sjbuf)) 600: goto Failure; 601: ret = startup(Role); 602: alarm(0); 603: if (ret != SUCCESS) { 604: logent("startup", _FAILED); 605: Failure: 606: US_SST(us_s_start); 607: systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" : 608: "STARTUP FAILED"); 609: goto next; 610: } else { 611: if (ttyn != NULL) { 612: char startupmsg[BUFSIZ]; 613: extern int linebaudrate; 614: sprintf(startupmsg, "startup %s %d baud", &ttyn[5], 615: linebaudrate); 616: logent(startupmsg, "OK"); 617: } else 618: logent("startup", "OK"); 619: US_SST(us_s_gress); 620: systat(Rmtname, SS_INPROGRESS, "TALKING"); 621: ret = cntrl(Role, wkpre); 622: DEBUG(1, "cntrl - %d\n", ret); 623: signal(SIGINT, SIG_IGN); 624: signal(SIGHUP, SIG_IGN); 625: signal(SIGALRM, timeout); 626: if (ret == SUCCESS) { 627: logent("conversation complete", "OK"); 628: US_SST(us_s_ok); 629: rmstat(Rmtname); 630: 631: } else { 632: logent("conversation complete", _FAILED); 633: US_SST(us_s_cf); 634: systat(Rmtname, SS_FAIL, "CONVERSATION FAILED"); 635: } 636: alarm(MAXMSGTIME); 637: DEBUG(4, "send OO %d,", ret); 638: if (!setjmp(Sjbuf)) { 639: for (;;) { 640: omsg('O', "OOOOO", Ofn); 641: ret = imsg(msg, Ifn); 642: if (ret != 0) 643: break; 644: if (msg[0] == 'O') 645: break; 646: } 647: } 648: alarm(0); 649: clsacu(); 650: rmlock(CNULL); 651: } 652: next: 653: if (!onesys) { 654: goto loop; 655: } 656: cleanup(0); 657: } 658: 659: #ifndef USG 660: struct sgttyb Hupvec; 661: #endif 662: 663: /* 664: * cleanup and exit with "code" status 665: */ 666: cleanup(code) 667: register int code; 668: { 669: signal(SIGINT, SIG_IGN); 670: signal(SIGHUP, SIG_IGN); 671: rmlock(CNULL); 672: sleep(5); /* Wait for any pending output */ 673: clsacu(); 674: logcls(); 675: if (Role == SLAVE) { 676: if (!IsTcpIp) { 677: #ifdef USG 678: Savettyb.c_cflag |= HUPCL; 679: (void) ioctl(0, TCSETA, &Savettyb); 680: #else !USG 681: (void) ioctl(0, TIOCHPCL, STBNULL); 682: #ifdef TIOCSDTR 683: (void) ioctl(0, TIOCCDTR, STBNULL); 684: sleep(2); 685: (void) ioctl(0, TIOCSDTR, STBNULL); 686: #else !TIOCSDTR 687: (void) ioctl(0, TIOCGETP, &Hupvec); 688: Hupvec.sg_ispeed = B0; 689: Hupvec.sg_ospeed = B0; 690: (void) ioctl(0, TIOCSETP, &Hupvec); 691: #endif !TIOCSDTR 692: sleep(2); 693: (void) ioctl(0, TIOCSETP, &Savettyb); 694: /* make *sure* exclusive access is off */ 695: (void) ioctl(0, TIOCNXCL, STBNULL); 696: #endif !USG 697: } 698: if (ttyn != NULL) 699: chmod(ttyn, 0600); 700: } 701: if (Ofn != -1) { 702: if (Role == MASTER) 703: write(Ofn, EOTMSG, strlen(EOTMSG)); 704: close(Ifn); 705: close(Ofn); 706: } 707: #ifdef DIALINOUT 708: /* reenable logins on dialout */ 709: reenable(); 710: #endif DIALINOUT 711: if (code == 0) 712: xuuxqt(); 713: else 714: DEBUG(1, "exit code %d\n", code); 715: setdebug (DBG_CLEAN); 716: exit(code); 717: } 718: 719: /* 720: * on interrupt - remove locks and exit 721: */ 722: 723: onintr(inter) 724: register int inter; 725: { 726: char str[30]; 727: signal(inter, SIG_IGN); 728: sprintf(str, "SIGNAL %d", inter); 729: logent(str, "CAUGHT"); 730: US_SST(us_s_intr); 731: if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) 732: systat(Rmtname, SS_FAIL, str); 733: if (inter == SIGPIPE && !onesys) 734: longjmp(Pipebuf, 1); 735: cleanup(inter); 736: } 737: 738: /* 739: * Catch a special signal 740: * (SIGFPE, ugh), and toggle debugging between 0 and 30. 741: * Handy for looking in on long running uucicos. 742: */ 743: dbg_signal() 744: { 745: Debug = (Debug == 0) ? 30 : 0; 746: setdebug(DBG_PERM); 747: if (Debug > 0) 748: logent("Signal Enabled", "DEBUG"); 749: } 750: 751: 752: /* 753: * Check debugging requests, and open RMTDEBUG audit file if necessary. If an 754: * audit file is needed, the parm argument indicates how to create the file: 755: * 756: * DBG_TEMP - Open a temporary file, with filename = RMTDEBUG/pid. 757: * DBG_PERM - Open a permanent audit file, filename = RMTDEBUG/Rmtname. 758: * If a temp file already exists, it is mv'ed to be permanent. 759: * DBG_CLEAN - Cleanup; unlink temp files. 760: * 761: * Restrictions - this code can only cope with one open debug file at a time. 762: * Each call creates a new file; if an old one of the same name exists it will 763: * be overwritten. 764: */ 765: setdebug(parm) 766: int parm; 767: { 768: char buf[BUFSIZ]; /* Buffer for building filenames */ 769: static char *temp = NULL; /* Ptr to temporary file name */ 770: static int auditopen = 0; /* Set to 1 when we open a file */ 771: struct stat stbuf; /* File status buffer */ 772: 773: /* 774: * If movement or cleanup of a temp file is indicated, we do it no 775: * matter what. 776: */ 777: if (temp != CNULL && parm == DBG_PERM) { 778: sprintf(buf, "%s/%s", RMTDEBUG, Rmtname); 779: unlink(buf); 780: if (link(temp, buf) != 0) { 781: Debug = 0; 782: assert("RMTDEBUG LINK FAIL", temp, errno); 783: cleanup(1); 784: } 785: parm = DBG_CLEAN; 786: } 787: if (parm == DBG_CLEAN) { 788: if (temp != CNULL) { 789: unlink(temp); 790: free(temp); 791: temp = CNULL; 792: } 793: return; 794: } 795: 796: if (Debug == 0) 797: return; /* Gotta be in debug to come here. */ 798: 799: /* 800: * If we haven't opened a file already, we can just return if it's 801: * alright to use the stderr we came in with. We can if: 802: * 803: * Role == MASTER, and Stderr is a regular file, a TTY or a pipe. 804: * 805: * Caution: Detecting when stderr is a pipe is tricky, because the 4.2 806: * man page for fstat(2) disagrees with reality, and System V leaves it 807: * undefined, which means different implementations act differently. 808: */ 809: if (!auditopen && Role == MASTER) { 810: if (isatty(fileno(stderr))) 811: return; 812: else if (fstat(fileno(stderr), &stbuf) == 0) { 813: #ifdef USG 814: /* Is Regular File or Fifo */ 815: if ((stbuf.st_mode & 0060000) == 0) 816: return; 817: #else !USG 818: #ifdef BSD4_2 819: /* Is Regular File */ 820: if ((stbuf.st_mode & S_IFMT) == S_IFREG || 821: stbuf.st_mode == 0) /* Is a pipe */ 822: return; 823: #else !BSD4_2 824: /* Is Regular File or Pipe */ 825: if ((stbuf.st_mode & S_IFMT) == S_IFREG) 826: return; 827: #endif BSD4_2 828: #endif USG 829: } 830: } 831: 832: /* 833: * We need RMTDEBUG directory to do auditing. If the file doesn't exist, 834: * then we forget about debugging; if it exists but has improper owner- 835: * ship or modes, we gripe about it in ERRLOG. 836: */ 837: if (stat(RMTDEBUG, &stbuf) != SUCCESS) { 838: Debug = 0; 839: return; 840: } 841: if ((geteuid() != stbuf.st_uid) || /* We must own it */ 842: ((stbuf.st_mode & 0170700) != 040700)) { /* Directory, rwx */ 843: Debug = 0; 844: assert("INVALID RMTDEBUG DIRECTORY:", RMTDEBUG, stbuf.st_mode); 845: return; 846: } 847: 848: if (parm == DBG_TEMP) { 849: sprintf(buf, "%s/%d", RMTDEBUG, getpid()); 850: temp = malloc(strlen (buf) + 1); 851: if (temp == CNULL) { 852: Debug = 0; 853: assert("RMTDEBUG MALLOC ERROR:", temp, errno); 854: cleanup(1); 855: } 856: strcpy(temp, buf); 857: } else 858: sprintf(buf, "%s/%s", RMTDEBUG, Rmtname); 859: 860: unlink(buf); 861: if (freopen(buf, "w", stderr) != stderr) { 862: Debug = 0; 863: assert("FAILED RMTDEBUG FILE OPEN:", buf, errno); 864: cleanup(1); 865: } 866: setbuf(stderr, CNULL); 867: auditopen = 1; 868: } 869: 870: /* 871: * catch SIGALRM routine 872: */ 873: timeout() 874: { 875: extern int HaveSentHup; 876: if (!HaveSentHup) { 877: logent(Rmtname, "TIMEOUT"); 878: if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) { 879: US_SST(us_s_tmot); 880: systat(Rmtname, SS_FAIL, "TIMEOUT"); 881: } 882: } 883: longjmp(Sjbuf, 1); 884: } 885: 886: static char * 887: pskip(p) 888: register char *p; 889: { 890: while(*p && *p != ' ') 891: ++p; 892: while(*p && *p == ' ') 893: *p++ = 0; 894: return p; 895: }