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