Annotation of src/usr.bin/tip/cmds.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: cmds.c,v 1.5 1995/09/26 06:02:08 jtc Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1983, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: #ifndef lint
! 37: #if 0
! 38: static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
! 39: #endif
! 40: static char rcsid[] = "$NetBSD: cmds.c,v 1.5 1995/09/26 06:02:08 jtc Exp $";
! 41: #endif /* not lint */
! 42:
! 43: #include "tip.h"
! 44: #include "pathnames.h"
! 45:
! 46: /*
! 47: * tip
! 48: *
! 49: * miscellaneous commands
! 50: */
! 51:
! 52: int quant[] = { 60, 60, 24 };
! 53:
! 54: char null = '\0';
! 55: char *sep[] = { "second", "minute", "hour" };
! 56: static char *argv[10]; /* argument vector for take and put */
! 57:
! 58: void timeout(); /* timeout function called on alarm */
! 59: void stopsnd(); /* SIGINT handler during file transfers */
! 60: void intcopy(); /* interrupt routine for file transfers */
! 61:
! 62: /*
! 63: * FTP - remote ==> local
! 64: * get a file from the remote host
! 65: */
! 66: getfl(c)
! 67: char c;
! 68: {
! 69: char buf[256], *cp, *expand();
! 70:
! 71: putchar(c);
! 72: /*
! 73: * get the UNIX receiving file's name
! 74: */
! 75: if (prompt("Local file name? ", copyname))
! 76: return;
! 77: cp = expand(copyname);
! 78: if ((sfd = creat(cp, 0666)) < 0) {
! 79: printf("\r\n%s: cannot creat\r\n", copyname);
! 80: return;
! 81: }
! 82:
! 83: /*
! 84: * collect parameters
! 85: */
! 86: if (prompt("List command for remote system? ", buf)) {
! 87: unlink(copyname);
! 88: return;
! 89: }
! 90: transfer(buf, sfd, value(EOFREAD));
! 91: }
! 92:
! 93: /*
! 94: * Cu-like take command
! 95: */
! 96: cu_take(cc)
! 97: char cc;
! 98: {
! 99: int fd, argc;
! 100: char line[BUFSIZ], *expand(), *cp;
! 101:
! 102: if (prompt("[take] ", copyname))
! 103: return;
! 104: if ((argc = args(copyname, argv)) < 1 || argc > 2) {
! 105: 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 ((fd = creat(cp, 0666)) < 0) {
! 112: printf("\r\n%s: cannot create\r\n", argv[1]);
! 113: return;
! 114: }
! 115: sprintf(line, "cat %s;echo \01", argv[0]);
! 116: transfer(line, fd, "\01");
! 117: }
! 118:
! 119: static jmp_buf intbuf;
! 120: /*
! 121: * Bulk transfer routine --
! 122: * used by getfl(), cu_take(), and pipefile()
! 123: */
! 124: transfer(buf, fd, eofchars)
! 125: char *buf, *eofchars;
! 126: {
! 127: register int ct;
! 128: char c, buffer[BUFSIZ];
! 129: register char *p = buffer;
! 130: register int cnt, eof;
! 131: time_t start;
! 132: sig_t f;
! 133: char r;
! 134:
! 135: pwrite(FD, buf, size(buf));
! 136: quit = 0;
! 137: kill(pid, SIGIOT);
! 138: read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
! 139:
! 140: /*
! 141: * finish command
! 142: */
! 143: r = '\r';
! 144: pwrite(FD, &r, 1);
! 145: do
! 146: read(FD, &c, 1);
! 147: while ((c&0177) != '\n');
! 148: ioctl(0, TIOCSETC, &defchars);
! 149:
! 150: (void) setjmp(intbuf);
! 151: f = signal(SIGINT, intcopy);
! 152: start = time(0);
! 153: for (ct = 0; !quit;) {
! 154: eof = read(FD, &c, 1) <= 0;
! 155: c &= 0177;
! 156: if (quit)
! 157: continue;
! 158: if (eof || any(c, eofchars))
! 159: break;
! 160: if (c == 0)
! 161: continue; /* ignore nulls */
! 162: if (c == '\r')
! 163: continue;
! 164: *p++ = c;
! 165:
! 166: if (c == '\n' && boolean(value(VERBOSE)))
! 167: printf("\r%d", ++ct);
! 168: if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
! 169: if (write(fd, buffer, cnt) != cnt) {
! 170: printf("\r\nwrite error\r\n");
! 171: quit = 1;
! 172: }
! 173: p = buffer;
! 174: }
! 175: }
! 176: if (cnt = (p-buffer))
! 177: if (write(fd, buffer, cnt) != cnt)
! 178: printf("\r\nwrite error\r\n");
! 179:
! 180: if (boolean(value(VERBOSE)))
! 181: prtime(" lines transferred in ", time(0)-start);
! 182: ioctl(0, TIOCSETC, &tchars);
! 183: write(fildes[1], (char *)&ccc, 1);
! 184: signal(SIGINT, f);
! 185: close(fd);
! 186: }
! 187:
! 188: /*
! 189: * FTP - remote ==> local process
! 190: * send remote input to local process via pipe
! 191: */
! 192: pipefile()
! 193: {
! 194: int cpid, pdes[2];
! 195: char buf[256];
! 196: int status, p;
! 197: extern int errno;
! 198:
! 199: if (prompt("Local command? ", buf))
! 200: return;
! 201:
! 202: if (pipe(pdes)) {
! 203: printf("can't establish pipe\r\n");
! 204: return;
! 205: }
! 206:
! 207: if ((cpid = fork()) < 0) {
! 208: printf("can't fork!\r\n");
! 209: return;
! 210: } else if (cpid) {
! 211: if (prompt("List command for remote system? ", buf)) {
! 212: close(pdes[0]), close(pdes[1]);
! 213: kill (cpid, SIGKILL);
! 214: } else {
! 215: close(pdes[0]);
! 216: signal(SIGPIPE, intcopy);
! 217: transfer(buf, pdes[1], value(EOFREAD));
! 218: signal(SIGPIPE, SIG_DFL);
! 219: while ((p = wait(&status)) > 0 && p != cpid)
! 220: ;
! 221: }
! 222: } else {
! 223: register int f;
! 224:
! 225: dup2(pdes[0], 0);
! 226: close(pdes[0]);
! 227: for (f = 3; f < 20; f++)
! 228: close(f);
! 229: execute(buf);
! 230: printf("can't execl!\r\n");
! 231: exit(0);
! 232: }
! 233: }
! 234:
! 235: /*
! 236: * Interrupt service routine for FTP
! 237: */
! 238: void
! 239: stopsnd()
! 240: {
! 241:
! 242: stop = 1;
! 243: signal(SIGINT, SIG_IGN);
! 244: }
! 245:
! 246: /*
! 247: * FTP - local ==> remote
! 248: * send local file to remote host
! 249: * terminate transmission with pseudo EOF sequence
! 250: */
! 251: sendfile(cc)
! 252: char cc;
! 253: {
! 254: FILE *fd;
! 255: char *fnamex;
! 256: char *expand();
! 257:
! 258: putchar(cc);
! 259: /*
! 260: * get file name
! 261: */
! 262: if (prompt("Local file name? ", fname))
! 263: return;
! 264:
! 265: /*
! 266: * look up file
! 267: */
! 268: fnamex = expand(fname);
! 269: if ((fd = fopen(fnamex, "r")) == NULL) {
! 270: printf("%s: cannot open\r\n", fname);
! 271: return;
! 272: }
! 273: transmit(fd, value(EOFWRITE), NULL);
! 274: if (!boolean(value(ECHOCHECK))) {
! 275: struct sgttyb buf;
! 276:
! 277: ioctl(FD, TIOCGETP, &buf); /* this does a */
! 278: ioctl(FD, TIOCSETP, &buf); /* wflushtty */
! 279: }
! 280: }
! 281:
! 282: /*
! 283: * Bulk transfer routine to remote host --
! 284: * used by sendfile() and cu_put()
! 285: */
! 286: transmit(fd, eofchars, command)
! 287: FILE *fd;
! 288: char *eofchars, *command;
! 289: {
! 290: char *pc, lastc;
! 291: int c, ccount, lcount;
! 292: time_t start_t, stop_t;
! 293: sig_t f;
! 294:
! 295: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
! 296: stop = 0;
! 297: f = signal(SIGINT, stopsnd);
! 298: ioctl(0, TIOCSETC, &defchars);
! 299: read(repdes[0], (char *)&ccc, 1);
! 300: if (command != NULL) {
! 301: for (pc = command; *pc; pc++)
! 302: send(*pc);
! 303: if (boolean(value(ECHOCHECK)))
! 304: read(FD, (char *)&c, 1); /* trailing \n */
! 305: else {
! 306: struct sgttyb buf;
! 307:
! 308: ioctl(FD, TIOCGETP, &buf); /* this does a */
! 309: ioctl(FD, TIOCSETP, &buf); /* wflushtty */
! 310: sleep(5); /* wait for remote stty to take effect */
! 311: }
! 312: }
! 313: lcount = 0;
! 314: lastc = '\0';
! 315: start_t = time(0);
! 316: while (1) {
! 317: ccount = 0;
! 318: do {
! 319: c = getc(fd);
! 320: if (stop)
! 321: goto out;
! 322: if (c == EOF)
! 323: goto out;
! 324: if (c == 0177 && !boolean(value(RAWFTP)))
! 325: continue;
! 326: lastc = c;
! 327: if (c < 040) {
! 328: if (c == '\n') {
! 329: if (!boolean(value(RAWFTP)))
! 330: c = '\r';
! 331: }
! 332: else if (c == '\t') {
! 333: if (!boolean(value(RAWFTP))) {
! 334: if (boolean(value(TABEXPAND))) {
! 335: send(' ');
! 336: while ((++ccount % 8) != 0)
! 337: send(' ');
! 338: continue;
! 339: }
! 340: }
! 341: } else
! 342: if (!boolean(value(RAWFTP)))
! 343: continue;
! 344: }
! 345: send(c);
! 346: } while (c != '\r' && !boolean(value(RAWFTP)));
! 347: if (boolean(value(VERBOSE)))
! 348: printf("\r%d", ++lcount);
! 349: if (boolean(value(ECHOCHECK))) {
! 350: timedout = 0;
! 351: alarm((long)value(ETIMEOUT));
! 352: do { /* wait for prompt */
! 353: read(FD, (char *)&c, 1);
! 354: if (timedout || stop) {
! 355: if (timedout)
! 356: printf("\r\ntimed out at eol\r\n");
! 357: alarm(0);
! 358: goto out;
! 359: }
! 360: } while ((c&0177) != character(value(PROMPT)));
! 361: alarm(0);
! 362: }
! 363: }
! 364: out:
! 365: if (lastc != '\n' && !boolean(value(RAWFTP)))
! 366: send('\r');
! 367: if (eofchars) {
! 368: for (pc = eofchars; *pc; pc++)
! 369: send(*pc);
! 370: }
! 371: stop_t = time(0);
! 372: fclose(fd);
! 373: signal(SIGINT, f);
! 374: if (boolean(value(VERBOSE)))
! 375: if (boolean(value(RAWFTP)))
! 376: prtime(" chars transferred in ", stop_t-start_t);
! 377: else
! 378: prtime(" lines transferred in ", stop_t-start_t);
! 379: write(fildes[1], (char *)&ccc, 1);
! 380: ioctl(0, TIOCSETC, &tchars);
! 381: }
! 382:
! 383: /*
! 384: * Cu-like put command
! 385: */
! 386: cu_put(cc)
! 387: char cc;
! 388: {
! 389: FILE *fd;
! 390: char line[BUFSIZ];
! 391: int argc;
! 392: char *expand();
! 393: char *copynamex;
! 394:
! 395: if (prompt("[put] ", copyname))
! 396: return;
! 397: if ((argc = args(copyname, argv)) < 1 || argc > 2) {
! 398: printf("usage: <put> from [to]\r\n");
! 399: return;
! 400: }
! 401: if (argc == 1)
! 402: argv[1] = argv[0];
! 403: copynamex = expand(argv[0]);
! 404: if ((fd = fopen(copynamex, "r")) == NULL) {
! 405: printf("%s: cannot open\r\n", copynamex);
! 406: return;
! 407: }
! 408: if (boolean(value(ECHOCHECK)))
! 409: sprintf(line, "cat>%s\r", argv[1]);
! 410: else
! 411: sprintf(line, "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: send(c)
! 420: char c;
! 421: {
! 422: char cc;
! 423: int retry = 0;
! 424:
! 425: cc = c;
! 426: pwrite(FD, &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: alarm((long)value(ETIMEOUT));
! 441: read(FD, &cc, 1);
! 442: alarm(0);
! 443: if (timedout) {
! 444: printf("\r\ntimeout error (%s)\r\n", ctrl(c));
! 445: if (retry++ > 3)
! 446: return;
! 447: pwrite(FD, &null, 1); /* poke it */
! 448: goto tryagain;
! 449: }
! 450: }
! 451:
! 452: void
! 453: timeout()
! 454: {
! 455: signal(SIGALRM, timeout);
! 456: timedout = 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: pipeout(c)
! 464: {
! 465: char buf[256];
! 466: int cpid, status, p;
! 467: time_t start;
! 468:
! 469: putchar(c);
! 470: if (prompt("Local command? ", buf))
! 471: return;
! 472: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
! 473: signal(SIGINT, SIG_IGN);
! 474: signal(SIGQUIT, SIG_IGN);
! 475: ioctl(0, TIOCSETC, &defchars);
! 476: read(repdes[0], (char *)&ccc, 1);
! 477: /*
! 478: * Set up file descriptors in the child and
! 479: * let it go...
! 480: */
! 481: if ((cpid = fork()) < 0)
! 482: printf("can't fork!\r\n");
! 483: else if (cpid) {
! 484: start = time(0);
! 485: while ((p = wait(&status)) > 0 && p != cpid)
! 486: ;
! 487: } else {
! 488: register int i;
! 489:
! 490: dup2(FD, 1);
! 491: for (i = 3; i < 20; i++)
! 492: close(i);
! 493: signal(SIGINT, SIG_DFL);
! 494: signal(SIGQUIT, SIG_DFL);
! 495: execute(buf);
! 496: printf("can't find `%s'\r\n", buf);
! 497: exit(0);
! 498: }
! 499: if (boolean(value(VERBOSE)))
! 500: prtime("away for ", time(0)-start);
! 501: write(fildes[1], (char *)&ccc, 1);
! 502: ioctl(0, TIOCSETC, &tchars);
! 503: signal(SIGINT, SIG_DFL);
! 504: signal(SIGQUIT, SIG_DFL);
! 505: }
! 506:
! 507: #ifdef CONNECT
! 508: /*
! 509: * Fork a program with:
! 510: * 0 <-> remote tty in
! 511: * 1 <-> remote tty out
! 512: * 2 <-> local tty out
! 513: */
! 514: consh(c)
! 515: {
! 516: char buf[256];
! 517: int cpid, status, p;
! 518: time_t start;
! 519:
! 520: putchar(c);
! 521: if (prompt("Local command? ", buf))
! 522: return;
! 523: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
! 524: signal(SIGINT, SIG_IGN);
! 525: signal(SIGQUIT, SIG_IGN);
! 526: ioctl(0, TIOCSETC, &defchars);
! 527: read(repdes[0], (char *)&ccc, 1);
! 528: /*
! 529: * Set up file descriptors in the child and
! 530: * let it go...
! 531: */
! 532: if ((cpid = fork()) < 0)
! 533: printf("can't fork!\r\n");
! 534: else if (cpid) {
! 535: start = time(0);
! 536: while ((p = wait(&status)) > 0 && p != cpid)
! 537: ;
! 538: } else {
! 539: register int i;
! 540:
! 541: dup2(FD, 0);
! 542: dup2(3, 1);
! 543: for (i = 3; i < 20; i++)
! 544: close(i);
! 545: signal(SIGINT, SIG_DFL);
! 546: signal(SIGQUIT, SIG_DFL);
! 547: execute(buf);
! 548: printf("can't find `%s'\r\n", buf);
! 549: exit(0);
! 550: }
! 551: if (boolean(value(VERBOSE)))
! 552: prtime("away for ", time(0)-start);
! 553: write(fildes[1], (char *)&ccc, 1);
! 554: ioctl(0, TIOCSETC, &tchars);
! 555: signal(SIGINT, SIG_DFL);
! 556: signal(SIGQUIT, SIG_DFL);
! 557: }
! 558: #endif
! 559:
! 560: /*
! 561: * Escape to local shell
! 562: */
! 563: shell()
! 564: {
! 565: int shpid, status;
! 566: extern char **environ;
! 567: char *cp;
! 568:
! 569: printf("[sh]\r\n");
! 570: signal(SIGINT, SIG_IGN);
! 571: signal(SIGQUIT, SIG_IGN);
! 572: unraw();
! 573: if (shpid = fork()) {
! 574: while (shpid != wait(&status));
! 575: raw();
! 576: printf("\r\n!\r\n");
! 577: signal(SIGINT, SIG_DFL);
! 578: signal(SIGQUIT, SIG_DFL);
! 579: return;
! 580: } else {
! 581: signal(SIGQUIT, SIG_DFL);
! 582: signal(SIGINT, SIG_DFL);
! 583: if ((cp = rindex(value(SHELL), '/')) == NULL)
! 584: cp = value(SHELL);
! 585: else
! 586: cp++;
! 587: shell_uid();
! 588: execl(value(SHELL), cp, 0);
! 589: printf("\r\ncan't execl!\r\n");
! 590: exit(1);
! 591: }
! 592: }
! 593:
! 594: /*
! 595: * TIPIN portion of scripting
! 596: * initiate the conversation with TIPOUT
! 597: */
! 598: setscript()
! 599: {
! 600: char c;
! 601: /*
! 602: * enable TIPOUT side for dialogue
! 603: */
! 604: kill(pid, SIGEMT);
! 605: if (boolean(value(SCRIPT)))
! 606: write(fildes[1], value(RECORD), size(value(RECORD)));
! 607: write(fildes[1], "\n", 1);
! 608: /*
! 609: * wait for TIPOUT to finish
! 610: */
! 611: read(repdes[0], &c, 1);
! 612: if (c == 'n')
! 613: printf("can't create %s\r\n", value(RECORD));
! 614: }
! 615:
! 616: /*
! 617: * Change current working directory of
! 618: * local portion of tip
! 619: */
! 620: chdirectory()
! 621: {
! 622: char dirname[80];
! 623: register char *cp = dirname;
! 624:
! 625: if (prompt("[cd] ", dirname)) {
! 626: if (stoprompt)
! 627: return;
! 628: cp = value(HOME);
! 629: }
! 630: if (chdir(cp) < 0)
! 631: printf("%s: bad directory\r\n", cp);
! 632: printf("!\r\n");
! 633: }
! 634:
! 635: tipabort(msg)
! 636: char *msg;
! 637: {
! 638:
! 639: kill(pid, SIGTERM);
! 640: disconnect(msg);
! 641: if (msg != NOSTR)
! 642: printf("\r\n%s", msg);
! 643: printf("\r\n[EOT]\r\n");
! 644: daemon_uid();
! 645: (void)uu_unlock(uucplock);
! 646: unraw();
! 647: exit(0);
! 648: }
! 649:
! 650: finish()
! 651: {
! 652: char *dismsg;
! 653:
! 654: if ((dismsg = value(DISCONNECT)) != NOSTR) {
! 655: write(FD, dismsg, strlen(dismsg));
! 656: sleep(5);
! 657: }
! 658: tipabort(NOSTR);
! 659: }
! 660:
! 661: void
! 662: intcopy()
! 663: {
! 664: raw();
! 665: quit = 1;
! 666: longjmp(intbuf, 1);
! 667: }
! 668:
! 669: execute(s)
! 670: char *s;
! 671: {
! 672: register char *cp;
! 673:
! 674: if ((cp = rindex(value(SHELL), '/')) == NULL)
! 675: cp = value(SHELL);
! 676: else
! 677: cp++;
! 678: shell_uid();
! 679: execl(value(SHELL), cp, "-c", s, 0);
! 680: }
! 681:
! 682: args(buf, a)
! 683: char *buf, *a[];
! 684: {
! 685: register char *p = buf, *start;
! 686: register char **parg = a;
! 687: register int n = 0;
! 688:
! 689: do {
! 690: while (*p && (*p == ' ' || *p == '\t'))
! 691: p++;
! 692: start = p;
! 693: if (*p)
! 694: *parg = p;
! 695: while (*p && (*p != ' ' && *p != '\t'))
! 696: p++;
! 697: if (p != start)
! 698: parg++, n++;
! 699: if (*p)
! 700: *p++ = '\0';
! 701: } while (*p);
! 702:
! 703: return(n);
! 704: }
! 705:
! 706: prtime(s, a)
! 707: char *s;
! 708: time_t a;
! 709: {
! 710: register i;
! 711: int nums[3];
! 712:
! 713: for (i = 0; i < 3; i++) {
! 714: nums[i] = (int)(a % quant[i]);
! 715: a /= quant[i];
! 716: }
! 717: printf("%s", s);
! 718: while (--i >= 0)
! 719: if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
! 720: printf("%d %s%c ", nums[i], sep[i],
! 721: nums[i] == 1 ? '\0' : 's');
! 722: printf("\r\n!\r\n");
! 723: }
! 724:
! 725: variable()
! 726: {
! 727: char buf[256];
! 728:
! 729: if (prompt("[set] ", buf))
! 730: return;
! 731: vlex(buf);
! 732: if (vtable[BEAUTIFY].v_access&CHANGED) {
! 733: vtable[BEAUTIFY].v_access &= ~CHANGED;
! 734: kill(pid, SIGSYS);
! 735: }
! 736: if (vtable[SCRIPT].v_access&CHANGED) {
! 737: vtable[SCRIPT].v_access &= ~CHANGED;
! 738: setscript();
! 739: /*
! 740: * So that "set record=blah script" doesn't
! 741: * cause two transactions to occur.
! 742: */
! 743: if (vtable[RECORD].v_access&CHANGED)
! 744: vtable[RECORD].v_access &= ~CHANGED;
! 745: }
! 746: if (vtable[RECORD].v_access&CHANGED) {
! 747: vtable[RECORD].v_access &= ~CHANGED;
! 748: if (boolean(value(SCRIPT)))
! 749: setscript();
! 750: }
! 751: if (vtable[TAND].v_access&CHANGED) {
! 752: vtable[TAND].v_access &= ~CHANGED;
! 753: if (boolean(value(TAND)))
! 754: tandem("on");
! 755: else
! 756: tandem("off");
! 757: }
! 758: if (vtable[LECHO].v_access&CHANGED) {
! 759: vtable[LECHO].v_access &= ~CHANGED;
! 760: HD = boolean(value(LECHO));
! 761: }
! 762: if (vtable[PARITY].v_access&CHANGED) {
! 763: vtable[PARITY].v_access &= ~CHANGED;
! 764: setparity();
! 765: }
! 766: }
! 767:
! 768: /*
! 769: * Turn tandem mode on or off for remote tty.
! 770: */
! 771: tandem(option)
! 772: char *option;
! 773: {
! 774: struct sgttyb rmtty;
! 775:
! 776: ioctl(FD, TIOCGETP, &rmtty);
! 777: if (strcmp(option,"on") == 0) {
! 778: rmtty.sg_flags |= TANDEM;
! 779: arg.sg_flags |= TANDEM;
! 780: } else {
! 781: rmtty.sg_flags &= ~TANDEM;
! 782: arg.sg_flags &= ~TANDEM;
! 783: }
! 784: ioctl(FD, TIOCSETP, &rmtty);
! 785: ioctl(0, TIOCSETP, &arg);
! 786: }
! 787:
! 788: /*
! 789: * Send a break.
! 790: */
! 791: genbrk()
! 792: {
! 793:
! 794: ioctl(FD, TIOCSBRK, NULL);
! 795: sleep(1);
! 796: ioctl(FD, TIOCCBRK, NULL);
! 797: }
! 798:
! 799: /*
! 800: * Suspend tip
! 801: */
! 802: suspend(c)
! 803: char c;
! 804: {
! 805:
! 806: unraw();
! 807: kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
! 808: raw();
! 809: }
! 810:
! 811: /*
! 812: * expand a file name if it includes shell meta characters
! 813: */
! 814:
! 815: char *
! 816: expand(name)
! 817: char name[];
! 818: {
! 819: static char xname[BUFSIZ];
! 820: char cmdbuf[BUFSIZ];
! 821: register int pid, l, rc;
! 822: register char *cp, *Shell;
! 823: int s, pivec[2], (*sigint)();
! 824:
! 825: if (!anyof(name, "~{[*?$`'\"\\"))
! 826: return(name);
! 827: /* sigint = signal(SIGINT, SIG_IGN); */
! 828: if (pipe(pivec) < 0) {
! 829: perror("pipe");
! 830: /* signal(SIGINT, sigint) */
! 831: return(name);
! 832: }
! 833: sprintf(cmdbuf, "echo %s", name);
! 834: if ((pid = vfork()) == 0) {
! 835: Shell = value(SHELL);
! 836: if (Shell == NOSTR)
! 837: Shell = _PATH_BSHELL;
! 838: close(pivec[0]);
! 839: close(1);
! 840: dup(pivec[1]);
! 841: close(pivec[1]);
! 842: close(2);
! 843: shell_uid();
! 844: execl(Shell, Shell, "-c", cmdbuf, 0);
! 845: _exit(1);
! 846: }
! 847: if (pid == -1) {
! 848: perror("fork");
! 849: close(pivec[0]);
! 850: close(pivec[1]);
! 851: return(NOSTR);
! 852: }
! 853: close(pivec[1]);
! 854: l = read(pivec[0], xname, BUFSIZ);
! 855: close(pivec[0]);
! 856: while (wait(&s) != pid);
! 857: ;
! 858: s &= 0377;
! 859: if (s != 0 && s != SIGPIPE) {
! 860: fprintf(stderr, "\"Echo\" failed\n");
! 861: return(NOSTR);
! 862: }
! 863: if (l < 0) {
! 864: perror("read");
! 865: return(NOSTR);
! 866: }
! 867: if (l == 0) {
! 868: fprintf(stderr, "\"%s\": No match\n", name);
! 869: return(NOSTR);
! 870: }
! 871: if (l == BUFSIZ) {
! 872: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
! 873: return(NOSTR);
! 874: }
! 875: xname[l] = 0;
! 876: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
! 877: ;
! 878: *++cp = '\0';
! 879: return(xname);
! 880: }
! 881:
! 882: /*
! 883: * Are any of the characters in the two strings the same?
! 884: */
! 885:
! 886: anyof(s1, s2)
! 887: register char *s1, *s2;
! 888: {
! 889: register int c;
! 890:
! 891: while (c = *s1++)
! 892: if (any(c, s2))
! 893: return(1);
! 894: return(0);
! 895: }