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