[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.2

1.2     ! deraadt     1: /*     $NetBSD: cmds.c,v 1.6 1995/10/29 00:49:38 pk Exp $      */
1.1       deraadt     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
1.2     ! deraadt    40: static char rcsid[] = "$NetBSD: cmds.c,v 1.6 1995/10/29 00:49:38 pk Exp $";
1.1       deraadt    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);
1.2     ! deraadt   147:        while ((c&STRIP_PAR) != '\n');
        !           148:        tcsetattr(0, TCSAFLUSH, &defchars);
1.1       deraadt   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;
1.2     ! deraadt   155:                c &= STRIP_PAR;
1.1       deraadt   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);
1.2     ! deraadt   182:        tcsetattr(0, TCSAFLUSH, &term);
1.1       deraadt   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);
1.2     ! deraadt   274:        if (!boolean(value(ECHOCHECK)))
        !           275:                tcdrain(FD);
1.1       deraadt   276: }
                    277:
                    278: /*
                    279:  * Bulk transfer routine to remote host --
                    280:  *   used by sendfile() and cu_put()
                    281:  */
                    282: transmit(fd, eofchars, command)
                    283:        FILE *fd;
                    284:        char *eofchars, *command;
                    285: {
                    286:        char *pc, lastc;
                    287:        int c, ccount, lcount;
                    288:        time_t start_t, stop_t;
                    289:        sig_t f;
                    290:
                    291:        kill(pid, SIGIOT);      /* put TIPOUT into a wait state */
                    292:        stop = 0;
                    293:        f = signal(SIGINT, stopsnd);
1.2     ! deraadt   294:        tcsetattr(0, TCSAFLUSH, &defchars);
1.1       deraadt   295:        read(repdes[0], (char *)&ccc, 1);
                    296:        if (command != NULL) {
                    297:                for (pc = command; *pc; pc++)
                    298:                        send(*pc);
                    299:                if (boolean(value(ECHOCHECK)))
                    300:                        read(FD, (char *)&c, 1);        /* trailing \n */
                    301:                else {
1.2     ! deraadt   302:                        tcdrain(FD);
1.1       deraadt   303:                        sleep(5); /* wait for remote stty to take effect */
                    304:                }
                    305:        }
                    306:        lcount = 0;
                    307:        lastc = '\0';
                    308:        start_t = time(0);
                    309:        while (1) {
                    310:                ccount = 0;
                    311:                do {
                    312:                        c = getc(fd);
                    313:                        if (stop)
                    314:                                goto out;
                    315:                        if (c == EOF)
                    316:                                goto out;
                    317:                        if (c == 0177 && !boolean(value(RAWFTP)))
                    318:                                continue;
                    319:                        lastc = c;
                    320:                        if (c < 040) {
                    321:                                if (c == '\n') {
                    322:                                        if (!boolean(value(RAWFTP)))
                    323:                                                c = '\r';
                    324:                                }
                    325:                                else if (c == '\t') {
                    326:                                        if (!boolean(value(RAWFTP))) {
                    327:                                                if (boolean(value(TABEXPAND))) {
                    328:                                                        send(' ');
                    329:                                                        while ((++ccount % 8) != 0)
                    330:                                                                send(' ');
                    331:                                                        continue;
                    332:                                                }
                    333:                                        }
                    334:                                } else
                    335:                                        if (!boolean(value(RAWFTP)))
                    336:                                                continue;
                    337:                        }
                    338:                        send(c);
                    339:                } while (c != '\r' && !boolean(value(RAWFTP)));
                    340:                if (boolean(value(VERBOSE)))
                    341:                        printf("\r%d", ++lcount);
                    342:                if (boolean(value(ECHOCHECK))) {
                    343:                        timedout = 0;
                    344:                        alarm((long)value(ETIMEOUT));
                    345:                        do {    /* wait for prompt */
                    346:                                read(FD, (char *)&c, 1);
                    347:                                if (timedout || stop) {
                    348:                                        if (timedout)
                    349:                                                printf("\r\ntimed out at eol\r\n");
                    350:                                        alarm(0);
                    351:                                        goto out;
                    352:                                }
1.2     ! deraadt   353:                        } while ((c&STRIP_PAR) != character(value(PROMPT)));
1.1       deraadt   354:                        alarm(0);
                    355:                }
                    356:        }
                    357: out:
                    358:        if (lastc != '\n' && !boolean(value(RAWFTP)))
                    359:                send('\r');
                    360:        if (eofchars) {
                    361:                for (pc = eofchars; *pc; pc++)
                    362:                        send(*pc);
                    363:        }
                    364:        stop_t = time(0);
                    365:        fclose(fd);
                    366:        signal(SIGINT, f);
                    367:        if (boolean(value(VERBOSE)))
                    368:                if (boolean(value(RAWFTP)))
                    369:                        prtime(" chars transferred in ", stop_t-start_t);
                    370:                else
                    371:                        prtime(" lines transferred in ", stop_t-start_t);
                    372:        write(fildes[1], (char *)&ccc, 1);
1.2     ! deraadt   373:        tcsetattr(0, TCSAFLUSH, &term);
1.1       deraadt   374: }
                    375:
                    376: /*
                    377:  * Cu-like put command
                    378:  */
                    379: cu_put(cc)
                    380:        char cc;
                    381: {
                    382:        FILE *fd;
                    383:        char line[BUFSIZ];
                    384:        int argc;
                    385:        char *expand();
                    386:        char *copynamex;
                    387:
                    388:        if (prompt("[put] ", copyname))
                    389:                return;
                    390:        if ((argc = args(copyname, argv)) < 1 || argc > 2) {
                    391:                printf("usage: <put> from [to]\r\n");
                    392:                return;
                    393:        }
                    394:        if (argc == 1)
                    395:                argv[1] = argv[0];
                    396:        copynamex = expand(argv[0]);
                    397:        if ((fd = fopen(copynamex, "r")) == NULL) {
                    398:                printf("%s: cannot open\r\n", copynamex);
                    399:                return;
                    400:        }
                    401:        if (boolean(value(ECHOCHECK)))
                    402:                sprintf(line, "cat>%s\r", argv[1]);
                    403:        else
                    404:                sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]);
                    405:        transmit(fd, "\04", line);
                    406: }
                    407:
                    408: /*
                    409:  * FTP - send single character
                    410:  *  wait for echo & handle timeout
                    411:  */
                    412: send(c)
                    413:        char c;
                    414: {
                    415:        char cc;
                    416:        int retry = 0;
                    417:
                    418:        cc = c;
                    419:        pwrite(FD, &cc, 1);
                    420: #ifdef notdef
                    421:        if (number(value(CDELAY)) > 0 && c != '\r')
                    422:                nap(number(value(CDELAY)));
                    423: #endif
                    424:        if (!boolean(value(ECHOCHECK))) {
                    425: #ifdef notdef
                    426:                if (number(value(LDELAY)) > 0 && c == '\r')
                    427:                        nap(number(value(LDELAY)));
                    428: #endif
                    429:                return;
                    430:        }
                    431: tryagain:
                    432:        timedout = 0;
                    433:        alarm((long)value(ETIMEOUT));
                    434:        read(FD, &cc, 1);
                    435:        alarm(0);
                    436:        if (timedout) {
                    437:                printf("\r\ntimeout error (%s)\r\n", ctrl(c));
                    438:                if (retry++ > 3)
                    439:                        return;
                    440:                pwrite(FD, &null, 1); /* poke it */
                    441:                goto tryagain;
                    442:        }
                    443: }
                    444:
                    445: void
                    446: timeout()
                    447: {
                    448:        signal(SIGALRM, timeout);
                    449:        timedout = 1;
                    450: }
                    451:
                    452: /*
                    453:  * Stolen from consh() -- puts a remote file on the output of a local command.
                    454:  *     Identical to consh() except for where stdout goes.
                    455:  */
                    456: pipeout(c)
                    457: {
                    458:        char buf[256];
                    459:        int cpid, status, p;
                    460:        time_t start;
                    461:
                    462:        putchar(c);
                    463:        if (prompt("Local command? ", buf))
                    464:                return;
                    465:        kill(pid, SIGIOT);      /* put TIPOUT into a wait state */
                    466:        signal(SIGINT, SIG_IGN);
                    467:        signal(SIGQUIT, SIG_IGN);
1.2     ! deraadt   468:        tcsetattr(0, TCSAFLUSH, &defchars);
1.1       deraadt   469:        read(repdes[0], (char *)&ccc, 1);
                    470:        /*
                    471:         * Set up file descriptors in the child and
                    472:         *  let it go...
                    473:         */
                    474:        if ((cpid = fork()) < 0)
                    475:                printf("can't fork!\r\n");
                    476:        else if (cpid) {
                    477:                start = time(0);
                    478:                while ((p = wait(&status)) > 0 && p != cpid)
                    479:                        ;
                    480:        } else {
                    481:                register int i;
                    482:
                    483:                dup2(FD, 1);
                    484:                for (i = 3; i < 20; i++)
                    485:                        close(i);
                    486:                signal(SIGINT, SIG_DFL);
                    487:                signal(SIGQUIT, SIG_DFL);
                    488:                execute(buf);
                    489:                printf("can't find `%s'\r\n", buf);
                    490:                exit(0);
                    491:        }
                    492:        if (boolean(value(VERBOSE)))
                    493:                prtime("away for ", time(0)-start);
                    494:        write(fildes[1], (char *)&ccc, 1);
1.2     ! deraadt   495:        tcsetattr(0, TCSAFLUSH, &term);
1.1       deraadt   496:        signal(SIGINT, SIG_DFL);
                    497:        signal(SIGQUIT, SIG_DFL);
                    498: }
                    499:
                    500: #ifdef CONNECT
                    501: /*
                    502:  * Fork a program with:
                    503:  *  0 <-> remote tty in
                    504:  *  1 <-> remote tty out
                    505:  *  2 <-> local tty out
                    506:  */
                    507: consh(c)
                    508: {
                    509:        char buf[256];
                    510:        int cpid, status, p;
                    511:        time_t start;
                    512:
                    513:        putchar(c);
                    514:        if (prompt("Local command? ", buf))
                    515:                return;
                    516:        kill(pid, SIGIOT);      /* put TIPOUT into a wait state */
                    517:        signal(SIGINT, SIG_IGN);
                    518:        signal(SIGQUIT, SIG_IGN);
1.2     ! deraadt   519:        tcsetattr(0, TCSAFLUSH, &defchars);
1.1       deraadt   520:        read(repdes[0], (char *)&ccc, 1);
                    521:        /*
                    522:         * Set up file descriptors in the child and
                    523:         *  let it go...
                    524:         */
                    525:        if ((cpid = fork()) < 0)
                    526:                printf("can't fork!\r\n");
                    527:        else if (cpid) {
                    528:                start = time(0);
                    529:                while ((p = wait(&status)) > 0 && p != cpid)
                    530:                        ;
                    531:        } else {
                    532:                register int i;
                    533:
                    534:                dup2(FD, 0);
                    535:                dup2(3, 1);
                    536:                for (i = 3; i < 20; i++)
                    537:                        close(i);
                    538:                signal(SIGINT, SIG_DFL);
                    539:                signal(SIGQUIT, SIG_DFL);
                    540:                execute(buf);
                    541:                printf("can't find `%s'\r\n", buf);
                    542:                exit(0);
                    543:        }
                    544:        if (boolean(value(VERBOSE)))
                    545:                prtime("away for ", time(0)-start);
                    546:        write(fildes[1], (char *)&ccc, 1);
1.2     ! deraadt   547:        tcsetattr(0, TCSAFLUSH, &term);
1.1       deraadt   548:        signal(SIGINT, SIG_DFL);
                    549:        signal(SIGQUIT, SIG_DFL);
                    550: }
                    551: #endif
                    552:
                    553: /*
                    554:  * Escape to local shell
                    555:  */
                    556: shell()
                    557: {
                    558:        int shpid, status;
                    559:        extern char **environ;
                    560:        char *cp;
                    561:
                    562:        printf("[sh]\r\n");
                    563:        signal(SIGINT, SIG_IGN);
                    564:        signal(SIGQUIT, SIG_IGN);
                    565:        unraw();
                    566:        if (shpid = fork()) {
                    567:                while (shpid != wait(&status));
                    568:                raw();
                    569:                printf("\r\n!\r\n");
                    570:                signal(SIGINT, SIG_DFL);
                    571:                signal(SIGQUIT, SIG_DFL);
                    572:                return;
                    573:        } else {
                    574:                signal(SIGQUIT, SIG_DFL);
                    575:                signal(SIGINT, SIG_DFL);
                    576:                if ((cp = rindex(value(SHELL), '/')) == NULL)
                    577:                        cp = value(SHELL);
                    578:                else
                    579:                        cp++;
                    580:                shell_uid();
                    581:                execl(value(SHELL), cp, 0);
                    582:                printf("\r\ncan't execl!\r\n");
                    583:                exit(1);
                    584:        }
                    585: }
                    586:
                    587: /*
                    588:  * TIPIN portion of scripting
                    589:  *   initiate the conversation with TIPOUT
                    590:  */
                    591: setscript()
                    592: {
                    593:        char c;
                    594:        /*
                    595:         * enable TIPOUT side for dialogue
                    596:         */
                    597:        kill(pid, SIGEMT);
                    598:        if (boolean(value(SCRIPT)))
                    599:                write(fildes[1], value(RECORD), size(value(RECORD)));
                    600:        write(fildes[1], "\n", 1);
                    601:        /*
                    602:         * wait for TIPOUT to finish
                    603:         */
                    604:        read(repdes[0], &c, 1);
                    605:        if (c == 'n')
                    606:                printf("can't create %s\r\n", value(RECORD));
                    607: }
                    608:
                    609: /*
                    610:  * Change current working directory of
                    611:  *   local portion of tip
                    612:  */
                    613: chdirectory()
                    614: {
                    615:        char dirname[80];
                    616:        register char *cp = dirname;
                    617:
                    618:        if (prompt("[cd] ", dirname)) {
                    619:                if (stoprompt)
                    620:                        return;
                    621:                cp = value(HOME);
                    622:        }
                    623:        if (chdir(cp) < 0)
                    624:                printf("%s: bad directory\r\n", cp);
                    625:        printf("!\r\n");
                    626: }
                    627:
                    628: tipabort(msg)
                    629:        char *msg;
                    630: {
                    631:
                    632:        kill(pid, SIGTERM);
                    633:        disconnect(msg);
                    634:        if (msg != NOSTR)
                    635:                printf("\r\n%s", msg);
                    636:        printf("\r\n[EOT]\r\n");
                    637:        daemon_uid();
                    638:        (void)uu_unlock(uucplock);
                    639:        unraw();
                    640:        exit(0);
                    641: }
                    642:
                    643: finish()
                    644: {
                    645:        char *dismsg;
                    646:
                    647:        if ((dismsg = value(DISCONNECT)) != NOSTR) {
                    648:                write(FD, dismsg, strlen(dismsg));
                    649:                sleep(5);
                    650:        }
                    651:        tipabort(NOSTR);
                    652: }
                    653:
                    654: void
                    655: intcopy()
                    656: {
                    657:        raw();
                    658:        quit = 1;
                    659:        longjmp(intbuf, 1);
                    660: }
                    661:
                    662: execute(s)
                    663:        char *s;
                    664: {
                    665:        register char *cp;
                    666:
                    667:        if ((cp = rindex(value(SHELL), '/')) == NULL)
                    668:                cp = value(SHELL);
                    669:        else
                    670:                cp++;
                    671:        shell_uid();
                    672:        execl(value(SHELL), cp, "-c", s, 0);
                    673: }
                    674:
                    675: args(buf, a)
                    676:        char *buf, *a[];
                    677: {
                    678:        register char *p = buf, *start;
                    679:        register char **parg = a;
                    680:        register int n = 0;
                    681:
                    682:        do {
                    683:                while (*p && (*p == ' ' || *p == '\t'))
                    684:                        p++;
                    685:                start = p;
                    686:                if (*p)
                    687:                        *parg = p;
                    688:                while (*p && (*p != ' ' && *p != '\t'))
                    689:                        p++;
                    690:                if (p != start)
                    691:                        parg++, n++;
                    692:                if (*p)
                    693:                        *p++ = '\0';
                    694:        } while (*p);
                    695:
                    696:        return(n);
                    697: }
                    698:
                    699: prtime(s, a)
                    700:        char *s;
                    701:        time_t a;
                    702: {
                    703:        register i;
                    704:        int nums[3];
                    705:
                    706:        for (i = 0; i < 3; i++) {
                    707:                nums[i] = (int)(a % quant[i]);
                    708:                a /= quant[i];
                    709:        }
                    710:        printf("%s", s);
                    711:        while (--i >= 0)
                    712:                if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
                    713:                        printf("%d %s%c ", nums[i], sep[i],
                    714:                                nums[i] == 1 ? '\0' : 's');
                    715:        printf("\r\n!\r\n");
                    716: }
                    717:
                    718: variable()
                    719: {
                    720:        char    buf[256];
                    721:
                    722:        if (prompt("[set] ", buf))
                    723:                return;
                    724:        vlex(buf);
                    725:        if (vtable[BEAUTIFY].v_access&CHANGED) {
                    726:                vtable[BEAUTIFY].v_access &= ~CHANGED;
                    727:                kill(pid, SIGSYS);
                    728:        }
                    729:        if (vtable[SCRIPT].v_access&CHANGED) {
                    730:                vtable[SCRIPT].v_access &= ~CHANGED;
                    731:                setscript();
                    732:                /*
                    733:                 * So that "set record=blah script" doesn't
                    734:                 *  cause two transactions to occur.
                    735:                 */
                    736:                if (vtable[RECORD].v_access&CHANGED)
                    737:                        vtable[RECORD].v_access &= ~CHANGED;
                    738:        }
                    739:        if (vtable[RECORD].v_access&CHANGED) {
                    740:                vtable[RECORD].v_access &= ~CHANGED;
                    741:                if (boolean(value(SCRIPT)))
                    742:                        setscript();
                    743:        }
                    744:        if (vtable[TAND].v_access&CHANGED) {
                    745:                vtable[TAND].v_access &= ~CHANGED;
                    746:                if (boolean(value(TAND)))
                    747:                        tandem("on");
                    748:                else
                    749:                        tandem("off");
                    750:        }
                    751:        if (vtable[LECHO].v_access&CHANGED) {
                    752:                vtable[LECHO].v_access &= ~CHANGED;
                    753:                HD = boolean(value(LECHO));
                    754:        }
                    755:        if (vtable[PARITY].v_access&CHANGED) {
                    756:                vtable[PARITY].v_access &= ~CHANGED;
                    757:                setparity();
                    758:        }
                    759: }
                    760:
                    761: /*
                    762:  * Turn tandem mode on or off for remote tty.
                    763:  */
                    764: tandem(option)
                    765:        char *option;
                    766: {
1.2     ! deraadt   767:        struct termios  rmtty;
1.1       deraadt   768:
1.2     ! deraadt   769:        tcgetattr(FD, &rmtty);
        !           770:        if (strcmp(option, "on") == 0) {
        !           771:                rmtty.c_iflag |= IXOFF;
        !           772:                term.c_iflag |= IXOFF;
1.1       deraadt   773:        } else {
1.2     ! deraadt   774:                rmtty.c_iflag &= ~IXOFF;
        !           775:                term.c_iflag &= ~IXOFF;
1.1       deraadt   776:        }
1.2     ! deraadt   777:        tcsetattr(FD, TCSADRAIN, &rmtty);
        !           778:        tcsetattr(0, TCSADRAIN, &term);
1.1       deraadt   779: }
                    780:
                    781: /*
                    782:  * Send a break.
                    783:  */
                    784: genbrk()
                    785: {
                    786:
                    787:        ioctl(FD, TIOCSBRK, NULL);
                    788:        sleep(1);
                    789:        ioctl(FD, TIOCCBRK, NULL);
                    790: }
                    791:
                    792: /*
                    793:  * Suspend tip
                    794:  */
                    795: suspend(c)
                    796:        char c;
                    797: {
                    798:
                    799:        unraw();
                    800:        kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
                    801:        raw();
                    802: }
                    803:
                    804: /*
                    805:  *     expand a file name if it includes shell meta characters
                    806:  */
                    807:
                    808: char *
                    809: expand(name)
                    810:        char name[];
                    811: {
                    812:        static char xname[BUFSIZ];
                    813:        char cmdbuf[BUFSIZ];
                    814:        register int pid, l, rc;
                    815:        register char *cp, *Shell;
                    816:        int s, pivec[2], (*sigint)();
                    817:
                    818:        if (!anyof(name, "~{[*?$`'\"\\"))
                    819:                return(name);
                    820:        /* sigint = signal(SIGINT, SIG_IGN); */
                    821:        if (pipe(pivec) < 0) {
                    822:                perror("pipe");
                    823:                /* signal(SIGINT, sigint) */
                    824:                return(name);
                    825:        }
                    826:        sprintf(cmdbuf, "echo %s", name);
                    827:        if ((pid = vfork()) == 0) {
                    828:                Shell = value(SHELL);
                    829:                if (Shell == NOSTR)
                    830:                        Shell = _PATH_BSHELL;
                    831:                close(pivec[0]);
                    832:                close(1);
                    833:                dup(pivec[1]);
                    834:                close(pivec[1]);
                    835:                close(2);
                    836:                shell_uid();
                    837:                execl(Shell, Shell, "-c", cmdbuf, 0);
                    838:                _exit(1);
                    839:        }
                    840:        if (pid == -1) {
                    841:                perror("fork");
                    842:                close(pivec[0]);
                    843:                close(pivec[1]);
                    844:                return(NOSTR);
                    845:        }
                    846:        close(pivec[1]);
                    847:        l = read(pivec[0], xname, BUFSIZ);
                    848:        close(pivec[0]);
                    849:        while (wait(&s) != pid);
                    850:                ;
                    851:        s &= 0377;
                    852:        if (s != 0 && s != SIGPIPE) {
                    853:                fprintf(stderr, "\"Echo\" failed\n");
                    854:                return(NOSTR);
                    855:        }
                    856:        if (l < 0) {
                    857:                perror("read");
                    858:                return(NOSTR);
                    859:        }
                    860:        if (l == 0) {
                    861:                fprintf(stderr, "\"%s\": No match\n", name);
                    862:                return(NOSTR);
                    863:        }
                    864:        if (l == BUFSIZ) {
                    865:                fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
                    866:                return(NOSTR);
                    867:        }
                    868:        xname[l] = 0;
                    869:        for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
                    870:                ;
                    871:        *++cp = '\0';
                    872:        return(xname);
                    873: }
                    874:
                    875: /*
                    876:  * Are any of the characters in the two strings the same?
                    877:  */
                    878:
                    879: anyof(s1, s2)
                    880:        register char *s1, *s2;
                    881: {
                    882:        register int c;
                    883:
                    884:        while (c = *s1++)
                    885:                if (any(c, s2))
                    886:                        return(1);
                    887:        return(0);
                    888: }