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