1*7593Sshannon /* tip.c 4.12 82/07/29 */ 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 113696Sroot /* 123696Sroot * Baud rate mapping table 133696Sroot */ 143696Sroot int bauds[] = { 153696Sroot 0, 50, 75, 110, 134, 150, 200, 300, 600, 163696Sroot 1200, 1800, 2400, 4800, 9600, 19200, -1 173696Sroot }; 183696Sroot 194004Ssam #ifdef VMUNIX 204004Ssam int disc = OTTYDISC; /* tip normally runs this way */ 214004Ssam #endif 224004Ssam 233696Sroot int intprompt(); 243696Sroot int timeout(); 255136Ssam int cleanup(); 265257Sshannon char *sname(); 275257Sshannon extern char *sprintf(); 283696Sroot 293696Sroot main(argc, argv) 304962Ssam char *argv[]; 313696Sroot { 323696Sroot char *system = NOSTR; 333696Sroot register int i; 345257Sshannon register char *p; 355257Sshannon char sbuf[12]; 363696Sroot 375257Sshannon if (equal(sname(argv[0]), "cu")) { 385136Ssam cumain(argc, argv); 395136Ssam cumode = 1; 405136Ssam goto cucommon; 415136Ssam } 425136Ssam 433696Sroot if (argc > 4) { 443696Sroot fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 453696Sroot exit(1); 463696Sroot } 473696Sroot if (!isatty(0)) { 483696Sroot fprintf(stderr, "tip: must be interactive\n"); 493696Sroot exit(1); 503696Sroot } 515257Sshannon 525257Sshannon for (; argc > 1; argv++, argc--) { 535257Sshannon if (argv[1][0] != '-') 545257Sshannon system = argv[1]; 555257Sshannon else switch (argv[1][1]) { 565257Sshannon 575257Sshannon case 'v': 585257Sshannon vflag++; 595257Sshannon break; 605257Sshannon 615257Sshannon case '0': case '1': case '2': case '3': case '4': 625257Sshannon case '5': case '6': case '7': case '8': case '9': 635257Sshannon BR = atoi(&argv[1][1]); 645257Sshannon break; 655257Sshannon 665257Sshannon default: 675257Sshannon fprintf(stderr, "tip: %s, unknown option\n", argv[1]); 685257Sshannon break; 695257Sshannon } 705257Sshannon } 715257Sshannon 72*7593Sshannon if (system == NOSTR) 73*7593Sshannon goto notnumber; 745257Sshannon for (p = system; *p; p++) 755257Sshannon if (isalpha(*p)) 765257Sshannon goto notnumber; 775257Sshannon PN = system; /* system name is really a phone number */ 785257Sshannon system = sprintf(sbuf, "tip%d", BR); 795257Sshannon 805257Sshannon notnumber: 813696Sroot signal(SIGINT, cleanup); 823696Sroot signal(SIGQUIT, cleanup); 833696Sroot signal(SIGHUP, cleanup); 843696Sroot signal(SIGTERM, cleanup); 853898Ssam 863696Sroot if ((i = hunt(system)) == 0) { 873696Sroot printf("all ports busy\n"); 883696Sroot exit(3); 893696Sroot } 903696Sroot if (i == -1) { 913696Sroot printf("link down\n"); 924232Ssam delock(uucplock); 933696Sroot exit(3); 943696Sroot } 953719Ssam setbuf(stdout, NULL); 963696Sroot loginit(); 973696Sroot /* 983696Sroot * Now that we have the logfile and the ACU open 993696Sroot * return to the real uid and gid. These things will 1003696Sroot * be closed on exit. Note that we can't run as root, 1013696Sroot * because locking mechanism on the tty and the accounting 1023696Sroot * will be bypassed. 1033696Sroot */ 1043696Sroot setuid(getuid()); 1053696Sroot setgid(getgid()); 1065257Sshannon 1073696Sroot /* 1083696Sroot * Kludge, their's no easy way to get the initialization 1093696Sroot * in the right order, so force it here 1103696Sroot */ 1113696Sroot if ((PH = getenv("PHONES")) == NOSTR) 1123696Sroot PH = "/etc/phones"; 1133696Sroot vinit(); /* init variables */ 1144004Ssam if ((i = speed(number(value(BAUDRATE)))) == NULL) { 1153696Sroot printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 1163696Sroot delock(uucplock); 1173696Sroot exit(3); 1183696Sroot } 1193898Ssam 1204004Ssam /* 1214004Ssam * Hardwired connections require the 1224004Ssam * line speed set before they make any transmissions 1234004Ssam * (this is particularly true of things like a DF03-AC) 1244004Ssam */ 1254004Ssam if (HW) 1264004Ssam ttysetup(i); 1273898Ssam if (p = connect()) { 1283898Ssam printf("\07%s\n[EOT]\n", p); 1293898Ssam delock(uucplock); 1303898Ssam exit(1); 1313898Ssam } 1324004Ssam if (!HW) 1334004Ssam ttysetup(i); 1345136Ssam cucommon: 1353696Sroot /* 1365136Ssam * From here down the code is shared with 1375136Ssam * the "cu" version of tip. 1383696Sroot */ 1394004Ssam ioctl(0, TIOCGETP, (char *)&defarg); 1404004Ssam ioctl(0, TIOCGETC, (char *)&defchars); 1414013Ssam #ifdef VMUNIX 1424004Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1434013Ssam #endif 1443696Sroot arg = defarg; 1453696Sroot arg.sg_flags = ANYP | CBREAK; 1463696Sroot tchars = defchars; 1473696Sroot tchars.t_intrc = tchars.t_quitc = -1; 1483696Sroot raw(); 1494004Ssam 1503696Sroot pipe(fildes); pipe(repdes); 1513696Sroot signal(SIGALRM, timeout); 1523898Ssam 1533898Ssam /* 1543898Ssam * Everything's set up now: 1553898Ssam * connection established (hardwired or diaulup) 1563898Ssam * line conditioned (baud rate, mode, etc.) 1573898Ssam * internal data structures (variables) 1583898Ssam * so, fork one process for local side and one for remote. 1593898Ssam */ 1605136Ssam printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 1613696Sroot if (pid = fork()) 1623696Sroot tipin(); 1633696Sroot else 1643696Sroot tipout(); 1653696Sroot /*NOTREACHED*/ 1663696Sroot } 1673696Sroot 1683696Sroot cleanup() 1693696Sroot { 1703696Sroot delock(uucplock); 1713898Ssam #ifdef VMUNIX 1723898Ssam if (odisc) 1733898Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1743898Ssam #endif 1753696Sroot exit(0); 1763696Sroot } 1773696Sroot 1783696Sroot /* 1793696Sroot * put the controlling keyboard into raw mode 1803696Sroot */ 1813696Sroot raw() 1823696Sroot { 1833696Sroot ioctl(0, TIOCSETP, &arg); 1843696Sroot ioctl(0, TIOCSETC, &tchars); 1854004Ssam #ifdef VMUNIX 1864004Ssam ioctl(0, TIOCSETD, (char *)&disc); 1874004Ssam #endif 1883696Sroot } 1893696Sroot 1903696Sroot 1913696Sroot /* 1923696Sroot * return keyboard to normal mode 1933696Sroot */ 1943696Sroot unraw() 1953696Sroot { 1964004Ssam #ifdef VMUNIX 1974004Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1984004Ssam #endif 1994004Ssam ioctl(0, TIOCSETP, (char *)&defarg); 2004004Ssam ioctl(0, TIOCSETC, (char *)&defchars); 2013696Sroot } 2023696Sroot 2033696Sroot /* 2043696Sroot * Print string ``s'', then read a string 2053696Sroot * in from the terminal. Handles signals & allows use of 2063696Sroot * normal erase and kill characters. 2073696Sroot */ 2083696Sroot prompt(s, p) 2093696Sroot char *s; 2103696Sroot register char *p; 2113696Sroot { 2123696Sroot register char *b = p; 2133696Sroot 2143696Sroot stoprompt = 0; 2153696Sroot signal(SIGINT, intprompt); 2163696Sroot signal(SIGQUIT, SIG_IGN); 2173696Sroot unraw(); 2183696Sroot printf("%s", s); 2193696Sroot while ((*p = getchar()) != EOF && *p != '\n') { 2203696Sroot if (stoprompt) 2213696Sroot goto pbreak; 2223696Sroot p++; 2233696Sroot } 2243696Sroot *p = '\0'; 2253696Sroot pbreak: 2263696Sroot raw(); 2273696Sroot signal(SIGINT, SIG_DFL); 2283696Sroot signal(SIGQUIT,SIG_DFL); 2293696Sroot return(stoprompt || p == b); 2303696Sroot } 2313696Sroot 2323696Sroot /* 2333696Sroot * Interrupt service routine during prompting 2343696Sroot */ 2353696Sroot intprompt() 2363696Sroot { 2373696Sroot signal(SIGINT, SIG_IGN); 2383696Sroot stoprompt = 1; 2393696Sroot printf("\r\n"); 2403696Sroot } 2413696Sroot 2423696Sroot /* 2433696Sroot * ****TIPIN TIPIN**** 2443696Sroot */ 2453696Sroot tipin() 2463696Sroot { 2473696Sroot char gch, bol = 1; 2483696Sroot 2493796Ssam /* 2503796Ssam * Kinda klugey here... 2513796Ssam * check for scripting being turned on from the .tiprc file, 2523796Ssam * but be careful about just using setscript(), as we may 2533796Ssam * send a SIGEMT before tipout has a chance to set up catching 2543796Ssam * it; so wait a second, then setscript() 2553796Ssam */ 2563796Ssam if (boolean(value(SCRIPT))) { 2573796Ssam sleep(1); 2583796Ssam setscript(); 2593796Ssam } 2603796Ssam 2613696Sroot while (1) { 2623696Sroot gch = getchar()&0177; 2633696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2643696Sroot if (!(gch = escape())) 2653696Sroot continue; 2665136Ssam } else if (!cumode && gch == character(value(RAISECHAR))) { 2673696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2683696Sroot continue; 2693696Sroot } else if (gch == '\r') { 2703696Sroot bol = 1; 2713696Sroot write(FD, &gch, 1); 2723696Sroot continue; 2735136Ssam } else if (!cumode && gch == character(value(FORCE))) 2743696Sroot gch = getchar()&0177; 2753696Sroot bol = any(gch, value(EOL)); 2763696Sroot if (boolean(value(RAISE)) && islower(gch)) 2773696Sroot toupper(gch); 2783696Sroot write(FD, &gch, 1); 2793696Sroot } 2803696Sroot } 2813696Sroot 2823696Sroot /* 2833696Sroot * Escape handler -- 2843696Sroot * called on recognition of ``escapec'' at the beginning of a line 2853696Sroot */ 2863696Sroot escape() 2873696Sroot { 2883696Sroot register char gch; 2893696Sroot register esctable_t *p; 2903696Sroot char c = character(value(ESCAPE)); 2913696Sroot extern esctable_t etable[]; 2923696Sroot 2933696Sroot gch = (getchar()&0177); 2943696Sroot for (p = etable; p->e_char; p++) 2953696Sroot if (p->e_char == gch) { 2963696Sroot if ((p->e_flags&PRIV) && getuid()) 2973696Sroot continue; 2983696Sroot printf("%s", ctrl(c)); 2993696Sroot (*p->e_func)(gch); 3003696Sroot return(0); 3013696Sroot } 3024146Ssam /* ESCAPE ESCAPE forces ESCAPE */ 3034146Ssam if (c != gch) 3044146Ssam write(FD, &c, 1); 3053696Sroot return(gch); 3063696Sroot } 3073696Sroot 3083696Sroot speed(n) 3093696Sroot { 3103696Sroot register int *p; 3113696Sroot 3123696Sroot for (p = bauds; *p != -1; p++) 3133696Sroot if (*p == n) 3143696Sroot return(p-bauds); 3153696Sroot return(NULL); 3163696Sroot } 3173696Sroot 3183696Sroot any(c, p) 3193696Sroot register char c, *p; 3203696Sroot { 321*7593Sshannon if (p) 3223696Sroot while (*p) 3233696Sroot if (*p++ == c) 3243696Sroot return(1); 3253696Sroot return(0); 3263696Sroot } 3273696Sroot 3283696Sroot size(s) 3293696Sroot register char *s; 3303696Sroot { 3313696Sroot register int i = 0; 3323696Sroot 3333696Sroot while (*s++) i++; 3343696Sroot return(i); 3353696Sroot } 3363696Sroot 3373696Sroot char * 3383696Sroot interp(s) 3393696Sroot register char *s; 3403696Sroot { 3413696Sroot static char buf[256]; 3423696Sroot register char *p = buf, c, *q; 3433696Sroot 3443696Sroot while (c = *s++) { 3453696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3463696Sroot if (*q++ == c) { 3473696Sroot *p++ = '\\'; *p++ = *q; 3483696Sroot goto next; 3493696Sroot } 3503696Sroot if (c < 040) { 3513696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3523696Sroot } else if (c == 0177) { 3533696Sroot *p++ = '^'; *p++ = '?'; 3543696Sroot } else 3553696Sroot *p++ = c; 3563696Sroot next: 3573696Sroot ; 3583696Sroot } 3593696Sroot *p = '\0'; 3603696Sroot return(buf); 3613696Sroot } 3623696Sroot 3633696Sroot char * 3643696Sroot ctrl(c) 3653696Sroot char c; 3663696Sroot { 3673696Sroot static char s[3]; 3683696Sroot 3693696Sroot if (c < 040 || c == 0177) { 3703696Sroot s[0] = '^'; 3713696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3723696Sroot s[2] = '\0'; 3733696Sroot } else { 3743696Sroot s[0] = c; 3753696Sroot s[1] = '\0'; 3763696Sroot } 3773696Sroot return(s); 3783696Sroot } 3793696Sroot 3803696Sroot /* 3813696Sroot * Help command 3823696Sroot */ 3833696Sroot help(c) 3843696Sroot char c; 3853696Sroot { 3863696Sroot register esctable_t *p; 3873696Sroot extern esctable_t etable[]; 3883696Sroot 3893696Sroot printf("%c\r\n", c); 3903696Sroot for (p = etable; p->e_char; p++) { 3913696Sroot if ((p->e_flags&PRIV) && getuid()) 3923696Sroot continue; 3933696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 3943696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 3953696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 3963696Sroot } 3973696Sroot } 3984004Ssam 3994004Ssam /* 4004004Ssam * Set up the "remote" tty's state 4014004Ssam */ 4024004Ssam ttysetup(speed) 4034004Ssam { 4044004Ssam #ifdef VMUNIX 4054004Ssam unsigned bits = LDECCTQ; 4064004Ssam #endif 4074004Ssam 4084004Ssam arg.sg_ispeed = arg.sg_ospeed = speed; 4094004Ssam arg.sg_flags = TANDEM|RAW; 4104004Ssam ioctl(FD, TIOCSETP, (char *)&arg); 4114004Ssam #ifdef VMUNIX 4124004Ssam ioctl(FD, TIOCLBIS, (char *)&bits); 4134004Ssam #endif 4144004Ssam } 4155257Sshannon 4165257Sshannon /* 4175257Sshannon * Return "simple" name from a file name, 4185257Sshannon * strip leading directories. 4195257Sshannon */ 4205257Sshannon char * 4215257Sshannon sname(s) 4225257Sshannon register char *s; 4235257Sshannon { 4245257Sshannon register char *p = s; 4255257Sshannon 4265257Sshannon while (*s) 4275257Sshannon if (*s++ == '/') 4285257Sshannon p = s; 4295257Sshannon return (p); 4305257Sshannon } 431