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