1*13139Sralph /* tip.c 4.14 83/06/15 */ 25136Ssam 33696Sroot /* 45136Ssam * tip - UNIX link to other systems 53696Sroot * tip [-v] [-speed] system-name 65136Ssam * or 75136Ssam * cu phone-number [-s speed] [-l line] [-a acu] 83696Sroot */ 93696Sroot #include "tip.h" 103696Sroot 11*13139Sralph static char *sccsid = "@(#)tip.c 4.14 06/15/83"; 12*13139Sralph 133696Sroot /* 143696Sroot * Baud rate mapping table 153696Sroot */ 163696Sroot int bauds[] = { 173696Sroot 0, 50, 75, 110, 134, 150, 200, 300, 600, 183696Sroot 1200, 1800, 2400, 4800, 9600, 19200, -1 193696Sroot }; 203696Sroot 214004Ssam #ifdef VMUNIX 224004Ssam int disc = OTTYDISC; /* tip normally runs this way */ 234004Ssam #endif 244004Ssam 253696Sroot int intprompt(); 263696Sroot int timeout(); 275136Ssam int cleanup(); 285257Sshannon char *sname(); 295257Sshannon extern char *sprintf(); 303696Sroot 313696Sroot main(argc, argv) 324962Ssam char *argv[]; 333696Sroot { 343696Sroot char *system = NOSTR; 353696Sroot register int i; 365257Sshannon register char *p; 375257Sshannon char sbuf[12]; 383696Sroot 395257Sshannon if (equal(sname(argv[0]), "cu")) { 405136Ssam cumain(argc, argv); 415136Ssam cumode = 1; 425136Ssam goto cucommon; 435136Ssam } 445136Ssam 453696Sroot if (argc > 4) { 463696Sroot fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 473696Sroot exit(1); 483696Sroot } 493696Sroot if (!isatty(0)) { 503696Sroot fprintf(stderr, "tip: must be interactive\n"); 513696Sroot exit(1); 523696Sroot } 535257Sshannon 545257Sshannon for (; argc > 1; argv++, argc--) { 555257Sshannon if (argv[1][0] != '-') 565257Sshannon system = argv[1]; 575257Sshannon else switch (argv[1][1]) { 585257Sshannon 595257Sshannon case 'v': 605257Sshannon vflag++; 615257Sshannon break; 625257Sshannon 635257Sshannon case '0': case '1': case '2': case '3': case '4': 645257Sshannon case '5': case '6': case '7': case '8': case '9': 655257Sshannon BR = atoi(&argv[1][1]); 665257Sshannon break; 675257Sshannon 685257Sshannon default: 695257Sshannon fprintf(stderr, "tip: %s, unknown option\n", argv[1]); 705257Sshannon break; 715257Sshannon } 725257Sshannon } 735257Sshannon 747593Sshannon if (system == NOSTR) 757593Sshannon goto notnumber; 765257Sshannon for (p = system; *p; p++) 775257Sshannon if (isalpha(*p)) 785257Sshannon goto notnumber; 795257Sshannon PN = system; /* system name is really a phone number */ 805257Sshannon system = sprintf(sbuf, "tip%d", BR); 815257Sshannon 825257Sshannon notnumber: 833696Sroot signal(SIGINT, cleanup); 843696Sroot signal(SIGQUIT, cleanup); 853696Sroot signal(SIGHUP, cleanup); 863696Sroot signal(SIGTERM, cleanup); 873898Ssam 883696Sroot if ((i = hunt(system)) == 0) { 893696Sroot printf("all ports busy\n"); 903696Sroot exit(3); 913696Sroot } 923696Sroot if (i == -1) { 933696Sroot printf("link down\n"); 944232Ssam delock(uucplock); 953696Sroot exit(3); 963696Sroot } 973719Ssam setbuf(stdout, NULL); 983696Sroot loginit(); 993696Sroot /* 1003696Sroot * Now that we have the logfile and the ACU open 1013696Sroot * return to the real uid and gid. These things will 1023696Sroot * be closed on exit. Note that we can't run as root, 1033696Sroot * because locking mechanism on the tty and the accounting 1043696Sroot * will be bypassed. 1053696Sroot */ 106*13139Sralph setgid(getgid()); 1073696Sroot setuid(getuid()); 1085257Sshannon 1093696Sroot /* 1103696Sroot * Kludge, their's no easy way to get the initialization 1113696Sroot * in the right order, so force it here 1123696Sroot */ 1133696Sroot if ((PH = getenv("PHONES")) == NOSTR) 1143696Sroot PH = "/etc/phones"; 1153696Sroot vinit(); /* init variables */ 116*13139Sralph setparity(); /* set the parity table */ 1174004Ssam if ((i = speed(number(value(BAUDRATE)))) == NULL) { 1183696Sroot printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 1193696Sroot delock(uucplock); 1203696Sroot exit(3); 1213696Sroot } 1223898Ssam 1234004Ssam /* 1244004Ssam * Hardwired connections require the 1254004Ssam * line speed set before they make any transmissions 1264004Ssam * (this is particularly true of things like a DF03-AC) 1274004Ssam */ 1284004Ssam if (HW) 1294004Ssam ttysetup(i); 1303898Ssam if (p = connect()) { 1313898Ssam printf("\07%s\n[EOT]\n", p); 1323898Ssam delock(uucplock); 1333898Ssam exit(1); 1343898Ssam } 1354004Ssam if (!HW) 1364004Ssam ttysetup(i); 1375136Ssam cucommon: 1383696Sroot /* 1395136Ssam * From here down the code is shared with 1405136Ssam * the "cu" version of tip. 1413696Sroot */ 1424004Ssam ioctl(0, TIOCGETP, (char *)&defarg); 1434004Ssam ioctl(0, TIOCGETC, (char *)&defchars); 14412478Sroot ioctl(0, TIOCGLTC, (char *)&deflchars); 1454013Ssam #ifdef VMUNIX 1464004Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1474013Ssam #endif 1483696Sroot arg = defarg; 1493696Sroot arg.sg_flags = ANYP | CBREAK; 1503696Sroot tchars = defchars; 1513696Sroot tchars.t_intrc = tchars.t_quitc = -1; 15212478Sroot ltchars = deflchars; 15312478Sroot ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc 15412478Sroot = ltchars.t_lnextc = -1; 1553696Sroot raw(); 1564004Ssam 1573696Sroot pipe(fildes); pipe(repdes); 1583696Sroot signal(SIGALRM, timeout); 1593898Ssam 1603898Ssam /* 1613898Ssam * Everything's set up now: 1623898Ssam * connection established (hardwired or diaulup) 1633898Ssam * line conditioned (baud rate, mode, etc.) 1643898Ssam * internal data structures (variables) 1653898Ssam * so, fork one process for local side and one for remote. 1663898Ssam */ 1675136Ssam printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 1683696Sroot if (pid = fork()) 1693696Sroot tipin(); 1703696Sroot else 1713696Sroot tipout(); 1723696Sroot /*NOTREACHED*/ 1733696Sroot } 1743696Sroot 1753696Sroot cleanup() 1763696Sroot { 1773696Sroot delock(uucplock); 1783898Ssam #ifdef VMUNIX 1793898Ssam if (odisc) 1803898Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1813898Ssam #endif 1823696Sroot exit(0); 1833696Sroot } 1843696Sroot 1853696Sroot /* 1863696Sroot * put the controlling keyboard into raw mode 1873696Sroot */ 1883696Sroot raw() 1893696Sroot { 1903696Sroot ioctl(0, TIOCSETP, &arg); 1913696Sroot ioctl(0, TIOCSETC, &tchars); 19212478Sroot ioctl(0, TIOCSLTC, <chars); 1934004Ssam #ifdef VMUNIX 1944004Ssam ioctl(0, TIOCSETD, (char *)&disc); 1954004Ssam #endif 1963696Sroot } 1973696Sroot 1983696Sroot 1993696Sroot /* 2003696Sroot * return keyboard to normal mode 2013696Sroot */ 2023696Sroot unraw() 2033696Sroot { 2044004Ssam #ifdef VMUNIX 2054004Ssam ioctl(0, TIOCSETD, (char *)&odisc); 2064004Ssam #endif 2074004Ssam ioctl(0, TIOCSETP, (char *)&defarg); 2084004Ssam ioctl(0, TIOCSETC, (char *)&defchars); 20912478Sroot ioctl(0, TIOCSLTC, (char *)&deflchars); 2103696Sroot } 2113696Sroot 2123696Sroot /* 2133696Sroot * Print string ``s'', then read a string 2143696Sroot * in from the terminal. Handles signals & allows use of 2153696Sroot * normal erase and kill characters. 2163696Sroot */ 2173696Sroot prompt(s, p) 2183696Sroot char *s; 2193696Sroot register char *p; 2203696Sroot { 2213696Sroot register char *b = p; 2223696Sroot 2233696Sroot stoprompt = 0; 2243696Sroot signal(SIGINT, intprompt); 2253696Sroot signal(SIGQUIT, SIG_IGN); 2263696Sroot unraw(); 2273696Sroot printf("%s", s); 2283696Sroot while ((*p = getchar()) != EOF && *p != '\n') { 2293696Sroot if (stoprompt) 2303696Sroot goto pbreak; 2313696Sroot p++; 2323696Sroot } 2333696Sroot *p = '\0'; 2343696Sroot pbreak: 2353696Sroot raw(); 2363696Sroot signal(SIGINT, SIG_DFL); 2373696Sroot signal(SIGQUIT,SIG_DFL); 2383696Sroot return(stoprompt || p == b); 2393696Sroot } 2403696Sroot 2413696Sroot /* 2423696Sroot * Interrupt service routine during prompting 2433696Sroot */ 2443696Sroot intprompt() 2453696Sroot { 2463696Sroot signal(SIGINT, SIG_IGN); 2473696Sroot stoprompt = 1; 2483696Sroot printf("\r\n"); 2493696Sroot } 2503696Sroot 2513696Sroot /* 2523696Sroot * ****TIPIN TIPIN**** 2533696Sroot */ 2543696Sroot tipin() 2553696Sroot { 2563696Sroot char gch, bol = 1; 2573696Sroot 2583796Ssam /* 2593796Ssam * Kinda klugey here... 2603796Ssam * check for scripting being turned on from the .tiprc file, 2613796Ssam * but be careful about just using setscript(), as we may 2623796Ssam * send a SIGEMT before tipout has a chance to set up catching 2633796Ssam * it; so wait a second, then setscript() 2643796Ssam */ 2653796Ssam if (boolean(value(SCRIPT))) { 2663796Ssam sleep(1); 2673796Ssam setscript(); 2683796Ssam } 2693796Ssam 2703696Sroot while (1) { 2713696Sroot gch = getchar()&0177; 2723696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2733696Sroot if (!(gch = escape())) 2743696Sroot continue; 2755136Ssam } else if (!cumode && gch == character(value(RAISECHAR))) { 2763696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2773696Sroot continue; 2783696Sroot } else if (gch == '\r') { 2793696Sroot bol = 1; 280*13139Sralph pwrite(FD, &gch, 1); 281*13139Sralph if (boolean(value(HALFDUPLEX))) 282*13139Sralph printf("\r\n"); 2833696Sroot continue; 2845136Ssam } else if (!cumode && gch == character(value(FORCE))) 2853696Sroot gch = getchar()&0177; 2863696Sroot bol = any(gch, value(EOL)); 2873696Sroot if (boolean(value(RAISE)) && islower(gch)) 288*13139Sralph gch = toupper(gch); 289*13139Sralph pwrite(FD, &gch, 1); 290*13139Sralph if (boolean(value(HALFDUPLEX))) 291*13139Sralph printf("%c", gch); 2923696Sroot } 2933696Sroot } 2943696Sroot 2953696Sroot /* 2963696Sroot * Escape handler -- 2973696Sroot * called on recognition of ``escapec'' at the beginning of a line 2983696Sroot */ 2993696Sroot escape() 3003696Sroot { 3013696Sroot register char gch; 3023696Sroot register esctable_t *p; 3033696Sroot char c = character(value(ESCAPE)); 3043696Sroot extern esctable_t etable[]; 3053696Sroot 3063696Sroot gch = (getchar()&0177); 3073696Sroot for (p = etable; p->e_char; p++) 3083696Sroot if (p->e_char == gch) { 3093696Sroot if ((p->e_flags&PRIV) && getuid()) 3103696Sroot continue; 3113696Sroot printf("%s", ctrl(c)); 3123696Sroot (*p->e_func)(gch); 3133696Sroot return(0); 3143696Sroot } 3154146Ssam /* ESCAPE ESCAPE forces ESCAPE */ 3164146Ssam if (c != gch) 317*13139Sralph pwrite(FD, &c, 1); 3183696Sroot return(gch); 3193696Sroot } 3203696Sroot 3213696Sroot speed(n) 3223696Sroot { 3233696Sroot register int *p; 3243696Sroot 3253696Sroot for (p = bauds; *p != -1; p++) 3263696Sroot if (*p == n) 3273696Sroot return(p-bauds); 3283696Sroot return(NULL); 3293696Sroot } 3303696Sroot 3313696Sroot any(c, p) 3323696Sroot register char c, *p; 3333696Sroot { 3347593Sshannon if (p) 3353696Sroot while (*p) 3363696Sroot if (*p++ == c) 3373696Sroot return(1); 3383696Sroot return(0); 3393696Sroot } 3403696Sroot 3413696Sroot size(s) 3423696Sroot register char *s; 3433696Sroot { 3443696Sroot register int i = 0; 3453696Sroot 3463696Sroot while (*s++) i++; 3473696Sroot return(i); 3483696Sroot } 3493696Sroot 3503696Sroot char * 3513696Sroot interp(s) 3523696Sroot register char *s; 3533696Sroot { 3543696Sroot static char buf[256]; 3553696Sroot register char *p = buf, c, *q; 3563696Sroot 3573696Sroot while (c = *s++) { 3583696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3593696Sroot if (*q++ == c) { 3603696Sroot *p++ = '\\'; *p++ = *q; 3613696Sroot goto next; 3623696Sroot } 3633696Sroot if (c < 040) { 3643696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3653696Sroot } else if (c == 0177) { 3663696Sroot *p++ = '^'; *p++ = '?'; 3673696Sroot } else 3683696Sroot *p++ = c; 3693696Sroot next: 3703696Sroot ; 3713696Sroot } 3723696Sroot *p = '\0'; 3733696Sroot return(buf); 3743696Sroot } 3753696Sroot 3763696Sroot char * 3773696Sroot ctrl(c) 3783696Sroot char c; 3793696Sroot { 3803696Sroot static char s[3]; 3813696Sroot 3823696Sroot if (c < 040 || c == 0177) { 3833696Sroot s[0] = '^'; 3843696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3853696Sroot s[2] = '\0'; 3863696Sroot } else { 3873696Sroot s[0] = c; 3883696Sroot s[1] = '\0'; 3893696Sroot } 3903696Sroot return(s); 3913696Sroot } 3923696Sroot 3933696Sroot /* 3943696Sroot * Help command 3953696Sroot */ 3963696Sroot help(c) 3973696Sroot char c; 3983696Sroot { 3993696Sroot register esctable_t *p; 4003696Sroot extern esctable_t etable[]; 4013696Sroot 4023696Sroot printf("%c\r\n", c); 4033696Sroot for (p = etable; p->e_char; p++) { 4043696Sroot if ((p->e_flags&PRIV) && getuid()) 4053696Sroot continue; 4063696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 4073696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 4083696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 4093696Sroot } 4103696Sroot } 4114004Ssam 4124004Ssam /* 4134004Ssam * Set up the "remote" tty's state 4144004Ssam */ 4154004Ssam ttysetup(speed) 4164004Ssam { 4174004Ssam #ifdef VMUNIX 4184004Ssam unsigned bits = LDECCTQ; 4194004Ssam #endif 4204004Ssam 4214004Ssam arg.sg_ispeed = arg.sg_ospeed = speed; 422*13139Sralph if (boolean(value(TAND))) 423*13139Sralph arg.sg_flags = TANDEM|RAW; 424*13139Sralph else 425*13139Sralph arg.sg_flags = RAW; 4264004Ssam ioctl(FD, TIOCSETP, (char *)&arg); 4274004Ssam #ifdef VMUNIX 4284004Ssam ioctl(FD, TIOCLBIS, (char *)&bits); 4294004Ssam #endif 4304004Ssam } 4315257Sshannon 4325257Sshannon /* 4335257Sshannon * Return "simple" name from a file name, 4345257Sshannon * strip leading directories. 4355257Sshannon */ 4365257Sshannon char * 4375257Sshannon sname(s) 4385257Sshannon register char *s; 4395257Sshannon { 4405257Sshannon register char *p = s; 4415257Sshannon 4425257Sshannon while (*s) 4435257Sshannon if (*s++ == '/') 4445257Sshannon p = s; 4455257Sshannon return (p); 4465257Sshannon } 447*13139Sralph 448*13139Sralph extern char chartab[]; 449*13139Sralph static char partab[0200]; 450*13139Sralph 451*13139Sralph /* 452*13139Sralph * do a write to the remote machine with the correct parity 453*13139Sralph * we are doing 8 bit wide output, so we just generate a character 454*13139Sralph * with the right parity and output it. 455*13139Sralph */ 456*13139Sralph pwrite(fd, buf, n) 457*13139Sralph int fd; 458*13139Sralph char *buf; 459*13139Sralph register int n; 460*13139Sralph { 461*13139Sralph register int i; 462*13139Sralph register char *bp = buf; 463*13139Sralph 464*13139Sralph for (i = 0, bp = buf; i < n; i++, bp++) { 465*13139Sralph *bp = partab[(*bp) & 0177]; 466*13139Sralph } 467*13139Sralph write(fd, buf, n); 468*13139Sralph } 469*13139Sralph 470*13139Sralph /* 471*13139Sralph * build a parity table with the right high-order bit 472*13139Sralph * copy an even-parity table and doctor it 473*13139Sralph */ 474*13139Sralph setparity() 475*13139Sralph { 476*13139Sralph int i; 477*13139Sralph char *parity; 478*13139Sralph 479*13139Sralph if (value(PARITY) == NOSTR) 480*13139Sralph value(PARITY) = "even"; 481*13139Sralph 482*13139Sralph parity = value(PARITY); 483*13139Sralph 484*13139Sralph for (i = 0; i < 0200; i++) 485*13139Sralph partab[i] = chartab[i]; 486*13139Sralph 487*13139Sralph if (equal(parity, "odd")) { 488*13139Sralph for (i = 0; i < 0200; i++) 489*13139Sralph partab[i] ^= 0200; /* reverse bit 7 */ 490*13139Sralph } 491*13139Sralph else if (equal(parity, "none") || equal(parity, "zero")) { 492*13139Sralph for (i = 0; i < 0200; i++) 493*13139Sralph partab[i] &= ~0200; /* turn off bit 7 */ 494*13139Sralph } 495*13139Sralph else if (equal(parity, "one")) { 496*13139Sralph for (i = 0; i < 0200; i++) 497*13139Sralph partab[i] |= 0200; /* turn on bit 7 */ 498*13139Sralph } 499*13139Sralph else if (equal(parity, "even")) { 500*13139Sralph /* table is already even parity */ 501*13139Sralph } 502*13139Sralph else { 503*13139Sralph fprintf(stderr, "parity value %s unknown\n", PA); 504*13139Sralph fflush(stderr); 505*13139Sralph } 506*13139Sralph } 507