1*3719Ssam /* tip.c 4.2 81/05/10 */ 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 } 94*3719Ssam 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 2393696Sroot while (1) { 2403696Sroot gch = getchar()&0177; 2413696Sroot if ((gch == character(value(ESCAPE))) && bol) { 2423696Sroot if (!(gch = escape())) 2433696Sroot continue; 2443696Sroot } else if (gch == character(value(RAISECHAR))) { 2453696Sroot boolean(value(RAISE)) = !boolean(value(RAISE)); 2463696Sroot printf("%s", ctrl(character(value(RAISECHAR)))); 2473696Sroot continue; 2483696Sroot } else if (gch == '\r') { 2493696Sroot bol = 1; 2503696Sroot write(FD, &gch, 1); 2513696Sroot continue; 2523696Sroot } else if (gch == character(value(FORCE))) { 2533696Sroot printf("%s", ctrl(character(value(FORCE)))); 2543696Sroot gch = getchar()&0177; 2553696Sroot } 2563696Sroot bol = any(gch, value(EOL)); 2573696Sroot if (boolean(value(RAISE)) && islower(gch)) 2583696Sroot toupper(gch); 2593696Sroot write(FD, &gch, 1); 2603696Sroot } 2613696Sroot } 2623696Sroot 2633696Sroot /* 2643696Sroot * Escape handler -- 2653696Sroot * called on recognition of ``escapec'' at the beginning of a line 2663696Sroot */ 2673696Sroot escape() 2683696Sroot { 2693696Sroot register char gch; 2703696Sroot register esctable_t *p; 2713696Sroot char c = character(value(ESCAPE)); 2723696Sroot extern esctable_t etable[]; 2733696Sroot 2743696Sroot gch = (getchar()&0177); 2753696Sroot for (p = etable; p->e_char; p++) 2763696Sroot if (p->e_char == gch) { 2773696Sroot if ((p->e_flags&PRIV) && getuid()) 2783696Sroot continue; 2793696Sroot printf("%s", ctrl(c)); 2803696Sroot (*p->e_func)(gch); 2813696Sroot return(0); 2823696Sroot } 2833696Sroot 2843696Sroot write(FD, &c, 1); 2853696Sroot return(gch); 2863696Sroot } 2873696Sroot 2883696Sroot speed(n) 2893696Sroot { 2903696Sroot register int *p; 2913696Sroot 2923696Sroot for (p = bauds; *p != -1; p++) 2933696Sroot if (*p == n) 2943696Sroot return(p-bauds); 2953696Sroot return(NULL); 2963696Sroot } 2973696Sroot 2983696Sroot any(c, p) 2993696Sroot register char c, *p; 3003696Sroot { 3013696Sroot while (*p) 3023696Sroot if (*p++ == c) 3033696Sroot return(1); 3043696Sroot return(0); 3053696Sroot } 3063696Sroot 3073696Sroot size(s) 3083696Sroot register char *s; 3093696Sroot { 3103696Sroot register int i = 0; 3113696Sroot 3123696Sroot while (*s++) i++; 3133696Sroot return(i); 3143696Sroot } 3153696Sroot 3163696Sroot char * 3173696Sroot interp(s) 3183696Sroot register char *s; 3193696Sroot { 3203696Sroot static char buf[256]; 3213696Sroot register char *p = buf, c, *q; 3223696Sroot 3233696Sroot while (c = *s++) { 3243696Sroot for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 3253696Sroot if (*q++ == c) { 3263696Sroot *p++ = '\\'; *p++ = *q; 3273696Sroot goto next; 3283696Sroot } 3293696Sroot if (c < 040) { 3303696Sroot *p++ = '^'; *p++ = c + 'A'-1; 3313696Sroot } else if (c == 0177) { 3323696Sroot *p++ = '^'; *p++ = '?'; 3333696Sroot } else 3343696Sroot *p++ = c; 3353696Sroot next: 3363696Sroot ; 3373696Sroot } 3383696Sroot *p = '\0'; 3393696Sroot return(buf); 3403696Sroot } 3413696Sroot 3423696Sroot char * 3433696Sroot ctrl(c) 3443696Sroot char c; 3453696Sroot { 3463696Sroot static char s[3]; 3473696Sroot 3483696Sroot if (c < 040 || c == 0177) { 3493696Sroot s[0] = '^'; 3503696Sroot s[1] = c == 0177 ? '?' : c+'A'-1; 3513696Sroot s[2] = '\0'; 3523696Sroot } else { 3533696Sroot s[0] = c; 3543696Sroot s[1] = '\0'; 3553696Sroot } 3563696Sroot return(s); 3573696Sroot } 3583696Sroot 3593696Sroot /* 3603696Sroot * Help command 3613696Sroot */ 3623696Sroot help(c) 3633696Sroot char c; 3643696Sroot { 3653696Sroot register esctable_t *p; 3663696Sroot extern esctable_t etable[]; 3673696Sroot 3683696Sroot printf("%c\r\n", c); 3693696Sroot for (p = etable; p->e_char; p++) { 3703696Sroot if ((p->e_flags&PRIV) && getuid()) 3713696Sroot continue; 3723696Sroot printf("%2s", ctrl(character(value(ESCAPE)))); 3733696Sroot printf("%-2s %c %s\r\n", ctrl(p->e_char), 3743696Sroot p->e_flags&EXP ? '*': ' ', p->e_help); 3753696Sroot } 3763696Sroot } 377