1 /* cmds.c 4.1 81/05/09 */ 2 #include "tip.h" 3 /* 4 * tip 5 * 6 * miscellaneous commands 7 */ 8 9 int quant[] = { 60, 60, 24 }; 10 11 char null = '\0'; 12 char *sep[] = { "second", "minute", "hour" }; 13 static char *argv[10]; /* argument vector for take and put */ 14 15 int timeout(); /* timeout function called on alarm */ 16 int stopsnd(); /* SIGINT handler during file transfers */ 17 int intprompt(); /* used in handling SIG_INT during prompt */ 18 int intcopy(); /* interrupt routine for file transfers */ 19 20 /* 21 * FTP - remote ==> local 22 * get a file from the remote host 23 */ 24 getfl(c) 25 char c; 26 { 27 char buf[256]; 28 29 putchar(c); 30 /* 31 * get the UNIX receiving file's name 32 */ 33 if (prompt("Local file name? ", copyname)) 34 return; 35 if ((sfd = creat(copyname, 0666)) < 0) { 36 printf("\r\n%s: cannot creat\r\n", copyname); 37 return; 38 } 39 40 /* 41 * collect parameters 42 */ 43 if (prompt("List command for remote system? ", buf)) { 44 unlink(copyname); 45 return; 46 } 47 transfer(buf, sfd, value(EOFREAD)); 48 } 49 50 /* 51 * Cu-like take command 52 */ 53 cu_take(cc) 54 char cc; 55 { 56 int fd, argc; 57 char line[BUFSIZ]; 58 59 if (prompt("[take] ", copyname)) 60 return; 61 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 62 printf("usage: <take> from [to]\r\n"); 63 return; 64 } 65 if (argc == 1) 66 argv[1] = argv[0]; 67 if ((fd = creat(argv[1], 0666)) < 0) { 68 printf("\r\n%s: cannot create\r\n", argv[1]); 69 return; 70 } 71 sprintf(line, "cat '%s';echo \01", argv[0]); 72 transfer(line, fd, "\01"); 73 } 74 75 /* 76 * Bulk transfer routine -- 77 * used by getfl(), cu_take(), and pipefile() 78 */ 79 transfer(buf, fd, eofchars) 80 char *buf, *eofchars; 81 { 82 register int ct; 83 char c, buffer[BUFSIZ]; 84 register char *p = buffer; 85 register int cnt, eof; 86 time_t start; 87 88 write(FD, buf, size(buf)); 89 quit = 0; 90 signal(SIGINT, intcopy); 91 kill(pid, SIGIOT); 92 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 93 94 /* 95 * finish command 96 */ 97 write(FD, "\r", 1); 98 do 99 read(FD, &c, 1); 100 while ((c&0177) != '\n'); 101 ioctl(0, TIOCSETC, &defchars); 102 103 start = time(0); 104 for (ct = 0; !quit;) { 105 eof = read(FD, &c, 1) <= 0; 106 c &= 0177; 107 if (quit) 108 continue; 109 if (eof || any(c, eofchars)) 110 break; 111 if (c == 0) 112 continue; /* ignore nulls */ 113 if (c == '\r') 114 continue; 115 *p++ = c; 116 117 if (c == '\n' && boolean(value(VERBOSE))) 118 printf("\r%d", ++ct); 119 if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) { 120 if (write(fd, buffer, cnt) != cnt) { 121 printf("\r\nwrite error\r\n"); 122 quit = 1; 123 } 124 p = buffer; 125 } 126 } 127 if (cnt = (p-buffer)) 128 if (write(fd, buffer, cnt) != cnt) 129 printf("\r\nwrite error\r\n"); 130 131 if (boolean(value(VERBOSE))) 132 prtime(" lines transferred in ", time(0)-start); 133 ioctl(0, TIOCSETC, &tchars); 134 write(fildes[1], (char *)&ccc, 1); 135 signal(SIGINT, SIG_DFL); 136 close(fd); 137 } 138 139 /* 140 * FTP - remote ==> local process 141 * send remote input to local process via pipe 142 */ 143 pipefile() 144 { 145 int cpid, pdes[2]; 146 char buf[256]; 147 int status, p; 148 extern int errno; 149 150 if (prompt("Local command? ", buf)) 151 return; 152 153 if (pipe(pdes)) { 154 printf("can't establish pipe\r\n"); 155 return; 156 } 157 158 if ((cpid = fork()) < 0) { 159 printf("can't fork!\r\n"); 160 return; 161 } else if (cpid) { 162 if (prompt("List command for remote system? ", buf)) { 163 close(pdes[0]), close(pdes[1]); 164 kill (cpid, SIGKILL); 165 } else { 166 close(pdes[0]); 167 signal(SIGPIPE, intcopy); 168 transfer(buf, pdes[1], value(EOFREAD)); 169 signal(SIGPIPE, SIG_DFL); 170 while ((p = wait(&status)) > 0 && p != cpid) 171 ; 172 } 173 } else { 174 register int f; 175 176 dup2(pdes[0], 0); 177 close(pdes[0]); 178 for (f = 3; f < 20; f++) 179 close(f); 180 execute(buf); 181 printf("can't execl!\r\n"); 182 exit(0); 183 } 184 } 185 186 /* 187 * Interrupt service routine for FTP 188 */ 189 stopsnd() 190 { 191 stop = 1; 192 signal(SIGINT, SIG_IGN); 193 } 194 195 /* 196 * FTP - local ==> remote 197 * send local file to remote host 198 * terminate transmission with pseudo EOF sequence 199 */ 200 sendfile(cc) 201 char cc; 202 { 203 FILE *fd; 204 205 putchar(cc); 206 /* 207 * get file name 208 */ 209 if (prompt("Local file name? ", fname)) 210 return; 211 212 /* 213 * look up file 214 */ 215 if ((fd = fopen(fname, "r")) == NULL) { 216 printf("%s: cannot open\r\n", fname); 217 return; 218 } 219 transmit(fd, value(EOFWRITE), NULL); 220 } 221 222 /* 223 * Bulk transfer routine to remote host -- 224 * used by sendfile() and cu_put() 225 */ 226 transmit(fd, eofchars, command) 227 FILE *fd; 228 char *eofchars, *command; 229 { 230 char *pc, lastc; 231 int c, ccount, lcount; 232 time_t start_t, stop_t; 233 234 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 235 signal(SIGINT, stopsnd); 236 stop = 0; 237 ioctl(0, TIOCSETC, &defchars); 238 read(repdes[0], (char *)&ccc, 1); 239 if (command != NULL) { 240 for (pc = command; *pc; pc++) 241 send(*pc); 242 read(FD, (char *)&c, 1); /* trailing \n */ 243 } 244 lcount = 0; 245 lastc = '\0'; 246 start_t = time(0); 247 while(1) { 248 ccount = 0; 249 do { 250 c = getc(fd); 251 if (stop) 252 goto out; 253 if (c == EOF) 254 goto out; 255 if (c == 0177) 256 continue; 257 lastc = c; 258 if (c < 040) { 259 if (c == '\n') 260 c = '\r'; 261 else if (c == '\t') { 262 if (boolean(value(TABEXPAND))) { 263 send(' '); 264 while((++ccount % 8) != 0) 265 send(' '); 266 continue; 267 } 268 } else 269 continue; 270 } 271 send(c); 272 } while (c != '\r'); 273 if (boolean(value(VERBOSE))) 274 printf("\r%d", ++lcount); 275 alarm(10); 276 timedout = 0; 277 do { /* wait for prompt */ 278 read(FD, (char *)&c, 1); 279 if (timedout || stop) { 280 if (timedout) 281 printf("\r\ntimed out at eol\r\n"); 282 alarm(0); 283 goto out; 284 } 285 } while ((c&0177) != character(value(PROMPT))); 286 alarm(0); 287 } 288 out: 289 if (lastc != '\n') 290 send('\r'); 291 for (pc = eofchars; *pc; pc++) 292 send(*pc); 293 stop_t = time(0); 294 fclose(fd); 295 signal(SIGINT, SIG_DFL); 296 if (boolean(value(VERBOSE))) 297 prtime(" lines transferred in ", stop_t-start_t); 298 write(fildes[1], (char *)&ccc, 1); 299 ioctl(0, TIOCSETC, &tchars); 300 } 301 302 /* 303 * Cu-like put command 304 */ 305 cu_put(cc) 306 char cc; 307 { 308 FILE *fd; 309 char line[BUFSIZ]; 310 int argc; 311 312 if (prompt("[put] ", copyname)) 313 return; 314 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 315 printf("usage: <put> from [to]\r\n"); 316 return; 317 } 318 if (argc == 1) 319 argv[1] = argv[0]; 320 if ((fd = fopen(argv[0], "r")) == NULL) { 321 printf("%s: cannot open\r\n", argv[0]); 322 return; 323 } 324 sprintf(line, "cat>'%s'\r", argv[1]); 325 transmit(fd, "\04", line); 326 } 327 328 /* 329 * FTP - send single character 330 * wait for echo & handle timeout 331 */ 332 send(c) 333 char c; 334 { 335 int cc; 336 int retry = 0; 337 338 cc = c; 339 write(FD, (char *)&cc, 1); 340 tryagain: 341 timedout = 0; 342 alarm(10); 343 read(FD, (char *)&cc, 1); 344 alarm(0); 345 if (timedout) { 346 printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 347 if (retry++ > 3) 348 return; 349 write(FD, &null, 1); /* poke it */ 350 goto tryagain; 351 } 352 } 353 354 timeout() 355 { 356 signal(SIGALRM, timeout); 357 timedout = 1; 358 } 359 360 #ifdef CONNECT 361 /* 362 * Fork a program with: 363 * 0 <-> local tty in 364 * 1 <-> local tty out 365 * 2 <-> local tty out 366 * 3 <-> remote tty in 367 * 4 <-> remote tty out 368 */ 369 consh(c) 370 { 371 char buf[256]; 372 int cpid, status, p; 373 time_t start; 374 375 putchar(c); 376 if (prompt("Local command? ", buf)) 377 return; 378 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 379 signal(SIGINT, SIG_IGN); 380 signal(SIGQUIT, SIG_IGN); 381 ioctl(0, TIOCSETC, &defchars); 382 read(repdes[0], (char *)&ccc, 1); 383 /* 384 * Set up file descriptors in the child and 385 * let it go... 386 */ 387 if ((cpid = fork()) < 0) 388 printf("can't fork!\r\n"); 389 else if (cpid) { 390 start = time(0); 391 while ((p = wait(&status)) > 0 && p != cpid) 392 ; 393 } else { 394 register int i; 395 396 dup2(FD, 3); 397 dup2(3, 4); 398 for (i = 5; i < 20; i++) 399 close(i); 400 signal(SIGINT, SIG_DFL); 401 signal(SIGQUIT, SIG_DFL); 402 execute(buf); 403 printf("can't find `%s'\r\n", buf); 404 exit(0); 405 } 406 if (boolean(value(VERBOSE))) 407 prtime("away for ", time(0)-start); 408 write(fildes[1], (char *)&ccc, 1); 409 ioctl(0, TIOCSETC, &tchars); 410 signal(SIGINT, SIG_DFL); 411 signal(SIGQUIT, SIG_DFL); 412 } 413 #endif 414 415 /* 416 * Escape to local shell 417 */ 418 shell() 419 { 420 int shpid, status; 421 extern char **environ; 422 char *cp; 423 424 printf("[sh]\r\n"); 425 signal(SIGINT, SIG_IGN); 426 signal(SIGQUIT, SIG_IGN); 427 unraw(); 428 if (shpid = fork()) { 429 while (shpid != wait(&status)); 430 raw(); 431 printf("\r\n!\r\n"); 432 signal(SIGINT, SIG_DFL); 433 signal(SIGQUIT, SIG_DFL); 434 return; 435 } else { 436 signal(SIGQUIT, SIG_DFL); 437 signal(SIGINT, SIG_DFL); 438 if ((cp = rindex(value(SHELL), '/')) == NULL) 439 cp = value(SHELL); 440 else 441 cp++; 442 execl(value(SHELL), cp, 0); 443 printf("\r\ncan't execl!\r\n"); 444 exit(1); 445 } 446 } 447 448 /* 449 * TIPIN portion of scripting 450 * initiate the conversation with TIPOUT 451 */ 452 setscript() 453 { 454 char c; 455 /* 456 * enable TIPOUT side for dialogue 457 */ 458 kill(pid, SIGEMT); 459 if (boolean(value(SCRIPT))) 460 write(fildes[1], value(RECORD), size(value(RECORD))); 461 write(fildes[1], "\n", 1); 462 /* 463 * wait for TIPOUT to finish 464 */ 465 read(repdes[0], &c, 1); 466 if (c == 'n') 467 printf("can't create %s\r\n", value(RECORD)); 468 } 469 470 /* 471 * Change current working directory of 472 * local portion of tip 473 */ 474 chdirectory() 475 { 476 char dirname[80]; 477 register char *cp = dirname; 478 479 if (prompt("[cd] ", dirname)) 480 if (stoprompt) 481 return; 482 else 483 cp = value(HOME); 484 if (chdir(cp) < 0) 485 printf("%s: bad directory\r\n", cp); 486 printf("!\r\n"); 487 } 488 489 finish() 490 { 491 kill(pid, SIGTERM); 492 disconnect(); 493 printf("\r\n[EOT]\r\n"); 494 delock(uucplock); 495 #ifdef VMUNIX 496 ioctl(0, TIOCSETD, (char *)&odisc); 497 #endif 498 unraw(); 499 exit(0); 500 } 501 502 intcopy() 503 { 504 raw(); 505 quit = 1; 506 } 507 508 execute(s) 509 char *s; 510 { 511 register char *cp; 512 513 if ((cp = rindex(value(SHELL), '/')) == NULL) 514 cp = value(SHELL); 515 else 516 cp++; 517 execl(value(SHELL), cp, "-c", s, 0); 518 } 519 520 args(buf, a) 521 char *buf, *a[]; 522 { 523 register char *p = buf, *start; 524 register char **parg = a; 525 register int n = 0; 526 527 do { 528 while (*p && (*p == ' ' || *p == '\t')) 529 p++; 530 start = p; 531 if (*p) 532 *parg = p; 533 while (*p && (*p != ' ' && *p != '\t')) 534 p++; 535 if (p != start) 536 parg++, n++; 537 if (*p) 538 *p++ = '\0'; 539 } while (*p); 540 541 return(n); 542 } 543 544 prtime(s, a) 545 char *s; 546 time_t a; 547 { 548 register i; 549 int nums[3]; 550 551 for (i = 0; i < 3; i++) { 552 nums[i] = (int)(a % quant[i]); 553 a /= quant[i]; 554 } 555 printf("%s", s); 556 while (--i >= 0) 557 if (nums[i]) 558 printf("%d %s%c ", nums[i], sep[i], 559 nums[i] == 1 ? '\0' : 's'); 560 printf("\r\n!\r\n"); 561 } 562 563 variable() 564 { 565 char buf[256]; 566 567 if (prompt("[set] ", buf)) 568 return; 569 vlex(buf); 570 if (vtable[BEAUTIFY].v_access&CHANGED) { 571 vtable[BEAUTIFY].v_access &= ~CHANGED; 572 signal(pid, SIGSYS); 573 } 574 if (vtable[SCRIPT].v_access&CHANGED) { 575 vtable[SCRIPT].v_access &= ~CHANGED; 576 setscript(); 577 } 578 if (vtable[RECORD].v_access&CHANGED) { 579 vtable[RECORD].v_access &= ~CHANGED; 580 if (boolean(value(SCRIPT))) 581 setscript(); 582 } 583 } 584