10Sstevel@tonic-gate /* 2*2590Ssn199410 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 5549Smuffin 60Sstevel@tonic-gate /* 70Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 80Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 90Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 100Sstevel@tonic-gate */ 110Sstevel@tonic-gate 12549Smuffin #pragma ident "%Z%%M% %I% %E% SMI" 130Sstevel@tonic-gate 140Sstevel@tonic-gate /* 150Sstevel@tonic-gate * tip - UNIX link to other systems 160Sstevel@tonic-gate * tip [-v] [-speed] system-name 170Sstevel@tonic-gate * or 180Sstevel@tonic-gate * cu phone-number [-s speed] [-l line] [-a acu] 190Sstevel@tonic-gate */ 200Sstevel@tonic-gate #include "tip.h" 210Sstevel@tonic-gate #include <sys/wait.h> 220Sstevel@tonic-gate #include <locale.h> 230Sstevel@tonic-gate 240Sstevel@tonic-gate /* 250Sstevel@tonic-gate * Baud rate mapping table 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate int bauds[] = { 280Sstevel@tonic-gate 0, 50, 75, 110, 134, 150, 200, 300, 600, 290Sstevel@tonic-gate 1200, 1800, 2400, 4800, 9600, 19200, 38400, 300Sstevel@tonic-gate 57600, 76800, 115200, 153600, 230400, 307200, 460800, -1 310Sstevel@tonic-gate }; 320Sstevel@tonic-gate 33549Smuffin extern void tipout(void) __NORETURN; 34549Smuffin extern void timeout(void); 35549Smuffin extern esctable_t etable[]; 36549Smuffin extern unsigned char evenpartab[]; 37549Smuffin 38549Smuffin void intprompt(void); 39549Smuffin void deadkid(void); 40549Smuffin void cleanup(void); 41549Smuffin void tipin(void) __NORETURN; 42549Smuffin unsigned char escape(void); 43549Smuffin char *sname(char *); 44549Smuffin char PNbuf[256]; /* This limits the size of a number */ 450Sstevel@tonic-gate int noparity = 0; 460Sstevel@tonic-gate 47549Smuffin int 48549Smuffin main(int argc, char *argv[]) 490Sstevel@tonic-gate { 500Sstevel@tonic-gate char *system = NOSTR; 51549Smuffin int i; 52549Smuffin char *p; 53*2590Ssn199410 char sbuf[15]; 540Sstevel@tonic-gate 550Sstevel@tonic-gate gid = getgid(); 560Sstevel@tonic-gate egid = getegid(); 570Sstevel@tonic-gate uid = getuid(); 580Sstevel@tonic-gate euid = geteuid(); 590Sstevel@tonic-gate if (equal(sname(argv[0]), "cu")) { 600Sstevel@tonic-gate cumode = 1; 610Sstevel@tonic-gate cumain(argc, argv); 620Sstevel@tonic-gate goto cucommon; 630Sstevel@tonic-gate } 640Sstevel@tonic-gate 650Sstevel@tonic-gate if (argc > 4) { 66549Smuffin (void) fprintf(stderr, 67549Smuffin "usage: tip [-v] [-speed] [system-name]\n"); 68549Smuffin return (1); 690Sstevel@tonic-gate } 700Sstevel@tonic-gate if (!isatty(0)) { 71549Smuffin (void) fprintf(stderr, "tip: must be interactive\n"); 72549Smuffin return (1); 730Sstevel@tonic-gate } 740Sstevel@tonic-gate 750Sstevel@tonic-gate for (; argc > 1; argv++, argc--) { 760Sstevel@tonic-gate if (argv[1][0] != '-') 770Sstevel@tonic-gate system = argv[1]; 780Sstevel@tonic-gate else switch (argv[1][1]) { 790Sstevel@tonic-gate 800Sstevel@tonic-gate case 'v': 810Sstevel@tonic-gate vflag++; 820Sstevel@tonic-gate break; 830Sstevel@tonic-gate 840Sstevel@tonic-gate case '0': case '1': case '2': case '3': case '4': 850Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9': 860Sstevel@tonic-gate BR = atoi(&argv[1][1]); 870Sstevel@tonic-gate break; 880Sstevel@tonic-gate 890Sstevel@tonic-gate default: 90549Smuffin (void) fprintf(stderr, "tip: %s, unknown option\n", 91549Smuffin argv[1]); 920Sstevel@tonic-gate break; 930Sstevel@tonic-gate } 940Sstevel@tonic-gate } 950Sstevel@tonic-gate 960Sstevel@tonic-gate (void) setlocale(LC_CTYPE, ""); 970Sstevel@tonic-gate 980Sstevel@tonic-gate if (system == NOSTR) 990Sstevel@tonic-gate goto notnumber; 1000Sstevel@tonic-gate for (p = system; *p; p++) 1010Sstevel@tonic-gate if (isalpha(*p)) 1020Sstevel@tonic-gate goto notnumber; 1030Sstevel@tonic-gate /* 1040Sstevel@tonic-gate * System name is really a phone number... 1050Sstevel@tonic-gate * Copy the number then stomp on the original (in case the number 1060Sstevel@tonic-gate * is private, we don't want 'ps' or 'w' to find it). 1070Sstevel@tonic-gate */ 1080Sstevel@tonic-gate if (strlen(system) > sizeof (PNbuf) - 1) { 109549Smuffin (void) fprintf(stderr, 110549Smuffin "tip: phone number too long (max = %d bytes)\n", 1110Sstevel@tonic-gate sizeof (PNbuf) - 1); 112549Smuffin return (1); 1130Sstevel@tonic-gate } 114549Smuffin (void) strncpy(PNbuf, system, sizeof (PNbuf) - 1); 1150Sstevel@tonic-gate for (p = system; *p; p++) 1160Sstevel@tonic-gate *p = '\0'; 1170Sstevel@tonic-gate PN = PNbuf; 118*2590Ssn199410 (void) snprintf(sbuf, sizeof (sbuf), "tip%d", BR); 1190Sstevel@tonic-gate system = sbuf; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate notnumber: 122549Smuffin (void) signal(SIGINT, (sig_handler_t)cleanup); 123549Smuffin (void) signal(SIGQUIT, (sig_handler_t)cleanup); 124549Smuffin (void) signal(SIGHUP, (sig_handler_t)cleanup); 125549Smuffin (void) signal(SIGTERM, (sig_handler_t)cleanup); 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate if ((i = hunt(system)) == 0) { 128549Smuffin (void) printf("all ports busy\n"); 129549Smuffin return (3); 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate if (i == -1) { 132549Smuffin (void) printf("link down\n"); 1330Sstevel@tonic-gate delock(uucplock); 134549Smuffin return (3); 1350Sstevel@tonic-gate } 1360Sstevel@tonic-gate setbuf(stdout, NULL); 1370Sstevel@tonic-gate loginit(); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * Now that we have the logfile and the ACU open 1410Sstevel@tonic-gate * return to the real uid and gid. These things will 1420Sstevel@tonic-gate * be closed on exit. The saved-setuid uid and gid 1430Sstevel@tonic-gate * allows us to get the original setuid permissions back 1440Sstevel@tonic-gate * for removing the uucp lock. 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate userperm(); 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate /* 1490Sstevel@tonic-gate * Kludge, there's no easy way to get the initialization 1500Sstevel@tonic-gate * in the right order, so force it here. 1510Sstevel@tonic-gate * Do the open here, before we change back to real uid. 1520Sstevel@tonic-gate * We will check whether the open succeeded later, when 1530Sstevel@tonic-gate * (and if) we actually go to use the file. 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate if ((PH = getenv("PHONES")) == NOSTR) { 1560Sstevel@tonic-gate myperm(); 1570Sstevel@tonic-gate PH = "/etc/phones"; 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate phfd = fopen(PH, "r"); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate userperm(); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate vinit(); /* init variables */ 1640Sstevel@tonic-gate setparity("none"); /* set the parity table */ 1650Sstevel@tonic-gate if ((i = speed(number(value(BAUDRATE)))) == NULL) { 166549Smuffin (void) printf("tip: bad baud rate %d\n", 167549Smuffin number(value(BAUDRATE))); 1680Sstevel@tonic-gate myperm(); 1690Sstevel@tonic-gate delock(uucplock); 170549Smuffin return (3); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * Hardwired connections require the 1760Sstevel@tonic-gate * line speed set before they make any transmissions 1770Sstevel@tonic-gate * (this is particularly true of things like a DF03-AC) 1780Sstevel@tonic-gate */ 1790Sstevel@tonic-gate if (HW) 1800Sstevel@tonic-gate ttysetup(i); 1810Sstevel@tonic-gate if (p = connect()) { 182549Smuffin (void) printf("\07%s\n[EOT]\n", p); 1830Sstevel@tonic-gate myperm(); 1840Sstevel@tonic-gate delock(uucplock); 185549Smuffin return (1); 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * Always setup the tty again here in case hardware flow 1900Sstevel@tonic-gate * control was selected, which can only be set after the 1910Sstevel@tonic-gate * connection is made, or in case this is not a hardwired 1920Sstevel@tonic-gate * modem (rare these days) that likewise can only be setup 1930Sstevel@tonic-gate * after the connection is made. 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate ttysetup(i); 1960Sstevel@tonic-gate cucommon: 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * From here down the code is shared with 1990Sstevel@tonic-gate * the "cu" version of tip. 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate 202549Smuffin (void) ioctl(0, TCGETS, (char *)&defarg); 2030Sstevel@tonic-gate arg = defarg; 2040Sstevel@tonic-gate /* turn off input processing */ 2050Sstevel@tonic-gate arg.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN); 2060Sstevel@tonic-gate arg.c_cc[VMIN] = 1; 2070Sstevel@tonic-gate arg.c_cc[VTIME] = 0; 2080Sstevel@tonic-gate arg.c_iflag &= ~(INPCK|IXON|IXOFF|ICRNL); 2090Sstevel@tonic-gate arg.c_oflag = 0; /* turn off all output processing */ 2100Sstevel@tonic-gate /* handle tandem mode in case was set in remote file */ 2110Sstevel@tonic-gate if (boolean(value(TAND))) 2120Sstevel@tonic-gate tandem("on"); 2130Sstevel@tonic-gate else 2140Sstevel@tonic-gate tandem("off"); 2150Sstevel@tonic-gate raw(); 2160Sstevel@tonic-gate 217549Smuffin (void) pipe(fildes); (void) pipe(repdes); 218549Smuffin (void) signal(SIGALRM, (sig_handler_t)timeout); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* 2210Sstevel@tonic-gate * Everything's set up now: 2220Sstevel@tonic-gate * connection established (hardwired or dialup) 2230Sstevel@tonic-gate * line conditioned (baud rate, mode, etc.) 2240Sstevel@tonic-gate * internal data structures (variables) 2250Sstevel@tonic-gate * so, fork one process for local side and one for remote. 2260Sstevel@tonic-gate */ 2270Sstevel@tonic-gate if (CM != NOSTR) { 228549Smuffin (void) sleep(2); /* let line settle */ 229549Smuffin parwrite(FD, (unsigned char *)CM, strlen(CM)); 2300Sstevel@tonic-gate } 231549Smuffin (void) printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 232549Smuffin (void) signal(SIGCHLD, (sig_handler_t)deadkid); 2330Sstevel@tonic-gate if (pid = fork()) 2340Sstevel@tonic-gate tipin(); 2350Sstevel@tonic-gate else 2360Sstevel@tonic-gate tipout(); 2370Sstevel@tonic-gate /*NOTREACHED*/ 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate void 241549Smuffin deadkid(void) 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate if (pid >= 0 && waitpid(pid, NULL, WNOHANG) == pid) 245549Smuffin tip_abort("Connection Closed"); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate void 249549Smuffin cleanup(void) 2500Sstevel@tonic-gate { 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (uid != getuid()) { 2530Sstevel@tonic-gate myperm(); 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate delock(uucplock); 2560Sstevel@tonic-gate exit(0); 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate /* 2600Sstevel@tonic-gate * put the controlling keyboard into raw mode 2610Sstevel@tonic-gate */ 262549Smuffin void 263549Smuffin raw(void) 2640Sstevel@tonic-gate { 2650Sstevel@tonic-gate 266549Smuffin (void) ioctl(0, TCSETSF, (char *)&arg); 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* 2710Sstevel@tonic-gate * return keyboard to normal mode 2720Sstevel@tonic-gate */ 273549Smuffin void 274549Smuffin unraw(void) 2750Sstevel@tonic-gate { 2760Sstevel@tonic-gate 277549Smuffin (void) ioctl(0, TCSETSF, (char *)&defarg); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* 2810Sstevel@tonic-gate * switch to using invoking user's permissions 2820Sstevel@tonic-gate */ 283549Smuffin void 284549Smuffin userperm(void) 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate 287549Smuffin (void) setegid(gid); 288549Smuffin (void) seteuid(uid); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /* 2920Sstevel@tonic-gate * switch to using my special (setuid) permissions 2930Sstevel@tonic-gate */ 294549Smuffin void 295549Smuffin myperm(void) 2960Sstevel@tonic-gate { 2970Sstevel@tonic-gate 298549Smuffin (void) setegid(egid); 299549Smuffin (void) seteuid(euid); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate static sigjmp_buf promptbuf; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate /* 3050Sstevel@tonic-gate * Print string ``s'', then read a string 3060Sstevel@tonic-gate * in from the terminal. Handles signals & allows use of 3070Sstevel@tonic-gate * normal erase and kill characters. 3080Sstevel@tonic-gate */ 309549Smuffin int 310549Smuffin prompt(char *s, char *p, size_t len) 3110Sstevel@tonic-gate { 312549Smuffin char *b = p; 313549Smuffin int c; 314549Smuffin sig_handler_t ointr, oquit; 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate stoprompt = 0; 317549Smuffin ointr = signal(SIGINT, (sig_handler_t)intprompt); 3180Sstevel@tonic-gate oquit = signal(SIGQUIT, SIG_IGN); 3190Sstevel@tonic-gate unraw(); 320549Smuffin (void) printf("%s", s); 3210Sstevel@tonic-gate if (sigsetjmp(promptbuf, 1) == 0) 3220Sstevel@tonic-gate while (p < b + len - 1 && 3230Sstevel@tonic-gate ((c = getchar()) != EOF) && (c != '\n')) 3240Sstevel@tonic-gate *p++ = c; 3250Sstevel@tonic-gate *p = '\0'; 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate raw(); 328549Smuffin (void) signal(SIGINT, ointr); 329549Smuffin (void) signal(SIGQUIT, oquit); 3300Sstevel@tonic-gate return (stoprompt || p == b); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* 3340Sstevel@tonic-gate * Interrupt service routine during prompting 3350Sstevel@tonic-gate */ 3360Sstevel@tonic-gate void 337549Smuffin intprompt(void) 3380Sstevel@tonic-gate { 3390Sstevel@tonic-gate 340549Smuffin (void) signal(SIGINT, SIG_IGN); 341549Smuffin (void) signal(SIGQUIT, SIG_IGN); 3420Sstevel@tonic-gate stoprompt = 1; 343549Smuffin (void) printf("\r\n"); 3440Sstevel@tonic-gate siglongjmp(promptbuf, 1); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * ****TIPIN TIPIN**** 3490Sstevel@tonic-gate */ 350549Smuffin void 351549Smuffin tipin(void) 3520Sstevel@tonic-gate { 3530Sstevel@tonic-gate unsigned char gch, c; 3540Sstevel@tonic-gate int bol = 1; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /* 3570Sstevel@tonic-gate * Kinda klugey here... 3580Sstevel@tonic-gate * check for scripting being turned on from the .tiprc file, 3590Sstevel@tonic-gate * but be careful about just using setscript(), as we may 3600Sstevel@tonic-gate * send a SIGEMT before tipout has a chance to set up catching 3610Sstevel@tonic-gate * it; so wait a second, then setscript() 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate if (boolean(value(SCRIPT))) { 364549Smuffin (void) sleep(1); 3650Sstevel@tonic-gate setscript(); 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate for (;;) { 3690Sstevel@tonic-gate gch = getchar()&0377; 3700Sstevel@tonic-gate if ((gch == character(value(ESCAPE))) && bol) { 3710Sstevel@tonic-gate if (!(gch = escape())) 3720Sstevel@tonic-gate continue; 3730Sstevel@tonic-gate } else if (!cumode && gch == character(value(RAISECHAR))) { 3740Sstevel@tonic-gate boolean(value(RAISE)) = !boolean(value(RAISE)); 3750Sstevel@tonic-gate continue; 3760Sstevel@tonic-gate } else if (gch == '\r') { 3770Sstevel@tonic-gate bol = 1; 3780Sstevel@tonic-gate parwrite(FD, &gch, 1); 3790Sstevel@tonic-gate if (boolean(value(HALFDUPLEX))) 380549Smuffin (void) printf("\r\n"); 3810Sstevel@tonic-gate continue; 3820Sstevel@tonic-gate } else if (!cumode && gch == character(value(FORCE))) 3830Sstevel@tonic-gate gch = getchar()&0377; 3840Sstevel@tonic-gate bol = any(gch, value(EOL)); 3850Sstevel@tonic-gate if (boolean(value(RAISE)) && islower(gch)) 3860Sstevel@tonic-gate gch = toupper(gch); 3870Sstevel@tonic-gate c = gch; 3880Sstevel@tonic-gate parwrite(FD, &gch, 1); 3890Sstevel@tonic-gate if (boolean(value(HALFDUPLEX))) 390549Smuffin (void) putchar(c); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate /* 3950Sstevel@tonic-gate * Escape handler -- 3960Sstevel@tonic-gate * called on recognition of ``escapec'' at the beginning of a line 3970Sstevel@tonic-gate */ 398549Smuffin unsigned char 399549Smuffin escape(void) 4000Sstevel@tonic-gate { 401549Smuffin unsigned char gch; 402549Smuffin esctable_t *p; 4030Sstevel@tonic-gate char c = character(value(ESCAPE)); 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate gch = (getchar()&0377); 4060Sstevel@tonic-gate for (p = etable; p->e_char; p++) 4070Sstevel@tonic-gate if (p->e_char == gch) { 4080Sstevel@tonic-gate if ((p->e_flags&PRIV) && uid) 4090Sstevel@tonic-gate continue; 410549Smuffin (void) printf("%s", ctrl(c)); 4110Sstevel@tonic-gate (*p->e_func)(gch); 4120Sstevel@tonic-gate return (0); 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate /* ESCAPE ESCAPE forces ESCAPE */ 4150Sstevel@tonic-gate if (c != gch) 416549Smuffin parwrite(FD, (unsigned char *)&c, 1); 4170Sstevel@tonic-gate return (gch); 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate 420549Smuffin int 421549Smuffin speed(int n) 4220Sstevel@tonic-gate { 423549Smuffin int *p; 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate for (p = bauds; *p != -1; p++) 4260Sstevel@tonic-gate if (*p == n) 4270Sstevel@tonic-gate return (p - bauds); 428549Smuffin return (0); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 431549Smuffin int 432549Smuffin any(char c, char *p) 4330Sstevel@tonic-gate { 4340Sstevel@tonic-gate while (p && *p) 4350Sstevel@tonic-gate if (*p++ == c) 4360Sstevel@tonic-gate return (1); 4370Sstevel@tonic-gate return (0); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate char * 441549Smuffin interp(char *s) 4420Sstevel@tonic-gate { 4430Sstevel@tonic-gate static char buf[256]; 444549Smuffin char *p = buf, c, *q; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate while (c = *s++) { 4470Sstevel@tonic-gate for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 4480Sstevel@tonic-gate if (*q++ == c) { 4490Sstevel@tonic-gate *p++ = '\\'; *p++ = *q; 4500Sstevel@tonic-gate goto next; 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate if (c < 040) { 4530Sstevel@tonic-gate *p++ = '^'; *p++ = c + 'A'-1; 4540Sstevel@tonic-gate } else if (c == 0177) { 4550Sstevel@tonic-gate *p++ = '^'; *p++ = '?'; 4560Sstevel@tonic-gate } else 4570Sstevel@tonic-gate *p++ = c; 4580Sstevel@tonic-gate next: 4590Sstevel@tonic-gate ; 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate *p = '\0'; 4620Sstevel@tonic-gate return (buf); 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate char * 466549Smuffin ctrl(char c) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate static char s[3]; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate if (c < 040 || c == 0177) { 4710Sstevel@tonic-gate s[0] = '^'; 4720Sstevel@tonic-gate s[1] = c == 0177 ? '?' : c+'A'-1; 4730Sstevel@tonic-gate s[2] = '\0'; 4740Sstevel@tonic-gate } else { 4750Sstevel@tonic-gate s[0] = c; 4760Sstevel@tonic-gate s[1] = '\0'; 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate return (s); 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * Help command 4830Sstevel@tonic-gate */ 484549Smuffin void 485549Smuffin help(int c) 4860Sstevel@tonic-gate { 487549Smuffin esctable_t *p; 4880Sstevel@tonic-gate 489549Smuffin (void) printf("%c\r\n", c); 4900Sstevel@tonic-gate for (p = etable; p->e_char; p++) { 4910Sstevel@tonic-gate if ((p->e_flags&PRIV) && uid) 4920Sstevel@tonic-gate continue; 493549Smuffin (void) printf("%2s", ctrl(character(value(ESCAPE)))); 494549Smuffin (void) printf("%-2s %c %s\r\n", ctrl(p->e_char), 495549Smuffin p->e_flags&EXP ? '*': ' ', p->e_help); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate /* 5000Sstevel@tonic-gate * Set up the "remote" tty's state 5010Sstevel@tonic-gate */ 502549Smuffin void 503549Smuffin ttysetup(int speed) 5040Sstevel@tonic-gate { 5050Sstevel@tonic-gate struct termios buf; 5060Sstevel@tonic-gate char *loc; 5070Sstevel@tonic-gate 508549Smuffin (void) ioctl(FD, TCGETS, (char *)&buf); 5090Sstevel@tonic-gate buf.c_cflag &= (CREAD|HUPCL|CLOCAL|CRTSCTS|CRTSXOFF); 5100Sstevel@tonic-gate buf.c_cflag |= CS8; 511549Smuffin (void) cfsetospeed(&buf, speed); 5120Sstevel@tonic-gate if (boolean(value(HARDWAREFLOW))) { 5130Sstevel@tonic-gate int i = TIOCM_CAR; 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* 5160Sstevel@tonic-gate * Only set hardware flow control if carrier is up, 5170Sstevel@tonic-gate * because some devices require both CD and RTS to 5180Sstevel@tonic-gate * be up before sending. 5190Sstevel@tonic-gate */ 520549Smuffin (void) ioctl(FD, TIOCMGET, &i); 5210Sstevel@tonic-gate if (i & TIOCM_CAR) 5220Sstevel@tonic-gate buf.c_cflag |= (CRTSCTS|CRTSXOFF); 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate /* 5260Sstevel@tonic-gate * Careful to only penalize the 8-bit users here on the 5270Sstevel@tonic-gate * incoming tty port. The default 7-bit users will 5280Sstevel@tonic-gate * still get the parity bit from the other side's login 5290Sstevel@tonic-gate * process (which happens to be the default for sun tip 5300Sstevel@tonic-gate * configurations). 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate loc = setlocale(LC_CTYPE, NULL); 5330Sstevel@tonic-gate if (noparity && loc != 0 && strcmp(loc, "C") != 0) 5340Sstevel@tonic-gate buf.c_iflag = 0; 5350Sstevel@tonic-gate else 5360Sstevel@tonic-gate buf.c_iflag = ISTRIP; 5370Sstevel@tonic-gate buf.c_oflag = 0; 5380Sstevel@tonic-gate buf.c_lflag = 0; 5390Sstevel@tonic-gate buf.c_cc[VMIN] = 1; 5400Sstevel@tonic-gate buf.c_cc[VTIME] = 0; 541549Smuffin (void) ioctl(FD, TCSETSF, (char *)&buf); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate /* 5450Sstevel@tonic-gate * Return "simple" name from a file name, 5460Sstevel@tonic-gate * strip leading directories. 5470Sstevel@tonic-gate */ 5480Sstevel@tonic-gate char * 549549Smuffin sname(char *s) 5500Sstevel@tonic-gate { 551549Smuffin char *p = s; 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate while (*s) 5540Sstevel@tonic-gate if (*s++ == '/') 5550Sstevel@tonic-gate p = s; 5560Sstevel@tonic-gate return (p); 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate static char partab[0400]; 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate /* 5620Sstevel@tonic-gate * Do a write to the remote machine with the correct parity. 5630Sstevel@tonic-gate * We are doing 8 bit wide output, so we just generate a character 5640Sstevel@tonic-gate * with the right parity and output it. 5650Sstevel@tonic-gate */ 566549Smuffin void 567549Smuffin parwrite(int fd, unsigned char *buf, int n) 5680Sstevel@tonic-gate { 569549Smuffin int i; 570549Smuffin unsigned char *bp; 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate bp = buf; 5730Sstevel@tonic-gate for (i = 0; i < n; i++) { 5740Sstevel@tonic-gate *bp = partab[(*bp)&0377]; 5750Sstevel@tonic-gate bp++; 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate if (write(fd, buf, n) < 0) { 5780Sstevel@tonic-gate if (errno == EIO || errno == ENXIO) 579549Smuffin tip_abort("Lost carrier."); 5800Sstevel@tonic-gate /* this is questionable */ 5810Sstevel@tonic-gate perror("write"); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate /* 5860Sstevel@tonic-gate * Build a parity table with appropriate high-order bit. 5870Sstevel@tonic-gate */ 588549Smuffin void 589549Smuffin setparity(char *defparity) 5900Sstevel@tonic-gate { 591549Smuffin int i; 5920Sstevel@tonic-gate char *parity; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate if (value(PARITY) == NOSTR) 5950Sstevel@tonic-gate value(PARITY) = defparity; 5960Sstevel@tonic-gate parity = value(PARITY); 5970Sstevel@tonic-gate for (i = 0; i < 0400; i++) 5980Sstevel@tonic-gate partab[i] = evenpartab[i]; 599549Smuffin if (equal(parity, "even")) { 600549Smuffin /* EMPTY */ 601549Smuffin } else if (equal(parity, "odd")) { 6020Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6030Sstevel@tonic-gate partab[i] ^= 0200; /* reverse bit 7 */ 6040Sstevel@tonic-gate } else if (equal(parity, "none")) { 6050Sstevel@tonic-gate /* Do nothing so we can pass thru 8-bit chars */ 6060Sstevel@tonic-gate noparity = 1; 6070Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6080Sstevel@tonic-gate partab[i] = i; 6090Sstevel@tonic-gate } else if (equal(parity, "zero")) { 6100Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6110Sstevel@tonic-gate partab[i] &= ~0200; /* turn off bit 7 */ 6120Sstevel@tonic-gate } else if (equal(parity, "one")) { 6130Sstevel@tonic-gate for (i = 0; i < 0400; i++) 6140Sstevel@tonic-gate partab[i] |= 0200; /* turn on bit 7 */ 6150Sstevel@tonic-gate } else { 616549Smuffin (void) fprintf(stderr, "%s: unknown parity value\n", PA); 617549Smuffin (void) fflush(stderr); 6180Sstevel@tonic-gate } 6190Sstevel@tonic-gate } 620