1 /* tip.c 4.12 82/07/29 */ 2 3 /* 4 * tip - UNIX link to other systems 5 * tip [-v] [-speed] system-name 6 * or 7 * cu phone-number [-s speed] [-l line] [-a acu] 8 */ 9 #include "tip.h" 10 11 /* 12 * Baud rate mapping table 13 */ 14 int bauds[] = { 15 0, 50, 75, 110, 134, 150, 200, 300, 600, 16 1200, 1800, 2400, 4800, 9600, 19200, -1 17 }; 18 19 #ifdef VMUNIX 20 int disc = OTTYDISC; /* tip normally runs this way */ 21 #endif 22 23 int intprompt(); 24 int timeout(); 25 int cleanup(); 26 char *sname(); 27 extern char *sprintf(); 28 29 main(argc, argv) 30 char *argv[]; 31 { 32 char *system = NOSTR; 33 register int i; 34 register char *p; 35 char sbuf[12]; 36 37 if (equal(sname(argv[0]), "cu")) { 38 cumain(argc, argv); 39 cumode = 1; 40 goto cucommon; 41 } 42 43 if (argc > 4) { 44 fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); 45 exit(1); 46 } 47 if (!isatty(0)) { 48 fprintf(stderr, "tip: must be interactive\n"); 49 exit(1); 50 } 51 52 for (; argc > 1; argv++, argc--) { 53 if (argv[1][0] != '-') 54 system = argv[1]; 55 else switch (argv[1][1]) { 56 57 case 'v': 58 vflag++; 59 break; 60 61 case '0': case '1': case '2': case '3': case '4': 62 case '5': case '6': case '7': case '8': case '9': 63 BR = atoi(&argv[1][1]); 64 break; 65 66 default: 67 fprintf(stderr, "tip: %s, unknown option\n", argv[1]); 68 break; 69 } 70 } 71 72 if (system == NOSTR) 73 goto notnumber; 74 for (p = system; *p; p++) 75 if (isalpha(*p)) 76 goto notnumber; 77 PN = system; /* system name is really a phone number */ 78 system = sprintf(sbuf, "tip%d", BR); 79 80 notnumber: 81 signal(SIGINT, cleanup); 82 signal(SIGQUIT, cleanup); 83 signal(SIGHUP, cleanup); 84 signal(SIGTERM, cleanup); 85 86 if ((i = hunt(system)) == 0) { 87 printf("all ports busy\n"); 88 exit(3); 89 } 90 if (i == -1) { 91 printf("link down\n"); 92 delock(uucplock); 93 exit(3); 94 } 95 setbuf(stdout, NULL); 96 loginit(); 97 /* 98 * Now that we have the logfile and the ACU open 99 * return to the real uid and gid. These things will 100 * be closed on exit. Note that we can't run as root, 101 * because locking mechanism on the tty and the accounting 102 * will be bypassed. 103 */ 104 setuid(getuid()); 105 setgid(getgid()); 106 107 /* 108 * Kludge, their's no easy way to get the initialization 109 * in the right order, so force it here 110 */ 111 if ((PH = getenv("PHONES")) == NOSTR) 112 PH = "/etc/phones"; 113 vinit(); /* init variables */ 114 if ((i = speed(number(value(BAUDRATE)))) == NULL) { 115 printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); 116 delock(uucplock); 117 exit(3); 118 } 119 120 /* 121 * Hardwired connections require the 122 * line speed set before they make any transmissions 123 * (this is particularly true of things like a DF03-AC) 124 */ 125 if (HW) 126 ttysetup(i); 127 if (p = connect()) { 128 printf("\07%s\n[EOT]\n", p); 129 delock(uucplock); 130 exit(1); 131 } 132 if (!HW) 133 ttysetup(i); 134 cucommon: 135 /* 136 * From here down the code is shared with 137 * the "cu" version of tip. 138 */ 139 ioctl(0, TIOCGETP, (char *)&defarg); 140 ioctl(0, TIOCGETC, (char *)&defchars); 141 #ifdef VMUNIX 142 ioctl(0, TIOCGETD, (char *)&odisc); 143 #endif 144 arg = defarg; 145 arg.sg_flags = ANYP | CBREAK; 146 tchars = defchars; 147 tchars.t_intrc = tchars.t_quitc = -1; 148 raw(); 149 150 pipe(fildes); pipe(repdes); 151 signal(SIGALRM, timeout); 152 153 /* 154 * Everything's set up now: 155 * connection established (hardwired or diaulup) 156 * line conditioned (baud rate, mode, etc.) 157 * internal data structures (variables) 158 * so, fork one process for local side and one for remote. 159 */ 160 printf(cumode ? "Connected\r\n" : "\07connected\r\n"); 161 if (pid = fork()) 162 tipin(); 163 else 164 tipout(); 165 /*NOTREACHED*/ 166 } 167 168 cleanup() 169 { 170 delock(uucplock); 171 #ifdef VMUNIX 172 if (odisc) 173 ioctl(0, TIOCSETD, (char *)&odisc); 174 #endif 175 exit(0); 176 } 177 178 /* 179 * put the controlling keyboard into raw mode 180 */ 181 raw() 182 { 183 ioctl(0, TIOCSETP, &arg); 184 ioctl(0, TIOCSETC, &tchars); 185 #ifdef VMUNIX 186 ioctl(0, TIOCSETD, (char *)&disc); 187 #endif 188 } 189 190 191 /* 192 * return keyboard to normal mode 193 */ 194 unraw() 195 { 196 #ifdef VMUNIX 197 ioctl(0, TIOCSETD, (char *)&odisc); 198 #endif 199 ioctl(0, TIOCSETP, (char *)&defarg); 200 ioctl(0, TIOCSETC, (char *)&defchars); 201 } 202 203 /* 204 * Print string ``s'', then read a string 205 * in from the terminal. Handles signals & allows use of 206 * normal erase and kill characters. 207 */ 208 prompt(s, p) 209 char *s; 210 register char *p; 211 { 212 register char *b = p; 213 214 stoprompt = 0; 215 signal(SIGINT, intprompt); 216 signal(SIGQUIT, SIG_IGN); 217 unraw(); 218 printf("%s", s); 219 while ((*p = getchar()) != EOF && *p != '\n') { 220 if (stoprompt) 221 goto pbreak; 222 p++; 223 } 224 *p = '\0'; 225 pbreak: 226 raw(); 227 signal(SIGINT, SIG_DFL); 228 signal(SIGQUIT,SIG_DFL); 229 return(stoprompt || p == b); 230 } 231 232 /* 233 * Interrupt service routine during prompting 234 */ 235 intprompt() 236 { 237 signal(SIGINT, SIG_IGN); 238 stoprompt = 1; 239 printf("\r\n"); 240 } 241 242 /* 243 * ****TIPIN TIPIN**** 244 */ 245 tipin() 246 { 247 char gch, bol = 1; 248 249 /* 250 * Kinda klugey here... 251 * check for scripting being turned on from the .tiprc file, 252 * but be careful about just using setscript(), as we may 253 * send a SIGEMT before tipout has a chance to set up catching 254 * it; so wait a second, then setscript() 255 */ 256 if (boolean(value(SCRIPT))) { 257 sleep(1); 258 setscript(); 259 } 260 261 while (1) { 262 gch = getchar()&0177; 263 if ((gch == character(value(ESCAPE))) && bol) { 264 if (!(gch = escape())) 265 continue; 266 } else if (!cumode && gch == character(value(RAISECHAR))) { 267 boolean(value(RAISE)) = !boolean(value(RAISE)); 268 continue; 269 } else if (gch == '\r') { 270 bol = 1; 271 write(FD, &gch, 1); 272 continue; 273 } else if (!cumode && gch == character(value(FORCE))) 274 gch = getchar()&0177; 275 bol = any(gch, value(EOL)); 276 if (boolean(value(RAISE)) && islower(gch)) 277 toupper(gch); 278 write(FD, &gch, 1); 279 } 280 } 281 282 /* 283 * Escape handler -- 284 * called on recognition of ``escapec'' at the beginning of a line 285 */ 286 escape() 287 { 288 register char gch; 289 register esctable_t *p; 290 char c = character(value(ESCAPE)); 291 extern esctable_t etable[]; 292 293 gch = (getchar()&0177); 294 for (p = etable; p->e_char; p++) 295 if (p->e_char == gch) { 296 if ((p->e_flags&PRIV) && getuid()) 297 continue; 298 printf("%s", ctrl(c)); 299 (*p->e_func)(gch); 300 return(0); 301 } 302 /* ESCAPE ESCAPE forces ESCAPE */ 303 if (c != gch) 304 write(FD, &c, 1); 305 return(gch); 306 } 307 308 speed(n) 309 { 310 register int *p; 311 312 for (p = bauds; *p != -1; p++) 313 if (*p == n) 314 return(p-bauds); 315 return(NULL); 316 } 317 318 any(c, p) 319 register char c, *p; 320 { 321 if (p) 322 while (*p) 323 if (*p++ == c) 324 return(1); 325 return(0); 326 } 327 328 size(s) 329 register char *s; 330 { 331 register int i = 0; 332 333 while (*s++) i++; 334 return(i); 335 } 336 337 char * 338 interp(s) 339 register char *s; 340 { 341 static char buf[256]; 342 register char *p = buf, c, *q; 343 344 while (c = *s++) { 345 for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) 346 if (*q++ == c) { 347 *p++ = '\\'; *p++ = *q; 348 goto next; 349 } 350 if (c < 040) { 351 *p++ = '^'; *p++ = c + 'A'-1; 352 } else if (c == 0177) { 353 *p++ = '^'; *p++ = '?'; 354 } else 355 *p++ = c; 356 next: 357 ; 358 } 359 *p = '\0'; 360 return(buf); 361 } 362 363 char * 364 ctrl(c) 365 char c; 366 { 367 static char s[3]; 368 369 if (c < 040 || c == 0177) { 370 s[0] = '^'; 371 s[1] = c == 0177 ? '?' : c+'A'-1; 372 s[2] = '\0'; 373 } else { 374 s[0] = c; 375 s[1] = '\0'; 376 } 377 return(s); 378 } 379 380 /* 381 * Help command 382 */ 383 help(c) 384 char c; 385 { 386 register esctable_t *p; 387 extern esctable_t etable[]; 388 389 printf("%c\r\n", c); 390 for (p = etable; p->e_char; p++) { 391 if ((p->e_flags&PRIV) && getuid()) 392 continue; 393 printf("%2s", ctrl(character(value(ESCAPE)))); 394 printf("%-2s %c %s\r\n", ctrl(p->e_char), 395 p->e_flags&EXP ? '*': ' ', p->e_help); 396 } 397 } 398 399 /* 400 * Set up the "remote" tty's state 401 */ 402 ttysetup(speed) 403 { 404 #ifdef VMUNIX 405 unsigned bits = LDECCTQ; 406 #endif 407 408 arg.sg_ispeed = arg.sg_ospeed = speed; 409 arg.sg_flags = TANDEM|RAW; 410 ioctl(FD, TIOCSETP, (char *)&arg); 411 #ifdef VMUNIX 412 ioctl(FD, TIOCLBIS, (char *)&bits); 413 #endif 414 } 415 416 /* 417 * Return "simple" name from a file name, 418 * strip leading directories. 419 */ 420 char * 421 sname(s) 422 register char *s; 423 { 424 register char *p = s; 425 426 while (*s) 427 if (*s++ == '/') 428 p = s; 429 return (p); 430 } 431