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

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