1: #ifndef lint 2: static char sccsid[] = "@(#)cico.c 5.2 (Berkeley) 7/19/83"; 3: #endif 4: 5: #include "uucp.h" 6: #include <signal.h> 7: #include <setjmp.h> 8: #include <sys/types.h> 9: #ifdef SYSIII 10: #include <termio.h> 11: #endif 12: #ifndef SYSIII 13: #include <sgtty.h> 14: #endif 15: 16: 17: #ifdef UNET 18: #include <UNET/unetio.h> 19: #include <UNET/tcp.h> 20: static struct uiocstate ust; 21: #endif 22: 23: jmp_buf Sjbuf; 24: /* call fail text */ 25: char *Stattext[] = { 26: "", 27: "BAD SYSTEM", 28: "WRONG TIME", 29: "SYSTEM LOCKED", 30: "NO DEVICE", 31: "DIAL FAILED", 32: "LOGIN FAILED", 33: "BAD SEQUENCE" 34: }; 35: 36: int Role = 0; 37: /* call fail codes */ 38: int Stattype[] = {0, 0, 0, 0, 39: SS_NODEVICE, SS_FAIL, SS_FAIL, SS_BADSEQ 40: }; 41: 42: 43: int Errorrate = 0; 44: #ifdef SYSIII 45: struct termio Savettyb; 46: #endif 47: #ifndef SYSIII 48: struct sgttyb Savettyb; 49: #endif 50: 51: /******* 52: * cico - this program is used to place a call to a 53: * remote machine, login, and copy files between the two machines. 54: */ 55: 56: main(argc, argv) 57: register char *argv[]; 58: { 59: register int ret; 60: int seq; 61: int onesys = 0; 62: char wkpre[NAMESIZE], file[NAMESIZE]; 63: char msg[BUFSIZ], *q; 64: register char *p; 65: extern onintr(), timeout(), setdebug(); 66: extern intrEXIT(); 67: extern char *pskip(); 68: char rflags[30]; 69: char *ttyn; 70: int orig_uid = getuid(); 71: 72: strcpy(Progname, "uucico"); 73: uucpname(Myname); 74: 75: /* Try to run as uucp -- rti!trt */ 76: setgid(getegid()); 77: setuid(geteuid()); 78: 79: signal(SIGILL, intrEXIT); 80: signal(SIGTRAP, intrEXIT); 81: signal(SIGIOT, intrEXIT); 82: signal(SIGEMT, intrEXIT); 83: signal(SIGFPE, intrEXIT); 84: signal(SIGBUS, intrEXIT); 85: signal(SIGSEGV, intrEXIT); 86: signal(SIGSYS, intrEXIT); 87: signal(SIGINT, onintr); 88: signal(SIGHUP, onintr); 89: signal(SIGQUIT, onintr); 90: signal(SIGTERM, onintr); 91: signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */ 92: signal(SIGFPE, setdebug); 93: ret = guinfo(getuid(), User, msg); 94: strcpy(Loginuser, User); 95: ASSERT(ret == 0, "BAD UID ", "", ret); 96: 97: rflags[0] = '\0'; 98: umask(WFMASK); 99: strcpy(Rmtname, Myname); 100: Ifn = Ofn = -1; 101: while(argc>1 && argv[1][0] == '-'){ 102: switch(argv[1][1]){ 103: case 'd': 104: Spool = &argv[1][2]; 105: break; 106: #ifdef PROTODEBUG 107: case 'E': 108: Errorrate = atoi(&argv[1][2]); 109: if (Errorrate <= 0) 110: Errorrate = 100; 111: break; 112: case 'g': 113: Pkdrvon = 1; 114: break; 115: case 'G': 116: Pkdrvon = 1; 117: strcat(rflags, " -g "); 118: break; 119: #endif 120: case 'r': 121: Role = atoi(&argv[1][2]); 122: break; 123: case 's': 124: sprintf(Rmtname, "%.7s", &argv[1][2]); 125: if (Rmtname[0] != '\0') 126: onesys = 1; 127: break; 128: case 'x': 129: chkdebug(orig_uid); 130: Debug = atoi(&argv[1][2]); 131: if (Debug <= 0) 132: Debug = 1; 133: strcat(rflags, argv[1]); 134: logent("ENABLED", "DEBUG"); 135: break; 136: default: 137: printf("unknown flag %s\n", argv[1]); 138: break; 139: } 140: --argc; argv++; 141: } 142: 143: subchdir(Spool); 144: strcpy(Wrkdir, Spool); 145: 146: #ifdef UNET 147: /* 148: * Determine if we are on UNET 149: */ 150: ret = ioctl(0, UIOCSTATE, &ust); 151: if (ret == 0) { 152: Unet = 1; 153: DEBUG(4, "UNET connection -- ioctl-s disabled\n", ""); 154: } 155: #endif 156: if (Role == SLAVE) { 157: /* initial handshake */ 158: onesys = 1; 159: if (!Unet) { 160: #ifdef SYSIII 161: ret = ioctl(0, TCGETA, &Savettyb); 162: Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7; 163: Savettyb.c_oflag |= OPOST; 164: Savettyb.c_lflag |= (ISIG|ICANON|ECHO); 165: #endif 166: #ifndef SYSIII 167: ret = ioctl(0, TIOCGETP, &Savettyb); 168: Savettyb.sg_flags |= ECHO; 169: Savettyb.sg_flags &= ~RAW; 170: #endif 171: } 172: Ifn = 0; 173: Ofn = 1; 174: fixmode(Ifn); 175: fclose(stderr); 176: fopen(RMTDEBUG, "w"); 177: omsg('S', "here", Ofn); 178: signal(SIGALRM, timeout); 179: alarm(MAXMSGTIME); 180: if (setjmp(Sjbuf)) { 181: /* timed out */ 182: if (!Unet) { 183: #ifdef SYSIII 184: ret = ioctl(0, TCSETA, &Savettyb); 185: #endif 186: #ifndef SYSIII 187: ret = ioctl(0, TIOCSETP, &Savettyb); 188: #endif 189: } 190: exit(0); 191: } 192: for (;;) { 193: ret = imsg(msg, Ifn); 194: if (ret != 0) { 195: alarm(0); 196: if (!Unet) { 197: #ifdef SYSIII 198: ret = ioctl(0, TCSETA, &Savettyb); 199: #endif 200: #ifndef SYSIII 201: ret = ioctl(0, TIOCSETP, &Savettyb); 202: #endif 203: } 204: exit(0); 205: } 206: if (msg[0] == 'S') 207: break; 208: } 209: alarm(0); 210: q = &msg[1]; 211: p = pskip(q); 212: sprintf(Rmtname, "%.7s", q); 213: DEBUG(4, "sys-%s\n", Rmtname); 214: if (mlock(Rmtname)) { 215: omsg('R', "LCK", Ofn); 216: cleanup(0); 217: } 218: else if (callback(Loginuser)) { 219: signal(SIGINT, SIG_IGN); 220: signal(SIGHUP, SIG_IGN); 221: omsg('R', "CB", Ofn); 222: logent("CALLBACK", "REQUIRED"); 223: /* set up for call back */ 224: systat(Rmtname, SS_CALLBACK, "CALL BACK"); 225: gename(CMDPRE, Rmtname, 'C', file); 226: close(creat(subfile(file), 0666)); 227: xuucico(Rmtname); 228: cleanup(0); 229: } 230: seq = 0; 231: while (*p == '-') { 232: q = pskip(p); 233: switch(*(++p)) { 234: case 'g': 235: Pkdrvon = 1; 236: break; 237: case 'x': 238: Debug = atoi(++p); 239: if (Debug <= 0) 240: Debug = 1; 241: break; 242: case 'Q': 243: seq = atoi(++p); 244: break; 245: default: 246: break; 247: } 248: p = q; 249: } 250: if (callok(Rmtname) == SS_BADSEQ) { 251: logent("BADSEQ", "PREVIOUS"); 252: omsg('R', "BADSEQ", Ofn); 253: cleanup(0); 254: } 255: if ((ret = gnxseq(Rmtname)) == seq) { 256: omsg('R', "OK", Ofn); 257: cmtseq(); 258: } 259: else { 260: systat(Rmtname, Stattype[7], Stattext[7]); 261: logent("BAD SEQ", "HANDSHAKE FAILED"); 262: ulkseq(); 263: omsg('R', "BADSEQ", Ofn); 264: cleanup(0); 265: } 266: ttyn = ttyname(Ifn); 267: if (ttyn != NULL) 268: chmod(ttyn, 0600); 269: } 270: loop: 271: if (!onesys) { 272: ret = gnsys(Rmtname, Spool, CMDPRE); 273: if (ret == FAIL) 274: cleanup(100); 275: if (ret == 0) 276: cleanup(0); 277: } 278: else if (Role == MASTER && callok(Rmtname) != 0) { 279: logent("SYSTEM STATUS", "CAN NOT CALL"); 280: cleanup(0); 281: } 282: 283: sprintf(wkpre, "%c.%.7s", CMDPRE, Rmtname); 284: 285: if (Role == MASTER) { 286: /* master part */ 287: signal(SIGINT, SIG_IGN); 288: signal(SIGHUP, SIG_IGN); 289: signal(SIGQUIT, SIG_IGN); 290: if (!iswrk(file, "chk", Spool, wkpre) && !onesys) { 291: logent(Rmtname, "NO WORK"); 292: goto next; 293: } 294: if (Ifn != -1 && Role == MASTER) { 295: write(Ofn, EOTMSG, strlen(EOTMSG)); 296: clsacu(); 297: close(Ofn); 298: close(Ifn); 299: Ifn = Ofn = -1; 300: rmlock(CNULL); 301: sleep(3); 302: } 303: sprintf(msg, "call to %s ", Rmtname); 304: if (mlock(Rmtname) != 0) { 305: logent(msg, "LOCKED"); 306: goto next; 307: } 308: Ofn = Ifn = conn(Rmtname); 309: if (Ofn < 0) { 310: logent(msg, "FAILED"); 311: systat(Rmtname, Stattype[-Ofn], 312: Stattext[-Ofn]); 313: goto next; 314: } 315: else { 316: logent(msg, "SUCCEEDED"); 317: } 318: 319: if (setjmp(Sjbuf)) 320: goto next; 321: signal(SIGALRM, timeout); 322: alarm(2 * MAXMSGTIME); 323: for (;;) { 324: ret = imsg(msg, Ifn); 325: if (ret != 0) { 326: alarm(0); 327: logent("imsg 1", "FAILED"); 328: goto next; 329: } 330: if (msg[0] == 'S') 331: break; 332: } 333: alarm(MAXMSGTIME); 334: seq = gnxseq(Rmtname); 335: sprintf(msg, "%.7s -Q%d %s", Myname, seq, rflags); 336: omsg('S', msg, Ofn); 337: for (;;) { 338: ret = imsg(msg, Ifn); 339: DEBUG(4, "msg-%s\n", msg); 340: if (ret != 0) { 341: alarm(0); 342: ulkseq(); 343: logent("imsg 2", "FAILED"); 344: goto next; 345: } 346: if (msg[0] == 'R') 347: break; 348: } 349: alarm(0); 350: if (msg[1] == 'B') { 351: /* bad sequence */ 352: logent("BAD SEQ", "HANDSHAKE FAILED"); 353: systat(Rmtname, Stattype[7], Stattext[7]); 354: ulkseq(); 355: goto next; 356: } 357: if (strcmp(&msg[1], "OK") != SAME) { 358: logent(&msg[1], "HANDSHAKE FAILED"); 359: ulkseq(); 360: goto next; 361: } 362: cmtseq(); 363: } 364: DEBUG(1, " Rmtname %s, ", Rmtname); 365: DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE"); 366: DEBUG(1, "Ifn - %d, ", Ifn); 367: DEBUG(1, "Loginuser - %s\n", Loginuser); 368: 369: alarm(MAXMSGTIME); 370: if (setjmp(Sjbuf)) 371: goto Failure; 372: ret = startup(Role); 373: alarm(0); 374: if (ret != SUCCESS) { 375: Failure: 376: logent("startup", "FAILED"); 377: systat(Rmtname, SS_FAIL, "STARTUP"); 378: goto next; 379: } 380: else { 381: logent("startup", "OK"); 382: systat(Rmtname, SS_INPROGRESS, "TALKING"); 383: ret = cntrl(Role, wkpre); 384: DEBUG(1, "cntrl - %d\n", ret); 385: signal(SIGINT, SIG_IGN); 386: signal(SIGHUP, SIG_IGN); 387: signal(SIGALRM, timeout); 388: if (ret == 0) { 389: logent("conversation complete", "OK"); 390: rmstat(Rmtname); 391: 392: } 393: else { 394: logent("conversation complete", "FAILED"); 395: systat(Rmtname, SS_FAIL, "CONVERSATION"); 396: } 397: alarm(MAXMSGTIME); 398: omsg('O', "OOOOO", Ofn); 399: DEBUG(4, "send OO %d,", ret); 400: if (!setjmp(Sjbuf)) { 401: for (;;) { 402: omsg('O', "OOOOO", Ofn); 403: ret = imsg(msg, Ifn); 404: if (ret != 0) 405: break; 406: if (msg[0] == 'O') 407: break; 408: } 409: } 410: alarm(0); 411: clsacu(); /* rti!trt: is this needed? */ 412: } 413: next: 414: if (!onesys) { 415: goto loop; 416: } 417: cleanup(0); 418: } 419: 420: #ifndef SYSIII 421: struct sgttyb Hupvec; 422: #endif 423: 424: /*** 425: * cleanup(code) cleanup and exit with "code" status 426: * int code; 427: */ 428: 429: cleanup(code) 430: register int code; 431: { 432: register int ret; 433: register char *ttyn; 434: 435: signal(SIGINT, SIG_IGN); 436: signal(SIGHUP, SIG_IGN); 437: rmlock(CNULL); 438: clsacu(); 439: logcls(); 440: if (Role == SLAVE) { 441: if (!Unet) { 442: #ifdef SYSIII 443: Savettyb.c_cflag |= HUPCL; 444: ret = ioctl(0, TCSETA, &Savettyb); 445: #endif 446: #ifndef SYSIII 447: /* rti!trt: use more robust hang up sequence */ 448: ret = ioctl(0, TIOCHPCL, STBNULL); 449: ret = ioctl(0, TIOCGETP, &Hupvec); 450: Hupvec.sg_ispeed = B0; 451: Hupvec.sg_ospeed = B0; 452: ret = ioctl(0, TIOCSETP, &Hupvec); 453: sleep(2); 454: ret = ioctl(0, TIOCSETP, &Savettyb); 455: #endif 456: DEBUG(4, "ret ioctl - %d\n", ret); 457: } 458: ttyn = ttyname(Ifn); 459: if (ttyn != NULL) 460: chmod(ttyn, 0600); 461: } 462: if (Ofn != -1) { 463: if (Role == MASTER) 464: write(Ofn, EOTMSG, strlen(EOTMSG)); 465: close(Ifn); 466: close(Ofn); 467: } 468: DEBUG(1, "exit code %d\n", code); 469: if (code == 0) 470: xuuxqt(); 471: exit(code); 472: } 473: 474: /*** 475: * onintr(inter) interrupt - remove locks and exit 476: */ 477: 478: onintr(inter) 479: register int inter; 480: { 481: char str[30]; 482: signal(inter, SIG_IGN); 483: sprintf(str, "SIGNAL %d", inter); 484: logent(str, "CAUGHT"); 485: systat(Rmtname, SS_FAIL, str); 486: cleanup(inter); 487: } 488: 489: /* changed to single version of intrEXIT. Is this okay? rti!trt */ 490: intrEXIT(signo) 491: int signo; 492: { 493: signal(signo, SIG_DFL); 494: setgid(getgid()); 495: setuid(getuid()); 496: abort(); 497: } 498: /* 499: * Catch a special signal 500: * (SIGFPE, ugh), and toggle debugging between 0 and 30. 501: * Handy for looking in on long running uucicos. 502: */ 503: setdebug() 504: { 505: if (Debug < 30) 506: Debug = 30; 507: else 508: Debug = 0; 509: } 510: 511: 512: /*** 513: * fixmode(tty) fix kill/echo/raw on line 514: * 515: * return codes: none 516: */ 517: 518: fixmode(tty) 519: register int tty; 520: { 521: #ifdef SYSIII 522: struct termio ttbuf; 523: #endif 524: #ifndef SYSIII 525: struct sgttyb ttbuf; 526: #endif 527: register int ret; 528: 529: if (Unet) 530: return; 531: #ifdef SYSIII 532: ioctl(tty, TCGETA, &ttbuf); 533: ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0; 534: ttbuf.c_cflag &= (CBAUD); 535: ttbuf.c_cflag |= (CS8|CREAD); 536: ttbuf.c_cc[VMIN] = 6; 537: ttbuf.c_cc[VTIME] = 1; 538: ret = ioctl(tty, TCSETA, &ttbuf); 539: #endif 540: #ifndef SYSIII 541: ioctl(tty, TIOCGETP, &ttbuf); 542: ttbuf.sg_flags = (ANYP | RAW); 543: ret = ioctl(tty, TIOCSETP, &ttbuf); 544: #endif 545: ASSERT(ret >= 0, "STTY FAILED", "", ret); 546: #ifndef SYSIII 547: ioctl(tty, TIOCEXCL, STBNULL); 548: #endif 549: } 550: 551: 552: /*** 553: * timeout() catch SIGALRM routine 554: */ 555: 556: timeout() 557: { 558: logent(Rmtname, "TIMEOUT"); 559: systat(Rmtname, SS_FAIL, "TIMEOUT"); 560: longjmp(Sjbuf, 1); 561: } 562: 563: static char * 564: pskip(p) 565: register char *p; 566: { 567: while( *p && *p != ' ' ) 568: ++p; 569: if( *p ) *p++ = 0; 570: return(p); 571: }