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