|
|
1.1 ! root 1: /* %W% ! 2: ! 3: * uucp file transfer program: ! 4: * to place a call to a remote machine, login, and ! 5: * copy files between the two machines. ! 6: ! 7: */ ! 8: #include "uucp.h" ! 9: VERSION(%W%); ! 10: ! 11: #ifndef V7 ! 12: #include <sys/sysmacros.h> ! 13: #endif ! 14: ! 15: jmp_buf Sjbuf; ! 16: extern int Errorrate; ! 17: char uuxqtarg[MAXBASENAME] = {'\0'}; ! 18: ! 19: #define USAGE "[-xNUM] [-r[0|1]] -sSYSTEM" ! 20: ! 21: extern void closedem(); ! 22: ! 23: main(argc, argv, envp) ! 24: char *argv[]; ! 25: char **envp; ! 26: { ! 27: extern onintr(), timeout(); ! 28: extern intrEXIT(); ! 29: extern char *pskip(); ! 30: int ret, seq, exitcode; ! 31: char file[NAMESIZE]; ! 32: char msg[BUFSIZ], *p, *q; ! 33: char xflag[6]; /* -xN N is single digit */ ! 34: char *ttyn; ! 35: char cb[128]; ! 36: time_t ts, tconv; ! 37: #ifndef V7 ! 38: long minulimit, dummy; ! 39: #endif V7 ! 40: ! 41: Uid = getuid(); ! 42: Euid = geteuid(); /* this should be UUCPUID */ ! 43: if (Uid == 0) ! 44: setuid(UUCPUID); /* fails in ATTSV, but so what? */ ! 45: Env = envp; ! 46: Role = SLAVE; ! 47: strcpy(Logfile, LOGCICO); ! 48: *Rmtname = NULLCHAR; ! 49: ! 50: closedem(); ! 51: time(&Nstat.t_qtime); ! 52: tconv = Nstat.t_start = Nstat.t_qtime; ! 53: strcpy(Progname, "uucico"); ! 54: Pchar = 'C'; ! 55: (void) signal(SIGILL, intrEXIT); ! 56: (void) signal(SIGTRAP, intrEXIT); ! 57: (void) signal(SIGIOT, intrEXIT); ! 58: (void) signal(SIGEMT, intrEXIT); ! 59: (void) signal(SIGFPE, intrEXIT); ! 60: (void) signal(SIGBUS, intrEXIT); ! 61: (void) signal(SIGSEGV, intrEXIT); ! 62: (void) signal(SIGSYS, intrEXIT); ! 63: (void) signal(SIGPIPE, SIG_IGN); ! 64: (void) signal(SIGINT, onintr); ! 65: (void) signal(SIGHUP, onintr); ! 66: (void) signal(SIGQUIT, onintr); ! 67: (void) signal(SIGTERM, onintr); ! 68: #ifdef ATTSV ! 69: (void) signal(SIGUSR1, SIG_IGN); ! 70: (void) signal(SIGUSR2, SIG_IGN); ! 71: #endif ! 72: ret = guinfo(Euid, User); ! 73: ASSERT(ret == 0, "BAD UID ", "", ret); ! 74: strncpy(Uucp, User, NAMESIZE); ! 75: ! 76: setuucp(User); ! 77: ret = guinfo(Uid, Loginuser); ! 78: ASSERT(ret == 0, "BAD LOGIN_UID ", "", ret); ! 79: ! 80: *xflag = NULLCHAR; ! 81: Ifn = Ofn = -1; ! 82: while ((ret = getopt(argc, argv, "d:r:s:x:")) != EOF) { ! 83: switch (ret) { ! 84: case 'd': ! 85: Spool = optarg; ! 86: break; ! 87: case 'r': ! 88: Role = atoi(optarg); ! 89: break; ! 90: case 's': ! 91: if (versys(optarg, 0)) { ! 92: DEBUG(4, "%s not in Systems file\n", optarg); ! 93: cleanup(101); ! 94: } ! 95: strncpy(Rmtname, optarg, MAXBASENAME); ! 96: Rmtname[MAXBASENAME] = '\0'; ! 97: /* set args for possible xuuxqt call */ ! 98: strcpy(uuxqtarg, Rmtname); ! 99: break; ! 100: case 'x': ! 101: Debug = atoi(optarg); ! 102: if (Debug <= 0) ! 103: Debug = 1; ! 104: if (Debug > 9) ! 105: Debug = 9; ! 106: (void) sprintf(xflag, "-x%d", Debug); ! 107: break; ! 108: default: ! 109: (void) fprintf(stderr, "\tusage: %s %s\n", ! 110: Progname, USAGE); ! 111: exit(1); ! 112: } ! 113: } ! 114: ! 115: if (Role == MASTER) { ! 116: if (*Rmtname == NULLCHAR) { ! 117: DEBUG(5, "No -s specified\n" , ""); ! 118: cleanup(101); ! 119: } ! 120: /* get Myname - it depends on who I'm calling--Rmtname */ ! 121: (void) mchFind(Rmtname); ! 122: myName(Myname); ! 123: if (EQUALSN(Rmtname, Myname, SYSNSIZE)) { ! 124: DEBUG(5, "This system specified: -sMyname: %s, ", Myname); ! 125: cleanup(101); ! 126: } ! 127: } ! 128: ! 129: ASSERT(chdir(Spool) == 0, Ct_CHDIR, Spool, errno); ! 130: strcpy(Wrkdir, Spool); ! 131: ! 132: if (Role == SLAVE) { ! 133: ! 134: /* ! 135: * initial handshake ! 136: */ ! 137: ret = savline(); ! 138: Ifn = 0; ! 139: Ofn = 1; ! 140: fixline(Ifn, 0, D_ACU); ! 141: freopen(RMTDEBUG, "a", stderr); ! 142: /* get MyName - use logFind to check PERMISSIONS file */ ! 143: (void) logFind(Loginuser, ""); ! 144: myName(Myname); ! 145: ! 146: DEBUG(4,"cico.c: Myname - %s\n",Myname); ! 147: DEBUG(4,"cico.c: Loginuser - %s\n",Loginuser); ! 148: Nstat.t_scall = times(&Nstat.t_tga); ! 149: (void) sprintf(msg, "here=%s", Myname); ! 150: omsg('S', msg, Ofn); ! 151: (void) signal(SIGALRM, timeout); ! 152: (void) alarm(2 * MAXMSGTIME); /* give slow machines a second chance */ ! 153: if (setjmp(Sjbuf)) { ! 154: ! 155: /* ! 156: * timed out ! 157: */ ! 158: ret = restline(); ! 159: rmlock(CNULL); ! 160: exit(0); ! 161: } ! 162: for (;;) { ! 163: ret = imsg(msg, Ifn); ! 164: if (ret != 0) { ! 165: (void) alarm(0); ! 166: ret = restline(); ! 167: rmlock(CNULL); ! 168: exit(0); ! 169: } ! 170: if (msg[0] == 'S') ! 171: break; ! 172: } ! 173: Nstat.t_ecall = times(&Nstat.t_tga); ! 174: (void) alarm(0); ! 175: q = &msg[1]; ! 176: p = pskip(q); ! 177: strncpy(Rmtname, q, MAXBASENAME); ! 178: Rmtname[MAXBASENAME] = '\0'; ! 179: ! 180: seq = 0; ! 181: while (*p == '-') { ! 182: q = pskip(p); ! 183: switch(*(++p)) { ! 184: case 'x': ! 185: Debug = atoi(++p); ! 186: if (Debug <= 0) ! 187: Debug = 1; ! 188: break; ! 189: case 'Q': ! 190: seq = atoi(++p); ! 191: break; ! 192: default: ! 193: break; ! 194: } ! 195: p = q; ! 196: } ! 197: DEBUG(4, "sys-%s\n", Rmtname); ! 198: ! 199: #ifdef NOSTRANGERS ! 200: /* here's the place to look the remote system up in the Systems file. ! 201: * If the command NOSTRANGERS is executable and ! 202: /* If they're not in my file then hang up */ ! 203: if ( (access(NOSTRANGERS, 1) == 0) && versys(Rmtname, 1)) { ! 204: char unkcmd[64]; ! 205: register char *p; ! 206: ! 207: omsg('R', "You are unknown to me", Ofn); ! 208: for (p = Rmtname; *p; p++) ! 209: if (*p == '\'') ! 210: *p = ' '; /* cheap hack. who cares. */ ! 211: (void) sprintf(unkcmd, "%s '%s'", NOSTRANGERS, Rmtname); ! 212: system(unkcmd); ! 213: cleanup(101); ! 214: } ! 215: #endif NOSTRANGERS ! 216: ! 217: if (mlock(Rmtname)) { ! 218: omsg('R', "LCK", Ofn); ! 219: cleanup(101); ! 220: } ! 221: ! 222: /* validate login using PERMISSIONS file */ ! 223: if (logFind(Loginuser, Rmtname) == FAIL) { ! 224: Uerror = SS_BAD_LOG_MCH; ! 225: logent(UERRORTEXT, "FAILED"); ! 226: systat(Rmtname, SS_BAD_LOG_MCH, UERRORTEXT, ! 227: Retrytime); ! 228: omsg('R', "LOGIN", Ofn); ! 229: cleanup(101); ! 230: } ! 231: ! 232: ret = callBack(); ! 233: DEBUG(4,"return from callcheck: %s",ret ? "TRUE" : "FALSE"); ! 234: if (ret==TRUE) { ! 235: (void) signal(SIGINT, SIG_IGN); ! 236: (void) signal(SIGHUP, SIG_IGN); ! 237: omsg('R', "CB", Ofn); ! 238: logent("CALLBACK", "REQUIRED"); ! 239: ! 240: /* ! 241: * set up for call back ! 242: */ ! 243: systat(Rmtname, SS_CALLBACK, "CALL BACK", Retrytime); ! 244: gename(CMDPRE, Rmtname, 'C', file); ! 245: (void) close(creat(file, CFILEMODE)); ! 246: xuucico(Rmtname); ! 247: cleanup(101); ! 248: } ! 249: ! 250: if (callok(Rmtname) == SS_SEQBAD) { ! 251: Uerror = SS_SEQBAD; ! 252: logent(UERRORTEXT, "PREVIOUS"); ! 253: omsg('R', "BADSEQ", Ofn); ! 254: cleanup(101); ! 255: } ! 256: ! 257: if ((ret = gnxseq(Rmtname)) == seq) { ! 258: omsg('R', "OK", Ofn); ! 259: cmtseq(); ! 260: } else { ! 261: Uerror = SS_SEQBAD; ! 262: systat(Rmtname, SS_SEQBAD, UERRORTEXT, Retrytime); ! 263: logent(UERRORTEXT, "HANDSHAKE FAILED"); ! 264: ulkseq(); ! 265: omsg('R', "BADSEQ", Ofn); ! 266: cleanup(101); ! 267: } ! 268: ttyn = ttyname(Ifn); ! 269: if (ttyn != NULL) { ! 270: strcpy(Dc, BASENAME(ttyn, '/')); ! 271: chmod(ttyn, 0666); /* can fail, but who cares? */ ! 272: } else ! 273: strcpy(Dc, "notty"); ! 274: /* set args for possible xuuxqt call */ ! 275: strcpy(uuxqtarg, Rmtname); ! 276: } ! 277: ! 278: strcpy(User, Uucp); ! 279: /* ! 280: * Ensure reasonable ulimit (MINULIMIT) ! 281: */ ! 282: ! 283: #ifndef V7 ! 284: minulimit = ulimit(1,dummy); ! 285: ASSERT(minulimit >= MINULIMIT, "ULIMIT TOO SMALL", ! 286: Loginuser, minulimit); ! 287: #endif ! 288: if (Role == MASTER && callok(Rmtname) != 0) { ! 289: logent("SYSTEM STATUS", "CAN NOT CALL"); ! 290: cleanup(101); ! 291: } ! 292: ! 293: chremdir(Rmtname); ! 294: ! 295: (void) strcpy(Wrkdir, RemSpool); ! 296: if (Role == MASTER) { ! 297: ! 298: /* ! 299: * master part ! 300: */ ! 301: (void) signal(SIGINT, SIG_IGN); ! 302: (void) signal(SIGHUP, SIG_IGN); ! 303: (void) signal(SIGQUIT, SIG_IGN); ! 304: if (Ifn != -1 && Role == MASTER) { ! 305: (void) write(Ofn, EOTMSG, strlen(EOTMSG)); ! 306: (void) close(Ofn); ! 307: (void) close(Ifn); ! 308: Ifn = Ofn = -1; ! 309: rmlock(CNULL); ! 310: sleep(3); ! 311: } ! 312: (void) sprintf(msg, "call to %s ", Rmtname); ! 313: if (mlock(Rmtname) != 0) { ! 314: logent(msg, "LOCKED"); ! 315: CDEBUG(1, "Currently Talking With %s\n", ! 316: Rmtname); ! 317: cleanup(100); ! 318: } ! 319: Nstat.t_scall = times(&Nstat.t_tga); ! 320: Ofn = Ifn = conn(Rmtname); ! 321: Nstat.t_ecall = times(&Nstat.t_tga); ! 322: if (Ofn < 0) { ! 323: delock(Rmtname); ! 324: logent(UERRORTEXT, "CONN FAILED"); ! 325: systat(Rmtname, Uerror, UERRORTEXT, Retrytime); ! 326: cleanup(101); ! 327: } else { ! 328: logent(msg, "SUCCEEDED"); ! 329: ttyn = ttyname(Ifn); ! 330: if (ttyn != NULL) ! 331: chmod(ttyn, DEVICEMODE); ! 332: } ! 333: ! 334: if (setjmp(Sjbuf)) { ! 335: delock(Rmtname); ! 336: Uerror = SS_LOGIN_FAILED; ! 337: logent(Rmtname, UERRORTEXT); ! 338: systat(Rmtname, SS_LOGIN_FAILED, ! 339: UERRORTEXT, Retrytime); ! 340: DEBUG(4, "%s - failed\n", UERRORTEXT); ! 341: cleanup(101); ! 342: } ! 343: (void) signal(SIGALRM, timeout); ! 344: /* give slow guys lots of time to thrash */ ! 345: (void) alarm(3 * MAXMSGTIME); ! 346: for (;;) { ! 347: ret = imsg(msg, Ifn); ! 348: if (ret != 0) { ! 349: continue; /* try again */ ! 350: } ! 351: if (msg[0] == 'S') ! 352: break; ! 353: } ! 354: (void) alarm(0); ! 355: if(EQUALSN("here=", &msg[1], 5)){ ! 356: /* ! 357: /* this is a problem. We'd like to compare with an ! 358: * untruncated Rmtname but we fear incompatability. ! 359: * So we'll look at most 6 chars (at most). ! 360: */ ! 361: if(!EQUALSN(&msg[6], Rmtname, (strlen(Rmtname)< 7 ? ! 362: strlen(Rmtname) : 6))){ ! 363: delock(Rmtname); ! 364: Uerror = SS_WRONG_MCH; ! 365: logent(&msg[6], UERRORTEXT); ! 366: systat(Rmtname, SS_WRONG_MCH, UERRORTEXT, ! 367: Retrytime); ! 368: DEBUG(4, "%s - failed\n", UERRORTEXT); ! 369: cleanup(101); ! 370: } ! 371: } ! 372: CDEBUG(1,"Login Successful: System=%s\n",&msg[6]); ! 373: seq = gnxseq(Rmtname); ! 374: (void) sprintf(msg, "%s -Q%d %s", Myname, seq, xflag); ! 375: omsg('S', msg, Ofn); ! 376: (void) alarm(2 * MAXMSGTIME); /* give slow guys some thrash time */ ! 377: for (;;) { ! 378: ret = imsg(msg, Ifn); ! 379: DEBUG(4, "msg-%s\n", msg); ! 380: if (ret != 0) { ! 381: (void) alarm(0); ! 382: delock(Rmtname); ! 383: ulkseq(); ! 384: cleanup(101); ! 385: } ! 386: if (msg[0] == 'R') ! 387: break; ! 388: } ! 389: (void) alarm(0); ! 390: ! 391: /* check for rejects from remote */ ! 392: Uerror = 0; ! 393: if (EQUALS(&msg[1], "LCK")) ! 394: Uerror = SS_RLOCKED; ! 395: else if (EQUALS(&msg[1], "LOGIN")) ! 396: Uerror = SS_RLOGIN; ! 397: else if (EQUALS(&msg[1], "CB")) ! 398: Uerror = SS_CALLBACK; ! 399: else if (EQUALS(&msg[1], "You are unknown to me")) ! 400: Uerror = SS_RUNKNOWN; ! 401: else if (EQUALS(&msg[1], "BADSEQ")) ! 402: Uerror = SS_SEQBAD; ! 403: else if (!EQUALS(&msg[1], "OK")) ! 404: Uerror = SS_UNKNOWN_RESPONSE; ! 405: if (Uerror) { ! 406: delock(Rmtname); ! 407: systat(Rmtname, Uerror, UERRORTEXT, Retrytime); ! 408: logent(UERRORTEXT, "HANDSHAKE FAILED"); ! 409: CDEBUG(1, "HANDSHAKE FAILED: %s\n", UERRORTEXT); ! 410: ulkseq(); ! 411: cleanup(101); ! 412: } ! 413: cmtseq(); ! 414: } ! 415: DEBUG(4, " Rmtname %s, ", Rmtname); ! 416: DEBUG(4, "Role %s, ", Role ? "MASTER" : "SLAVE"); ! 417: DEBUG(4, "Ifn - %d, ", Ifn); ! 418: DEBUG(4, "Loginuser - %s\n", Loginuser); ! 419: ! 420: /* alarm/setjmp added here due to experience with uucico ! 421: * hanging for hours in imsg(). ! 422: */ ! 423: if (setjmp(Sjbuf)) { ! 424: delock(Rmtname); ! 425: logent("startup", "TIMEOUT"); ! 426: DEBUG(4, "%s - timeout\n", "startup"); ! 427: cleanup(101); ! 428: } ! 429: (void) alarm(MAXSTART); ! 430: ret = startup(Role); ! 431: (void) alarm(0); ! 432: ! 433: if (ret != SUCCESS) { ! 434: delock(Rmtname); ! 435: logent("startup", "FAILED"); ! 436: Uerror = SS_STARTUP; ! 437: CDEBUG(1, "%s\n", UERRORTEXT); ! 438: systat(Rmtname, Uerror, UERRORTEXT, Retrytime); ! 439: exitcode = 101; ! 440: } else { ! 441: logent("startup", "OK"); ! 442: systat(Rmtname, SS_INPROGRESS, UTEXT(SS_INPROGRESS),Retrytime); ! 443: Nstat.t_sftp = times(&Nstat.t_tga); ! 444: ! 445: exitcode = cntrl(Role); ! 446: Nstat.t_eftp = times(&Nstat.t_tga); ! 447: DEBUG(4, "cntrl - %d\n", exitcode); ! 448: (void) signal(SIGINT, SIG_IGN); ! 449: (void) signal(SIGHUP, SIG_IGN); ! 450: (void) signal(SIGALRM, timeout); ! 451: ! 452: if (exitcode == 0) { ! 453: (void) time(&ts); ! 454: (void) sprintf(cb, "conversation complete %s %ld", ! 455: Dc, ts - tconv); ! 456: logent(cb, "OK"); ! 457: systat(Rmtname, SS_OK, UTEXT(SS_OK), Retrytime); ! 458: ! 459: } else { ! 460: logent("conversation complete", "FAILED"); ! 461: systat(Rmtname, SS_CONVERSATION, ! 462: UTEXT(SS_CONVERSATION), Retrytime); ! 463: } ! 464: (void) alarm(2 * MAXMSGTIME); /* give slow guys some thrash time */ ! 465: omsg('O', "OOOOO", Ofn); ! 466: CDEBUG(4, "send OO %d,", ret); ! 467: if (!setjmp(Sjbuf)) { ! 468: for (;;) { ! 469: omsg('O', "OOOOO", Ofn); ! 470: ret = imsg(msg, Ifn); ! 471: if (ret != 0) ! 472: break; ! 473: if (msg[0] == 'O') ! 474: break; ! 475: } ! 476: } ! 477: (void) alarm(0); ! 478: } ! 479: cleanup(exitcode); ! 480: } ! 481: ! 482: /* ! 483: * clean and exit with "code" status ! 484: */ ! 485: cleanup(code) ! 486: register int code; ! 487: { ! 488: int ret; ! 489: char *ttyn; ! 490: ! 491: (void) signal(SIGINT, SIG_IGN); ! 492: (void) signal(SIGHUP, SIG_IGN); ! 493: rmlock(CNULL); ! 494: closedem(); ! 495: if (Role == SLAVE) { ! 496: ret = restline(); ! 497: DEBUG(4, "ret restline - %d\n", ret); ! 498: sethup(0); ! 499: } ! 500: if (Ofn != -1) { ! 501: if (Role == MASTER) ! 502: (void) write(Ofn, EOTMSG, strlen(EOTMSG)); ! 503: ttyn = ttyname(Ifn); ! 504: if (ttyn != NULL) ! 505: chmod(ttyn, 0644); /* can fail, but who cares? */ ! 506: (void) close(Ifn); ! 507: (void) close(Ofn); ! 508: } ! 509: DEBUG(4, "exit code %d\n", code); ! 510: CDEBUG(1, "Conversation Complete: Status %s\n\n", ! 511: code ? "FAILED" : "SUCCEEDED"); ! 512: ! 513: cleanTM(); ! 514: if (code == 0) ! 515: xuuxqt(uuxqtarg); ! 516: exit(code); ! 517: } ! 518: ! 519: short TM_cnt = 0; ! 520: char TM_name[MAXNAMESIZE]; ! 521: ! 522: cleanTM() ! 523: { ! 524: register int i; ! 525: char tm_name[MAXNAMESIZE]; ! 526: ! 527: DEBUG(7,"TM_cnt: %d\n",TM_cnt); ! 528: for(i=0; i < TM_cnt; i++) { ! 529: (void) sprintf(tm_name, "%s.%3.3d", TM_name, i); ! 530: DEBUG(7, "tm_name: %s\n", tm_name); ! 531: unlink(tm_name); ! 532: } ! 533: } ! 534: ! 535: TMname(file, pnum) ! 536: char *file; ! 537: { ! 538: ! 539: (void) sprintf(file, "%s/TM.%.5d.%.3d", RemSpool, pnum, TM_cnt); ! 540: if (TM_cnt == 0) ! 541: (void) sprintf(TM_name, "%s/TM.%.5d", RemSpool, pnum); ! 542: DEBUG(7, "TMname(%s)\n", file); ! 543: TM_cnt++; ! 544: } ! 545: ! 546: /* ! 547: * intrrupt - remove locks and exit ! 548: */ ! 549: onintr(inter) ! 550: register int inter; ! 551: { ! 552: char str[30]; ! 553: /* I'm putting a test for zero here because I saw it happen ! 554: * and don't know how or why, but it seemed to then loop ! 555: * here for ever? ! 556: */ ! 557: if (inter == 0) ! 558: exit(99); ! 559: (void) signal(inter, SIG_IGN); ! 560: (void) sprintf(str, "SIGNAL %d", inter); ! 561: logent(str, "CAUGHT"); ! 562: cleanup(inter); ! 563: } ! 564: ! 565: /*ARGSUSED*/ ! 566: intrEXIT(inter) ! 567: { ! 568: char cb[10]; ! 569: extern int errno; ! 570: ! 571: (void) sprintf(cb, "%d", errno); ! 572: logent("INTREXIT", cb); ! 573: (void) signal(SIGIOT, SIG_DFL); ! 574: (void) signal(SIGILL, SIG_DFL); ! 575: rmlock(CNULL); ! 576: closedem(); ! 577: (void) setuid(Uid); ! 578: abort(); ! 579: } ! 580: ! 581: /* ! 582: * catch SIGALRM routine ! 583: */ ! 584: timeout() ! 585: { ! 586: longjmp(Sjbuf, 1); ! 587: } ! 588: ! 589: static char * ! 590: pskip(p) ! 591: register char *p; ! 592: { ! 593: while( *p && *p != ' ' ) ! 594: ++p; ! 595: if( *p ) *p++ = 0; ! 596: return(p); ! 597: } ! 598: ! 599: void ! 600: closedem() ! 601: { ! 602: register i; ! 603: ! 604: for(i=3;i<_NFILE;i++) ! 605: (void) close(i); ! 606: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.