|
|
1.1 ! root 1: /* ! 2: * dcpsys.c ! 3: * ! 4: * System File Parsing and Initial Login Negotiation Routines for uucico ! 5: */ ! 6: ! 7: /* #include <sys/dir.h> */ ! 8: #include "dirent.h" ! 9: #include <ctype.h> ! 10: #include "dcp.h" ! 11: #include "lsys.h" ! 12: ! 13: /* ! 14: * Communication Protocol Declarations and Definitions ! 15: */ ! 16: ! 17: #define PROTOS "g" ! 18: int (*getpkt)(), (*sendpkt)(), (*openpk)(), (*closepk)(); ! 19: ! 20: extern int ggetpkt(), gsendpkt(), gopenpk(), gclosepk(); ! 21: #if 0 ! 22: extern int kgetpkt(), ksendpkt(), kopenpk(), kclosepk(); ! 23: extern int rgetpkt(), rsendpkt(), ropenpk(), rclosepk(); ! 24: extern int tgetpkt(), tsendpkt(), topenpk(), tclosepk(); ! 25: #endif ! 26: ! 27: typedef struct proto { ! 28: char type; /* One character Protocol Type */ ! 29: int (*getpkt)(); /* Get Packet Function */ ! 30: int (*sendpkt)(); /* Send Packet Function */ ! 31: int (*openpk)(); /* Open Packet Function */ ! 32: int (*closepk)(); /* Close Packet Function */ ! 33: } PROTO; ! 34: ! 35: PROTO protolst[] = ! 36: { ! 37: { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk }, ! 38: #if 0 ! 39: { 'k', kgetpkt, ksendpkt, kopenpk, kclosepk }, ! 40: { 'r', rgetpkt, rsendpkt, ropenpk, rclosepk }, ! 41: { 't', tgetpkt, tsendpkt, topenpk, tclosepk }, ! 42: #endif ! 43: { '\0' } ! 44: }; ! 45: ! 46: int leavelock = 0; /* Leave the rmtname lock file */ ! 47: ! 48: /* ! 49: * getsystem() ! 50: * Retrieve and Process an "L.sys" file entry. ! 51: */ ! 52: ! 53: getsystem() ! 54: { ! 55: if ( lsys_next() == 0 ) ! 56: return('A'); ! 57: ! 58: rmtname = lsys_value(sys_e); ! 59: if ( strcmp(rmtname, sysname) ) { ! 60: if ( strcmp(sysname, "all") && strcmp(sysname, "any") ) ! 61: return('I'); ! 62: if ( scandir() != 'S' ) ! 63: return('I'); ! 64: } ! 65: printmsg(M_CALL, "Thinking of calling system: %s", rmtname); ! 66: if ( !checktime(lsys_value(sched_e)) ) ! 67: return('I'); ! 68: ! 69: open_the_logfile("uucico"); ! 70: if (cfp != NULL) ! 71: fclose(cfp); /* in case matched scandir */ ! 72: if ( lockit(rmtname) < 0 ) { ! 73: plog(M_CALL, "Site Locked: %s", rmtname); ! 74: close_logfile(); ! 75: return('I'); ! 76: } ! 77: return('S'); ! 78: } ! 79: ! 80: /* ! 81: * checkrmt() ! 82: * Scan through L.sys file to verify that we know about the given ! 83: * remote system name. ! 84: * Returns: (1) if we found match, (0) if rmtname unknown. ! 85: */ ! 86: ! 87: checkrmt() ! 88: { ! 89: lsys_open(); ! 90: while ( lsys_next() ) { ! 91: if ( strcmp(rmtname, lsys_value(sys_e)) == 0 ) ! 92: return(1); ! 93: } ! 94: lsys_close(); ! 95: return(0); ! 96: } ! 97: ! 98: /* ! 99: * rmsg(msg, maxlen) char *msg; int maxlen; ! 100: * Read a ^P (DLE) type msg from the remote uucp. (startup negotiation). ! 101: * ! 102: * wmsg(msg) char *msg; ! 103: * Write a ^P (DLE) type msg to the remote uucp. (startup negotiation). ! 104: */ ! 105: ! 106: #define MAXDROP 2048 /* Maximum characters to drop waiting for ^P */ ! 107: ! 108: rmsg(msg, maxlen) ! 109: char *msg; ! 110: int maxlen; ! 111: { ! 112: char ch; ! 113: register char *cp; ! 114: int i; ! 115: ! 116: for (i=0; i<MAXDROP; i++) { ! 117: if ( sread(&ch, 1, MSGTIME) != 1 ){ ! 118: goto badrmsg; ! 119: } ! 120: if ( ch == DLE ) ! 121: break; ! 122: } ! 123: ! 124: ! 125: if ( ch != DLE ){ ! 126: goto nodle; ! 127: } ! 128: ! 129: for (cp=msg,i=1; i<maxlen; i++) { ! 130: if ( sread(&ch, 1, MSGTIME) != 1 ) ! 131: goto badrmsg; ! 132: if ( (ch == '\0') || (ch == '\r') || (ch == '\n') ) ! 133: break; ! 134: *cp++ = ch; ! 135: } ! 136: *cp = '\0'; ! 137: printmsg(M_DEBUG, "rmsg {%s}", visib(msg)); ! 138: return( strlen(msg) ); ! 139: ! 140: badrmsg: ! 141: /* *cp = '\0'; this is a NONO, cp never has valid characters here ! 142: * when we've determined that we were missing DLE ! 143: */ ! 144: printmsg(M_CALL, "Bad received message {%s}", visib(msg)); ! 145: return(-1); ! 146: nodle: ! 147: /* *cp = '\0'; this is a NONO, cp never has valid characters here */ ! 148: printmsg(M_CALL, "Remote machine not sending DLE startup (uucico)"); ! 149: return(-1); ! 150: } ! 151: ! 152: wmsg(msg) ! 153: char *msg; ! 154: { ! 155: char buf[2] = {'\0', DLE}; ! 156: ! 157: printmsg(M_DEBUG, "wmsg {%s}", visib(msg)); ! 158: swrite(&buf[0], 2); ! 159: swrite(msg, strlen(msg)); ! 160: swrite(&buf[0], 1); ! 161: } ! 162: ! 163: /* ! 164: * startup() ! 165: * ! 166: * Initiate communication with a remote uucp. ! 167: */ ! 168: ! 169: #define FAIL1(x) {errmsg=(x); errarg=NULL; goto failure;} ! 170: #define FAIL2(x, y) {errmsg=(x); errarg=(y); goto failure;} ! 171: ! 172: startup() ! 173: { ! 174: char msg[BUFSIZ]; ! 175: char *errmsg, *errarg, *cp, ch; ! 176: static char locbuf[SITELEN+1]; ! 177: static char *readymsg = "Ready for transactions"; ! 178: ! 179: sysended = 0; ! 180: leavelock = 0; ! 181: if (role == MASTER) { ! 182: if ( rmsg(msg, BUFSIZ) < 0 ){ ! 183: FAIL1("Logon failed: 1st msg (broken communication?)"); ! 184: } ! 185: printmsg(M_CALLMSG, "1st msg = {%s}", visib(msg)); ! 186: if ( strncmp(msg, "Shere", 5) ){ ! 187: FAIL1("Bad format for 1st msg"); ! 188: } ! 189: if ( (msg[5] == '\0') || (msg[5] == '\n') || ! 190: (msg[6] == '\0') || (msg[6] == '\n') ) ! 191: plog(M_CALL, "Warning: Null sitename contacted"); ! 192: else if ( strncmp(&msg[6], rmtname, SITESIG) ) ! 193: FAIL2("Incorrect sitename contacted: %s", &msg[6]); ! 194: ! 195: sprintf(msg, "S%.*s -Q0 -x%d", SITESIG, nodename, debuglevel); ! 196: printmsg(M_CALLMSG, "Reply to 1st msg = {%s}", msg); ! 197: wmsg(msg); ! 198: ! 199: if ( rmsg(msg, BUFSIZ) < 0 ) ! 200: FAIL1("Logon failed: 2nd msg (remote site stale LCK?)"); ! 201: ! 202: printmsg(M_CALLMSG, "2nd msg = {%s}", visib(msg)); ! 203: if ( strncmp(msg, "ROK", 2) ) ! 204: FAIL1("Bad format for 2nd msg"); ! 205: ! 206: if ( rmsg(msg, BUFSIZ) < 0 ) ! 207: FAIL1("Logon failed: 3rd msg (broken communication?)"); ! 208: printmsg(M_CALLMSG, "3rd msg = {%s}", visib(msg)); ! 209: if ( *msg != 'P' ) ! 210: FAIL1("Bad format for 3rd msg"); ! 211: ch = 'N'; ! 212: for (cp=PROTOS; *cp; cp++) ! 213: if ( index(&msg[1], *cp) != NULL ) { ! 214: ch = *cp; ! 215: break; ! 216: } ! 217: sprintf(msg, "U%c", ch); ! 218: printmsg(M_CALLMSG, "Reply to 3rd msg = {%s}", msg); ! 219: wmsg(msg); ! 220: if ( ch == 'N' ) ! 221: FAIL1("No common protocol"); ! 222: setproto(ch); ! 223: plog(M_CALL, readymsg); ! 224: return('D'); ! 225: } else { ! 226: sprintf(msg, "Shere=%s", nodename); ! 227: printmsg(M_CALLMSG, "1st msg = {%s}", msg); ! 228: wmsg(msg); ! 229: ! 230: if ( rmsg(msg, BUFSIZ) < 0 ) ! 231: FAIL1("Logon failed: 1st reply (wrong sitename?)"); ! 232: printmsg(M_CALLMSG, "Reply to 1st msg = {%s}", visib(msg)); ! 233: if ( *msg != 'S' ) ! 234: FAIL1("Bad format for reply to 1st msg"); ! 235: if ( (cp=index(msg+1, ' ')) != NULL ) ! 236: *cp = '\0'; ! 237: if ( strlen(msg) > (SITELEN+1) ) ! 238: FAIL1("Received sitename to long"); ! 239: strcpy(locbuf, msg+1); ! 240: rmtname = &locbuf[0]; ! 241: #ifdef BBS ! 242: #define BBSUSER "bbsuser" ! 243: ! 244: /* ! 245: * For BBS, anonymous caller's sitename is replaced by the ! 246: * device name, notice we skip over "/dev/". ! 247: */ ! 248: { ! 249: char *tmp; ! 250: ! 251: if ( (strcmp(rmtname, BBSUSER) == 0) && ! 252: ((tmp=ttyname(fileno(stdin))) != NULL) ) ! 253: sprintf(locbuf, "U%s", tmp+5); ! 254: printmsg(M_DEBUG, "BBS replaced new rmtname: <%s>", ! 255: rmtname); ! 256: } ! 257: #endif ! 258: open_the_logfile("uucico"); ! 259: plog(M_CALL, "Call received from %s {%d} (V%s)", ! 260: rmtname, processid, version); ! 261: plog(M_CALL,"Locking remote site %s",rmtname); ! 262: if ( lockit(rmtname) < 0 ) { ! 263: leavelock = 1; ! 264: FAIL2("Incoming site %s already locked", rmtname); ! 265: } ! 266: ! 267: if ( !checkrmt() ) ! 268: FAIL2("Unknown host %s", rmtname); ! 269: ! 270: if ( (rdevname=ttyname(fileno(stdin))) == NULL ) ! 271: FAIL1("No attached tty device."); ! 272: rdevname += 5; ! 273: ! 274: /* The incoming device will already have been locked by login. */ ! 275: if (MASTER == role) { ! 276: if ( locktty(rdevname) < 0 ) { ! 277: cp = rdevname; ! 278: rdevname = NULL; ! 279: FAIL2("Incoming device locked: %s", cp); ! 280: } ! 281: } ! 282: ! 283: sprintf(msg, "ROK"); ! 284: printmsg(M_CALLMSG, "2nd msg = {%s}", msg); ! 285: wmsg(msg); ! 286: sprintf(msg, "P%s", PROTOS); ! 287: printmsg(M_CALLMSG, "3rd msg = {%s}", msg); ! 288: wmsg(msg); ! 289: if ( rmsg(msg, BUFSIZ) < 0 ) ! 290: FAIL1("Logon failure: 3rd reply (lost communication?)"); ! 291: printmsg(M_CALLMSG, "Reply to 3rd msg = {%s}", visib(msg)); ! 292: if ( (msg[0] != 'U') || (index(PROTOS, msg[1]) == NULL) ) ! 293: FAIL1("No common communications protocol"); ! 294: setproto(msg[1]); ! 295: plog(M_CALL, readymsg); ! 296: return('R'); ! 297: } ! 298: ! 299: failure: ! 300: plog(M_CALL, errmsg, errarg); ! 301: terminatelevel++; ! 302: return('Y'); ! 303: } ! 304: ! 305: /* ! 306: * Assign the global protocol function variables to the specified ! 307: * protocol type. ! 308: */ ! 309: ! 310: setproto(type) ! 311: char type; ! 312: { ! 313: register PROTO *p; ! 314: ! 315: for(p=&protolst[0]; (p->type!='\0') && (p->type!=type); p++) ; ! 316: ! 317: if (p->type == '\0') ! 318: fatal("setproto('%c'): Unknown protocol type", type); ! 319: printmsg(M_CALL, "Agreed protocol: %c", type); ! 320: getpkt = p->getpkt; ! 321: sendpkt = p->sendpkt; ! 322: openpk = p->openpk; ! 323: closepk = p->closepk; ! 324: ! 325: } ! 326: ! 327: /* ! 328: * expectstr(str, timeout) char *str; int timeout; ! 329: * ! 330: * Wait to receive the specified "str" from the serial connection. ! 331: * Returns: (1) if string received, ! 332: * (0) for timeout occurred before string received. ! 333: */ ! 334: ! 335: expectstr(str, timeout) ! 336: char *str; ! 337: int timeout; ! 338: { ! 339: register char *cp; ! 340: char buf[BUFSIZ], ch; ! 341: int retval = 0; ! 342: int len; ! 343: ! 344: printmsg(M_DEBUG, "waiting for {%s}", str); ! 345: ! 346: if ( strcmp(str, "\"\"") == 0 ) ! 347: retval = 1; ! 348: len = strlen(str); ! 349: ! 350: cp = &buf[0]; ! 351: while ( !retval && (sread(&ch, 1, timeout) == 1) ) { ! 352: *cp++ = ch; ! 353: if ( (cp-buf) < len ) ! 354: continue; ! 355: *cp = '\0'; ! 356: if ( strncmp(str, cp-len, len) == 0 ) ! 357: retval = 1; ! 358: if ( cp == &buf[BUFSIZ-1] ) ! 359: break; ! 360: } ! 361: printmsg(M_CALL, "actually received {%s}", visbuf(buf, cp-buf)); ! 362: if ( retval ) ! 363: printmsg(M_CALL, "got that"); ! 364: return(retval); ! 365: } ! 366: ! 367: /* ! 368: * sendstr(str) char *str; ! 369: * Send string of chat script out the communications line. ! 370: */ ! 371: ! 372: sendstr(str) ! 373: char *str; ! 374: { ! 375: register char *cp = str; ! 376: char ch; ! 377: int slash, nocr; ! 378: ! 379: sleep(1); ! 380: if ( strncmp(str, "\"\"", 2) == 0 ) ! 381: str = ""; ! 382: ! 383: nocr = slash = 0; ! 384: while ( (ch=*cp++) ) { ! 385: if ( !slash ) { ! 386: if ( strncmp(cp-1, "EOT", 3) == 0 ) { ! 387: swrite("\004", 1); ! 388: cp += 2; ! 389: } else if ( strncmp(cp-1, "BREAK", 4) == 0 ) { ! 390: sendbrk(); ! 391: cp += 4; ! 392: } else if ( ch == '\\' ) { ! 393: slash = 1; ! 394: } else { ! 395: swrite(&ch, 1); ! 396: } ! 397: continue; ! 398: } ! 399: switch( ch ) { ! 400: case 'b': ! 401: swrite("\b", 1); ! 402: break; ! 403: case 'c': ! 404: nocr = 1; ! 405: break; ! 406: case 'd': ! 407: sleep(2); ! 408: break; ! 409: case 'K': ! 410: sendbrk(); ! 411: break; ! 412: case 'n': ! 413: swrite("\n", 1); ! 414: break; ! 415: case 'N': ! 416: swrite("\0", 1); ! 417: break; ! 418: case 'p': ! 419: sleep(1); ! 420: break; ! 421: case 'r': ! 422: swrite("\r", 1); ! 423: break; ! 424: case 's': ! 425: swrite(" ", 1); ! 426: break; ! 427: case 't': ! 428: swrite("\t", 1); ! 429: break; ! 430: case '\\': ! 431: swrite("\\", 1); ! 432: break; ! 433: default: ! 434: if ( !isdigit(ch) || ! 435: !isdigit(*cp) || ! 436: !isdigit(*(cp+1)) ) ! 437: fatal("Can't parse chat script: {%s}", str); ! 438: ch = ((ch-'0')<<6) | ((*cp-'0')<<3) | (*(cp+1)); ! 439: swrite(&ch, 1); ! 440: break; ! 441: } ! 442: slash = 0; ! 443: } ! 444: if ( !nocr ){ ! 445: swrite("\r", 1); ! 446: } ! 447: } ! 448: ! 449: /* ! 450: * callup() ! 451: * Initiate the call, and walk through the chat script. ! 452: */ ! 453: ! 454: callup() ! 455: { ! 456: char *device, *speed, *phone; ! 457: char *expect, *send, *dsh; ! 458: int i; ! 459: ! 460: plog(M_CALL, "Calling site %s {%d} (V%s)", rmtname, processid, version); ! 461: ! 462: device = lsys_value(device_e); ! 463: speed = lsys_value(speed_e); ! 464: phone = lsys_value(phone_e); ! 465: ! 466: if ( strcmp(device, "ACU") == 0 ) { ! 467: if ( !dcpdial(NULL, speed, phone) ) ! 468: goto calluperr; ! 469: } else if ( !dcpdial(device, speed, NULL) ) ! 470: goto calluperr; ! 471: ! 472: for (i=0; (expect=lsys_expect(i)) != NULL; i++) { ! 473: for (;;) { ! 474: printmsg(M_CALL, "callup: expecting {%s}", expect); ! 475: if ( (dsh=index(expect, '-')) != NULL ) ! 476: *dsh++ = '\0'; ! 477: if ( expectstr(expect, MSGTIME) ) ! 478: break; ! 479: if ( dsh == NULL ) { ! 480: plog(M_CALL, "Login failed."); ! 481: goto calluperr; ! 482: } ! 483: if ( (expect=index(dsh, '-')) == NULL ) ! 484: fatal("Chat script syntax error: %s", dsh); ! 485: *expect++ = '\0'; ! 486: printmsg(M_CALL, "callup: send alternate {%s}", dsh); ! 487: sendstr(dsh); ! 488: } ! 489: send = lsys_send(i); ! 490: printmsg(M_CALL, "callup: sending {%s}", send); ! 491: sendstr(send); ! 492: } ! 493: return('P'); ! 494: ! 495: calluperr: ! 496: terminatelevel++; ! 497: return('Y'); ! 498: } ! 499: ! 500: /* ! 501: * sysend() ! 502: * End UUCP session. ! 503: */ ! 504: ! 505: sysend() ! 506: { ! 507: ! 508: /* We may have a problem here. Someone else may be removing the remote ! 509: * device lock file before we call unlocktty. Tests have shown this to ! 510: * be unimportant because the lock file IS being removed. A warning ! 511: * will be printed to the log files for users to check for locks. ! 512: * Hopefully, this isn't going to be a bug. Bob H. 11/22/91. ! 513: */ ! 514: ! 515: /* December 4, 1991: Problem solved(?). When we are in master mode, ! 516: * we call dcpundial, which calls the hangup, which, in turn, calls ! 517: * undial. Undial removes the locks on the device. Thie following ! 518: * code USED to call dcpundial if in master mode, and THEN continued ! 519: * to call the unlocktty function, which had previously been called ! 520: * by dcpundial. I snuck in an 'else' statement to get around this. ! 521: * Tests show that this solves the problem described above, but who ! 522: * knows if this will cause problems when we are NOT in master mode. ! 523: */ ! 524: ! 525: if ( role == MASTER ){ ! 526: printmsg(M_DEBUG,"Sysend: calling undial and hangup routines."); ! 527: dcpundial(); ! 528: }else{ ! 529: plog(M_CALL,"Sysend: Removing remote device lock file."); ! 530: if(unlocktty(rdevname) != 0){ ! 531: plog(M_CALL,"sysend: Possible lock file removal failure."); ! 532: } ! 533: } ! 534: ! 535: ! 536: /* May 05, 1992 (Bob H.) problems communicating with a 386 based bbs ! 537: * and a customer complaint from Germany lead to the discovery of a ! 538: * condition where undial() was never called, which meant that cicio ! 539: * NEVER hung up the phone! Adding the dcpundial() in the following ! 540: * if... resolves this. ! 541: */ ! 542: if ( !leavelock && lockexist(rmtname) ){ ! 543: dcpundial(); ! 544: plog(M_CALL,"Removing remote site lock"); ! 545: if (lockexist(rmtname)){ ! 546: #ifndef _I386 ! 547: if (lockrm(rmtname)!= 0) { ! 548: #else ! 549: if (!lockrm(rmtname)) { ! 550: #endif ! 551: printmsg(M_LOG,"sysend: Remote site Lock file removal failed!"); ! 552: plog(M_CALL,"sysend: Remote site lock file removal failed!"); ! 553: } ! 554: } ! 555: } ! 556: plog(M_CALL, terminatelevel ? ! 557: "Abnormal completion {%d}" : ! 558: "Call completing normally {%d}", processid); ! 559: close_logfile(); ! 560: sysended = 1; ! 561: return( (role == MASTER) ? 'I': 'A' ); ! 562: } ! 563: ! 564: /* ! 565: * scandir() ! 566: * ! 567: * scan work dir for "C." files matching current remote host (rmtname) ! 568: * return: ! 569: * Y - can't open file ! 570: * S - ok ! 571: * Q - no files ! 572: */ ! 573: ! 574: extern DIR *opendir(); ! 575: extern struct direct *readdir(); ! 576: ! 577: scandir() ! 578: { ! 579: char fn[DIRSIZ+1]; ! 580: char dirname[CTLFLEN]; ! 581: DIR *dirp; ! 582: struct dirent *dp; ! 583: ! 584: sprintf(dirname, "%s/%s", SPOOLDIR, rmtname); /* build spool dir name */ ! 585: printmsg(M_INFO, "Scandir: %s", dirname); ! 586: ! 587: if ((dirp=opendir(dirname)) == NULL) /* open spool dir */ ! 588: return('Q'); ! 589: ! 590: fn[0] = fn[DIRSIZ] = '\0'; ! 591: while ( (dp=readdir(dirp)) != NULL ) { ! 592: printmsg(M_DEBUG, "Scandir: %s", dp->d_name); ! 593: if ( strncmp("C.", dp->d_name, 2) ) /* is this a C. file? */ ! 594: continue; ! 595: if ( (fn[0] == '\0') || (strncmp(dp->d_name, fn, DIRSIZ) < 0) ) ! 596: strncpy(fn, dp->d_name, DIRSIZ); ! 597: } ! 598: closedir(dirp); ! 599: ! 600: if (fn[0] != '\0') { ! 601: sprintf(cfile, "%s/%s/%s", SPOOLDIR, rmtname, fn); ! 602: printmsg(M_DEBUG, "Scandir: cfile: %s", cfile); ! 603: if ((cfp = fopen(cfile, "r")) == NULL) { ! 604: plog(M_DEBUG, "Unable to open control file %s", cfile); ! 605: terminatelevel++; ! 606: return('Y'); ! 607: } ! 608: return('S'); ! 609: } ! 610: return('Q'); ! 611: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.