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