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