1*4146Ssam /* tip.c 4.7 81/08/16 */ 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) 703696Sroot 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"); 973696Sroot exit(3); 983696Sroot } 993719Ssam setbuf(stdout, NULL); 1003696Sroot loginit(); 1013696Sroot /* 1023696Sroot * Now that we have the logfile and the ACU open 1033696Sroot * return to the real uid and gid. These things will 1043696Sroot * be closed on exit. Note that we can't run as root, 1053696Sroot * because locking mechanism on the tty and the accounting 1063696Sroot * will be bypassed. 1073696Sroot */ 1083696Sroot setuid(getuid()); 1093696Sroot setgid(getgid()); 1103696Sroot for (i = 1; i < argc-1; i++) 1113696Sroot if (equal(argv[i], "-v")) 1123696Sroot vflag++; 1133696Sroot /* 1143696Sroot * Kludge, their's no easy way to get the initialization 1153696Sroot * in the right order, so force it here 1163696Sroot */ 1173696Sroot if ((PH = getenv("PHONES")) == NOSTR) 1183696Sroot PH = "/etc/phones"; 1193696Sroot vinit(); /* init variables */ 1203696Sroot for (i = 1; i < argc-1; i++) 1213696Sroot if (argv[i][0] == '-' && argv[i][1] != 'v') { 1223696Sroot if (isnum(argv[i][1])) 1233696Sroot number(value(BAUDRATE)) = atoi(&argv[i][1]); 1243696Sroot else 1253696Sroot printf("%s: unknown option\n", argv[i]); 1263696Sroot } 1274004Ssam if ((i = speed(number(value(BAUDRATE)))) == NULL) { 1283696Sroot printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 1293696Sroot delock(uucplock); 1303696Sroot exit(3); 1313696Sroot } 1323898Ssam 1334004Ssam /* 1344004Ssam * Hardwired connections require the 1354004Ssam * line speed set before they make any transmissions 1364004Ssam * (this is particularly true of things like a DF03-AC) 1374004Ssam */ 1384004Ssam if (HW) 1394004Ssam ttysetup(i); 1403898Ssam if (p = connect()) { 1413898Ssam printf("\07%s\n[EOT]\n", p); 1423898Ssam delock(uucplock); 1433898Ssam exit(1); 1443898Ssam } 1454004Ssam if (!HW) 1464004Ssam ttysetup(i); 1474004Ssam 1483696Sroot /* 1494004Ssam * Set up local tty state 1503696Sroot */ 1514004Ssam ioctl(0, TIOCGETP, (char *)&defarg); 1524004Ssam ioctl(0, TIOCGETC, (char *)&defchars); 1534013Ssam #ifdef VMUNIX 1544004Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1554013Ssam #endif 1563696Sroot arg = defarg; 1573696Sroot arg.sg_flags = ANYP | CBREAK; 1583696Sroot tchars = defchars; 1593696Sroot tchars.t_intrc = tchars.t_quitc = -1; 1603696Sroot raw(); 1614004Ssam 1623696Sroot pipe(fildes); pipe(repdes); 1633696Sroot signal(SIGALRM, timeout); 1643898Ssam 1653898Ssam /* 1663898Ssam * Everything's set up now: 1673898Ssam * connection established (hardwired or diaulup) 1683898Ssam * line conditioned (baud rate, mode, etc.) 1693898Ssam * internal data structures (variables) 1703898Ssam * so, fork one process for local side and one for remote. 1713898Ssam */ 1723898Ssam write(1, "\07connected\r\n", 12); 1733696Sroot if (pid = fork()) 1743696Sroot tipin(); 1753696Sroot else 1763696Sroot tipout(); 1773696Sroot /*NOTREACHED*/ 1783696Sroot } 1793696Sroot 1803696Sroot static 1813696Sroot cleanup() 1823696Sroot { 1833696Sroot delock(uucplock); 1843898Ssam #ifdef VMUNIX 1853898Ssam if (odisc) 1863898Ssam ioctl(0, TIOCSETD, (char *)&odisc); 1873898Ssam #endif 1883696Sroot exit(0); 1893696Sroot } 1903696Sroot 1913696Sroot /* 1923696Sroot * put the controlling keyboard into raw mode 1933696Sroot */ 1943696Sroot raw() 1953696Sroot { 1963696Sroot ioctl(0, TIOCSETP, &arg); 1973696Sroot ioctl(0, TIOCSETC, &tchars); 1984004Ssam #ifdef VMUNIX 1994004Ssam ioctl(0, TIOCSETD, (char *)&disc); 2004004Ssam #endif 2013696Sroot } 2023696Sroot 2033696Sroot 2043696Sroot /* 2053696Sroot * return keyboard to normal mode 2063696Sroot */ 2073696Sroot unraw() 2083696Sroot { 2094004Ssam #ifdef VMUNIX 2104004Ssam ioctl(0, TIOCSETD, (char *)&odisc); 2114004Ssam #endif 2124004Ssam ioctl(0, TIOCSETP, (char *)&defarg); 2134004Ssam ioctl(0, TIOCSETC, (char *)&defchars); 2143696Sroot } 2153696Sroot 2163696Sroot /* 2173696Sroot * Print string ``s'', then read a string 2183696Sroot * in from the terminal. Handles signals & allows use of 2193696Sroot * normal erase and kill characters. 2203696Sroot */ 2213696Sroot prompt(s, p) 2223696Sroot char *s; 2233696Sroot register char *p; 2243696Sroot { 2253696Sroot register char *b = p; 2263696Sroot 2273696Sroot stoprompt = 0; 2283696Sroot signal(SIGINT, intprompt); 2293696Sroot signal(SIGQUIT, SIG_IGN); 2303696Sroot unraw(); 2313696Sroot printf("%s", s); 2323696Sroot while ((*p = getchar()) != EOF && *p != '\n') { 2333696Sroot if (stoprompt) 2343696Sroot goto pbreak; 2353696Sroot p++; 2363696Sroot } 2373696Sroot *p = '\0'; 2383696Sroot pbreak: 2393696Sroot raw(); 2403696Sroot signal(SIGINT, SIG_DFL); 2413696Sroot signal(SIGQUIT,SIG_DFL); 2423696Sroot return(stoprompt || p == b); 2433696Sroot } 2443696Sroot 2453696Sroot /* 2463696Sroot * Interrupt service routine during prompting 2473696Sroot */ 2483696Sroot intprompt() 2493696Sroot { 2503696Sroot signal(SIGINT, SIG_IGN); 2513696Sroot stoprompt = 1; 2523696Sroot printf("\r\n"); 2533696Sroot } 2543696Sroot 2553696Sroot /* 2563696Sroot * ****TIPIN TIPIN**** 2573696Sroot */ 2583696Sroot tipin() 2593696Sroot { 2603696Sroot char gch, bol = 1; 2613696Sroot 2623796Ssam /* 2633796Ssam * Kinda klugey here... 2643796Ssam * check for scripting being turned on from the .tiprc file, 2653796Ssam * but be careful about just using setscript(), as we may 2663796Ssam * send a SIGEMT before tipout has a chance to set up catching 2673796Ssam * it; so wait a second, then setscript() 2683796Ssam */ 2693796Ssam if (boolean(value(SCRIPT))) { 2703796Ssam sleep(1); 2713796Ssam setscript(); 2723796Ssam } 2733796Ssam 2743696Sroot while (1) { 2753696Sroot gch = getchar()&0177; 2763696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2773696Sroot if (!(gch = escape())) 2783696Sroot continue; 2793696Sroot } else if (gch == character(value(RAISECHAR))) { 2803696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2813696Sroot printf("%s", ctrl(character(value(RAISECHAR)))); 2823696Sroot continue; 2833696Sroot } else if (gch == '\r') { 2843696Sroot bol = 1; 2853696Sroot write(FD, &gch, 1); 2863696Sroot continue; 2873696Sroot } else if (gch == character(value(FORCE))) { 2883696Sroot printf("%s", ctrl(character(value(FORCE)))); 2893696Sroot gch = getchar()&0177; 2903696Sroot } 2913696Sroot bol = any(gch, value(EOL)); 2923696Sroot if (boolean(value(RAISE)) && islower(gch)) 2933696Sroot toupper(gch); 2943696Sroot write(FD, &gch, 1); 2953696Sroot } 2963696Sroot } 2973696Sroot 2983696Sroot /* 2993696Sroot * Escape handler -- 3003696Sroot * called on recognition of ``escapec'' at the beginning of a line 3013696Sroot */ 3023696Sroot escape() 3033696Sroot { 3043696Sroot register char gch; 3053696Sroot register esctable_t *p; 3063696Sroot char c = character(value(ESCAPE)); 3073696Sroot extern esctable_t etable[]; 3083696Sroot 3093696Sroot gch = (getchar()&0177); 3103696Sroot for (p = etable; p->e_char; p++) 3113696Sroot if (p->e_char == gch) { 3123696Sroot if ((p->e_flags&PRIV) && getuid()) 3133696Sroot continue; 3143696Sroot printf("%s", ctrl(c)); 3153696Sroot (*p->e_func)(gch); 3163696Sroot return(0); 3173696Sroot } 318*4146Ssam /* ESCAPE ESCAPE forces ESCAPE */ 319*4146Ssam if (c != gch) 320*4146Ssam write(FD, &c, 1); 3213696Sroot return(gch); 3223696Sroot } 3233696Sroot 3243696Sroot speed(n) 3253696Sroot { 3263696Sroot register int *p; 3273696Sroot 3283696Sroot for (p = bauds; *p != -1; p++) 3293696Sroot if (*p == n) 3303696Sroot return(p-bauds); 3313696Sroot return(NULL); 3323696Sroot } 3333696Sroot 3343696Sroot any(c, p) 3353696Sroot register char c, *p; 3363696Sroot { 3373696Sroot while (*p) 3383696Sroot if (*p++ == c) 3393696Sroot return(1); 3403696Sroot return(0); 3413696Sroot } 3423696Sroot 3433696Sroot size(s) 3443696Sroot register char *s; 3453696Sroot { 3463696Sroot register int i = 0; 3473696Sroot 3483696Sroot while (*s++) i++; 3493696Sroot return(i); 3503696Sroot } 3513696Sroot 3523696Sroot char * 3533696Sroot interp(s) 3543696Sroot register char *s; 3553696Sroot { 3563696Sroot static char buf[256]; 3573696Sroot register char *p = buf, c, *q; 3583696Sroot 3593696Sroot while (c = *s++) { 3603696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3613696Sroot if (*q++ == c) { 3623696Sroot *p++ = '\\'; *p++ = *q; 3633696Sroot goto next; 3643696Sroot } 3653696Sroot if (c < 040) { 3663696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3673696Sroot } else if (c == 0177) { 3683696Sroot *p++ = '^'; *p++ = '?'; 3693696Sroot } else 3703696Sroot *p++ = c; 3713696Sroot next: 3723696Sroot ; 3733696Sroot } 3743696Sroot *p = '\0'; 3753696Sroot return(buf); 3763696Sroot } 3773696Sroot 3783696Sroot char * 3793696Sroot ctrl(c) 3803696Sroot char c; 3813696Sroot { 3823696Sroot static char s[3]; 3833696Sroot 3843696Sroot if (c < 040 || c == 0177) { 3853696Sroot s[0] = '^'; 3863696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3873696Sroot s[2] = '\0'; 3883696Sroot } else { 3893696Sroot s[0] = c; 3903696Sroot s[1] = '\0'; 3913696Sroot } 3923696Sroot return(s); 3933696Sroot } 3943696Sroot 3953696Sroot /* 3963696Sroot * Help command 3973696Sroot */ 3983696Sroot help(c) 3993696Sroot char c; 4003696Sroot { 4013696Sroot register esctable_t *p; 4023696Sroot extern esctable_t etable[]; 4033696Sroot 4043696Sroot printf("%c\r\n", c); 4053696Sroot for (p = etable; p->e_char; p++) { 4063696Sroot if ((p->e_flags&PRIV) && getuid()) 4073696Sroot continue; 4083696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 4093696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 4103696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 4113696Sroot } 4123696Sroot } 4134004Ssam 4144004Ssam /* 4154004Ssam * Set up the "remote" tty's state 4164004Ssam */ 4174004Ssam static 4184004Ssam ttysetup(speed) 4194004Ssam { 4204004Ssam #ifdef VMUNIX 4214004Ssam unsigned bits = LDECCTQ; 4224004Ssam #endif 4234004Ssam 4244004Ssam arg.sg_ispeed = arg.sg_ospeed = speed; 4254004Ssam arg.sg_flags = TANDEM|RAW; 4264004Ssam ioctl(FD, TIOCSETP, (char *)&arg); 4274004Ssam #ifdef VMUNIX 4284004Ssam ioctl(FD, TIOCLBIS, (char *)&bits); 4294004Ssam #endif 4304004Ssam } 431