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