1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate /* 6*0Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 7*0Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 8*0Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 9*0Sstevel@tonic-gate */ 10*0Sstevel@tonic-gate 11*0Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* from UCB 5.4 4/3/86 */ 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gate /* 14*0Sstevel@tonic-gate * tip - UNIX link to other systems 15*0Sstevel@tonic-gate * tip [-v] [-speed] system-name 16*0Sstevel@tonic-gate * or 17*0Sstevel@tonic-gate * cu phone-number [-s speed] [-l line] [-a acu] 18*0Sstevel@tonic-gate */ 19*0Sstevel@tonic-gate #include "tip.h" 20*0Sstevel@tonic-gate #include <sys/wait.h> 21*0Sstevel@tonic-gate #include <locale.h> 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gate /* 24*0Sstevel@tonic-gate * Baud rate mapping table 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate int bauds[] = { 27*0Sstevel@tonic-gate 0, 50, 75, 110, 134, 150, 200, 300, 600, 28*0Sstevel@tonic-gate 1200, 1800, 2400, 4800, 9600, 19200, 38400, 29*0Sstevel@tonic-gate 57600, 76800, 115200, 153600, 230400, 307200, 460800, -1 30*0Sstevel@tonic-gate }; 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate void intprompt(); 33*0Sstevel@tonic-gate void timeout(); 34*0Sstevel@tonic-gate void deadkid(); 35*0Sstevel@tonic-gate void cleanup(); 36*0Sstevel@tonic-gate char *sname(); 37*0Sstevel@tonic-gate char PNbuf[256]; /* This limits the size of a number */ 38*0Sstevel@tonic-gate int noparity = 0; 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate main(argc, argv) 42*0Sstevel@tonic-gate char *argv[]; 43*0Sstevel@tonic-gate { 44*0Sstevel@tonic-gate char *system = NOSTR; 45*0Sstevel@tonic-gate register int i; 46*0Sstevel@tonic-gate register char *p; 47*0Sstevel@tonic-gate char sbuf[12]; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate gid = getgid(); 50*0Sstevel@tonic-gate egid = getegid(); 51*0Sstevel@tonic-gate uid = getuid(); 52*0Sstevel@tonic-gate euid = geteuid(); 53*0Sstevel@tonic-gate if (equal(sname(argv[0]), "cu")) { 54*0Sstevel@tonic-gate cumode = 1; 55*0Sstevel@tonic-gate cumain(argc, argv); 56*0Sstevel@tonic-gate goto cucommon; 57*0Sstevel@tonic-gate } 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate if (argc > 4) { 60*0Sstevel@tonic-gate fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 61*0Sstevel@tonic-gate exit(1); 62*0Sstevel@tonic-gate } 63*0Sstevel@tonic-gate if (!isatty(0)) { 64*0Sstevel@tonic-gate fprintf(stderr, "tip: must be interactive\n"); 65*0Sstevel@tonic-gate exit(1); 66*0Sstevel@tonic-gate } 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate for (; argc > 1; argv++, argc--) { 69*0Sstevel@tonic-gate if (argv[1][0] != '-') 70*0Sstevel@tonic-gate system = argv[1]; 71*0Sstevel@tonic-gate else switch (argv[1][1]) { 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate case 'v': 74*0Sstevel@tonic-gate vflag++; 75*0Sstevel@tonic-gate break; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate case '0': case '1': case '2': case '3': case '4': 78*0Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9': 79*0Sstevel@tonic-gate BR = atoi(&argv[1][1]); 80*0Sstevel@tonic-gate break; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate default: 83*0Sstevel@tonic-gate fprintf(stderr, "tip: %s, unknown option\n", argv[1]); 84*0Sstevel@tonic-gate break; 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate (void) setlocale(LC_CTYPE, ""); 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate if (system == NOSTR) 91*0Sstevel@tonic-gate goto notnumber; 92*0Sstevel@tonic-gate for (p = system; *p; p++) 93*0Sstevel@tonic-gate if (isalpha(*p)) 94*0Sstevel@tonic-gate goto notnumber; 95*0Sstevel@tonic-gate /* 96*0Sstevel@tonic-gate * System name is really a phone number... 97*0Sstevel@tonic-gate * Copy the number then stomp on the original (in case the number 98*0Sstevel@tonic-gate * is private, we don't want 'ps' or 'w' to find it). 99*0Sstevel@tonic-gate */ 100*0Sstevel@tonic-gate if (strlen(system) > sizeof (PNbuf) - 1) { 101*0Sstevel@tonic-gate fprintf(stderr, "tip: phone number too long (max = %d bytes)\n", 102*0Sstevel@tonic-gate sizeof (PNbuf) - 1); 103*0Sstevel@tonic-gate exit(1); 104*0Sstevel@tonic-gate } 105*0Sstevel@tonic-gate strncpy(PNbuf, system, sizeof (PNbuf) - 1); 106*0Sstevel@tonic-gate for (p = system; *p; p++) 107*0Sstevel@tonic-gate *p = '\0'; 108*0Sstevel@tonic-gate PN = PNbuf; 109*0Sstevel@tonic-gate sprintf(sbuf, "tip%d", BR); 110*0Sstevel@tonic-gate system = sbuf; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate notnumber: 113*0Sstevel@tonic-gate signal(SIGINT, cleanup); 114*0Sstevel@tonic-gate signal(SIGQUIT, cleanup); 115*0Sstevel@tonic-gate signal(SIGHUP, cleanup); 116*0Sstevel@tonic-gate signal(SIGTERM, cleanup); 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate if ((i = hunt(system)) == 0) { 119*0Sstevel@tonic-gate printf("all ports busy\n"); 120*0Sstevel@tonic-gate exit(3); 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate if (i == -1) { 123*0Sstevel@tonic-gate printf("link down\n"); 124*0Sstevel@tonic-gate delock(uucplock); 125*0Sstevel@tonic-gate exit(3); 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate setbuf(stdout, NULL); 128*0Sstevel@tonic-gate loginit(); 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate /* 131*0Sstevel@tonic-gate * Now that we have the logfile and the ACU open 132*0Sstevel@tonic-gate * return to the real uid and gid. These things will 133*0Sstevel@tonic-gate * be closed on exit. The saved-setuid uid and gid 134*0Sstevel@tonic-gate * allows us to get the original setuid permissions back 135*0Sstevel@tonic-gate * for removing the uucp lock. 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate userperm(); 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate /* 140*0Sstevel@tonic-gate * Kludge, there's no easy way to get the initialization 141*0Sstevel@tonic-gate * in the right order, so force it here. 142*0Sstevel@tonic-gate * Do the open here, before we change back to real uid. 143*0Sstevel@tonic-gate * We will check whether the open succeeded later, when 144*0Sstevel@tonic-gate * (and if) we actually go to use the file. 145*0Sstevel@tonic-gate */ 146*0Sstevel@tonic-gate if ((PH = getenv("PHONES")) == NOSTR) { 147*0Sstevel@tonic-gate myperm(); 148*0Sstevel@tonic-gate PH = "/etc/phones"; 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate phfd = fopen(PH, "r"); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate userperm(); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate vinit(); /* init variables */ 155*0Sstevel@tonic-gate setparity("none"); /* set the parity table */ 156*0Sstevel@tonic-gate if ((i = speed(number(value(BAUDRATE)))) == NULL) { 157*0Sstevel@tonic-gate printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 158*0Sstevel@tonic-gate myperm(); 159*0Sstevel@tonic-gate delock(uucplock); 160*0Sstevel@tonic-gate exit(3); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * Hardwired connections require the 166*0Sstevel@tonic-gate * line speed set before they make any transmissions 167*0Sstevel@tonic-gate * (this is particularly true of things like a DF03-AC) 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate if (HW) 170*0Sstevel@tonic-gate ttysetup(i); 171*0Sstevel@tonic-gate if (p = connect()) { 172*0Sstevel@tonic-gate printf("\07%s\n[EOT]\n", p); 173*0Sstevel@tonic-gate myperm(); 174*0Sstevel@tonic-gate delock(uucplock); 175*0Sstevel@tonic-gate exit(1); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate /* 179*0Sstevel@tonic-gate * Always setup the tty again here in case hardware flow 180*0Sstevel@tonic-gate * control was selected, which can only be set after the 181*0Sstevel@tonic-gate * connection is made, or in case this is not a hardwired 182*0Sstevel@tonic-gate * modem (rare these days) that likewise can only be setup 183*0Sstevel@tonic-gate * after the connection is made. 184*0Sstevel@tonic-gate */ 185*0Sstevel@tonic-gate ttysetup(i); 186*0Sstevel@tonic-gate cucommon: 187*0Sstevel@tonic-gate /* 188*0Sstevel@tonic-gate * From here down the code is shared with 189*0Sstevel@tonic-gate * the "cu" version of tip. 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate ioctl(0, TCGETS, (char *)&defarg); 193*0Sstevel@tonic-gate arg = defarg; 194*0Sstevel@tonic-gate /* turn off input processing */ 195*0Sstevel@tonic-gate arg.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN); 196*0Sstevel@tonic-gate arg.c_cc[VMIN] = 1; 197*0Sstevel@tonic-gate arg.c_cc[VTIME] = 0; 198*0Sstevel@tonic-gate arg.c_iflag &= ~(INPCK|IXON|IXOFF|ICRNL); 199*0Sstevel@tonic-gate arg.c_oflag = 0; /* turn off all output processing */ 200*0Sstevel@tonic-gate /* handle tandem mode in case was set in remote file */ 201*0Sstevel@tonic-gate if (boolean(value(TAND))) 202*0Sstevel@tonic-gate tandem("on"); 203*0Sstevel@tonic-gate else 204*0Sstevel@tonic-gate tandem("off"); 205*0Sstevel@tonic-gate raw(); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate pipe(fildes); pipe(repdes); 208*0Sstevel@tonic-gate signal(SIGALRM, timeout); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /* 211*0Sstevel@tonic-gate * Everything's set up now: 212*0Sstevel@tonic-gate * connection established (hardwired or dialup) 213*0Sstevel@tonic-gate * line conditioned (baud rate, mode, etc.) 214*0Sstevel@tonic-gate * internal data structures (variables) 215*0Sstevel@tonic-gate * so, fork one process for local side and one for remote. 216*0Sstevel@tonic-gate */ 217*0Sstevel@tonic-gate if (CM != NOSTR) { 218*0Sstevel@tonic-gate sleep(2); /* let line settle */ 219*0Sstevel@tonic-gate parwrite(FD, CM, strlen(CM)); 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 222*0Sstevel@tonic-gate signal(SIGCHLD, deadkid); 223*0Sstevel@tonic-gate if (pid = fork()) 224*0Sstevel@tonic-gate tipin(); 225*0Sstevel@tonic-gate else 226*0Sstevel@tonic-gate tipout(); 227*0Sstevel@tonic-gate /*NOTREACHED*/ 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate void 231*0Sstevel@tonic-gate deadkid() 232*0Sstevel@tonic-gate { 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate if (pid >= 0 && waitpid(pid, NULL, WNOHANG) == pid) 235*0Sstevel@tonic-gate abort("Connection Closed"); 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate void 239*0Sstevel@tonic-gate cleanup() 240*0Sstevel@tonic-gate { 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (uid != getuid()) { 243*0Sstevel@tonic-gate myperm(); 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate delock(uucplock); 246*0Sstevel@tonic-gate exit(0); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* 250*0Sstevel@tonic-gate * put the controlling keyboard into raw mode 251*0Sstevel@tonic-gate */ 252*0Sstevel@tonic-gate raw() 253*0Sstevel@tonic-gate { 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate ioctl(0, TCSETSF, (char *)&arg); 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * return keyboard to normal mode 261*0Sstevel@tonic-gate */ 262*0Sstevel@tonic-gate unraw() 263*0Sstevel@tonic-gate { 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate ioctl(0, TCSETSF, (char *)&defarg); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * switch to using invoking user's permissions 270*0Sstevel@tonic-gate */ 271*0Sstevel@tonic-gate userperm() 272*0Sstevel@tonic-gate { 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate setegid(gid); 275*0Sstevel@tonic-gate seteuid(uid); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * switch to using my special (setuid) permissions 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate myperm() 282*0Sstevel@tonic-gate { 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate setegid(egid); 285*0Sstevel@tonic-gate seteuid(euid); 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate static sigjmp_buf promptbuf; 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate /* 291*0Sstevel@tonic-gate * Print string ``s'', then read a string 292*0Sstevel@tonic-gate * in from the terminal. Handles signals & allows use of 293*0Sstevel@tonic-gate * normal erase and kill characters. 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate prompt(s, p, len) 296*0Sstevel@tonic-gate char *s; 297*0Sstevel@tonic-gate register char *p; 298*0Sstevel@tonic-gate size_t len; 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate register char *b = p; 301*0Sstevel@tonic-gate register int c; 302*0Sstevel@tonic-gate void (*ointr)(), (*oquit)(); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate stoprompt = 0; 305*0Sstevel@tonic-gate ointr = signal(SIGINT, intprompt); 306*0Sstevel@tonic-gate oquit = signal(SIGQUIT, SIG_IGN); 307*0Sstevel@tonic-gate unraw(); 308*0Sstevel@tonic-gate printf("%s", s); 309*0Sstevel@tonic-gate if (sigsetjmp(promptbuf, 1) == 0) 310*0Sstevel@tonic-gate while (p < b + len - 1 && 311*0Sstevel@tonic-gate ((c = getchar()) != EOF) && (c != '\n')) 312*0Sstevel@tonic-gate *p++ = c; 313*0Sstevel@tonic-gate *p = '\0'; 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate raw(); 316*0Sstevel@tonic-gate signal(SIGINT, ointr); 317*0Sstevel@tonic-gate signal(SIGQUIT, oquit); 318*0Sstevel@tonic-gate return (stoprompt || p == b); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* 322*0Sstevel@tonic-gate * Interrupt service routine during prompting 323*0Sstevel@tonic-gate */ 324*0Sstevel@tonic-gate void 325*0Sstevel@tonic-gate intprompt() 326*0Sstevel@tonic-gate { 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate signal(SIGINT, SIG_IGN); 329*0Sstevel@tonic-gate signal(SIGQUIT, SIG_IGN); 330*0Sstevel@tonic-gate stoprompt = 1; 331*0Sstevel@tonic-gate printf("\r\n"); 332*0Sstevel@tonic-gate siglongjmp(promptbuf, 1); 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * ****TIPIN TIPIN**** 337*0Sstevel@tonic-gate */ 338*0Sstevel@tonic-gate tipin() 339*0Sstevel@tonic-gate { 340*0Sstevel@tonic-gate unsigned char gch, c; 341*0Sstevel@tonic-gate int bol = 1; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate /* 344*0Sstevel@tonic-gate * Kinda klugey here... 345*0Sstevel@tonic-gate * check for scripting being turned on from the .tiprc file, 346*0Sstevel@tonic-gate * but be careful about just using setscript(), as we may 347*0Sstevel@tonic-gate * send a SIGEMT before tipout has a chance to set up catching 348*0Sstevel@tonic-gate * it; so wait a second, then setscript() 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate if (boolean(value(SCRIPT))) { 351*0Sstevel@tonic-gate sleep(1); 352*0Sstevel@tonic-gate setscript(); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate for (;;) { 356*0Sstevel@tonic-gate gch = getchar()&0377; 357*0Sstevel@tonic-gate if ((gch == character(value(ESCAPE))) && bol) { 358*0Sstevel@tonic-gate if (!(gch = escape())) 359*0Sstevel@tonic-gate continue; 360*0Sstevel@tonic-gate } else if (!cumode && gch == character(value(RAISECHAR))) { 361*0Sstevel@tonic-gate boolean(value(RAISE)) = !boolean(value(RAISE)); 362*0Sstevel@tonic-gate continue; 363*0Sstevel@tonic-gate } else if (gch == '\r') { 364*0Sstevel@tonic-gate bol = 1; 365*0Sstevel@tonic-gate parwrite(FD, &gch, 1); 366*0Sstevel@tonic-gate if (boolean(value(HALFDUPLEX))) 367*0Sstevel@tonic-gate printf("\r\n"); 368*0Sstevel@tonic-gate continue; 369*0Sstevel@tonic-gate } else if (!cumode && gch == character(value(FORCE))) 370*0Sstevel@tonic-gate gch = getchar()&0377; 371*0Sstevel@tonic-gate bol = any(gch, value(EOL)); 372*0Sstevel@tonic-gate if (boolean(value(RAISE)) && islower(gch)) 373*0Sstevel@tonic-gate gch = toupper(gch); 374*0Sstevel@tonic-gate c = gch; 375*0Sstevel@tonic-gate parwrite(FD, &gch, 1); 376*0Sstevel@tonic-gate if (boolean(value(HALFDUPLEX))) 377*0Sstevel@tonic-gate putchar(c); 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate /* 382*0Sstevel@tonic-gate * Escape handler -- 383*0Sstevel@tonic-gate * called on recognition of ``escapec'' at the beginning of a line 384*0Sstevel@tonic-gate */ 385*0Sstevel@tonic-gate escape() 386*0Sstevel@tonic-gate { 387*0Sstevel@tonic-gate register unsigned char gch; 388*0Sstevel@tonic-gate register esctable_t *p; 389*0Sstevel@tonic-gate char c = character(value(ESCAPE)); 390*0Sstevel@tonic-gate extern esctable_t etable[]; 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate gch = (getchar()&0377); 393*0Sstevel@tonic-gate for (p = etable; p->e_char; p++) 394*0Sstevel@tonic-gate if (p->e_char == gch) { 395*0Sstevel@tonic-gate if ((p->e_flags&PRIV) && uid) 396*0Sstevel@tonic-gate continue; 397*0Sstevel@tonic-gate printf("%s", ctrl(c)); 398*0Sstevel@tonic-gate (*p->e_func)(gch); 399*0Sstevel@tonic-gate return (0); 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate /* ESCAPE ESCAPE forces ESCAPE */ 402*0Sstevel@tonic-gate if (c != gch) 403*0Sstevel@tonic-gate parwrite(FD, &c, 1); 404*0Sstevel@tonic-gate return (gch); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate speed(n) 408*0Sstevel@tonic-gate int n; 409*0Sstevel@tonic-gate { 410*0Sstevel@tonic-gate register int *p; 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate for (p = bauds; *p != -1; p++) 413*0Sstevel@tonic-gate if (*p == n) 414*0Sstevel@tonic-gate return (p - bauds); 415*0Sstevel@tonic-gate return (NULL); 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate any(c, p) 419*0Sstevel@tonic-gate register char c, *p; 420*0Sstevel@tonic-gate { 421*0Sstevel@tonic-gate while (p && *p) 422*0Sstevel@tonic-gate if (*p++ == c) 423*0Sstevel@tonic-gate return (1); 424*0Sstevel@tonic-gate return (0); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate char * 428*0Sstevel@tonic-gate interp(s) 429*0Sstevel@tonic-gate register char *s; 430*0Sstevel@tonic-gate { 431*0Sstevel@tonic-gate static char buf[256]; 432*0Sstevel@tonic-gate register char *p = buf, c, *q; 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate while (c = *s++) { 435*0Sstevel@tonic-gate for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 436*0Sstevel@tonic-gate if (*q++ == c) { 437*0Sstevel@tonic-gate *p++ = '\\'; *p++ = *q; 438*0Sstevel@tonic-gate goto next; 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate if (c < 040) { 441*0Sstevel@tonic-gate *p++ = '^'; *p++ = c + 'A'-1; 442*0Sstevel@tonic-gate } else if (c == 0177) { 443*0Sstevel@tonic-gate *p++ = '^'; *p++ = '?'; 444*0Sstevel@tonic-gate } else 445*0Sstevel@tonic-gate *p++ = c; 446*0Sstevel@tonic-gate next: 447*0Sstevel@tonic-gate ; 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate *p = '\0'; 450*0Sstevel@tonic-gate return (buf); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate char * 454*0Sstevel@tonic-gate ctrl(c) 455*0Sstevel@tonic-gate char c; 456*0Sstevel@tonic-gate { 457*0Sstevel@tonic-gate static char s[3]; 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate if (c < 040 || c == 0177) { 460*0Sstevel@tonic-gate s[0] = '^'; 461*0Sstevel@tonic-gate s[1] = c == 0177 ? '?' : c+'A'-1; 462*0Sstevel@tonic-gate s[2] = '\0'; 463*0Sstevel@tonic-gate } else { 464*0Sstevel@tonic-gate s[0] = c; 465*0Sstevel@tonic-gate s[1] = '\0'; 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate return (s); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate /* 471*0Sstevel@tonic-gate * Help command 472*0Sstevel@tonic-gate */ 473*0Sstevel@tonic-gate help(c) 474*0Sstevel@tonic-gate char c; 475*0Sstevel@tonic-gate { 476*0Sstevel@tonic-gate register esctable_t *p; 477*0Sstevel@tonic-gate extern esctable_t etable[]; 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate printf("%c\r\n", c); 480*0Sstevel@tonic-gate for (p = etable; p->e_char; p++) { 481*0Sstevel@tonic-gate if ((p->e_flags&PRIV) && uid) 482*0Sstevel@tonic-gate continue; 483*0Sstevel@tonic-gate printf("%2s", ctrl(character(value(ESCAPE)))); 484*0Sstevel@tonic-gate printf("%-2s %c %s\r\n", ctrl(p->e_char), 485*0Sstevel@tonic-gate p->e_flags&EXP ? '*': ' ', p->e_help); 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * Set up the "remote" tty's state 491*0Sstevel@tonic-gate */ 492*0Sstevel@tonic-gate ttysetup(speed) 493*0Sstevel@tonic-gate int speed; 494*0Sstevel@tonic-gate { 495*0Sstevel@tonic-gate struct termios buf; 496*0Sstevel@tonic-gate char *loc; 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate ioctl(FD, TCGETS, (char *)&buf); 499*0Sstevel@tonic-gate buf.c_cflag &= (CREAD|HUPCL|CLOCAL|CRTSCTS|CRTSXOFF); 500*0Sstevel@tonic-gate buf.c_cflag |= CS8; 501*0Sstevel@tonic-gate cfsetospeed(&buf, speed); 502*0Sstevel@tonic-gate if (boolean(value(HARDWAREFLOW))) { 503*0Sstevel@tonic-gate int i = TIOCM_CAR; 504*0Sstevel@tonic-gate 505*0Sstevel@tonic-gate /* 506*0Sstevel@tonic-gate * Only set hardware flow control if carrier is up, 507*0Sstevel@tonic-gate * because some devices require both CD and RTS to 508*0Sstevel@tonic-gate * be up before sending. 509*0Sstevel@tonic-gate */ 510*0Sstevel@tonic-gate ioctl(FD, TIOCMGET, &i); 511*0Sstevel@tonic-gate if (i & TIOCM_CAR) 512*0Sstevel@tonic-gate buf.c_cflag |= (CRTSCTS|CRTSXOFF); 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* 516*0Sstevel@tonic-gate * Careful to only penalize the 8-bit users here on the 517*0Sstevel@tonic-gate * incoming tty port. The default 7-bit users will 518*0Sstevel@tonic-gate * still get the parity bit from the other side's login 519*0Sstevel@tonic-gate * process (which happens to be the default for sun tip 520*0Sstevel@tonic-gate * configurations). 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate loc = setlocale(LC_CTYPE, NULL); 523*0Sstevel@tonic-gate if (noparity && loc != 0 && strcmp(loc, "C") != 0) 524*0Sstevel@tonic-gate buf.c_iflag = 0; 525*0Sstevel@tonic-gate else 526*0Sstevel@tonic-gate buf.c_iflag = ISTRIP; 527*0Sstevel@tonic-gate buf.c_oflag = 0; 528*0Sstevel@tonic-gate buf.c_lflag = 0; 529*0Sstevel@tonic-gate buf.c_cc[VMIN] = 1; 530*0Sstevel@tonic-gate buf.c_cc[VTIME] = 0; 531*0Sstevel@tonic-gate ioctl(FD, TCSETSF, (char *)&buf); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate /* 535*0Sstevel@tonic-gate * Return "simple" name from a file name, 536*0Sstevel@tonic-gate * strip leading directories. 537*0Sstevel@tonic-gate */ 538*0Sstevel@tonic-gate char * 539*0Sstevel@tonic-gate sname(s) 540*0Sstevel@tonic-gate register char *s; 541*0Sstevel@tonic-gate { 542*0Sstevel@tonic-gate register char *p = s; 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate while (*s) 545*0Sstevel@tonic-gate if (*s++ == '/') 546*0Sstevel@tonic-gate p = s; 547*0Sstevel@tonic-gate return (p); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate static char partab[0400]; 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * Do a write to the remote machine with the correct parity. 554*0Sstevel@tonic-gate * We are doing 8 bit wide output, so we just generate a character 555*0Sstevel@tonic-gate * with the right parity and output it. 556*0Sstevel@tonic-gate */ 557*0Sstevel@tonic-gate parwrite(fd, buf, n) 558*0Sstevel@tonic-gate int fd; 559*0Sstevel@tonic-gate unsigned char *buf; 560*0Sstevel@tonic-gate register int n; 561*0Sstevel@tonic-gate { 562*0Sstevel@tonic-gate register int i; 563*0Sstevel@tonic-gate register unsigned char *bp; 564*0Sstevel@tonic-gate extern int errno; 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate bp = buf; 567*0Sstevel@tonic-gate for (i = 0; i < n; i++) { 568*0Sstevel@tonic-gate *bp = partab[(*bp)&0377]; 569*0Sstevel@tonic-gate bp++; 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate if (write(fd, buf, n) < 0) { 572*0Sstevel@tonic-gate if (errno == EIO || errno == ENXIO) 573*0Sstevel@tonic-gate abort("Lost carrier."); 574*0Sstevel@tonic-gate /* this is questionable */ 575*0Sstevel@tonic-gate perror("write"); 576*0Sstevel@tonic-gate } 577*0Sstevel@tonic-gate } 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate /* 580*0Sstevel@tonic-gate * Build a parity table with appropriate high-order bit. 581*0Sstevel@tonic-gate */ 582*0Sstevel@tonic-gate setparity(defparity) 583*0Sstevel@tonic-gate char *defparity; 584*0Sstevel@tonic-gate { 585*0Sstevel@tonic-gate register int i; 586*0Sstevel@tonic-gate char *parity; 587*0Sstevel@tonic-gate extern char evenpartab[]; 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate if (value(PARITY) == NOSTR) 590*0Sstevel@tonic-gate value(PARITY) = defparity; 591*0Sstevel@tonic-gate parity = value(PARITY); 592*0Sstevel@tonic-gate for (i = 0; i < 0400; i++) 593*0Sstevel@tonic-gate partab[i] = evenpartab[i]; 594*0Sstevel@tonic-gate if (equal(parity, "even")) 595*0Sstevel@tonic-gate ; 596*0Sstevel@tonic-gate else if (equal(parity, "odd")) { 597*0Sstevel@tonic-gate for (i = 0; i < 0400; i++) 598*0Sstevel@tonic-gate partab[i] ^= 0200; /* reverse bit 7 */ 599*0Sstevel@tonic-gate } else if (equal(parity, "none")) { 600*0Sstevel@tonic-gate /* Do nothing so we can pass thru 8-bit chars */ 601*0Sstevel@tonic-gate noparity = 1; 602*0Sstevel@tonic-gate for (i = 0; i < 0400; i++) 603*0Sstevel@tonic-gate partab[i] = i; 604*0Sstevel@tonic-gate } else if (equal(parity, "zero")) { 605*0Sstevel@tonic-gate for (i = 0; i < 0400; i++) 606*0Sstevel@tonic-gate partab[i] &= ~0200; /* turn off bit 7 */ 607*0Sstevel@tonic-gate } else if (equal(parity, "one")) { 608*0Sstevel@tonic-gate for (i = 0; i < 0400; i++) 609*0Sstevel@tonic-gate partab[i] |= 0200; /* turn on bit 7 */ 610*0Sstevel@tonic-gate } else { 611*0Sstevel@tonic-gate fprintf(stderr, "%s: unknown parity value\n", PA); 612*0Sstevel@tonic-gate fflush(stderr); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate } 615