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

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