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