1: #define CONN 2: #include "uucp.h" 3: #include <signal.h> 4: #include <sgtty.h> 5: #include <setjmp.h> 6: #include <ctype.h> 7: #include <sys/types.h> 8: #include <time.h> 9: 10: 11: #define F_NAME 0 12: #define F_TIME 1 13: #define F_LINE 2 14: #define F_SPEED 3 15: #define F_PHONE 4 16: #define F_LOGIN 5 17: 18: jmp_buf Sjbuf; 19: #define INVOKE(a, r) ret = a; if (ret<0) return(r); 20: /******* 21: * conn(system) 22: * char *system; 23: * 24: * conn - place a telephone call to system and 25: * login, etc. 26: * 27: * return codes: 28: * CF_SYSTEM: don't know system 29: * CF_TIME: wrong time to call 30: * CF_DIAL: call failed 31: * CF_LOGIN: login/password dialog failed 32: * 33: * >0 - file no. - connect ok 34: * 35: */ 36: 37: conn(system) 38: char *system; 39: { 40: int ret, nf; 41: int fn; 42: char *flds[50]; 43: DEBUG(4, "gdial %s\n", "called"); 44: INVOKE(gdial(), CF_DIAL) 45: DEBUG(4, "finds %s\n", "called"); 46: INVOKE(nf = finds(system, flds), nf) 47: DEBUG(4, "getto %s\n", "called"); 48: INVOKE(fn = getto(flds), CF_DIAL) 49: DEBUG(4, "login %s\n", "called"); 50: INVOKE(login(nf, flds, fn), CF_LOGIN) 51: return(fn); 52: } 53: 54: /*** 55: * char * 56: * lastc(s) return pointer to last character 57: * char *s; 58: * 59: */ 60: 61: char * 62: lastc(s) 63: char *s; 64: { 65: while (*s != '\0') s++; 66: return(s); 67: } 68: 69: #define MAXDEV 10 70: #define MAXDCH MAXDEV*20 71: #define MAXCODE 30 72: #define MAXCCH MAXCODE*20 73: /* This array tells us about possible acu's, etc. */ 74: struct Devices { 75: char *D_line; 76: char *D_acu; 77: int D_speed; 78: } Devs [MAXDEV]; 79: 80: char Devbuff[MAXDCH]; 81: 82: struct Codes { 83: char *C_locs; 84: char *C_prefix; 85: } Dialcodes [MAXCODE]; 86: 87: char Codebuff[MAXCCH]; 88: int Dcfull = 0; 89: 90: 91: /*** 92: * gdial() get device and dial info 93: * 94: * return codes: 0 | FAIL 95: */ 96: 97: gdial() 98: { 99: char *flds[10], *lt; 100: char *lb = Devbuff; 101: char *lc = Codebuff; 102: FILE *fn; 103: int nr; 104: struct Devices *pd; 105: struct Codes *pc; 106: if (Dcfull) return(0); 107: 108: fn = fopen(Devfile, "r"); 109: ASSERT(fn != NULL, "CAN'T OPEN %s", Devfile); 110: for (pd = Devs; fgets(lb, 200, fn); pd++) { 111: lt = lastc(lb); 112: nr = getargs(lb, flds); 113: ASSERT(nr == 3, "BAD LINE %s", lb); 114: pd->D_line = flds[0]; 115: pd->D_acu = flds[1]; 116: pd->D_speed = atoi(flds[2]); 117: lb = lt; 118: ASSERT(lb < Devbuff + MAXDCH, "TOO LONG %s", Devbuff); 119: ASSERT(pd < Devs + MAXDEV, "TOO MANY DEVICES %d", MAXCODE); 120: } 121: pd->D_line = NULL; 122: fclose(fn); 123: ASSERT(pd > Devs, "BAD FILE %s", Devfile); 124: /* Now dialcodes, same way */ 125: fn = fopen(Dialfile, "r"); 126: ASSERT(fn != NULL, "CAN'T OPEN %s", Dialfile); 127: for (pc = Dialcodes; fgets(lc, 200, fn); pc++) { 128: lt = lastc(lc); 129: nr = getargs(lc, flds); 130: if (nr == 1) flds[nr++] = ""; 131: ASSERT(nr == 2, "BAD LINE %s", lc); 132: pc->C_locs = flds[0]; 133: pc->C_prefix = flds[1]; 134: lc = lt; 135: ASSERT(lc < Codebuff + MAXCCH, "TOO LONG %s", Codebuff); 136: ASSERT(pc < Dialcodes + MAXCODE, "MANY DEVICES %d", MAXCODE); 137: } 138: pc->C_locs = 0; 139: fclose(fn); 140: return(0); 141: } 142: 143: 144: /*** 145: * ckdev(type, speed, ndev) 146: * char *type, *speed; 147: * int ndev; 148: * 149: * ckdev - return the device number in table Devs for 150: * a device with proper attributes. 151: * 152: * return codes: >= 0 (ok) | FAIL 153: */ 154: 155: ckdev(type, speed, ndev) 156: char *type, *speed; 157: int ndev; 158: { 159: int sp, acu; 160: struct Devices *pd; 161: 162: sp = atoi(speed); 163: acu =(strcmp(type, "ACU") == SAME); 164: for (pd = &Devs[ndev]; pd->D_line != NULL; pd++) { 165: if (sp != pd->D_speed) 166: continue; 167: if (acu && (strcmp(pd->D_acu, "0") != SAME) 168: && !mlock(pd->D_line)) 169: return(ndev = pd - Devs); 170: if (!acu && (strcmp(pd->D_line, type) == SAME) 171: && !mlock(type)) 172: return(ndev = pd - Devs); 173: } 174: return(FAIL); 175: } 176: 177: 178: /*** 179: * getto(flds) connect to remote machine 180: * char *flds[]; 181: * 182: * return codes: 183: * >0 - file number - ok 184: * FAIL - failed 185: */ 186: 187: getto(flds) 188: char *flds[]; 189: { 190: DEBUG(F_PHONE, "call: no. %s ", flds[4]); 191: DEBUG(4, "for sys %s ", flds[F_NAME]); 192: 193: if (strcmp(flds[F_LINE], "ACU") == SAME) 194: return(call(flds)); 195: else 196: return(direct(flds)); 197: } 198: 199: /*** 200: * call(flds) call remote machine 201: * char *flds[]; 202: * 203: * "flds" contains the call information (name, date, type, speed, 204: * phone no. ... 205: * Ndev has the device no. 206: * 207: * return codes: 208: * >0 - file number - ok 209: * FAIL - failed 210: */ 211: 212: call(flds) 213: char *flds[]; 214: { 215: char *pno, pref[20], phone[20]; 216: char *s1, *s2; 217: int dcr; 218: struct Codes *pc; 219: 220: pno = flds[F_PHONE]; 221: s1 = pref; s2 = pno; 222: while (isalpha(*s2)) 223: *s1++ = *s2++; 224: *s1 = '\0'; 225: for (pc = Dialcodes; pc->C_locs; pc++) 226: if (strcmp(pc->C_locs, pref) == SAME) { 227: s1 = pc->C_prefix; 228: break; 229: } 230: sprintf(phone, "%s%s", s1, s2); 231: DEBUG(4, "Dial %s\n", phone); 232: dcr = dialup(phone, flds); 233: DEBUG(4, "dcr returned as %d\n", dcr); 234: if (dcr == FAIL) 235: return(FAIL); 236: return(dcr); 237: 238: } 239: 240: /* file descriptor for call unit */ 241: int Dnf = 0; 242: 243: /*** 244: * dialup(ph, flds) dial remote machine 245: * char *ph; 246: * char *flds[]; 247: * 248: * return codes: 249: * file descriptor - succeeded 250: * FAIL - failed 251: */ 252: 253: dialup(ph, flds) 254: char *ph; 255: char *flds[]; 256: { 257: char dcname[20], dnname[20], phone[20]; 258: struct Devices *pd; 259: int nw, lt, pid, dcf, ndev; 260: extern int Error; 261: extern alarmtr(); 262: 263: for (ndev = 0;;ndev++) { 264: ndev = ckdev(flds[F_LINE], flds[F_SPEED], ndev); 265: if (ndev < 0) { 266: logent("AVAILABLE DEVICE", "NO"); 267: DEBUG(4, "NO AVAILABLE DEVICE %s\n", ""); 268: return(FAIL); 269: } 270: pd = &Devs[ndev]; 271: sprintf(dnname, "/dev/%s", pd->D_acu); 272: /* open call unit */ 273: Dnf = open(dnname, 1); 274: if (Dnf >= 0) 275: break; 276: delock(pd->D_line); 277: } 278: sprintf(dcname, "/dev/%s", pd->D_line); 279: sprintf(phone, "%s%s", ph, ACULAST); 280: DEBUG(4, "dc - %s, ", dcname); 281: DEBUG(4, "acu - %s\n", dnname); 282: if (setjmp(Sjbuf)) { 283: DEBUG(1, "DN write %s\n", "timeout"); 284: logent("DIALUP DN write", "TIMEOUT"); 285: kill(pid, 9); 286: close(Dnf); 287: return(FAIL); 288: } 289: signal(SIGALRM, alarmtr); 290: alarm(30); 291: if ((pid = fork()) == 0) { 292: sleep(2); 293: fclose(stdin); 294: fclose(stdout); 295: nw = write(Dnf, phone, lt = strlen(phone)); 296: if (nw != lt) { 297: DEBUG(1, "ACU write %s\n", "error"); 298: logent("DIALUP ACU write", "FAILED"); 299: exit(1); 300: } 301: DEBUG(4, "ACU write ok%s\n", ""); 302: exit(0); 303: } 304: /* open line - will return on carrier */ 305: dcf = open(dcname, 2); 306: DEBUG(4, "dcf is %d\n", dcf); 307: if (dcf < 0) { 308: DEBUG(1, "Line open %s\n", "failed"); 309: logent("DIALUP LINE open", "FAILED"); 310: alarm(0); 311: return(FAIL); 312: } 313: ioctl(dcf, TIOCHPCL, 0); 314: nw = wait(<); 315: alarm(0); 316: fflush(stdout); 317: fixline(dcf, pd->D_speed); 318: DEBUG(4, "Forked %d ", pid); 319: DEBUG(4, "Wait got %d ", nw); 320: DEBUG(4, "Status %o\n", lt); 321: if (lt != 0) { 322: close(dcf); 323: return(FAIL); 324: } 325: return(dcf); 326: } 327: 328: 329: /*** 330: * clsacu() close call unit 331: * 332: * return codes: none 333: */ 334: 335: clsacu() 336: { 337: if (Dnf > 0) { 338: close(Dnf); 339: Dnf = 0; 340: } 341: return; 342: } 343: 344: 345: /*** 346: * direct(flds) connect to hardware line 347: * char *flds[]; 348: * 349: * return codes: 350: * >0 - file number - ok 351: * FAIL - failed 352: */ 353: 354: direct(flds) 355: char *flds[]; 356: { 357: int dcr, ndev; 358: char dcname[20]; 359: 360: ndev = 0; 361: if ((ndev = ckdev(flds[F_LINE], flds[F_SPEED], ndev)) < 0) { 362: logent("DEVICE", "NOT AVAILABLE"); 363: return(FAIL); 364: } 365: sprintf(dcname, "/dev/%s", Devs[ndev].D_line); 366: signal(SIGALRM, alarmtr); 367: alarm(10); 368: if (setjmp(Sjbuf)) 369: return(FAIL); 370: dcr = open(dcname, 2); /* read/write */ 371: alarm(0); 372: if (dcr < 0) 373: return(FAIL); 374: fflush(stdout); 375: fixline(dcr, Devs[ndev].D_speed); 376: return(dcr); 377: } 378: 379: 380: 381: #define MAXC 300 382: 383: /*** 384: * finds(sysnam, flds) set system attribute vector 385: * char *sysnam, *flds[]; 386: * 387: * return codes: 388: * >0 - number of arguments in vector - succeeded 389: * CF_SYSTEM - system name not found 390: * CF_TIME - wrong time to call 391: */ 392: 393: finds(sysnam, flds) 394: char *sysnam, *flds[]; 395: { 396: FILE *fsys; 397: static char info[MAXC]; 398: char **fnp; 399: int na; 400: int fnd = 0; 401: 402: for (fnp = Sysfiles; *fnp != NULL && !fnd; fnp++) { 403: fsys = fopen(*fnp, "r"); 404: if (fsys == NULL) 405: continue; 406: while (!fnd && (fgets(info, MAXC, fsys) != NULL)) { 407: na = getargs(info, flds); 408: if (prefix(sysnam, flds[F_NAME])) 409: fnd = 1; 410: } 411: fclose(fsys); 412: } 413: if (fnd == 0) 414: return(CF_SYSTEM); 415: /* format of fields 416: * 0 name; 417: * 1 time 418: * 2 acu/hardwired 419: * 3 speed 420: * etc 421: */ 422: if (ifdate(flds[F_TIME]) == 0) { 423: DEBUG(1, "Wrong time to call %s\n", sysnam); 424: logent(sysnam, "WRONG TIME TO CALL"); 425: return(CF_TIME); 426: } 427: return(na); 428: } 429: 430: 431: /*** 432: * login(nf, flds, dcr) do log conversation 433: * char *flds[]; 434: * int nf; 435: * 436: * return codes: 0 | FAIL 437: */ 438: 439: login(nf, flds, fn) 440: char *flds[]; 441: int nf, fn; 442: { 443: char *want, *altern; 444: extern char *index(); 445: int k, ok; 446: 447: ASSERT(nf > 4, "TOO FEW LOG FIELDS %d", nf); 448: for (k = F_LOGIN; k < nf; k += 2) { 449: want = flds[k]; 450: ok = FAIL; 451: while (ok != 0) { 452: altern = index(want, '-'); 453: if (altern != NULL) 454: *altern++ = '\0'; 455: DEBUG(4, "wanted %s ", want); 456: ok = expect(want, fn); 457: DEBUG(4, "got %s\n", ok ? "?" : "that"); 458: if (ok == 0) 459: break; 460: if (altern == NULL) { 461: logent("LOGIN", "FAILED"); 462: return(FAIL); 463: } 464: want = index(altern, '-'); 465: if (want != NULL) 466: *want++ = '\0'; 467: sendthem(altern, fn); 468: } 469: sleep(2); 470: sendthem(flds[k+1], fn); 471: } 472: return(0); 473: } 474: 475: 476: struct sg_spds {int sp_val, sp_name;} spds[] = { 477: { 300, B300}, 478: {1200, B1200}, 479: {4800, B4800}, 480: {9600, B9600}, 481: {0, 0} }; 482: 483: /*** 484: * fixline(tty, spwant) set speed/echo/mode... 485: * int tty, spwant; 486: * 487: * return codes: none 488: */ 489: 490: fixline(tty, spwant) 491: int tty, spwant; 492: { 493: struct sgttyb ttbuf; 494: struct sg_spds *ps; 495: int speed = -1; 496: int ret; 497: 498: for (ps = spds; ps->sp_val; ps++) 499: if (ps->sp_val == spwant) 500: speed = ps->sp_name; 501: ASSERT(speed >= 0, "BAD SPEED %d", speed); 502: ioctl(tty, TIOCGETP, &ttbuf); 503: ttbuf.sg_flags |=(ANYP|RAW); 504: ttbuf.sg_flags &= ~(ECHO|ALLDELAY); 505: ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; 506: DEBUG(4, "Speed: want %d ", spwant); 507: DEBUG(4, "use %o ", speed); 508: DEBUG(4, "ps %d\n", ps-spds); 509: ret = ioctl(tty, TIOCSETP, &ttbuf); 510: ASSERT(ret >= 0, "RETURN FROM STTY %d", ret); 511: ioctl(tty, TIOCHPCL, 0); 512: ioctl(tty, TIOCEXCL, 0); 513: return; 514: } 515: 516: 517: #define MR 300 518: 519: int Error = 0; 520: 521: /*** 522: * expect(str, fn) look for expected string 523: * char *str; 524: * 525: * return codes: 526: * 0 - found 527: * FAIL - lost line or too many characters read 528: * some character - timed out 529: */ 530: 531: expect(str, fn) 532: char *str; 533: int fn; 534: { 535: static char rdvec[MR]; 536: extern alarmtr(); 537: char *rp = rdvec; 538: int nextch = 0, kr; 539: 540: if (strcmp(str, "\"\"") == SAME) 541: return(0); 542: *rp = 0; 543: if (setjmp(Sjbuf)) { 544: return(FAIL); 545: } 546: signal(SIGALRM, alarmtr); 547: while (notin(str, rdvec)) { 548: alarm(MAXCHARTIME); 549: kr = read(fn, &nextch, 1); 550: if (kr <= 0) { 551: DEBUG(4, "kr - %d\n", kr); 552: alarm(0); 553: DEBUG(4, "lost line kr - %d, ", kr); 554: DEBUG(4, "fn - %d\n", fn); 555: logent("LOGIN", "LOST LINE"); 556: return(FAIL); 557: } 558: { 559: int c; 560: c = nextch & 0177; 561: DEBUG(4, "%c", c > 040 ? c : '_'); 562: } 563: if ((*rp = nextch & 0177) != '\0') 564: rp++; 565: *rp = '\0'; 566: if (rp >= rdvec + MR) 567: return(FAIL); 568: } 569: alarm(0); 570: return(0); 571: } 572: 573: 574: /*** 575: * alarmtr() - catch alarm routine for "expect". 576: */ 577: 578: alarmtr() 579: { 580: longjmp(Sjbuf, 1); 581: } 582: 583: 584: /*** 585: * sendthem(str, fn) send line of login sequence 586: * char *str; 587: * 588: * return codes: none 589: */ 590: 591: sendthem(str, fn) 592: char *str; 593: int fn; 594: { 595: int nw, ns; 596: int nulls; 597: 598: if (prefix("BREAK", str)) { 599: sscanf(&str[5], "%1d", &nulls); 600: if (nulls <= 0 || nulls > 10) 601: nulls = 3; 602: /* send break */ 603: DEBUG(5, "%s,", str); 604: DEBUG(5, "%d\n", nulls); 605: genbrk(fn, Bspeed, nulls); 606: return; 607: } 608: 609: if (strcmp(str, "EOT") == SAME) { 610: write(fn, EOTMSG, strlen(EOTMSG)); 611: return; 612: } 613: if (strcmp(str, "") != SAME) { 614: nw = write(fn, str, ns = strlen(str)); 615: ASSERT(nw == ns, "BAD WRITE $s", str); 616: } 617: write(fn, "\n", 1); 618: return; 619: } 620: 621: 622: /*** 623: * genbrk(fn) send equivalent to break 624: * 625: * return codes; none 626: */ 627: 628: genbrk(fn, bspeed, bnulls) 629: int fn, bspeed, bnulls; 630: { 631: struct sgttyb ttbuf; 632: int ret, sospeed; 633: 634: ret = ioctl(fn, TIOCGETP, &ttbuf); 635: DEBUG(5, "ioctl ret %d\n", ret); 636: sospeed = ttbuf.sg_ospeed; 637: ttbuf.sg_ospeed = bspeed; 638: ret = ioctl(fn, TIOCSETP, &ttbuf); 639: DEBUG(5, "ioctl ret %d\n", ret); 640: ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls); 641: ASSERT(ret > 0, "BAD WRITE genbrk %d", ret); 642: ttbuf.sg_ospeed = sospeed; 643: ret = ioctl(fn, TIOCSETP, &ttbuf); 644: ret = write(fn, "@", 1); 645: ASSERT(ret > 0, "BAD WRITE genbrk %d", ret); 646: DEBUG(4, "sent BREAK nulls - %d\n", bnulls); 647: return; 648: } 649: 650: 651: /*** 652: * notin(sh, lg) check for occurrence of substring "sh" 653: * char *sh, *lg; 654: * 655: * return codes: 656: * 0 - found the string 657: * 1 - not in the string 658: */ 659: 660: notin(sh, lg) 661: char *sh, *lg; 662: { 663: while (*lg != '\0') { 664: if (prefix(sh, lg)) 665: return(0); 666: else 667: lg++; 668: } 669: return(1); 670: } 671: 672: 673: /******* 674: * ifdate(s) 675: * char *s; 676: * 677: * ifdate - this routine will check a string (s) 678: * like "MoTu0800-1730" to see if the present 679: * time is within the given limits. 680: * 681: * String alternatives: 682: * Wk - Mo thru Fr 683: * zero or one time means all day 684: * Any - any day 685: * 686: * return codes: 687: * 0 - not within limits 688: * 1 - within limits 689: */ 690: 691: ifdate(s) 692: char *s; 693: { 694: static char *days[]={ 695: "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0 696: }; 697: long clock; 698: int i, tl, th, tn, dayok=0; 699: struct tm *localtime(); 700: struct tm *tp; 701: 702: time(&clock); 703: tp = localtime(&clock); 704: while (isalpha(*s)) { 705: for (i = 0; days[i]; i++) { 706: if (prefix(days[i], s)) 707: if (tp->tm_wday == i) 708: dayok = 1; 709: } 710: 711: if (prefix("Wk", s)) 712: if (tp->tm_wday >= 1 && tp->tm_wday <= 5) 713: dayok = 1; 714: if (prefix("Any", s)) 715: dayok = 1; 716: s++; 717: } 718: 719: if (dayok == 0) 720: return(0); 721: i = sscanf(s, "%d-%d", &tl, &th); 722: tn = tp->tm_hour * 100 + tp->tm_min; 723: if (i < 2) 724: return(1); 725: if (tn >= tl && tn <= th) 726: return(1); 727: return(0); 728: }