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

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