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