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