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

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