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

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