1*4962Ssam /* tip.c 4.9 81/11/20 */ 23696Sroot /* 33696Sroot * tip - Unix link to other systems 43696Sroot * tip [-v] [-speed] system-name 53696Sroot * 63696Sroot * Uses remote file for system descriptions. 73696Sroot * Current commands (escapes): 83696Sroot * 93696Sroot * ~! fork a shell on the local machine 103696Sroot * ~c change working directory on local machine 113696Sroot * ~^D exit tip 123696Sroot * ~< fetch file from remote system 133696Sroot * ~> send file to remote system 143696Sroot * ~t take a file from a remote UNIX (uses cat & echo) 153696Sroot * ~p send a file to a remote UNIX (uses cat) 163696Sroot * ~| fetch file from remote system and pipe it to 173696Sroot * a local process 183696Sroot * ~% fork and wait for a program which inherits file 193696Sroot * descriptors 3 & 4 attached to the remote machine 203696Sroot * (optional by CONNECT define) 213696Sroot * ~s set or show variable 223696Sroot * ~? give a help summary 233696Sroot * 243696Sroot * Samuel J. Leffler 1-18-81 253696Sroot * 263696Sroot * sjl 2-11-81 273696Sroot * add auto-dial stuff for the BIZCOMP 283696Sroot * 293696Sroot * sjl 2-14-81 303696Sroot * cleaned up auto-dialer stuff and added variables 313696Sroot * 323696Sroot * sjl 2-19-81 333696Sroot * handle quit and interrupt during calls 343696Sroot * 353696Sroot * sjl 3-8-81 363696Sroot * made to pass lint 373696Sroot * 383696Sroot * sjl 4-11-81 393696Sroot * mods to handle both FIOCAPACITY and FIONREAD in biz.c 403696Sroot * 413696Sroot * sjl 4-17-81 423696Sroot * added take and put, made piping stuff work 433696Sroot * honor uucp locks 443696Sroot * rewrite remote file stuff for DN-11 like acu's and just to clean 453696Sroot * it up 463898Ssam * 473898Ssam * sjl 6-16-81 483898Ssam * real working setup for DN-11's 493696Sroot */ 503696Sroot 513696Sroot #include "tip.h" 523696Sroot 533696Sroot /* 543696Sroot * Baud rate mapping table 553696Sroot */ 563696Sroot int bauds[] = { 573696Sroot 0, 50, 75, 110, 134, 150, 200, 300, 600, 583696Sroot 1200, 1800, 2400, 4800, 9600, 19200, -1 593696Sroot }; 603696Sroot 614004Ssam #ifdef VMUNIX 624004Ssam int disc = OTTYDISC; /* tip normally runs this way */ 634004Ssam #endif 644004Ssam 653696Sroot int intprompt(); 663696Sroot int timeout(); 673696Sroot static int cleanup(); 683696Sroot 693696Sroot main(argc, argv) 70*4962Ssam char *argv[]; 713696Sroot { 723696Sroot char *system = NOSTR; 733696Sroot register int i; 743696Sroot char *p; 753696Sroot 763696Sroot if (argc > 4) { 773696Sroot fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 783696Sroot exit(1); 793696Sroot } 803696Sroot if (!isatty(0)) { 813696Sroot fprintf(stderr, "tip: must be interactive\n"); 823696Sroot exit(1); 833696Sroot } 843696Sroot if (argc > 1 && argv[argc-1][0] != '-') 853696Sroot system = argv[argc-1]; /* always last item */ 863696Sroot signal(SIGINT, cleanup); 873696Sroot signal(SIGQUIT, cleanup); 883696Sroot signal(SIGHUP, cleanup); 893696Sroot signal(SIGTERM, cleanup); 903898Ssam 913696Sroot if ((i = hunt(system)) == 0) { 923696Sroot printf("all ports busy\n"); 933696Sroot exit(3); 943696Sroot } 953696Sroot if (i == -1) { 963696Sroot printf("link down\n"); 974232Ssam delock(uucplock); 983696Sroot exit(3); 993696Sroot } 1003719Ssam setbuf(stdout, NULL); 1013696Sroot loginit(); 1023696Sroot /* 1033696Sroot * Now that we have the logfile and the ACU open 1043696Sroot * return to the real uid and gid. These things will 1053696Sroot * be closed on exit. Note that we can't run as root, 1063696Sroot * because locking mechanism on the tty and the accounting 1073696Sroot * will be bypassed. 1083696Sroot */ 1093696Sroot setuid(getuid()); 1103696Sroot setgid(getgid()); 1113696Sroot for (i = 1; i < argc-1; i++) 1123696Sroot if (equal(argv[i], "-v")) 1133696Sroot vflag++; 1143696Sroot /* 1153696Sroot * Kludge, their's no easy way to get the initialization 1163696Sroot * in the right order, so force it here 1173696Sroot */ 1183696Sroot if ((PH = getenv("PHONES")) == NOSTR) 1193696Sroot PH = "/etc/phones"; 1203696Sroot vinit(); /* init variables */ 1213696Sroot for (i = 1; i < argc-1; i++) 1223696Sroot if (argv[i][0] == '-' && argv[i][1] != 'v') { 1233696Sroot if (isnum(argv[i][1])) 1243696Sroot number(value(BAUDRATE)) = atoi(&argv[i][1]); 1253696Sroot else 1263696Sroot printf("%s: unknown option\n", argv[i]); 1273696Sroot } 1284004Ssam if ((i = speed(number(value(BAUDRATE)))) == NULL) { 1293696Sroot printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 1303696Sroot delock(uucplock); 1313696Sroot exit(3); 1323696Sroot } 1333898Ssam 1344004Ssam /* 1354004Ssam * Hardwired connections require the 1364004Ssam * line speed set before they make any transmissions 1374004Ssam * (this is particularly true of things like a DF03-AC) 1384004Ssam */ 1394004Ssam if (HW) 1404004Ssam ttysetup(i); 1413898Ssam if (p = connect()) { 1423898Ssam printf("\07%s\n[EOT]\n", p); 1433898Ssam delock(uucplock); 1443898Ssam exit(1); 1453898Ssam } 1464004Ssam if (!HW) 1474004Ssam ttysetup(i); 1484004Ssam 1493696Sroot /* 1504004Ssam * Set up local tty state 1513696Sroot */ 1524004Ssam ioctl(0, TIOCGETP, (char *)&defarg); 1534004Ssam ioctl(0, TIOCGETC, (char *)&defchars); 1544013Ssam #ifdef VMUNIX 1554004Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1564013Ssam #endif 1573696Sroot arg = defarg; 1583696Sroot arg.sg_flags = ANYP | CBREAK; 1593696Sroot tchars = defchars; 1603696Sroot tchars.t_intrc = tchars.t_quitc = -1; 1613696Sroot raw(); 1624004Ssam 1633696Sroot pipe(fildes); pipe(repdes); 1643696Sroot signal(SIGALRM, timeout); 1653898Ssam 1663898Ssam /* 1673898Ssam * Everything's set up now: 1683898Ssam * connection established (hardwired or diaulup) 1693898Ssam * line conditioned (baud rate, mode, etc.) 1703898Ssam * internal data structures (variables) 1713898Ssam * so, fork one process for local side and one for remote. 1723898Ssam */ 1733898Ssam write(1, "\07connected\r\n", 12); 1743696Sroot if (pid = fork()) 1753696Sroot tipin(); 1763696Sroot else 1773696Sroot tipout(); 1783696Sroot /*NOTREACHED*/ 1793696Sroot } 1803696Sroot 1813696Sroot static 1823696Sroot cleanup() 1833696Sroot { 1843696Sroot delock(uucplock); 1853898Ssam #ifdef VMUNIX 1863898Ssam if (odisc) 1873898Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1883898Ssam #endif 1893696Sroot exit(0); 1903696Sroot } 1913696Sroot 1923696Sroot /* 1933696Sroot * put the controlling keyboard into raw mode 1943696Sroot */ 1953696Sroot raw() 1963696Sroot { 1973696Sroot ioctl(0, TIOCSETP, &arg); 1983696Sroot ioctl(0, TIOCSETC, &tchars); 1994004Ssam #ifdef VMUNIX 2004004Ssam ioctl(0, TIOCSETD, (char *)&disc); 2014004Ssam #endif 2023696Sroot } 2033696Sroot 2043696Sroot 2053696Sroot /* 2063696Sroot * return keyboard to normal mode 2073696Sroot */ 2083696Sroot unraw() 2093696Sroot { 2104004Ssam #ifdef VMUNIX 2114004Ssam ioctl(0, TIOCSETD, (char *)&odisc); 2124004Ssam #endif 2134004Ssam ioctl(0, TIOCSETP, (char *)&defarg); 2144004Ssam ioctl(0, TIOCSETC, (char *)&defchars); 2153696Sroot } 2163696Sroot 2173696Sroot /* 2183696Sroot * Print string ``s'', then read a string 2193696Sroot * in from the terminal. Handles signals & allows use of 2203696Sroot * normal erase and kill characters. 2213696Sroot */ 2223696Sroot prompt(s, p) 2233696Sroot char *s; 2243696Sroot register char *p; 2253696Sroot { 2263696Sroot register char *b = p; 2273696Sroot 2283696Sroot stoprompt = 0; 2293696Sroot signal(SIGINT, intprompt); 2303696Sroot signal(SIGQUIT, SIG_IGN); 2313696Sroot unraw(); 2323696Sroot printf("%s", s); 2333696Sroot while ((*p = getchar()) != EOF && *p != '\n') { 2343696Sroot if (stoprompt) 2353696Sroot goto pbreak; 2363696Sroot p++; 2373696Sroot } 2383696Sroot *p = '\0'; 2393696Sroot pbreak: 2403696Sroot raw(); 2413696Sroot signal(SIGINT, SIG_DFL); 2423696Sroot signal(SIGQUIT,SIG_DFL); 2433696Sroot return(stoprompt || p == b); 2443696Sroot } 2453696Sroot 2463696Sroot /* 2473696Sroot * Interrupt service routine during prompting 2483696Sroot */ 2493696Sroot intprompt() 2503696Sroot { 2513696Sroot signal(SIGINT, SIG_IGN); 2523696Sroot stoprompt = 1; 2533696Sroot printf("\r\n"); 2543696Sroot } 2553696Sroot 2563696Sroot /* 2573696Sroot * ****TIPIN TIPIN**** 2583696Sroot */ 2593696Sroot tipin() 2603696Sroot { 2613696Sroot char gch, bol = 1; 2623696Sroot 2633796Ssam /* 2643796Ssam * Kinda klugey here... 2653796Ssam * check for scripting being turned on from the .tiprc file, 2663796Ssam * but be careful about just using setscript(), as we may 2673796Ssam * send a SIGEMT before tipout has a chance to set up catching 2683796Ssam * it; so wait a second, then setscript() 2693796Ssam */ 2703796Ssam if (boolean(value(SCRIPT))) { 2713796Ssam sleep(1); 2723796Ssam setscript(); 2733796Ssam } 2743796Ssam 2753696Sroot while (1) { 2763696Sroot gch = getchar()&0177; 2773696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2783696Sroot if (!(gch = escape())) 2793696Sroot continue; 2803696Sroot } else if (gch == character(value(RAISECHAR))) { 2813696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2823696Sroot printf("%s", ctrl(character(value(RAISECHAR)))); 2833696Sroot continue; 2843696Sroot } else if (gch == '\r') { 2853696Sroot bol = 1; 2863696Sroot write(FD, &gch, 1); 2873696Sroot continue; 2883696Sroot } else if (gch == character(value(FORCE))) { 2893696Sroot printf("%s", ctrl(character(value(FORCE)))); 2903696Sroot gch = getchar()&0177; 2913696Sroot } 2923696Sroot bol = any(gch, value(EOL)); 2933696Sroot if (boolean(value(RAISE)) && islower(gch)) 2943696Sroot toupper(gch); 2953696Sroot write(FD, &gch, 1); 2963696Sroot } 2973696Sroot } 2983696Sroot 2993696Sroot /* 3003696Sroot * Escape handler -- 3013696Sroot * called on recognition of ``escapec'' at the beginning of a line 3023696Sroot */ 3033696Sroot escape() 3043696Sroot { 3053696Sroot register char gch; 3063696Sroot register esctable_t *p; 3073696Sroot char c = character(value(ESCAPE)); 3083696Sroot extern esctable_t etable[]; 3093696Sroot 3103696Sroot gch = (getchar()&0177); 3113696Sroot for (p = etable; p->e_char; p++) 3123696Sroot if (p->e_char == gch) { 3133696Sroot if ((p->e_flags&PRIV) && getuid()) 3143696Sroot continue; 3153696Sroot printf("%s", ctrl(c)); 3163696Sroot (*p->e_func)(gch); 3173696Sroot return(0); 3183696Sroot } 3194146Ssam /* ESCAPE ESCAPE forces ESCAPE */ 3204146Ssam if (c != gch) 3214146Ssam write(FD, &c, 1); 3223696Sroot return(gch); 3233696Sroot } 3243696Sroot 3253696Sroot speed(n) 3263696Sroot { 3273696Sroot register int *p; 3283696Sroot 3293696Sroot for (p = bauds; *p != -1; p++) 3303696Sroot if (*p == n) 3313696Sroot return(p-bauds); 3323696Sroot return(NULL); 3333696Sroot } 3343696Sroot 3353696Sroot any(c, p) 3363696Sroot register char c, *p; 3373696Sroot { 3383696Sroot while (*p) 3393696Sroot if (*p++ == c) 3403696Sroot return(1); 3413696Sroot return(0); 3423696Sroot } 3433696Sroot 3443696Sroot size(s) 3453696Sroot register char *s; 3463696Sroot { 3473696Sroot register int i = 0; 3483696Sroot 3493696Sroot while (*s++) i++; 3503696Sroot return(i); 3513696Sroot } 3523696Sroot 3533696Sroot char * 3543696Sroot interp(s) 3553696Sroot register char *s; 3563696Sroot { 3573696Sroot static char buf[256]; 3583696Sroot register char *p = buf, c, *q; 3593696Sroot 3603696Sroot while (c = *s++) { 3613696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3623696Sroot if (*q++ == c) { 3633696Sroot *p++ = '\\'; *p++ = *q; 3643696Sroot goto next; 3653696Sroot } 3663696Sroot if (c < 040) { 3673696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3683696Sroot } else if (c == 0177) { 3693696Sroot *p++ = '^'; *p++ = '?'; 3703696Sroot } else 3713696Sroot *p++ = c; 3723696Sroot next: 3733696Sroot ; 3743696Sroot } 3753696Sroot *p = '\0'; 3763696Sroot return(buf); 3773696Sroot } 3783696Sroot 3793696Sroot char * 3803696Sroot ctrl(c) 3813696Sroot char c; 3823696Sroot { 3833696Sroot static char s[3]; 3843696Sroot 3853696Sroot if (c < 040 || c == 0177) { 3863696Sroot s[0] = '^'; 3873696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3883696Sroot s[2] = '\0'; 3893696Sroot } else { 3903696Sroot s[0] = c; 3913696Sroot s[1] = '\0'; 3923696Sroot } 3933696Sroot return(s); 3943696Sroot } 3953696Sroot 3963696Sroot /* 3973696Sroot * Help command 3983696Sroot */ 3993696Sroot help(c) 4003696Sroot char c; 4013696Sroot { 4023696Sroot register esctable_t *p; 4033696Sroot extern esctable_t etable[]; 4043696Sroot 4053696Sroot printf("%c\r\n", c); 4063696Sroot for (p = etable; p->e_char; p++) { 4073696Sroot if ((p->e_flags&PRIV) && getuid()) 4083696Sroot continue; 4093696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 4103696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 4113696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 4123696Sroot } 4133696Sroot } 4144004Ssam 4154004Ssam /* 4164004Ssam * Set up the "remote" tty's state 4174004Ssam */ 4184004Ssam static 4194004Ssam ttysetup(speed) 4204004Ssam { 4214004Ssam #ifdef VMUNIX 4224004Ssam unsigned bits = LDECCTQ; 4234004Ssam #endif 4244004Ssam 4254004Ssam arg.sg_ispeed = arg.sg_ospeed = speed; 4264004Ssam arg.sg_flags = TANDEM|RAW; 4274004Ssam ioctl(FD, TIOCSETP, (char *)&arg); 4284004Ssam #ifdef VMUNIX 4294004Ssam ioctl(FD, TIOCLBIS, (char *)&bits); 4304004Ssam #endif 4314004Ssam } 432