1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * 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 35 /*static char sccsid[] = "from: @(#)cmds.c 5.15 (Berkeley) 3/4/91";*/ 36 static char rcsid[] = "$Id: cmds.c,v 1.2 1993/08/01 18:06:43 mycroft Exp $"; 37 #endif /* not lint */ 38 39 #include "tip.h" 40 #include "pathnames.h" 41 42 /* 43 * tip 44 * 45 * miscellaneous commands 46 */ 47 48 int quant[] = { 60, 60, 24 }; 49 50 char null = '\0'; 51 char *sep[] = { "second", "minute", "hour" }; 52 static char *argv[10]; /* argument vector for take and put */ 53 54 void timeout(); /* timeout function called on alarm */ 55 void stopsnd(); /* SIGINT handler during file transfers */ 56 void intcopy(); /* interrupt routine for file transfers */ 57 58 /* 59 * FTP - remote ==> local 60 * get a file from the remote host 61 */ 62 getfl(c) 63 char c; 64 { 65 char buf[256], *cp, *expand(); 66 67 putchar(c); 68 /* 69 * get the UNIX receiving file's name 70 */ 71 if (prompt("Local file name? ", copyname)) 72 return; 73 cp = expand(copyname); 74 if ((sfd = creat(cp, 0666)) < 0) { 75 printf("\r\n%s: cannot creat\r\n", copyname); 76 return; 77 } 78 79 /* 80 * collect parameters 81 */ 82 if (prompt("List command for remote system? ", buf)) { 83 unlink(copyname); 84 return; 85 } 86 transfer(buf, sfd, value(EOFREAD)); 87 } 88 89 /* 90 * Cu-like take command 91 */ 92 cu_take(cc) 93 char cc; 94 { 95 int fd, argc; 96 char line[BUFSIZ], *expand(), *cp; 97 98 if (prompt("[take] ", copyname)) 99 return; 100 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 101 printf("usage: <take> from [to]\r\n"); 102 return; 103 } 104 if (argc == 1) 105 argv[1] = argv[0]; 106 cp = expand(argv[1]); 107 if ((fd = creat(cp, 0666)) < 0) { 108 printf("\r\n%s: cannot create\r\n", argv[1]); 109 return; 110 } 111 sprintf(line, "cat %s;echo \01", argv[0]); 112 transfer(line, fd, "\01"); 113 } 114 115 static jmp_buf intbuf; 116 /* 117 * Bulk transfer routine -- 118 * used by getfl(), cu_take(), and pipefile() 119 */ 120 transfer(buf, fd, eofchars) 121 char *buf, *eofchars; 122 { 123 register int ct; 124 char c, buffer[BUFSIZ]; 125 register char *p = buffer; 126 register int cnt, eof; 127 time_t start; 128 sig_t f; 129 130 pwrite(FD, buf, size(buf)); 131 quit = 0; 132 kill(pid, SIGIOT); 133 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 134 135 /* 136 * finish command 137 */ 138 pwrite(FD, "\r", 1); 139 do 140 read(FD, &c, 1); 141 while ((c&0177) != '\n'); 142 ioctl(0, TIOCSETC, &defchars); 143 144 (void) setjmp(intbuf); 145 f = signal(SIGINT, intcopy); 146 start = time(0); 147 for (ct = 0; !quit;) { 148 eof = read(FD, &c, 1) <= 0; 149 c &= 0177; 150 if (quit) 151 continue; 152 if (eof || any(c, eofchars)) 153 break; 154 if (c == 0) 155 continue; /* ignore nulls */ 156 if (c == '\r') 157 continue; 158 *p++ = c; 159 160 if (c == '\n' && boolean(value(VERBOSE))) 161 printf("\r%d", ++ct); 162 if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) { 163 if (write(fd, buffer, cnt) != cnt) { 164 printf("\r\nwrite error\r\n"); 165 quit = 1; 166 } 167 p = buffer; 168 } 169 } 170 if (cnt = (p-buffer)) 171 if (write(fd, buffer, cnt) != cnt) 172 printf("\r\nwrite error\r\n"); 173 174 if (boolean(value(VERBOSE))) 175 prtime(" lines transferred in ", time(0)-start); 176 ioctl(0, TIOCSETC, &tchars); 177 write(fildes[1], (char *)&ccc, 1); 178 signal(SIGINT, f); 179 close(fd); 180 } 181 182 /* 183 * FTP - remote ==> local process 184 * send remote input to local process via pipe 185 */ 186 pipefile() 187 { 188 int cpid, pdes[2]; 189 char buf[256]; 190 int status, p; 191 extern int errno; 192 193 if (prompt("Local command? ", buf)) 194 return; 195 196 if (pipe(pdes)) { 197 printf("can't establish pipe\r\n"); 198 return; 199 } 200 201 if ((cpid = fork()) < 0) { 202 printf("can't fork!\r\n"); 203 return; 204 } else if (cpid) { 205 if (prompt("List command for remote system? ", buf)) { 206 close(pdes[0]), close(pdes[1]); 207 kill (cpid, SIGKILL); 208 } else { 209 close(pdes[0]); 210 signal(SIGPIPE, intcopy); 211 transfer(buf, pdes[1], value(EOFREAD)); 212 signal(SIGPIPE, SIG_DFL); 213 while ((p = wait(&status)) > 0 && p != cpid) 214 ; 215 } 216 } else { 217 register int f; 218 219 dup2(pdes[0], 0); 220 close(pdes[0]); 221 for (f = 3; f < 20; f++) 222 close(f); 223 execute(buf); 224 printf("can't execl!\r\n"); 225 exit(0); 226 } 227 } 228 229 /* 230 * Interrupt service routine for FTP 231 */ 232 void 233 stopsnd() 234 { 235 236 stop = 1; 237 signal(SIGINT, SIG_IGN); 238 } 239 240 /* 241 * FTP - local ==> remote 242 * send local file to remote host 243 * terminate transmission with pseudo EOF sequence 244 */ 245 sendfile(cc) 246 char cc; 247 { 248 FILE *fd; 249 char *fnamex; 250 char *expand(); 251 252 putchar(cc); 253 /* 254 * get file name 255 */ 256 if (prompt("Local file name? ", fname)) 257 return; 258 259 /* 260 * look up file 261 */ 262 fnamex = expand(fname); 263 if ((fd = fopen(fnamex, "r")) == NULL) { 264 printf("%s: cannot open\r\n", fname); 265 return; 266 } 267 transmit(fd, value(EOFWRITE), NULL); 268 if (!boolean(value(ECHOCHECK))) { 269 struct sgttyb buf; 270 271 ioctl(FD, TIOCGETP, &buf); /* this does a */ 272 ioctl(FD, TIOCSETP, &buf); /* wflushtty */ 273 } 274 } 275 276 /* 277 * Bulk transfer routine to remote host -- 278 * used by sendfile() and cu_put() 279 */ 280 transmit(fd, eofchars, command) 281 FILE *fd; 282 char *eofchars, *command; 283 { 284 char *pc, lastc; 285 int c, ccount, lcount; 286 time_t start_t, stop_t; 287 sig_t f; 288 289 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 290 stop = 0; 291 f = signal(SIGINT, stopsnd); 292 ioctl(0, TIOCSETC, &defchars); 293 read(repdes[0], (char *)&ccc, 1); 294 if (command != NULL) { 295 for (pc = command; *pc; pc++) 296 send(*pc); 297 if (boolean(value(ECHOCHECK))) 298 read(FD, (char *)&c, 1); /* trailing \n */ 299 else { 300 struct sgttyb buf; 301 302 ioctl(FD, TIOCGETP, &buf); /* this does a */ 303 ioctl(FD, TIOCSETP, &buf); /* wflushtty */ 304 sleep(5); /* wait for remote stty to take effect */ 305 } 306 } 307 lcount = 0; 308 lastc = '\0'; 309 start_t = time(0); 310 while (1) { 311 ccount = 0; 312 do { 313 c = getc(fd); 314 if (stop) 315 goto out; 316 if (c == EOF) 317 goto out; 318 if (c == 0177 && !boolean(value(RAWFTP))) 319 continue; 320 lastc = c; 321 if (c < 040) { 322 if (c == '\n') { 323 if (!boolean(value(RAWFTP))) 324 c = '\r'; 325 } 326 else if (c == '\t') { 327 if (!boolean(value(RAWFTP))) { 328 if (boolean(value(TABEXPAND))) { 329 send(' '); 330 while ((++ccount % 8) != 0) 331 send(' '); 332 continue; 333 } 334 } 335 } else 336 if (!boolean(value(RAWFTP))) 337 continue; 338 } 339 send(c); 340 } while (c != '\r' && !boolean(value(RAWFTP))); 341 if (boolean(value(VERBOSE))) 342 printf("\r%d", ++lcount); 343 if (boolean(value(ECHOCHECK))) { 344 timedout = 0; 345 alarm((int)value(ETIMEOUT)); 346 do { /* wait for prompt */ 347 read(FD, (char *)&c, 1); 348 if (timedout || stop) { 349 if (timedout) 350 printf("\r\ntimed out at eol\r\n"); 351 alarm(0); 352 goto out; 353 } 354 } while ((c&0177) != character(value(PROMPT))); 355 alarm(0); 356 } 357 } 358 out: 359 if (lastc != '\n' && !boolean(value(RAWFTP))) 360 send('\r'); 361 for (pc = eofchars; *pc; pc++) 362 send(*pc); 363 stop_t = time(0); 364 fclose(fd); 365 signal(SIGINT, f); 366 if (boolean(value(VERBOSE))) 367 if (boolean(value(RAWFTP))) 368 prtime(" chars transferred in ", stop_t-start_t); 369 else 370 prtime(" lines transferred in ", stop_t-start_t); 371 write(fildes[1], (char *)&ccc, 1); 372 ioctl(0, TIOCSETC, &tchars); 373 } 374 375 /* 376 * Cu-like put command 377 */ 378 cu_put(cc) 379 char cc; 380 { 381 FILE *fd; 382 char line[BUFSIZ]; 383 int argc; 384 char *expand(); 385 char *copynamex; 386 387 if (prompt("[put] ", copyname)) 388 return; 389 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 390 printf("usage: <put> from [to]\r\n"); 391 return; 392 } 393 if (argc == 1) 394 argv[1] = argv[0]; 395 copynamex = expand(argv[0]); 396 if ((fd = fopen(copynamex, "r")) == NULL) { 397 printf("%s: cannot open\r\n", copynamex); 398 return; 399 } 400 if (boolean(value(ECHOCHECK))) 401 sprintf(line, "cat>%s\r", argv[1]); 402 else 403 sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]); 404 transmit(fd, "\04", line); 405 } 406 407 /* 408 * FTP - send single character 409 * wait for echo & handle timeout 410 */ 411 send(c) 412 char c; 413 { 414 char cc; 415 int retry = 0; 416 417 cc = c; 418 pwrite(FD, &cc, 1); 419 #ifdef notdef 420 if (number(value(CDELAY)) > 0 && c != '\r') 421 nap(number(value(CDELAY))); 422 #endif 423 if (!boolean(value(ECHOCHECK))) { 424 #ifdef notdef 425 if (number(value(LDELAY)) > 0 && c == '\r') 426 nap(number(value(LDELAY))); 427 #endif 428 return; 429 } 430 tryagain: 431 timedout = 0; 432 alarm((int)value(ETIMEOUT)); 433 read(FD, &cc, 1); 434 alarm(0); 435 if (timedout) { 436 printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 437 if (retry++ > 3) 438 return; 439 pwrite(FD, &null, 1); /* poke it */ 440 goto tryagain; 441 } 442 } 443 444 void 445 timeout() 446 { 447 signal(SIGALRM, timeout); 448 timedout = 1; 449 } 450 451 /* 452 * Stolen from consh() -- puts a remote file on the output of a local command. 453 * Identical to consh() except for where stdout goes. 454 */ 455 pipeout(c) 456 { 457 char buf[256]; 458 int cpid, status, p; 459 time_t start; 460 461 putchar(c); 462 if (prompt("Local command? ", buf)) 463 return; 464 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 465 signal(SIGINT, SIG_IGN); 466 signal(SIGQUIT, SIG_IGN); 467 ioctl(0, TIOCSETC, &defchars); 468 read(repdes[0], (char *)&ccc, 1); 469 /* 470 * Set up file descriptors in the child and 471 * let it go... 472 */ 473 if ((cpid = fork()) < 0) 474 printf("can't fork!\r\n"); 475 else if (cpid) { 476 start = time(0); 477 while ((p = wait(&status)) > 0 && p != cpid) 478 ; 479 } else { 480 register int i; 481 482 dup2(FD, 1); 483 for (i = 3; i < 20; i++) 484 close(i); 485 signal(SIGINT, SIG_DFL); 486 signal(SIGQUIT, SIG_DFL); 487 execute(buf); 488 printf("can't find `%s'\r\n", buf); 489 exit(0); 490 } 491 if (boolean(value(VERBOSE))) 492 prtime("away for ", time(0)-start); 493 write(fildes[1], (char *)&ccc, 1); 494 ioctl(0, TIOCSETC, &tchars); 495 signal(SIGINT, SIG_DFL); 496 signal(SIGQUIT, SIG_DFL); 497 } 498 499 #ifdef CONNECT 500 /* 501 * Fork a program with: 502 * 0 <-> remote tty in 503 * 1 <-> remote tty out 504 * 2 <-> local tty out 505 */ 506 consh(c) 507 { 508 char buf[256]; 509 int cpid, status, p; 510 time_t start; 511 512 putchar(c); 513 if (prompt("Local command? ", buf)) 514 return; 515 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 516 signal(SIGINT, SIG_IGN); 517 signal(SIGQUIT, SIG_IGN); 518 ioctl(0, TIOCSETC, &defchars); 519 read(repdes[0], (char *)&ccc, 1); 520 /* 521 * Set up file descriptors in the child and 522 * let it go... 523 */ 524 if ((cpid = fork()) < 0) 525 printf("can't fork!\r\n"); 526 else if (cpid) { 527 start = time(0); 528 while ((p = wait(&status)) > 0 && p != cpid) 529 ; 530 } else { 531 register int i; 532 533 dup2(1, 2); 534 dup2(FD, 0); 535 dup2(0, 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 ioctl(0, TIOCSETC, &tchars); 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 sgttyb rmtty; 768 769 ioctl(FD, TIOCGETP, &rmtty); 770 if (strcmp(option,"on") == 0) { 771 rmtty.sg_flags |= TANDEM; 772 arg.sg_flags |= TANDEM; 773 } else { 774 rmtty.sg_flags &= ~TANDEM; 775 arg.sg_flags &= ~TANDEM; 776 } 777 ioctl(FD, TIOCSETP, &rmtty); 778 ioctl(0, TIOCSETP, &arg); 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