1*3796Ssam /* tip.c 4.3 81/05/18 */ 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 463696Sroot */ 473696Sroot 483696Sroot #include "tip.h" 493696Sroot 503696Sroot /* 513696Sroot * Baud rate mapping table 523696Sroot */ 533696Sroot int bauds[] = { 543696Sroot 0, 50, 75, 110, 134, 150, 200, 300, 600, 553696Sroot 1200, 1800, 2400, 4800, 9600, 19200, -1 563696Sroot }; 573696Sroot 583696Sroot int intprompt(); 593696Sroot int timeout(); 603696Sroot static int cleanup(); 613696Sroot 623696Sroot main(argc, argv) 633696Sroot char *argv[]; 643696Sroot { 653696Sroot char *system = NOSTR; 663696Sroot register int i; 673696Sroot #ifdef VMUNIX 683696Sroot int disc; 693696Sroot #endif 703696Sroot char *p; 713696Sroot 723696Sroot if (argc > 4) { 733696Sroot fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 743696Sroot exit(1); 753696Sroot } 763696Sroot if (!isatty(0)) { 773696Sroot fprintf(stderr, "tip: must be interactive\n"); 783696Sroot exit(1); 793696Sroot } 803696Sroot if (argc > 1 && argv[argc-1][0] != '-') 813696Sroot system = argv[argc-1]; /* always last item */ 823696Sroot signal(SIGINT, cleanup); 833696Sroot signal(SIGQUIT, cleanup); 843696Sroot signal(SIGHUP, cleanup); 853696Sroot signal(SIGTERM, cleanup); 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"); 923696Sroot exit(3); 933696Sroot } 943719Ssam setbuf(stdout, NULL); 953696Sroot loginit(); 963696Sroot /* 973696Sroot * Now that we have the logfile and the ACU open 983696Sroot * return to the real uid and gid. These things will 993696Sroot * be closed on exit. Note that we can't run as root, 1003696Sroot * because locking mechanism on the tty and the accounting 1013696Sroot * will be bypassed. 1023696Sroot */ 1033696Sroot setuid(getuid()); 1043696Sroot setgid(getgid()); 1053696Sroot for (i = 1; i < argc-1; i++) 1063696Sroot if (equal(argv[i], "-v")) 1073696Sroot vflag++; 1083696Sroot /* 1093696Sroot * Kludge, their's no easy way to get the initialization 1103696Sroot * in the right order, so force it here 1113696Sroot */ 1123696Sroot if ((PH = getenv("PHONES")) == NOSTR) 1133696Sroot PH = "/etc/phones"; 1143696Sroot vinit(); /* init variables */ 1153696Sroot for (i = 1; i < argc-1; i++) 1163696Sroot if (argv[i][0] == '-' && argv[i][1] != 'v') { 1173696Sroot if (isnum(argv[i][1])) 1183696Sroot number(value(BAUDRATE)) = atoi(&argv[i][1]); 1193696Sroot else 1203696Sroot printf("%s: unknown option\n", argv[i]); 1213696Sroot } 1223696Sroot if ((arg.sg_ispeed = speed(number(value(BAUDRATE)))) == NULL) { 1233696Sroot printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 1243696Sroot delock(uucplock); 1253696Sroot exit(3); 1263696Sroot } 1273696Sroot arg.sg_ospeed = arg.sg_ispeed; 1283696Sroot /* 1293696Sroot * NOTE that remote side runs in TANDEM mode, 1303696Sroot * if the host doesn't honor X-ON/X-OFF with default 1313696Sroot * start/stop chars, the remote description must be 1323696Sroot * extended and tchars will have to be set up here. 1333696Sroot * If the host doesn't honor TANDEM mode, then watch 1343696Sroot * out, as you'll get garbage. 1353696Sroot */ 1363696Sroot arg.sg_flags = RAW | TANDEM; 1373696Sroot ioctl(FD, TIOCSETP, &arg); 1383696Sroot 1393696Sroot ioctl(0, TIOCGETP, &defarg); /* store initial status */ 1403696Sroot ioctl(0, TIOCGETC, &defchars); 1413696Sroot arg = defarg; 1423696Sroot arg.sg_flags = ANYP | CBREAK; 1433696Sroot tchars = defchars; 1443696Sroot tchars.t_intrc = tchars.t_quitc = -1; 1453696Sroot 1463696Sroot if (p = connect()) { 1473696Sroot printf("\07%s\n[EOT]\n", p); 1483696Sroot delock(uucplock); 1493696Sroot exit(1); 1503696Sroot } 1513696Sroot write(1, "\07connected\n", 11); 1523696Sroot raw(); 1533696Sroot #ifdef VMUNIX 1543696Sroot ioctl(0, TIOCGETD, (char *)&odisc); 1553696Sroot disc = OTTYDISC; 1563696Sroot ioctl(0, TIOCSETD, (char *)&disc); 1573696Sroot #endif 1583696Sroot pipe(fildes); pipe(repdes); 1593696Sroot signal(SIGALRM, timeout); 1603696Sroot if (pid = fork()) 1613696Sroot tipin(); 1623696Sroot else 1633696Sroot tipout(); 1643696Sroot /*NOTREACHED*/ 1653696Sroot } 1663696Sroot 1673696Sroot static 1683696Sroot cleanup() 1693696Sroot { 1703696Sroot delock(uucplock); 1713696Sroot exit(0); 1723696Sroot } 1733696Sroot 1743696Sroot /* 1753696Sroot * put the controlling keyboard into raw mode 1763696Sroot */ 1773696Sroot raw() 1783696Sroot { 1793696Sroot ioctl(0, TIOCSETP, &arg); 1803696Sroot ioctl(0, TIOCSETC, &tchars); 1813696Sroot } 1823696Sroot 1833696Sroot 1843696Sroot /* 1853696Sroot * return keyboard to normal mode 1863696Sroot */ 1873696Sroot unraw() 1883696Sroot { 1893696Sroot ioctl(0, TIOCSETP, &defarg); 1903696Sroot ioctl(0, TIOCSETC, &defchars); 1913696Sroot } 1923696Sroot 1933696Sroot /* 1943696Sroot * Print string ``s'', then read a string 1953696Sroot * in from the terminal. Handles signals & allows use of 1963696Sroot * normal erase and kill characters. 1973696Sroot */ 1983696Sroot prompt(s, p) 1993696Sroot char *s; 2003696Sroot register char *p; 2013696Sroot { 2023696Sroot register char *b = p; 2033696Sroot 2043696Sroot stoprompt = 0; 2053696Sroot signal(SIGINT, intprompt); 2063696Sroot signal(SIGQUIT, SIG_IGN); 2073696Sroot unraw(); 2083696Sroot printf("%s", s); 2093696Sroot while ((*p = getchar()) != EOF && *p != '\n') { 2103696Sroot if (stoprompt) 2113696Sroot goto pbreak; 2123696Sroot p++; 2133696Sroot } 2143696Sroot *p = '\0'; 2153696Sroot pbreak: 2163696Sroot raw(); 2173696Sroot signal(SIGINT, SIG_DFL); 2183696Sroot signal(SIGQUIT,SIG_DFL); 2193696Sroot return(stoprompt || p == b); 2203696Sroot } 2213696Sroot 2223696Sroot /* 2233696Sroot * Interrupt service routine during prompting 2243696Sroot */ 2253696Sroot intprompt() 2263696Sroot { 2273696Sroot signal(SIGINT, SIG_IGN); 2283696Sroot stoprompt = 1; 2293696Sroot printf("\r\n"); 2303696Sroot } 2313696Sroot 2323696Sroot /* 2333696Sroot * ****TIPIN TIPIN**** 2343696Sroot */ 2353696Sroot tipin() 2363696Sroot { 2373696Sroot char gch, bol = 1; 2383696Sroot 239*3796Ssam /* 240*3796Ssam * Kinda klugey here... 241*3796Ssam * check for scripting being turned on from the .tiprc file, 242*3796Ssam * but be careful about just using setscript(), as we may 243*3796Ssam * send a SIGEMT before tipout has a chance to set up catching 244*3796Ssam * it; so wait a second, then setscript() 245*3796Ssam */ 246*3796Ssam if (boolean(value(SCRIPT))) { 247*3796Ssam sleep(1); 248*3796Ssam setscript(); 249*3796Ssam } 250*3796Ssam 2513696Sroot while (1) { 2523696Sroot gch = getchar()&0177; 2533696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2543696Sroot if (!(gch = escape())) 2553696Sroot continue; 2563696Sroot } else if (gch == character(value(RAISECHAR))) { 2573696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2583696Sroot printf("%s", ctrl(character(value(RAISECHAR)))); 2593696Sroot continue; 2603696Sroot } else if (gch == '\r') { 2613696Sroot bol = 1; 2623696Sroot write(FD, &gch, 1); 2633696Sroot continue; 2643696Sroot } else if (gch == character(value(FORCE))) { 2653696Sroot printf("%s", ctrl(character(value(FORCE)))); 2663696Sroot gch = getchar()&0177; 2673696Sroot } 2683696Sroot bol = any(gch, value(EOL)); 2693696Sroot if (boolean(value(RAISE)) && islower(gch)) 2703696Sroot toupper(gch); 2713696Sroot write(FD, &gch, 1); 2723696Sroot } 2733696Sroot } 2743696Sroot 2753696Sroot /* 2763696Sroot * Escape handler -- 2773696Sroot * called on recognition of ``escapec'' at the beginning of a line 2783696Sroot */ 2793696Sroot escape() 2803696Sroot { 2813696Sroot register char gch; 2823696Sroot register esctable_t *p; 2833696Sroot char c = character(value(ESCAPE)); 2843696Sroot extern esctable_t etable[]; 2853696Sroot 2863696Sroot gch = (getchar()&0177); 2873696Sroot for (p = etable; p->e_char; p++) 2883696Sroot if (p->e_char == gch) { 2893696Sroot if ((p->e_flags&PRIV) && getuid()) 2903696Sroot continue; 2913696Sroot printf("%s", ctrl(c)); 2923696Sroot (*p->e_func)(gch); 2933696Sroot return(0); 2943696Sroot } 2953696Sroot 2963696Sroot write(FD, &c, 1); 2973696Sroot return(gch); 2983696Sroot } 2993696Sroot 3003696Sroot speed(n) 3013696Sroot { 3023696Sroot register int *p; 3033696Sroot 3043696Sroot for (p = bauds; *p != -1; p++) 3053696Sroot if (*p == n) 3063696Sroot return(p-bauds); 3073696Sroot return(NULL); 3083696Sroot } 3093696Sroot 3103696Sroot any(c, p) 3113696Sroot register char c, *p; 3123696Sroot { 3133696Sroot while (*p) 3143696Sroot if (*p++ == c) 3153696Sroot return(1); 3163696Sroot return(0); 3173696Sroot } 3183696Sroot 3193696Sroot size(s) 3203696Sroot register char *s; 3213696Sroot { 3223696Sroot register int i = 0; 3233696Sroot 3243696Sroot while (*s++) i++; 3253696Sroot return(i); 3263696Sroot } 3273696Sroot 3283696Sroot char * 3293696Sroot interp(s) 3303696Sroot register char *s; 3313696Sroot { 3323696Sroot static char buf[256]; 3333696Sroot register char *p = buf, c, *q; 3343696Sroot 3353696Sroot while (c = *s++) { 3363696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3373696Sroot if (*q++ == c) { 3383696Sroot *p++ = '\\'; *p++ = *q; 3393696Sroot goto next; 3403696Sroot } 3413696Sroot if (c < 040) { 3423696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3433696Sroot } else if (c == 0177) { 3443696Sroot *p++ = '^'; *p++ = '?'; 3453696Sroot } else 3463696Sroot *p++ = c; 3473696Sroot next: 3483696Sroot ; 3493696Sroot } 3503696Sroot *p = '\0'; 3513696Sroot return(buf); 3523696Sroot } 3533696Sroot 3543696Sroot char * 3553696Sroot ctrl(c) 3563696Sroot char c; 3573696Sroot { 3583696Sroot static char s[3]; 3593696Sroot 3603696Sroot if (c < 040 || c == 0177) { 3613696Sroot s[0] = '^'; 3623696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3633696Sroot s[2] = '\0'; 3643696Sroot } else { 3653696Sroot s[0] = c; 3663696Sroot s[1] = '\0'; 3673696Sroot } 3683696Sroot return(s); 3693696Sroot } 3703696Sroot 3713696Sroot /* 3723696Sroot * Help command 3733696Sroot */ 3743696Sroot help(c) 3753696Sroot char c; 3763696Sroot { 3773696Sroot register esctable_t *p; 3783696Sroot extern esctable_t etable[]; 3793696Sroot 3803696Sroot printf("%c\r\n", c); 3813696Sroot for (p = etable; p->e_char; p++) { 3823696Sroot if ((p->e_flags&PRIV) && getuid()) 3833696Sroot continue; 3843696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 3853696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 3863696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 3873696Sroot } 3883696Sroot } 389