[BACK]Return to cmds.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tip

Annotation of src/usr.bin/tip/cmds.c, Revision 1.1.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: }