1*5136Ssam /* tip.c 4.10 81/11/29 */ 2*5136Ssam 33696Sroot /* 4*5136Ssam * tip - UNIX link to other systems 53696Sroot * tip [-v] [-speed] system-name 6*5136Ssam * or 7*5136Ssam * 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(); 25*5136Ssam int cleanup(); 263696Sroot 273696Sroot main(argc, argv) 284962Ssam char *argv[]; 293696Sroot { 303696Sroot char *system = NOSTR; 313696Sroot register int i; 323696Sroot char *p; 333696Sroot 34*5136Ssam if (strcmp(argv[0], "tip")) { 35*5136Ssam cumain(argc, argv); 36*5136Ssam cumode = 1; 37*5136Ssam goto cucommon; 38*5136Ssam } 39*5136Ssam 403696Sroot if (argc > 4) { 413696Sroot fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 423696Sroot exit(1); 433696Sroot } 443696Sroot if (!isatty(0)) { 453696Sroot fprintf(stderr, "tip: must be interactive\n"); 463696Sroot exit(1); 473696Sroot } 483696Sroot if (argc > 1 && argv[argc-1][0] != '-') 493696Sroot system = argv[argc-1]; /* always last item */ 503696Sroot signal(SIGINT, cleanup); 513696Sroot signal(SIGQUIT, cleanup); 523696Sroot signal(SIGHUP, cleanup); 533696Sroot signal(SIGTERM, cleanup); 543898Ssam 553696Sroot if ((i = hunt(system)) == 0) { 563696Sroot printf("all ports busy\n"); 573696Sroot exit(3); 583696Sroot } 593696Sroot if (i == -1) { 603696Sroot printf("link down\n"); 614232Ssam delock(uucplock); 623696Sroot exit(3); 633696Sroot } 643719Ssam setbuf(stdout, NULL); 653696Sroot loginit(); 663696Sroot /* 673696Sroot * Now that we have the logfile and the ACU open 683696Sroot * return to the real uid and gid. These things will 693696Sroot * be closed on exit. Note that we can't run as root, 703696Sroot * because locking mechanism on the tty and the accounting 713696Sroot * will be bypassed. 723696Sroot */ 733696Sroot setuid(getuid()); 743696Sroot setgid(getgid()); 753696Sroot for (i = 1; i < argc-1; i++) 763696Sroot if (equal(argv[i], "-v")) 773696Sroot vflag++; 783696Sroot /* 793696Sroot * Kludge, their's no easy way to get the initialization 803696Sroot * in the right order, so force it here 813696Sroot */ 823696Sroot if ((PH = getenv("PHONES")) == NOSTR) 833696Sroot PH = "/etc/phones"; 843696Sroot vinit(); /* init variables */ 853696Sroot for (i = 1; i < argc-1; i++) 863696Sroot if (argv[i][0] == '-' && argv[i][1] != 'v') { 873696Sroot if (isnum(argv[i][1])) 883696Sroot number(value(BAUDRATE)) = atoi(&argv[i][1]); 893696Sroot else 903696Sroot printf("%s: unknown option\n", argv[i]); 913696Sroot } 924004Ssam if ((i = speed(number(value(BAUDRATE)))) == NULL) { 933696Sroot printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 943696Sroot delock(uucplock); 953696Sroot exit(3); 963696Sroot } 973898Ssam 984004Ssam /* 994004Ssam * Hardwired connections require the 1004004Ssam * line speed set before they make any transmissions 1014004Ssam * (this is particularly true of things like a DF03-AC) 1024004Ssam */ 1034004Ssam if (HW) 1044004Ssam ttysetup(i); 1053898Ssam if (p = connect()) { 1063898Ssam printf("\07%s\n[EOT]\n", p); 1073898Ssam delock(uucplock); 1083898Ssam exit(1); 1093898Ssam } 1104004Ssam if (!HW) 1114004Ssam ttysetup(i); 112*5136Ssam cucommon: 1133696Sroot /* 114*5136Ssam * From here down the code is shared with 115*5136Ssam * the "cu" version of tip. 1163696Sroot */ 1174004Ssam ioctl(0, TIOCGETP, (char *)&defarg); 1184004Ssam ioctl(0, TIOCGETC, (char *)&defchars); 1194013Ssam #ifdef VMUNIX 1204004Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1214013Ssam #endif 1223696Sroot arg = defarg; 1233696Sroot arg.sg_flags = ANYP | CBREAK; 1243696Sroot tchars = defchars; 1253696Sroot tchars.t_intrc = tchars.t_quitc = -1; 1263696Sroot raw(); 1274004Ssam 1283696Sroot pipe(fildes); pipe(repdes); 1293696Sroot signal(SIGALRM, timeout); 1303898Ssam 1313898Ssam /* 1323898Ssam * Everything's set up now: 1333898Ssam * connection established (hardwired or diaulup) 1343898Ssam * line conditioned (baud rate, mode, etc.) 1353898Ssam * internal data structures (variables) 1363898Ssam * so, fork one process for local side and one for remote. 1373898Ssam */ 138*5136Ssam printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 1393696Sroot if (pid = fork()) 1403696Sroot tipin(); 1413696Sroot else 1423696Sroot tipout(); 1433696Sroot /*NOTREACHED*/ 1443696Sroot } 1453696Sroot 1463696Sroot cleanup() 1473696Sroot { 1483696Sroot delock(uucplock); 1493898Ssam #ifdef VMUNIX 1503898Ssam if (odisc) 1513898Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1523898Ssam #endif 1533696Sroot exit(0); 1543696Sroot } 1553696Sroot 1563696Sroot /* 1573696Sroot * put the controlling keyboard into raw mode 1583696Sroot */ 1593696Sroot raw() 1603696Sroot { 1613696Sroot ioctl(0, TIOCSETP, &arg); 1623696Sroot ioctl(0, TIOCSETC, &tchars); 1634004Ssam #ifdef VMUNIX 1644004Ssam ioctl(0, TIOCSETD, (char *)&disc); 1654004Ssam #endif 1663696Sroot } 1673696Sroot 1683696Sroot 1693696Sroot /* 1703696Sroot * return keyboard to normal mode 1713696Sroot */ 1723696Sroot unraw() 1733696Sroot { 1744004Ssam #ifdef VMUNIX 1754004Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1764004Ssam #endif 1774004Ssam ioctl(0, TIOCSETP, (char *)&defarg); 1784004Ssam ioctl(0, TIOCSETC, (char *)&defchars); 1793696Sroot } 1803696Sroot 1813696Sroot /* 1823696Sroot * Print string ``s'', then read a string 1833696Sroot * in from the terminal. Handles signals & allows use of 1843696Sroot * normal erase and kill characters. 1853696Sroot */ 1863696Sroot prompt(s, p) 1873696Sroot char *s; 1883696Sroot register char *p; 1893696Sroot { 1903696Sroot register char *b = p; 1913696Sroot 1923696Sroot stoprompt = 0; 1933696Sroot signal(SIGINT, intprompt); 1943696Sroot signal(SIGQUIT, SIG_IGN); 1953696Sroot unraw(); 1963696Sroot printf("%s", s); 1973696Sroot while ((*p = getchar()) != EOF && *p != '\n') { 1983696Sroot if (stoprompt) 1993696Sroot goto pbreak; 2003696Sroot p++; 2013696Sroot } 2023696Sroot *p = '\0'; 2033696Sroot pbreak: 2043696Sroot raw(); 2053696Sroot signal(SIGINT, SIG_DFL); 2063696Sroot signal(SIGQUIT,SIG_DFL); 2073696Sroot return(stoprompt || p == b); 2083696Sroot } 2093696Sroot 2103696Sroot /* 2113696Sroot * Interrupt service routine during prompting 2123696Sroot */ 2133696Sroot intprompt() 2143696Sroot { 2153696Sroot signal(SIGINT, SIG_IGN); 2163696Sroot stoprompt = 1; 2173696Sroot printf("\r\n"); 2183696Sroot } 2193696Sroot 2203696Sroot /* 2213696Sroot * ****TIPIN TIPIN**** 2223696Sroot */ 2233696Sroot tipin() 2243696Sroot { 2253696Sroot char gch, bol = 1; 2263696Sroot 2273796Ssam /* 2283796Ssam * Kinda klugey here... 2293796Ssam * check for scripting being turned on from the .tiprc file, 2303796Ssam * but be careful about just using setscript(), as we may 2313796Ssam * send a SIGEMT before tipout has a chance to set up catching 2323796Ssam * it; so wait a second, then setscript() 2333796Ssam */ 2343796Ssam if (boolean(value(SCRIPT))) { 2353796Ssam sleep(1); 2363796Ssam setscript(); 2373796Ssam } 2383796Ssam 2393696Sroot while (1) { 2403696Sroot gch = getchar()&0177; 2413696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2423696Sroot if (!(gch = escape())) 2433696Sroot continue; 244*5136Ssam } else if (!cumode && gch == character(value(RAISECHAR))) { 2453696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2463696Sroot continue; 2473696Sroot } else if (gch == '\r') { 2483696Sroot bol = 1; 2493696Sroot write(FD, &gch, 1); 2503696Sroot continue; 251*5136Ssam } else if (!cumode && gch == character(value(FORCE))) 2523696Sroot gch = getchar()&0177; 2533696Sroot bol = any(gch, value(EOL)); 2543696Sroot if (boolean(value(RAISE)) && islower(gch)) 2553696Sroot toupper(gch); 2563696Sroot write(FD, &gch, 1); 2573696Sroot } 2583696Sroot } 2593696Sroot 2603696Sroot /* 2613696Sroot * Escape handler -- 2623696Sroot * called on recognition of ``escapec'' at the beginning of a line 2633696Sroot */ 2643696Sroot escape() 2653696Sroot { 2663696Sroot register char gch; 2673696Sroot register esctable_t *p; 2683696Sroot char c = character(value(ESCAPE)); 2693696Sroot extern esctable_t etable[]; 2703696Sroot 2713696Sroot gch = (getchar()&0177); 2723696Sroot for (p = etable; p->e_char; p++) 2733696Sroot if (p->e_char == gch) { 2743696Sroot if ((p->e_flags&PRIV) && getuid()) 2753696Sroot continue; 2763696Sroot printf("%s", ctrl(c)); 2773696Sroot (*p->e_func)(gch); 2783696Sroot return(0); 2793696Sroot } 2804146Ssam /* ESCAPE ESCAPE forces ESCAPE */ 2814146Ssam if (c != gch) 2824146Ssam write(FD, &c, 1); 2833696Sroot return(gch); 2843696Sroot } 2853696Sroot 2863696Sroot speed(n) 2873696Sroot { 2883696Sroot register int *p; 2893696Sroot 2903696Sroot for (p = bauds; *p != -1; p++) 2913696Sroot if (*p == n) 2923696Sroot return(p-bauds); 2933696Sroot return(NULL); 2943696Sroot } 2953696Sroot 2963696Sroot any(c, p) 2973696Sroot register char c, *p; 2983696Sroot { 2993696Sroot while (*p) 3003696Sroot if (*p++ == c) 3013696Sroot return(1); 3023696Sroot return(0); 3033696Sroot } 3043696Sroot 3053696Sroot size(s) 3063696Sroot register char *s; 3073696Sroot { 3083696Sroot register int i = 0; 3093696Sroot 3103696Sroot while (*s++) i++; 3113696Sroot return(i); 3123696Sroot } 3133696Sroot 3143696Sroot char * 3153696Sroot interp(s) 3163696Sroot register char *s; 3173696Sroot { 3183696Sroot static char buf[256]; 3193696Sroot register char *p = buf, c, *q; 3203696Sroot 3213696Sroot while (c = *s++) { 3223696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3233696Sroot if (*q++ == c) { 3243696Sroot *p++ = '\\'; *p++ = *q; 3253696Sroot goto next; 3263696Sroot } 3273696Sroot if (c < 040) { 3283696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3293696Sroot } else if (c == 0177) { 3303696Sroot *p++ = '^'; *p++ = '?'; 3313696Sroot } else 3323696Sroot *p++ = c; 3333696Sroot next: 3343696Sroot ; 3353696Sroot } 3363696Sroot *p = '\0'; 3373696Sroot return(buf); 3383696Sroot } 3393696Sroot 3403696Sroot char * 3413696Sroot ctrl(c) 3423696Sroot char c; 3433696Sroot { 3443696Sroot static char s[3]; 3453696Sroot 3463696Sroot if (c < 040 || c == 0177) { 3473696Sroot s[0] = '^'; 3483696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3493696Sroot s[2] = '\0'; 3503696Sroot } else { 3513696Sroot s[0] = c; 3523696Sroot s[1] = '\0'; 3533696Sroot } 3543696Sroot return(s); 3553696Sroot } 3563696Sroot 3573696Sroot /* 3583696Sroot * Help command 3593696Sroot */ 3603696Sroot help(c) 3613696Sroot char c; 3623696Sroot { 3633696Sroot register esctable_t *p; 3643696Sroot extern esctable_t etable[]; 3653696Sroot 3663696Sroot printf("%c\r\n", c); 3673696Sroot for (p = etable; p->e_char; p++) { 3683696Sroot if ((p->e_flags&PRIV) && getuid()) 3693696Sroot continue; 3703696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 3713696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 3723696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 3733696Sroot } 3743696Sroot } 3754004Ssam 3764004Ssam /* 3774004Ssam * Set up the "remote" tty's state 3784004Ssam */ 3794004Ssam ttysetup(speed) 3804004Ssam { 3814004Ssam #ifdef VMUNIX 3824004Ssam unsigned bits = LDECCTQ; 3834004Ssam #endif 3844004Ssam 3854004Ssam arg.sg_ispeed = arg.sg_ospeed = speed; 3864004Ssam arg.sg_flags = TANDEM|RAW; 3874004Ssam ioctl(FD, TIOCSETP, (char *)&arg); 3884004Ssam #ifdef VMUNIX 3894004Ssam ioctl(FD, TIOCLBIS, (char *)&bits); 3904004Ssam #endif 3914004Ssam } 392