cmds.c revision 7527
1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93"; 36#endif /* not lint */ 37 38#include "tipconf.h" 39#include "tip.h" 40#include "pathnames.h" 41 42#include <stdio.h> 43 44/* 45 * tip 46 * 47 * miscellaneous commands 48 */ 49 50int quant[] = { 60, 60, 24 }; 51 52char null = '\0'; 53char *sep[] = { "second", "minute", "hour" }; 54static char *argv[10]; /* argument vector for take and put */ 55 56void timeout(); /* timeout function called on alarm */ 57void stopsnd(); /* SIGINT handler during file transfers */ 58void intcopy(); /* interrupt routine for file transfers */ 59 60void 61usedefchars () 62{ 63#if HAVE_TERMIOS 64 int cnt; 65 struct termios ttermios; 66 ttermios = ctermios; 67 for (cnt = 0; cnt < NCCS; cnt++) 68 ttermios.c_cc [cnt] = otermios.c_cc [cnt]; 69 tcsetattr (0, TCSANOW, &ttermios); 70#else 71 ioctl(0, TIOCSETC, &defchars); 72#endif 73} 74 75void 76usetchars () 77{ 78#if HAVE_TERMIOS 79 tcsetattr (0, TCSANOW, &ctermios); 80#else 81 ioctl(0, TIOCSETC, &tchars); 82#endif 83} 84 85void 86flush_remote () 87{ 88#ifdef TIOCFLUSH 89 int cmd = 0; 90 ioctl (FD, TIOCFLUSH, &cmd); 91#else 92 struct sgttyb buf; 93 ioctl (FD, TIOCGETP, &buf); /* this does a */ 94 ioctl (FD, TIOCSETP, &buf); /* wflushtty */ 95#endif 96} 97 98/* 99 * FTP - remote ==> local 100 * get a file from the remote host 101 */ 102getfl(c) 103 char c; 104{ 105 char buf[256], *cp, *expand(); 106 107 putchar(c); 108 /* 109 * get the UNIX receiving file's name 110 */ 111 if (prompt("Local file name? ", copyname)) 112 return; 113 cp = expand(copyname); 114 if ((sfd = creat(cp, 0666)) < 0) { 115 printf("\r\n%s: cannot creat\r\n", copyname); 116 return; 117 } 118 119 /* 120 * collect parameters 121 */ 122 if (prompt("List command for remote system? ", buf)) { 123 unlink(copyname); 124 return; 125 } 126 transfer(buf, sfd, value(EOFREAD)); 127} 128 129/* 130 * Cu-like take command 131 */ 132cu_take(cc) 133 char cc; 134{ 135 int fd, argc; 136 char line[BUFSIZ], *expand(), *cp; 137 138 if (prompt("[take] ", copyname)) 139 return; 140 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 141 printf("usage: <take> from [to]\r\n"); 142 return; 143 } 144 if (argc == 1) 145 argv[1] = argv[0]; 146 cp = expand(argv[1]); 147 if ((fd = creat(cp, 0666)) < 0) { 148 printf("\r\n%s: cannot create\r\n", argv[1]); 149 return; 150 } 151 (void)sprintf(line, "cat %s ; echo \"\" ; echo ___tip_end_of_file_marker___", argv[0]); 152 xfer(line, fd, "\n___tip_end_of_file_marker___\n"); 153} 154 155extern jmp_buf intbuf; 156 157xfer(buf, fd, eofchars) 158 char *buf, *eofchars; 159{ 160 register int ct; 161 char c, *match; 162 register int cnt, eof, v; 163 time_t start; 164 sig_t f; 165 char r; 166 FILE *ff; 167 168 v = boolean(value(VERBOSE)); 169 170 if ((ff = fdopen (fd, "w")) == NULL) { 171 perror("file open"); 172 return; 173 } 174 if ((cnt = number(value(FRAMESIZE))) != BUFSIZ) 175 if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) { 176 perror("file allocation"); 177 (void)fclose(ff); 178 return; 179 } 180 181 pwrite(FD, buf, size(buf)); 182 quit = 0; 183 kill(pid, SIGIOT); 184 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 185 186 /* 187 * finish command 188 */ 189 r = '\r'; 190 pwrite(FD, &r, 1); 191 do 192 read(FD, &c, 1); 193 while ((c&0177) != '\n'); 194 195 usedefchars (); 196 197 (void) setjmp(intbuf); 198 f = signal(SIGINT, intcopy); 199 start = time(0); 200 match = eofchars; 201 for (ct = 0; !quit;) { 202 eof = read(FD, &c, 1) <= 0; 203 c &= 0177; 204 if (quit) 205 continue; 206 if (eof) 207 break; 208 if (c == 0) 209 continue; /* ignore nulls */ 210 if (c == '\r') 211 continue; 212 if (c != *match && match > eofchars) { 213 register char *p = eofchars; 214 while (p < match) { 215 if (*p == '\n'&& v) 216 (void)printf("\r%d", ++ct); 217 fputc(*p++, ff); 218 } 219 match = eofchars; 220 } 221 if (c == *match) { 222 if (*++match == '\0') 223 break; 224 } else { 225 if (c == '\n' && v) 226 (void)printf("\r%d", ++ct); 227 fputc(c, ff); 228 } 229 } 230 if (v) 231 prtime(" lines transferred in ", time(0)-start); 232 usetchars (); 233 write(fildes[1], (char *)&ccc, 1); 234 signal(SIGINT, f); 235 (void)fclose(ff); 236} 237 238static jmp_buf intbuf; 239/* 240 * Bulk transfer routine -- 241 * used by getfl(), cu_take(), and pipefile() 242 */ 243transfer(buf, fd, eofchars) 244 char *buf, *eofchars; 245{ 246 register int ct; 247 char c, buffer[BUFSIZ]; 248 register char *p = buffer; 249 register int cnt, eof, v; 250 time_t start; 251 sig_t f; 252 char r; 253 FILE *ff; 254 255 v = boolean(value(VERBOSE)); 256 257 if ((ff = fdopen (fd, "w")) == NULL) { 258 perror("file open"); 259 return; 260 } 261 if ((cnt = number(value(FRAMESIZE))) != BUFSIZ) 262 if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) { 263 perror("file allocation"); 264 (void)fclose(ff); 265 return; 266 } 267 268 pwrite(FD, buf, size(buf)); 269 quit = 0; 270 kill(pid, SIGIOT); 271 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 272 273 /* 274 * finish command 275 */ 276 r = '\r'; 277 pwrite(FD, &r, 1); 278 do 279 read(FD, &c, 1); 280 while ((c&0177) != '\n'); 281 usedefchars (); 282 (void) setjmp(intbuf); 283 f = signal(SIGINT, intcopy); 284 start = time(0); 285 for (ct = 0; !quit;) { 286 eof = read(FD, &c, 1) <= 0; 287 c &= 0177; 288 if (quit) 289 continue; 290 if (eof || any(c, eofchars)) 291 break; 292 if (c == 0) 293 continue; /* ignore nulls */ 294 if (c == '\r') 295 continue; 296 if (c == '\n' && v) 297 printf("\r%d", ++ct); 298 fputc(c, ff); 299 } 300 if (v) 301 prtime(" lines transferred in ", time(0)-start); 302 usetchars (); 303 write(fildes[1], (char *)&ccc, 1); 304 signal(SIGINT, f); 305 (void)fclose(ff); 306} 307 308/* 309 * FTP - remote ==> local process 310 * send remote input to local process via pipe 311 */ 312pipefile() 313{ 314 int cpid, pdes[2]; 315 char buf[256]; 316 int status, p; 317 extern int errno; 318 319 if (prompt("Local command? ", buf)) 320 return; 321 322 if (pipe(pdes)) { 323 printf("can't establish pipe\r\n"); 324 return; 325 } 326 327 if ((cpid = fork()) < 0) { 328 printf("can't fork!\r\n"); 329 return; 330 } else if (cpid) { 331 if (prompt("List command for remote system? ", buf)) { 332 close(pdes[0]), close(pdes[1]); 333 kill (cpid, SIGKILL); 334 } else { 335 close(pdes[0]); 336 signal(SIGPIPE, intcopy); 337 transfer(buf, pdes[1], value(EOFREAD)); 338 signal(SIGPIPE, SIG_DFL); 339 while ((p = wait(&status)) > 0 && p != cpid) 340 ; 341 } 342 } else { 343 register int f; 344 345 dup2(pdes[0], 0); 346 close(pdes[0]); 347 for (f = 3; f < 20; f++) 348 close(f); 349 execute(buf); 350 printf("can't execl!\r\n"); 351 exit(0); 352 } 353} 354 355/* 356 * Interrupt service routine for FTP 357 */ 358void 359stopsnd() 360{ 361 362 stop = 1; 363 signal(SIGINT, SIG_IGN); 364} 365 366/* 367 * FTP - local ==> remote 368 * send local file to remote host 369 * terminate transmission with pseudo EOF sequence 370 */ 371sendfile(cc) 372 char cc; 373{ 374 FILE *fd; 375 char *fnamex; 376 char *expand(); 377 378 putchar(cc); 379 /* 380 * get file name 381 */ 382 if (prompt("Local file name? ", fname)) 383 return; 384 385 /* 386 * look up file 387 */ 388 fnamex = expand(fname); 389 if ((fd = fopen(fnamex, "r")) == NULL) { 390 printf("%s: cannot open\r\n", fname); 391 return; 392 } 393 transmit(fd, value(EOFWRITE), NULL); 394 if (!boolean(value(ECHOCHECK))) { 395 flush_remote (); 396 } 397} 398 399/* 400 * Bulk transfer routine to remote host -- 401 * used by sendfile() and cu_put() 402 */ 403transmit(fd, eofchars, command) 404 FILE *fd; 405 char *eofchars, *command; 406{ 407 char *pc, lastc; 408 int c, ccount, lcount; 409 time_t start_t, stop_t; 410 sig_t f; 411 412 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 413 stop = 0; 414 f = signal(SIGINT, stopsnd); 415 usedefchars (); 416 read(repdes[0], (char *)&ccc, 1); 417 if (command != NULL) { 418 for (pc = command; *pc; pc++) 419 send(*pc); 420 if (boolean(value(ECHOCHECK))) 421 read(FD, (char *)&c, 1); /* trailing \n */ 422 else { 423 flush_remote (); 424 sleep(5); /* wait for remote stty to take effect */ 425 } 426 } 427 lcount = 0; 428 lastc = '\0'; 429 start_t = time(0); 430 while (1) { 431 ccount = 0; 432 do { 433 c = getc(fd); 434 if (stop) 435 goto out; 436 if (c == EOF) 437 goto out; 438 if (c == 0177 && !boolean(value(RAWFTP))) 439 continue; 440 lastc = c; 441 if (c < 040) { 442 if (c == '\n') { 443 if (!boolean(value(RAWFTP))) 444 c = '\r'; 445 } 446 else if (c == '\t') { 447 if (!boolean(value(RAWFTP))) { 448 if (boolean(value(TABEXPAND))) { 449 send(' '); 450 while ((++ccount % 8) != 0) 451 send(' '); 452 continue; 453 } 454 } 455 } else 456 if (!boolean(value(RAWFTP))) 457 continue; 458 } 459 send(c); 460 } while (c != '\r' && !boolean(value(RAWFTP))); 461 if (boolean(value(VERBOSE))) 462 printf("\r%d", ++lcount); 463 if (boolean(value(ECHOCHECK))) { 464 timedout = 0; 465 alarm((int)value(ETIMEOUT)); 466 do { /* wait for prompt */ 467 read(FD, (char *)&c, 1); 468 if (timedout || stop) { 469 if (timedout) 470 printf("\r\ntimed out at eol\r\n"); 471 alarm(0); 472 goto out; 473 } 474 } while ((c&0177) != character(value(PROMPT))); 475 alarm(0); 476 } 477 } 478out: 479 if (lastc != '\n' && !boolean(value(RAWFTP))) 480 send('\r'); 481 for (pc = eofchars; *pc; pc++) 482 send(*pc); 483 stop_t = time(0); 484 fclose(fd); 485 signal(SIGINT, f); 486 if (boolean(value(VERBOSE))) 487 if (boolean(value(RAWFTP))) 488 prtime(" chars transferred in ", stop_t-start_t); 489 else 490 prtime(" lines transferred in ", stop_t-start_t); 491 write(fildes[1], (char *)&ccc, 1); 492 usetchars (); 493} 494 495/* 496 * Cu-like put command 497 */ 498cu_put(cc) 499 char cc; 500{ 501 FILE *fd; 502 char line[BUFSIZ]; 503 int argc; 504 char *expand(); 505 char *copynamex; 506 507 if (prompt("[put] ", copyname)) 508 return; 509 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 510 printf("usage: <put> from [to]\r\n"); 511 return; 512 } 513 if (argc == 1) 514 argv[1] = argv[0]; 515 copynamex = expand(argv[0]); 516 if ((fd = fopen(copynamex, "r")) == NULL) { 517 printf("%s: cannot open\r\n", copynamex); 518 return; 519 } 520 if (boolean(value(ECHOCHECK))) 521 sprintf(line, "cat>%s\r", argv[1]); 522 else 523 sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]); 524 transmit(fd, "\04", line); 525} 526 527/* 528 * FTP - send single character 529 * wait for echo & handle timeout 530 */ 531send(c) 532 char c; 533{ 534 char cc; 535 int retry = 0; 536 537 cc = c; 538 pwrite(FD, &cc, 1); 539#ifdef notdef 540 if (number(value(CDELAY)) > 0 && c != '\r') 541 nap(number(value(CDELAY))); 542#endif 543 if (!boolean(value(ECHOCHECK))) { 544#ifdef notdef 545 if (number(value(LDELAY)) > 0 && c == '\r') 546 nap(number(value(LDELAY))); 547#endif 548 return; 549 } 550tryagain: 551 timedout = 0; 552 alarm((int)value(ETIMEOUT)); 553 read(FD, &cc, 1); 554 alarm(0); 555 if (timedout) { 556 printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 557 if (retry++ > 3) 558 return; 559 pwrite(FD, &null, 1); /* poke it */ 560 goto tryagain; 561 } 562} 563 564void 565timeout() 566{ 567 signal(SIGALRM, timeout); 568 timedout = 1; 569} 570 571/* 572 * Stolen from consh() -- puts a remote file on the output of a local command. 573 * Identical to consh() except for where stdout goes. 574 */ 575pipeout(c) 576{ 577 char buf[256]; 578 int cpid, status, p; 579 time_t start; 580 581 putchar(c); 582 if (prompt("Local command? ", buf)) 583 return; 584 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 585 signal(SIGINT, SIG_IGN); 586 signal(SIGQUIT, SIG_IGN); 587 usedefchars (); 588 read(repdes[0], (char *)&ccc, 1); 589 /* 590 * Set up file descriptors in the child and 591 * let it go... 592 */ 593 if ((cpid = fork()) < 0) 594 printf("can't fork!\r\n"); 595 else if (cpid) { 596 start = time(0); 597 while ((p = wait(&status)) > 0 && p != cpid) 598 ; 599 } else { 600 register int i; 601 602 dup2(FD, 1); 603 for (i = 3; i < 20; i++) 604 close(i); 605 signal(SIGINT, SIG_DFL); 606 signal(SIGQUIT, SIG_DFL); 607 execute(buf); 608 printf("can't find `%s'\r\n", buf); 609 exit(0); 610 } 611 if (boolean(value(VERBOSE))) 612 prtime("away for ", time(0)-start); 613 write(fildes[1], (char *)&ccc, 1); 614 usetchars (); 615 signal(SIGINT, SIG_DFL); 616 signal(SIGQUIT, SIG_DFL); 617} 618 619#if CONNECT 620 621int 622tiplink (char *cmd, unsigned int flags) 623{ 624 int cpid, status, p; 625 time_t start; 626 627 if (flags & TL_SIGNAL_TIPOUT) { 628 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 629 signal(SIGINT, SIG_IGN); 630 signal(SIGQUIT, SIG_IGN); 631 usedefchars (); 632 read(repdes[0], (char *)&ccc, 1); 633 } 634 635 /* 636 * Set up file descriptors in the child and 637 * let it go... 638 */ 639 if ((cpid = fork()) < 0) 640 printf("can't fork!\r\n"); 641 else if (cpid) { 642 start = time(0); 643 while ((p = wait(&status)) > 0 && p != cpid) 644 ; 645 } else { 646 register int fd; 647 648 dup2(FD, 0); 649 dup2(3, 1); 650 for (fd = 3; fd < 20; fd++) 651 close (fd); 652 signal(SIGINT, SIG_DFL); 653 signal(SIGQUIT, SIG_DFL); 654 execute (cmd); 655 printf("can't find `%s'\r\n", cmd); 656 exit(0); 657 } 658 659 if (flags & TL_VERBOSE && boolean(value(VERBOSE))) 660 prtime("away for ", time(0)-start); 661 662 if (flags & TL_SIGNAL_TIPOUT) { 663 write(fildes[1], (char *)&ccc, 1); 664 usetchars (); 665 signal(SIGINT, SIG_DFL); 666 signal(SIGQUIT, SIG_DFL); 667 } 668 669 return 0; 670} 671 672/* 673 * Fork a program with: 674 * 0 <-> remote tty in 675 * 1 <-> remote tty out 676 * 2 <-> local tty out 677 */ 678consh(c) 679{ 680 char buf[256]; 681 putchar(c); 682 if (prompt("Local command? ", buf)) 683 return; 684 tiplink (buf, TL_SIGNAL_TIPOUT | TL_VERBOSE); 685} 686#endif 687 688/* 689 * Escape to local shell 690 */ 691shell() 692{ 693 int shpid, status; 694 extern char **environ; 695 char *cp; 696 697 printf("[sh]\r\n"); 698 signal(SIGINT, SIG_IGN); 699 signal(SIGQUIT, SIG_IGN); 700 unraw(); 701 if (shpid = fork()) { 702 while (shpid != wait(&status)); 703 raw(); 704 printf("\r\n!\r\n"); 705 signal(SIGINT, SIG_DFL); 706 signal(SIGQUIT, SIG_DFL); 707 return; 708 } else { 709 signal(SIGQUIT, SIG_DFL); 710 signal(SIGINT, SIG_DFL); 711 if ((cp = rindex(value(SHELL), '/')) == NULL) 712 cp = value(SHELL); 713 else 714 cp++; 715 shell_uid(); 716 execl(value(SHELL), cp, 0); 717 printf("\r\ncan't execl!\r\n"); 718 exit(1); 719 } 720} 721 722/* 723 * TIPIN portion of scripting 724 * initiate the conversation with TIPOUT 725 */ 726setscript() 727{ 728 char c; 729 /* 730 * enable TIPOUT side for dialogue 731 */ 732 kill(pid, SIGEMT); 733 if (boolean(value(SCRIPT))) 734 write(fildes[1], value(RECORD), size(value(RECORD))); 735 write(fildes[1], "\n", 1); 736 /* 737 * wait for TIPOUT to finish 738 */ 739 read(repdes[0], &c, 1); 740 if (c == 'n') 741 printf("can't create %s\r\n", value(RECORD)); 742} 743 744/* 745 * Change current working directory of 746 * local portion of tip 747 */ 748chdirectory() 749{ 750 char dirname[80]; 751 register char *cp = dirname; 752 753 if (prompt("[cd] ", dirname)) { 754 if (stoprompt) 755 return; 756 cp = value(HOME); 757 } 758 if (chdir(cp) < 0) 759 printf("%s: bad directory\r\n", cp); 760 printf("!\r\n"); 761} 762 763tipabort(msg) 764 char *msg; 765{ 766 767 kill(pid, SIGTERM); 768 disconnect(msg); 769 if (msg != NOSTR) 770 printf("\r\n%s", msg); 771 printf("\r\n[EOT]\r\n"); 772 daemon_uid(); 773 (void)uu_unlock(uucplock); 774 unraw(); 775 exit(0); 776} 777 778finish() 779{ 780 char *abortmsg = NOSTR, *dismsg; 781 782 if (LO != NOSTR && tiplink (LO, TL_SIGNAL_TIPOUT) != 0) { 783 abortmsg = "logout failed"; 784 } 785 786 if ((dismsg = value(DISCONNECT)) != NOSTR) { 787 write(FD, dismsg, strlen(dismsg)); 788 sleep (2); 789 } 790 tipabort(abortmsg); 791} 792 793void 794intcopy() 795{ 796 raw(); 797 quit = 1; 798 longjmp(intbuf, 1); 799} 800 801execute(s) 802 char *s; 803{ 804 register char *cp; 805 806 if ((cp = rindex(value(SHELL), '/')) == NULL) 807 cp = value(SHELL); 808 else 809 cp++; 810 shell_uid(); 811 execl(value(SHELL), cp, "-c", s, 0); 812} 813 814args(buf, a) 815 char *buf, *a[]; 816{ 817 register char *p = buf, *start; 818 register char **parg = a; 819 register int n = 0; 820 821 do { 822 while (*p && (*p == ' ' || *p == '\t')) 823 p++; 824 start = p; 825 if (*p) 826 *parg = p; 827 while (*p && (*p != ' ' && *p != '\t')) 828 p++; 829 if (p != start) 830 parg++, n++; 831 if (*p) 832 *p++ = '\0'; 833 } while (*p); 834 835 return(n); 836} 837 838prtime(s, a) 839 char *s; 840 time_t a; 841{ 842 register i; 843 int nums[3]; 844 845 for (i = 0; i < 3; i++) { 846 nums[i] = (int)(a % quant[i]); 847 a /= quant[i]; 848 } 849 printf("%s", s); 850 while (--i >= 0) 851 if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0) 852 printf("%d %s%c ", nums[i], sep[i], 853 nums[i] == 1 ? '\0' : 's'); 854 printf("\r\n!\r\n"); 855} 856 857variable() 858{ 859 char buf[256]; 860 861 if (prompt("[set] ", buf)) 862 return; 863 vlex(buf); 864 if (vtable[BEAUTIFY].v_access&CHANGED) { 865 vtable[BEAUTIFY].v_access &= ~CHANGED; 866 kill(pid, SIGSYS); 867 } 868 if (vtable[SCRIPT].v_access&CHANGED) { 869 vtable[SCRIPT].v_access &= ~CHANGED; 870 setscript(); 871 /* 872 * So that "set record=blah script" doesn't 873 * cause two transactions to occur. 874 */ 875 if (vtable[RECORD].v_access&CHANGED) 876 vtable[RECORD].v_access &= ~CHANGED; 877 } 878 if (vtable[RECORD].v_access&CHANGED) { 879 vtable[RECORD].v_access &= ~CHANGED; 880 if (boolean(value(SCRIPT))) 881 setscript(); 882 } 883 if (vtable[TAND].v_access&CHANGED) { 884 vtable[TAND].v_access &= ~CHANGED; 885 if (boolean(value(TAND))) 886 tandem("on"); 887 else 888 tandem("off"); 889 } 890 if (vtable[LECHO].v_access&CHANGED) { 891 vtable[LECHO].v_access &= ~CHANGED; 892 HD = boolean(value(LECHO)); 893 } 894 if (vtable[PARITY].v_access&CHANGED) { 895 vtable[PARITY].v_access &= ~CHANGED; 896 setparity(); 897 } 898} 899 900/* 901 * Turn tandem mode on or off for remote tty. 902 */ 903tandem(option) 904 char *option; 905{ 906#if HAVE_TERMIOS 907 struct termios ttermios; 908 tcgetattr (FD, &ttermios); 909 if (strcmp(option,"on") == 0) { 910 ttermios.c_iflag |= IXOFF; 911 ctermios.c_iflag |= IXOFF; 912 } 913 else { 914 ttermios.c_iflag &= ~IXOFF; 915 ctermios.c_iflag &= ~IXOFF; 916 } 917 tcsetattr (FD, TCSANOW, &ttermios); 918 tcsetattr (0, TCSANOW, &ctermios); 919#else /* HAVE_TERMIOS */ 920 struct sgttyb rmtty; 921 922 ioctl(FD, TIOCGETP, &rmtty); 923 if (strcmp(option,"on") == 0) { 924 rmtty.sg_flags |= TANDEM; 925 arg.sg_flags |= TANDEM; 926 } else { 927 rmtty.sg_flags &= ~TANDEM; 928 arg.sg_flags &= ~TANDEM; 929 } 930 ioctl(FD, TIOCSETP, &rmtty); 931 ioctl(0, TIOCSETP, &arg); 932#endif /* HAVE_TERMIOS */ 933} 934 935/* 936 * Send a break. 937 */ 938genbrk() 939{ 940 941 ioctl(FD, TIOCSBRK, NULL); 942 sleep(1); 943 ioctl(FD, TIOCCBRK, NULL); 944} 945 946/* 947 * Suspend tip 948 */ 949suspend(c) 950 char c; 951{ 952 953 unraw(); 954 kill(c == CTRL('y') ? getpid() : 0, SIGTSTP); 955 raw(); 956} 957 958/* 959 * expand a file name if it includes shell meta characters 960 */ 961 962char * 963expand(name) 964 char name[]; 965{ 966 static char xname[BUFSIZ]; 967 char cmdbuf[BUFSIZ]; 968 register int pid, l, rc; 969 register char *cp, *Shell; 970 int s, pivec[2], (*sigint)(); 971 972 if (!anyof(name, "~{[*?$`'\"\\")) 973 return(name); 974 /* sigint = signal(SIGINT, SIG_IGN); */ 975 if (pipe(pivec) < 0) { 976 perror("pipe"); 977 /* signal(SIGINT, sigint) */ 978 return(name); 979 } 980 sprintf(cmdbuf, "echo %s", name); 981 if ((pid = vfork()) == 0) { 982 Shell = value(SHELL); 983 if (Shell == NOSTR) 984 Shell = _PATH_BSHELL; 985 close(pivec[0]); 986 close(1); 987 dup(pivec[1]); 988 close(pivec[1]); 989 close(2); 990 shell_uid(); 991 execl(Shell, Shell, "-c", cmdbuf, 0); 992 _exit(1); 993 } 994 if (pid == -1) { 995 perror("fork"); 996 close(pivec[0]); 997 close(pivec[1]); 998 return(NOSTR); 999 } 1000 close(pivec[1]); 1001 l = read(pivec[0], xname, BUFSIZ); 1002 close(pivec[0]); 1003 while (wait(&s) != pid); 1004 ; 1005 s &= 0377; 1006 if (s != 0 && s != SIGPIPE) { 1007 fprintf(stderr, "\"Echo\" failed\n"); 1008 return(NOSTR); 1009 } 1010 if (l < 0) { 1011 perror("read"); 1012 return(NOSTR); 1013 } 1014 if (l == 0) { 1015 fprintf(stderr, "\"%s\": No match\n", name); 1016 return(NOSTR); 1017 } 1018 if (l == BUFSIZ) { 1019 fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); 1020 return(NOSTR); 1021 } 1022 xname[l] = 0; 1023 for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) 1024 ; 1025 *++cp = '\0'; 1026 return(xname); 1027} 1028 1029/* 1030 * Are any of the characters in the two strings the same? 1031 */ 1032 1033anyof(s1, s2) 1034 register char *s1, *s2; 1035{ 1036 register int c; 1037 1038 while (c = *s1++) 1039 if (any(c, s2)) 1040 return(1); 1041 return(0); 1042} 1043