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