17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 5*8d489c7aSmuffin 67c478bd9Sstevel@tonic-gate /* 77c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 87c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 97c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 107c478bd9Sstevel@tonic-gate */ 117c478bd9Sstevel@tonic-gate 12*8d489c7aSmuffin #pragma ident "%Z%%M% %I% %E% SMI" 137c478bd9Sstevel@tonic-gate 147c478bd9Sstevel@tonic-gate /* 157c478bd9Sstevel@tonic-gate * tip - UNIX link to other systems 167c478bd9Sstevel@tonic-gate * tip [-v] [-speed] system-name 177c478bd9Sstevel@tonic-gate * or 187c478bd9Sstevel@tonic-gate * cu phone-number [-s speed] [-l line] [-a acu] 197c478bd9Sstevel@tonic-gate */ 207c478bd9Sstevel@tonic-gate #include "tip.h" 217c478bd9Sstevel@tonic-gate #include <sys/wait.h> 227c478bd9Sstevel@tonic-gate #include <locale.h> 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate /* 257c478bd9Sstevel@tonic-gate * Baud rate mapping table 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate int bauds[] = { 287c478bd9Sstevel@tonic-gate 0, 50, 75, 110, 134, 150, 200, 300, 600, 297c478bd9Sstevel@tonic-gate 1200, 1800, 2400, 4800, 9600, 19200, 38400, 307c478bd9Sstevel@tonic-gate 57600, 76800, 115200, 153600, 230400, 307200, 460800, -1 317c478bd9Sstevel@tonic-gate }; 327c478bd9Sstevel@tonic-gate 33*8d489c7aSmuffin extern void tipout(void) __NORETURN; 34*8d489c7aSmuffin extern void timeout(void); 35*8d489c7aSmuffin extern esctable_t etable[]; 36*8d489c7aSmuffin extern unsigned char evenpartab[]; 37*8d489c7aSmuffin 38*8d489c7aSmuffin void intprompt(void); 39*8d489c7aSmuffin void deadkid(void); 40*8d489c7aSmuffin void cleanup(void); 41*8d489c7aSmuffin void tipin(void) __NORETURN; 42*8d489c7aSmuffin unsigned char escape(void); 43*8d489c7aSmuffin char *sname(char *); 44*8d489c7aSmuffin char PNbuf[256]; /* This limits the size of a number */ 457c478bd9Sstevel@tonic-gate int noparity = 0; 467c478bd9Sstevel@tonic-gate 47*8d489c7aSmuffin int 48*8d489c7aSmuffin main(int argc, char *argv[]) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate char *system = NOSTR; 51*8d489c7aSmuffin int i; 52*8d489c7aSmuffin char *p; 537c478bd9Sstevel@tonic-gate char sbuf[12]; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate gid = getgid(); 567c478bd9Sstevel@tonic-gate egid = getegid(); 577c478bd9Sstevel@tonic-gate uid = getuid(); 587c478bd9Sstevel@tonic-gate euid = geteuid(); 597c478bd9Sstevel@tonic-gate if (equal(sname(argv[0]), "cu")) { 607c478bd9Sstevel@tonic-gate cumode = 1; 617c478bd9Sstevel@tonic-gate cumain(argc, argv); 627c478bd9Sstevel@tonic-gate goto cucommon; 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate if (argc > 4) { 66*8d489c7aSmuffin (void) fprintf(stderr, 67*8d489c7aSmuffin "usage: tip [-v] [-speed] [system-name]\n"); 68*8d489c7aSmuffin return (1); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate if (!isatty(0)) { 71*8d489c7aSmuffin (void) fprintf(stderr, "tip: must be interactive\n"); 72*8d489c7aSmuffin return (1); 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate for (; argc > 1; argv++, argc--) { 767c478bd9Sstevel@tonic-gate if (argv[1][0] != '-') 777c478bd9Sstevel@tonic-gate system = argv[1]; 787c478bd9Sstevel@tonic-gate else switch (argv[1][1]) { 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate case 'v': 817c478bd9Sstevel@tonic-gate vflag++; 827c478bd9Sstevel@tonic-gate break; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate case '0': case '1': case '2': case '3': case '4': 857c478bd9Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9': 867c478bd9Sstevel@tonic-gate BR = atoi(&argv[1][1]); 877c478bd9Sstevel@tonic-gate break; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate default: 90*8d489c7aSmuffin (void) fprintf(stderr, "tip: %s, unknown option\n", 91*8d489c7aSmuffin argv[1]); 927c478bd9Sstevel@tonic-gate break; 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate (void) setlocale(LC_CTYPE, ""); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (system == NOSTR) 997c478bd9Sstevel@tonic-gate goto notnumber; 1007c478bd9Sstevel@tonic-gate for (p = system; *p; p++) 1017c478bd9Sstevel@tonic-gate if (isalpha(*p)) 1027c478bd9Sstevel@tonic-gate goto notnumber; 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * System name is really a phone number... 1057c478bd9Sstevel@tonic-gate * Copy the number then stomp on the original (in case the number 1067c478bd9Sstevel@tonic-gate * is private, we don't want 'ps' or 'w' to find it). 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate if (strlen(system) > sizeof (PNbuf) - 1) { 109*8d489c7aSmuffin (void) fprintf(stderr, 110*8d489c7aSmuffin "tip: phone number too long (max = %d bytes)\n", 1117c478bd9Sstevel@tonic-gate sizeof (PNbuf) - 1); 112*8d489c7aSmuffin return (1); 1137c478bd9Sstevel@tonic-gate } 114*8d489c7aSmuffin (void) strncpy(PNbuf, system, sizeof (PNbuf) - 1); 1157c478bd9Sstevel@tonic-gate for (p = system; *p; p++) 1167c478bd9Sstevel@tonic-gate *p = '\0'; 1177c478bd9Sstevel@tonic-gate PN = PNbuf; 118*8d489c7aSmuffin (void) sprintf(sbuf, "tip%d", BR); 1197c478bd9Sstevel@tonic-gate system = sbuf; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate notnumber: 122*8d489c7aSmuffin (void) signal(SIGINT, (sig_handler_t)cleanup); 123*8d489c7aSmuffin (void) signal(SIGQUIT, (sig_handler_t)cleanup); 124*8d489c7aSmuffin (void) signal(SIGHUP, (sig_handler_t)cleanup); 125*8d489c7aSmuffin (void) signal(SIGTERM, (sig_handler_t)cleanup); 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate if ((i = hunt(system)) == 0) { 128*8d489c7aSmuffin (void) printf("all ports busy\n"); 129*8d489c7aSmuffin return (3); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate if (i == -1) { 132*8d489c7aSmuffin (void) printf("link down\n"); 1337c478bd9Sstevel@tonic-gate delock(uucplock); 134*8d489c7aSmuffin return (3); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate setbuf(stdout, NULL); 1377c478bd9Sstevel@tonic-gate loginit(); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * Now that we have the logfile and the ACU open 1417c478bd9Sstevel@tonic-gate * return to the real uid and gid. These things will 1427c478bd9Sstevel@tonic-gate * be closed on exit. The saved-setuid uid and gid 1437c478bd9Sstevel@tonic-gate * allows us to get the original setuid permissions back 1447c478bd9Sstevel@tonic-gate * for removing the uucp lock. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate userperm(); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * Kludge, there's no easy way to get the initialization 1507c478bd9Sstevel@tonic-gate * in the right order, so force it here. 1517c478bd9Sstevel@tonic-gate * Do the open here, before we change back to real uid. 1527c478bd9Sstevel@tonic-gate * We will check whether the open succeeded later, when 1537c478bd9Sstevel@tonic-gate * (and if) we actually go to use the file. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate if ((PH = getenv("PHONES")) == NOSTR) { 1567c478bd9Sstevel@tonic-gate myperm(); 1577c478bd9Sstevel@tonic-gate PH = "/etc/phones"; 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate phfd = fopen(PH, "r"); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate userperm(); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate vinit(); /* init variables */ 1647c478bd9Sstevel@tonic-gate setparity("none"); /* set the parity table */ 1657c478bd9Sstevel@tonic-gate if ((i = speed(number(value(BAUDRATE)))) == NULL) { 166*8d489c7aSmuffin (void) printf("tip: bad baud rate %d\n", 167*8d489c7aSmuffin number(value(BAUDRATE))); 1687c478bd9Sstevel@tonic-gate myperm(); 1697c478bd9Sstevel@tonic-gate delock(uucplock); 170*8d489c7aSmuffin return (3); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * Hardwired connections require the 1767c478bd9Sstevel@tonic-gate * line speed set before they make any transmissions 1777c478bd9Sstevel@tonic-gate * (this is particularly true of things like a DF03-AC) 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate if (HW) 1807c478bd9Sstevel@tonic-gate ttysetup(i); 1817c478bd9Sstevel@tonic-gate if (p = connect()) { 182*8d489c7aSmuffin (void) printf("\07%s\n[EOT]\n", p); 1837c478bd9Sstevel@tonic-gate myperm(); 1847c478bd9Sstevel@tonic-gate delock(uucplock); 185*8d489c7aSmuffin return (1); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * Always setup the tty again here in case hardware flow 1907c478bd9Sstevel@tonic-gate * control was selected, which can only be set after the 1917c478bd9Sstevel@tonic-gate * connection is made, or in case this is not a hardwired 1927c478bd9Sstevel@tonic-gate * modem (rare these days) that likewise can only be setup 1937c478bd9Sstevel@tonic-gate * after the connection is made. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate ttysetup(i); 1967c478bd9Sstevel@tonic-gate cucommon: 1977c478bd9Sstevel@tonic-gate /* 1987c478bd9Sstevel@tonic-gate * From here down the code is shared with 1997c478bd9Sstevel@tonic-gate * the "cu" version of tip. 2007c478bd9Sstevel@tonic-gate */ 2017c478bd9Sstevel@tonic-gate 202*8d489c7aSmuffin (void) ioctl(0, TCGETS, (char *)&defarg); 2037c478bd9Sstevel@tonic-gate arg = defarg; 2047c478bd9Sstevel@tonic-gate /* turn off input processing */ 2057c478bd9Sstevel@tonic-gate arg.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN); 2067c478bd9Sstevel@tonic-gate arg.c_cc[VMIN] = 1; 2077c478bd9Sstevel@tonic-gate arg.c_cc[VTIME] = 0; 2087c478bd9Sstevel@tonic-gate arg.c_iflag &= ~(INPCK|IXON|IXOFF|ICRNL); 2097c478bd9Sstevel@tonic-gate arg.c_oflag = 0; /* turn off all output processing */ 2107c478bd9Sstevel@tonic-gate /* handle tandem mode in case was set in remote file */ 2117c478bd9Sstevel@tonic-gate if (boolean(value(TAND))) 2127c478bd9Sstevel@tonic-gate tandem("on"); 2137c478bd9Sstevel@tonic-gate else 2147c478bd9Sstevel@tonic-gate tandem("off"); 2157c478bd9Sstevel@tonic-gate raw(); 2167c478bd9Sstevel@tonic-gate 217*8d489c7aSmuffin (void) pipe(fildes); (void) pipe(repdes); 218*8d489c7aSmuffin (void) signal(SIGALRM, (sig_handler_t)timeout); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * Everything's set up now: 2227c478bd9Sstevel@tonic-gate * connection established (hardwired or dialup) 2237c478bd9Sstevel@tonic-gate * line conditioned (baud rate, mode, etc.) 2247c478bd9Sstevel@tonic-gate * internal data structures (variables) 2257c478bd9Sstevel@tonic-gate * so, fork one process for local side and one for remote. 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate if (CM != NOSTR) { 228*8d489c7aSmuffin (void) sleep(2); /* let line settle */ 229*8d489c7aSmuffin parwrite(FD, (unsigned char *)CM, strlen(CM)); 2307c478bd9Sstevel@tonic-gate } 231*8d489c7aSmuffin (void) printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 232*8d489c7aSmuffin (void) signal(SIGCHLD, (sig_handler_t)deadkid); 2337c478bd9Sstevel@tonic-gate if (pid = fork()) 2347c478bd9Sstevel@tonic-gate tipin(); 2357c478bd9Sstevel@tonic-gate else 2367c478bd9Sstevel@tonic-gate tipout(); 2377c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate void 241*8d489c7aSmuffin deadkid(void) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (pid >= 0 && waitpid(pid, NULL, WNOHANG) == pid) 245*8d489c7aSmuffin tip_abort("Connection Closed"); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate void 249*8d489c7aSmuffin cleanup(void) 2507c478bd9Sstevel@tonic-gate { 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (uid != getuid()) { 2537c478bd9Sstevel@tonic-gate myperm(); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate delock(uucplock); 2567c478bd9Sstevel@tonic-gate exit(0); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * put the controlling keyboard into raw mode 2617c478bd9Sstevel@tonic-gate */ 262*8d489c7aSmuffin void 263*8d489c7aSmuffin raw(void) 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate 266*8d489c7aSmuffin (void) ioctl(0, TCSETSF, (char *)&arg); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * return keyboard to normal mode 2727c478bd9Sstevel@tonic-gate */ 273*8d489c7aSmuffin void 274*8d489c7aSmuffin unraw(void) 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate 277*8d489c7aSmuffin (void) ioctl(0, TCSETSF, (char *)&defarg); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * switch to using invoking user's permissions 2827c478bd9Sstevel@tonic-gate */ 283*8d489c7aSmuffin void 284*8d489c7aSmuffin userperm(void) 2857c478bd9Sstevel@tonic-gate { 2867c478bd9Sstevel@tonic-gate 287*8d489c7aSmuffin (void) setegid(gid); 288*8d489c7aSmuffin (void) seteuid(uid); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * switch to using my special (setuid) permissions 2937c478bd9Sstevel@tonic-gate */ 294*8d489c7aSmuffin void 295*8d489c7aSmuffin myperm(void) 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate 298*8d489c7aSmuffin (void) setegid(egid); 299*8d489c7aSmuffin (void) seteuid(euid); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate static sigjmp_buf promptbuf; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * Print string ``s'', then read a string 3067c478bd9Sstevel@tonic-gate * in from the terminal. Handles signals & allows use of 3077c478bd9Sstevel@tonic-gate * normal erase and kill characters. 3087c478bd9Sstevel@tonic-gate */ 309*8d489c7aSmuffin int 310*8d489c7aSmuffin prompt(char *s, char *p, size_t len) 3117c478bd9Sstevel@tonic-gate { 312*8d489c7aSmuffin char *b = p; 313*8d489c7aSmuffin int c; 314*8d489c7aSmuffin sig_handler_t ointr, oquit; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate stoprompt = 0; 317*8d489c7aSmuffin ointr = signal(SIGINT, (sig_handler_t)intprompt); 3187c478bd9Sstevel@tonic-gate oquit = signal(SIGQUIT, SIG_IGN); 3197c478bd9Sstevel@tonic-gate unraw(); 320*8d489c7aSmuffin (void) printf("%s", s); 3217c478bd9Sstevel@tonic-gate if (sigsetjmp(promptbuf, 1) == 0) 3227c478bd9Sstevel@tonic-gate while (p < b + len - 1 && 3237c478bd9Sstevel@tonic-gate ((c = getchar()) != EOF) && (c != '\n')) 3247c478bd9Sstevel@tonic-gate *p++ = c; 3257c478bd9Sstevel@tonic-gate *p = '\0'; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate raw(); 328*8d489c7aSmuffin (void) signal(SIGINT, ointr); 329*8d489c7aSmuffin (void) signal(SIGQUIT, oquit); 3307c478bd9Sstevel@tonic-gate return (stoprompt || p == b); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * Interrupt service routine during prompting 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate void 337*8d489c7aSmuffin intprompt(void) 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate 340*8d489c7aSmuffin (void) signal(SIGINT, SIG_IGN); 341*8d489c7aSmuffin (void) signal(SIGQUIT, SIG_IGN); 3427c478bd9Sstevel@tonic-gate stoprompt = 1; 343*8d489c7aSmuffin (void) printf("\r\n"); 3447c478bd9Sstevel@tonic-gate siglongjmp(promptbuf, 1); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * ****TIPIN TIPIN**** 3497c478bd9Sstevel@tonic-gate */ 350*8d489c7aSmuffin void 351*8d489c7aSmuffin tipin(void) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate unsigned char gch, c; 3547c478bd9Sstevel@tonic-gate int bol = 1; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * Kinda klugey here... 3587c478bd9Sstevel@tonic-gate * check for scripting being turned on from the .tiprc file, 3597c478bd9Sstevel@tonic-gate * but be careful about just using setscript(), as we may 3607c478bd9Sstevel@tonic-gate * send a SIGEMT before tipout has a chance to set up catching 3617c478bd9Sstevel@tonic-gate * it; so wait a second, then setscript() 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate if (boolean(value(SCRIPT))) { 364*8d489c7aSmuffin (void) sleep(1); 3657c478bd9Sstevel@tonic-gate setscript(); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate for (;;) { 3697c478bd9Sstevel@tonic-gate gch = getchar()&0377; 3707c478bd9Sstevel@tonic-gate if ((gch == character(value(ESCAPE))) && bol) { 3717c478bd9Sstevel@tonic-gate if (!(gch = escape())) 3727c478bd9Sstevel@tonic-gate continue; 3737c478bd9Sstevel@tonic-gate } else if (!cumode && gch == character(value(RAISECHAR))) { 3747c478bd9Sstevel@tonic-gate boolean(value(RAISE)) = !boolean(value(RAISE)); 3757c478bd9Sstevel@tonic-gate continue; 3767c478bd9Sstevel@tonic-gate } else if (gch == '\r') { 3777c478bd9Sstevel@tonic-gate bol = 1; 3787c478bd9Sstevel@tonic-gate parwrite(FD, &gch, 1); 3797c478bd9Sstevel@tonic-gate if (boolean(value(HALFDUPLEX))) 380*8d489c7aSmuffin (void) printf("\r\n"); 3817c478bd9Sstevel@tonic-gate continue; 3827c478bd9Sstevel@tonic-gate } else if (!cumode && gch == character(value(FORCE))) 3837c478bd9Sstevel@tonic-gate gch = getchar()&0377; 3847c478bd9Sstevel@tonic-gate bol = any(gch, value(EOL)); 3857c478bd9Sstevel@tonic-gate if (boolean(value(RAISE)) && islower(gch)) 3867c478bd9Sstevel@tonic-gate gch = toupper(gch); 3877c478bd9Sstevel@tonic-gate c = gch; 3887c478bd9Sstevel@tonic-gate parwrite(FD, &gch, 1); 3897c478bd9Sstevel@tonic-gate if (boolean(value(HALFDUPLEX))) 390*8d489c7aSmuffin (void) putchar(c); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * Escape handler -- 3967c478bd9Sstevel@tonic-gate * called on recognition of ``escapec'' at the beginning of a line 3977c478bd9Sstevel@tonic-gate */ 398*8d489c7aSmuffin unsigned char 399*8d489c7aSmuffin escape(void) 4007c478bd9Sstevel@tonic-gate { 401*8d489c7aSmuffin unsigned char gch; 402*8d489c7aSmuffin esctable_t *p; 4037c478bd9Sstevel@tonic-gate char c = character(value(ESCAPE)); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate gch = (getchar()&0377); 4067c478bd9Sstevel@tonic-gate for (p = etable; p->e_char; p++) 4077c478bd9Sstevel@tonic-gate if (p->e_char == gch) { 4087c478bd9Sstevel@tonic-gate if ((p->e_flags&PRIV) && uid) 4097c478bd9Sstevel@tonic-gate continue; 410*8d489c7aSmuffin (void) printf("%s", ctrl(c)); 4117c478bd9Sstevel@tonic-gate (*p->e_func)(gch); 4127c478bd9Sstevel@tonic-gate return (0); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate /* ESCAPE ESCAPE forces ESCAPE */ 4157c478bd9Sstevel@tonic-gate if (c != gch) 416*8d489c7aSmuffin parwrite(FD, (unsigned char *)&c, 1); 4177c478bd9Sstevel@tonic-gate return (gch); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 420*8d489c7aSmuffin int 421*8d489c7aSmuffin speed(int n) 4227c478bd9Sstevel@tonic-gate { 423*8d489c7aSmuffin int *p; 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate for (p = bauds; *p != -1; p++) 4267c478bd9Sstevel@tonic-gate if (*p == n) 4277c478bd9Sstevel@tonic-gate return (p - bauds); 428*8d489c7aSmuffin return (0); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 431*8d489c7aSmuffin int 432*8d489c7aSmuffin any(char c, char *p) 4337c478bd9Sstevel@tonic-gate { 4347c478bd9Sstevel@tonic-gate while (p && *p) 4357c478bd9Sstevel@tonic-gate if (*p++ == c) 4367c478bd9Sstevel@tonic-gate return (1); 4377c478bd9Sstevel@tonic-gate return (0); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate char * 441*8d489c7aSmuffin interp(char *s) 4427c478bd9Sstevel@tonic-gate { 4437c478bd9Sstevel@tonic-gate static char buf[256]; 444*8d489c7aSmuffin char *p = buf, c, *q; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate while (c = *s++) { 4477c478bd9Sstevel@tonic-gate for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 4487c478bd9Sstevel@tonic-gate if (*q++ == c) { 4497c478bd9Sstevel@tonic-gate *p++ = '\\'; *p++ = *q; 4507c478bd9Sstevel@tonic-gate goto next; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate if (c < 040) { 4537c478bd9Sstevel@tonic-gate *p++ = '^'; *p++ = c + 'A'-1; 4547c478bd9Sstevel@tonic-gate } else if (c == 0177) { 4557c478bd9Sstevel@tonic-gate *p++ = '^'; *p++ = '?'; 4567c478bd9Sstevel@tonic-gate } else 4577c478bd9Sstevel@tonic-gate *p++ = c; 4587c478bd9Sstevel@tonic-gate next: 4597c478bd9Sstevel@tonic-gate ; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate *p = '\0'; 4627c478bd9Sstevel@tonic-gate return (buf); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate char * 466*8d489c7aSmuffin ctrl(char c) 4677c478bd9Sstevel@tonic-gate { 4687c478bd9Sstevel@tonic-gate static char s[3]; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if (c < 040 || c == 0177) { 4717c478bd9Sstevel@tonic-gate s[0] = '^'; 4727c478bd9Sstevel@tonic-gate s[1] = c == 0177 ? '?' : c+'A'-1; 4737c478bd9Sstevel@tonic-gate s[2] = '\0'; 4747c478bd9Sstevel@tonic-gate } else { 4757c478bd9Sstevel@tonic-gate s[0] = c; 4767c478bd9Sstevel@tonic-gate s[1] = '\0'; 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate return (s); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Help command 4837c478bd9Sstevel@tonic-gate */ 484*8d489c7aSmuffin void 485*8d489c7aSmuffin help(int c) 4867c478bd9Sstevel@tonic-gate { 487*8d489c7aSmuffin esctable_t *p; 4887c478bd9Sstevel@tonic-gate 489*8d489c7aSmuffin (void) printf("%c\r\n", c); 4907c478bd9Sstevel@tonic-gate for (p = etable; p->e_char; p++) { 4917c478bd9Sstevel@tonic-gate if ((p->e_flags&PRIV) && uid) 4927c478bd9Sstevel@tonic-gate continue; 493*8d489c7aSmuffin (void) printf("%2s", ctrl(character(value(ESCAPE)))); 494*8d489c7aSmuffin (void) printf("%-2s %c %s\r\n", ctrl(p->e_char), 495*8d489c7aSmuffin p->e_flags&EXP ? '*': ' ', p->e_help); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Set up the "remote" tty's state 5017c478bd9Sstevel@tonic-gate */ 502*8d489c7aSmuffin void 503*8d489c7aSmuffin ttysetup(int speed) 5047c478bd9Sstevel@tonic-gate { 5057c478bd9Sstevel@tonic-gate struct termios buf; 5067c478bd9Sstevel@tonic-gate char *loc; 5077c478bd9Sstevel@tonic-gate 508*8d489c7aSmuffin (void) ioctl(FD, TCGETS, (char *)&buf); 5097c478bd9Sstevel@tonic-gate buf.c_cflag &= (CREAD|HUPCL|CLOCAL|CRTSCTS|CRTSXOFF); 5107c478bd9Sstevel@tonic-gate buf.c_cflag |= CS8; 511*8d489c7aSmuffin (void) cfsetospeed(&buf, speed); 5127c478bd9Sstevel@tonic-gate if (boolean(value(HARDWAREFLOW))) { 5137c478bd9Sstevel@tonic-gate int i = TIOCM_CAR; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * Only set hardware flow control if carrier is up, 5177c478bd9Sstevel@tonic-gate * because some devices require both CD and RTS to 5187c478bd9Sstevel@tonic-gate * be up before sending. 5197c478bd9Sstevel@tonic-gate */ 520*8d489c7aSmuffin (void) ioctl(FD, TIOCMGET, &i); 5217c478bd9Sstevel@tonic-gate if (i & TIOCM_CAR) 5227c478bd9Sstevel@tonic-gate buf.c_cflag |= (CRTSCTS|CRTSXOFF); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * Careful to only penalize the 8-bit users here on the 5277c478bd9Sstevel@tonic-gate * incoming tty port. The default 7-bit users will 5287c478bd9Sstevel@tonic-gate * still get the parity bit from the other side's login 5297c478bd9Sstevel@tonic-gate * process (which happens to be the default for sun tip 5307c478bd9Sstevel@tonic-gate * configurations). 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate loc = setlocale(LC_CTYPE, NULL); 5337c478bd9Sstevel@tonic-gate if (noparity && loc != 0 && strcmp(loc, "C") != 0) 5347c478bd9Sstevel@tonic-gate buf.c_iflag = 0; 5357c478bd9Sstevel@tonic-gate else 5367c478bd9Sstevel@tonic-gate buf.c_iflag = ISTRIP; 5377c478bd9Sstevel@tonic-gate buf.c_oflag = 0; 5387c478bd9Sstevel@tonic-gate buf.c_lflag = 0; 5397c478bd9Sstevel@tonic-gate buf.c_cc[VMIN] = 1; 5407c478bd9Sstevel@tonic-gate buf.c_cc[VTIME] = 0; 541*8d489c7aSmuffin (void) ioctl(FD, TCSETSF, (char *)&buf); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * Return "simple" name from a file name, 5467c478bd9Sstevel@tonic-gate * strip leading directories. 5477c478bd9Sstevel@tonic-gate */ 5487c478bd9Sstevel@tonic-gate char * 549*8d489c7aSmuffin sname(char *s) 5507c478bd9Sstevel@tonic-gate { 551*8d489c7aSmuffin char *p = s; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate while (*s) 5547c478bd9Sstevel@tonic-gate if (*s++ == '/') 5557c478bd9Sstevel@tonic-gate p = s; 5567c478bd9Sstevel@tonic-gate return (p); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate static char partab[0400]; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* 5627c478bd9Sstevel@tonic-gate * Do a write to the remote machine with the correct parity. 5637c478bd9Sstevel@tonic-gate * We are doing 8 bit wide output, so we just generate a character 5647c478bd9Sstevel@tonic-gate * with the right parity and output it. 5657c478bd9Sstevel@tonic-gate */ 566*8d489c7aSmuffin void 567*8d489c7aSmuffin parwrite(int fd, unsigned char *buf, int n) 5687c478bd9Sstevel@tonic-gate { 569*8d489c7aSmuffin int i; 570*8d489c7aSmuffin unsigned char *bp; 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate bp = buf; 5737c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 5747c478bd9Sstevel@tonic-gate *bp = partab[(*bp)&0377]; 5757c478bd9Sstevel@tonic-gate bp++; 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate if (write(fd, buf, n) < 0) { 5787c478bd9Sstevel@tonic-gate if (errno == EIO || errno == ENXIO) 579*8d489c7aSmuffin tip_abort("Lost carrier."); 5807c478bd9Sstevel@tonic-gate /* this is questionable */ 5817c478bd9Sstevel@tonic-gate perror("write"); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * Build a parity table with appropriate high-order bit. 5877c478bd9Sstevel@tonic-gate */ 588*8d489c7aSmuffin void 589*8d489c7aSmuffin setparity(char *defparity) 5907c478bd9Sstevel@tonic-gate { 591*8d489c7aSmuffin int i; 5927c478bd9Sstevel@tonic-gate char *parity; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate if (value(PARITY) == NOSTR) 5957c478bd9Sstevel@tonic-gate value(PARITY) = defparity; 5967c478bd9Sstevel@tonic-gate parity = value(PARITY); 5977c478bd9Sstevel@tonic-gate for (i = 0; i < 0400; i++) 5987c478bd9Sstevel@tonic-gate partab[i] = evenpartab[i]; 599*8d489c7aSmuffin if (equal(parity, "even")) { 600*8d489c7aSmuffin /* EMPTY */ 601*8d489c7aSmuffin } else if (equal(parity, "odd")) { 6027c478bd9Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6037c478bd9Sstevel@tonic-gate partab[i] ^= 0200; /* reverse bit 7 */ 6047c478bd9Sstevel@tonic-gate } else if (equal(parity, "none")) { 6057c478bd9Sstevel@tonic-gate /* Do nothing so we can pass thru 8-bit chars */ 6067c478bd9Sstevel@tonic-gate noparity = 1; 6077c478bd9Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6087c478bd9Sstevel@tonic-gate partab[i] = i; 6097c478bd9Sstevel@tonic-gate } else if (equal(parity, "zero")) { 6107c478bd9Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6117c478bd9Sstevel@tonic-gate partab[i] &= ~0200; /* turn off bit 7 */ 6127c478bd9Sstevel@tonic-gate } else if (equal(parity, "one")) { 6137c478bd9Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6147c478bd9Sstevel@tonic-gate partab[i] |= 0200; /* turn on bit 7 */ 6157c478bd9Sstevel@tonic-gate } else { 616*8d489c7aSmuffin (void) fprintf(stderr, "%s: unknown parity value\n", PA); 617*8d489c7aSmuffin (void) fflush(stderr); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate } 620