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

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