[BACK]Return to tip.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tip

Annotation of src/usr.bin/tip/tip.c, Revision 1.56

1.56    ! deraadt     1: /*     $OpenBSD: tip.c,v 1.55 2015/02/07 10:07:15 deraadt Exp $        */
1.5       millert     2: /*     $NetBSD: tip.c,v 1.13 1997/04/20 00:03:05 mellon 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.20      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: /*
                     34:  * tip - UNIX link to other systems
                     35:  *  tip [-v] [-speed] system-name
                     36:  */
1.36      nicm       37:
                     38: #include <sys/types.h>
                     39: #include <sys/socket.h>
                     40:
1.49      nicm       41: #include <util.h>
                     42:
1.1       deraadt    43: #include "tip.h"
                     44:
1.26      moritz     45: static void    intprompt(int);
                     46: static void    tipin(void);
                     47: static int     escape(void);
                     48:
1.8       deraadt    49: int
1.25      deraadt    50: main(int argc, char *argv[])
1.1       deraadt    51: {
1.47      chl        52:        char *sys = NULL;
1.56    ! deraadt    53:        const char *errstr;
        !            54:        int baud;
1.36      nicm       55:        int i, pair[2];
1.32      mcbride    56:
1.53      nicm       57:        vinit();
                     58:
1.32      mcbride    59:        /* XXX preserve previous braindamaged behavior */
1.48      nicm       60:        vsetnum(DC, 1);
1.1       deraadt    61:
                     62:        if (argc > 4) {
1.34      sobrado    63:                fprintf(stderr, "usage: tip [-nv] [-speed] [system-name]\n");
1.1       deraadt    64:                exit(1);
                     65:        }
                     66:        if (!isatty(0)) {
1.13      millert    67:                fprintf(stderr, "%s: must be interactive\n", __progname);
1.1       deraadt    68:                exit(1);
                     69:        }
                     70:
                     71:        for (; argc > 1; argv++, argc--) {
                     72:                if (argv[1][0] != '-')
1.27      deraadt    73:                        sys = argv[1];
1.1       deraadt    74:                else switch (argv[1][1]) {
                     75:
                     76:                case 'v':
                     77:                        vflag++;
                     78:                        break;
                     79:
1.9       todd       80:                case 'n':
                     81:                        noesc++;
                     82:                        break;
                     83:
1.1       deraadt    84:                case '0': case '1': case '2': case '3': case '4':
                     85:                case '5': case '6': case '7': case '8': case '9':
1.56    ! deraadt    86:                        baud = strtonum(&argv[1][1], 0, INT_MAX, &errstr);
        !            87:                        if (errstr) {
        !            88:                                fprintf(stderr, "incorrect speed: %s\n", errstr);
        !            89:                                exit(1);
        !            90:                        }
        !            91:                        vsetnum(BAUDRATE, baud);
1.1       deraadt    92:                        break;
                     93:
                     94:                default:
1.13      millert    95:                        fprintf(stderr, "%s: %s, unknown option\n", __progname,
                     96:                            argv[1]);
1.1       deraadt    97:                        break;
                     98:                }
                     99:        }
                    100:
                    101:        (void)signal(SIGINT, cleanup);
                    102:        (void)signal(SIGQUIT, cleanup);
                    103:        (void)signal(SIGHUP, cleanup);
                    104:        (void)signal(SIGTERM, cleanup);
1.24      otto      105:        (void)signal(SIGCHLD, SIG_DFL);
1.52      nicm      106:
1.50      nicm      107:        FD = hunt(sys);
1.1       deraadt   108:        setbuf(stdout, NULL);
1.52      nicm      109:
1.1       deraadt   110:        loginit();
1.12      millert   111:        setparity("none");                      /* set the parity table */
1.1       deraadt   112:
1.48      nicm      113:        if (ttysetup(vgetnum(BAUDRATE))) {
1.49      nicm      114:                fprintf(stderr, "%s: bad baud rate %d\n", __progname,
1.48      nicm      115:                    vgetnum(BAUDRATE));
1.19      millert   116:                (void)uu_unlock(uucplock);
                    117:                exit(3);
                    118:        }
1.40      nicm      119:        con();
1.41      nicm      120:
1.10      jason     121:        i = fcntl(FD, F_GETFL);
                    122:        if (i == -1) {
                    123:                perror("fcntl");
1.23      deraadt   124:                cleanup(0);
1.10      jason     125:        }
                    126:        i = fcntl(FD, F_SETFL, i & ~O_NONBLOCK);
                    127:        if (i == -1) {
                    128:                perror("fcntl");
1.23      deraadt   129:                cleanup(0);
1.10      jason     130:        }
1.1       deraadt   131:
1.2       deraadt   132:        tcgetattr(0, &defterm);
1.22      deraadt   133:        gotdefterm = 1;
1.2       deraadt   134:        term = defterm;
                    135:        term.c_lflag &= ~(ICANON|IEXTEN|ECHO);
                    136:        term.c_iflag &= ~(INPCK|ICRNL);
                    137:        term.c_oflag &= ~OPOST;
                    138:        term.c_cc[VMIN] = 1;
                    139:        term.c_cc[VTIME] = 0;
                    140:        defchars = term;
                    141:        term.c_cc[VINTR] = term.c_cc[VQUIT] = term.c_cc[VSUSP] =
1.25      deraadt   142:            term.c_cc[VDSUSP] = term.c_cc[VDISCARD] =
                    143:            term.c_cc[VLNEXT] = _POSIX_VDISABLE;
1.1       deraadt   144:        raw();
                    145:
                    146:        (void)signal(SIGALRM, timeout);
1.29      deraadt   147:
1.48      nicm      148:        if (vgetnum(LINEDISC) != TTYDISC) {
                    149:                int ld = (int)vgetnum(LINEDISC);
1.29      deraadt   150:                ioctl(FD, TIOCSETD, &ld);
1.48      nicm      151:        }
1.1       deraadt   152:
1.36      nicm      153:        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) {
                    154:                (void)uu_unlock(uucplock);
                    155:                err(3, "socketpair");
                    156:        }
                    157:
1.1       deraadt   158:        /*
                    159:         * Everything's set up now:
                    160:         *      connection established (hardwired or dialup)
                    161:         *      line conditioned (baud rate, mode, etc.)
                    162:         *      internal data structures (variables)
                    163:         * so, fork one process for local side and one for remote.
                    164:         */
1.55      deraadt   165:        printf("\07connected\r\n");
1.23      deraadt   166:        tipin_pid = getpid();
1.36      nicm      167:        switch (tipout_pid = fork()) {
                    168:        case -1:
                    169:                (void)uu_unlock(uucplock);
                    170:                err(3, "fork");
                    171:        case 0:
                    172:                close(pair[1]);
                    173:                tipin_fd = pair[0];
                    174:                tipout();
                    175:        default:
                    176:                close(pair[0]);
                    177:                tipout_fd = pair[1];
1.1       deraadt   178:                tipin();
1.36      nicm      179:        }
1.1       deraadt   180:        /*NOTREACHED*/
1.8       deraadt   181:        exit(0);
1.40      nicm      182: }
                    183:
                    184: void
                    185: con(void)
                    186: {
1.48      nicm      187:        if (vgetstr(CONNECT) != NULL)
                    188:                parwrite(FD, vgetstr(CONNECT), size(vgetstr(CONNECT)));
                    189:        logent(vgetstr(HOST), vgetstr(DEVICE), "call completed");
1.1       deraadt   190: }
                    191:
                    192: void
1.23      deraadt   193: cleanup(int signo)
1.1       deraadt   194: {
                    195:        (void)uu_unlock(uucplock);
                    196:        if (odisc)
1.27      deraadt   197:                ioctl(0, TIOCSETD, &odisc);
1.22      deraadt   198:        unraw();
1.23      deraadt   199:        if (signo && tipout_pid) {
                    200:                kill(tipout_pid, signo);
                    201:                wait(NULL);
                    202:        }
1.1       deraadt   203:        exit(0);
                    204: }
                    205:
                    206: /*
                    207:  * put the controlling keyboard into raw mode
                    208:  */
1.8       deraadt   209: void
1.25      deraadt   210: raw(void)
1.1       deraadt   211: {
1.2       deraadt   212:        tcsetattr(0, TCSADRAIN, &term);
1.1       deraadt   213: }
                    214:
                    215:
                    216: /*
                    217:  * return keyboard to normal mode
                    218:  */
1.8       deraadt   219: void
1.25      deraadt   220: unraw(void)
1.1       deraadt   221: {
1.22      deraadt   222:        if (gotdefterm)
                    223:                tcsetattr(0, TCSADRAIN, &defterm);
1.1       deraadt   224: }
                    225:
                    226: static jmp_buf promptbuf;
                    227:
                    228: /*
                    229:  * Print string ``s'', then read a string
                    230:  *  in from the terminal.  Handles signals & allows use of
                    231:  *  normal erase and kill characters.
                    232:  */
1.8       deraadt   233: int
1.25      deraadt   234: prompt(char *s, char *p, size_t sz)
1.1       deraadt   235: {
1.15      millert   236:        int c;
                    237:        char *b = p;
1.1       deraadt   238:        sig_t oint, oquit;
                    239:
                    240:        stoprompt = 0;
                    241:        oint = signal(SIGINT, intprompt);
                    242:        oquit = signal(SIGQUIT, SIG_IGN);
                    243:        unraw();
                    244:        printf("%s", s);
                    245:        if (setjmp(promptbuf) == 0)
1.6       millert   246:                while ((c = getchar()) != EOF && (*p = c) != '\n' && --sz > 0)
1.1       deraadt   247:                        p++;
                    248:        *p = '\0';
                    249:
                    250:        raw();
                    251:        (void)signal(SIGINT, oint);
                    252:        (void)signal(SIGQUIT, oquit);
                    253:        return (stoprompt || p == b);
                    254: }
                    255:
                    256: /*
                    257:  * Interrupt service routine during prompting
                    258:  */
1.27      deraadt   259: /*ARGSUSED*/
1.26      moritz    260: static void
                    261: intprompt(int signo)
1.1       deraadt   262: {
                    263:        (void)signal(SIGINT, SIG_IGN);
                    264:        stoprompt = 1;
                    265:        printf("\r\n");
                    266:        longjmp(promptbuf, 1);
                    267: }
                    268:
                    269: /*
                    270:  * ****TIPIN   TIPIN****
                    271:  */
1.26      moritz    272: static void
1.25      deraadt   273: tipin(void)
1.1       deraadt   274: {
1.27      deraadt   275:        int bol = 1;
1.16      deraadt   276:        int gch;
1.17      deraadt   277:        char ch;
1.1       deraadt   278:
                    279:        /*
                    280:         * Kinda klugey here...
                    281:         *   check for scripting being turned on from the .tiprc file,
                    282:         *   but be careful about just using setscript(), as we may
                    283:         *   send a SIGEMT before tipout has a chance to set up catching
                    284:         *   it; so wait a second, then setscript()
                    285:         */
1.48      nicm      286:        if (vgetnum(SCRIPT)) {
1.1       deraadt   287:                sleep(1);
                    288:                setscript();
                    289:        }
                    290:
                    291:        while (1) {
1.54      kettenis  292:                gch = getchar();
                    293:                if (gch == EOF)
                    294:                        cleanup(0);
                    295:                gch &= STRIP_PAR;
1.48      nicm      296:                if (gch == vgetnum(ESCAPE) && bol) {
1.9       todd      297:                        if (!noesc) {
                    298:                                if (!(gch = escape()))
                    299:                                        continue;
                    300:                        }
1.55      deraadt   301:                } else if (gch == vgetnum(RAISECHAR)) {
1.48      nicm      302:                        vsetnum(RAISE, !vgetnum(RAISE));
1.1       deraadt   303:                        continue;
                    304:                } else if (gch == '\r') {
                    305:                        bol = 1;
1.17      deraadt   306:                        ch = gch;
                    307:                        parwrite(FD, &ch, 1);
1.48      nicm      308:                        if (vgetnum(HALFDUPLEX))
1.1       deraadt   309:                                printf("\r\n");
                    310:                        continue;
1.55      deraadt   311:                } else if (gch == vgetnum(FORCE)) {
1.54      kettenis  312:                        gch = getchar();
                    313:                        if (gch == EOF)
                    314:                                cleanup(0);
                    315:                        gch &= STRIP_PAR;
                    316:                }
1.48      nicm      317:                bol = any(gch, vgetstr(EOL));
                    318:                if (vgetnum(RAISE) && islower(gch))
1.1       deraadt   319:                        gch = toupper(gch);
1.17      deraadt   320:                ch = gch;
                    321:                parwrite(FD, &ch, 1);
1.48      nicm      322:                if (vgetnum(HALFDUPLEX))
1.17      deraadt   323:                        printf("%c", ch);
1.1       deraadt   324:        }
                    325: }
                    326:
                    327: extern esctable_t etable[];
                    328:
                    329: /*
                    330:  * Escape handler --
                    331:  *  called on recognition of ``escapec'' at the beginning of a line
                    332:  */
1.26      moritz    333: static int
1.25      deraadt   334: escape(void)
1.1       deraadt   335: {
1.16      deraadt   336:        int gch;
1.15      millert   337:        esctable_t *p;
1.48      nicm      338:        char c = vgetnum(ESCAPE);
1.1       deraadt   339:
1.54      kettenis  340:        gch = getchar();
                    341:        if (gch == EOF)
                    342:                cleanup(0);
                    343:        gch &= STRIP_PAR;
1.1       deraadt   344:        for (p = etable; p->e_char; p++)
                    345:                if (p->e_char == gch) {
                    346:                        printf("%s", ctrl(c));
                    347:                        (*p->e_func)(gch);
                    348:                        return (0);
                    349:                }
                    350:        /* ESCAPE ESCAPE forces ESCAPE */
                    351:        if (c != gch)
1.11      deraadt   352:                parwrite(FD, &c, 1);
1.1       deraadt   353:        return (gch);
                    354: }
                    355:
1.8       deraadt   356: int
1.25      deraadt   357: any(int cc, char *p)
1.1       deraadt   358: {
1.8       deraadt   359:        char c = cc;
1.1       deraadt   360:        while (p && *p)
                    361:                if (*p++ == c)
                    362:                        return (1);
                    363:        return (0);
                    364: }
                    365:
1.28      deraadt   366: size_t
1.25      deraadt   367: size(char *s)
1.1       deraadt   368: {
1.28      deraadt   369:        size_t i = 0;
1.1       deraadt   370:
                    371:        while (s && *s++)
                    372:                i++;
                    373:        return (i);
                    374: }
                    375:
                    376: char *
1.25      deraadt   377: interp(char *s)
1.1       deraadt   378: {
                    379:        static char buf[256];
1.15      millert   380:        char *p = buf, c, *q;
1.1       deraadt   381:
1.8       deraadt   382:        while ((c = *s++)) {
1.1       deraadt   383:                for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
                    384:                        if (*q++ == c) {
                    385:                                *p++ = '\\'; *p++ = *q;
                    386:                                goto next;
                    387:                        }
                    388:                if (c < 040) {
                    389:                        *p++ = '^'; *p++ = c + 'A'-1;
                    390:                } else if (c == 0177) {
                    391:                        *p++ = '^'; *p++ = '?';
                    392:                } else
                    393:                        *p++ = c;
                    394:        next:
                    395:                ;
                    396:        }
                    397:        *p = '\0';
                    398:        return (buf);
                    399: }
                    400:
                    401: char *
1.25      deraadt   402: ctrl(char c)
1.1       deraadt   403: {
                    404:        static char s[3];
                    405:
                    406:        if (c < 040 || c == 0177) {
                    407:                s[0] = '^';
                    408:                s[1] = c == 0177 ? '?' : c+'A'-1;
                    409:                s[2] = '\0';
                    410:        } else {
                    411:                s[0] = c;
                    412:                s[1] = '\0';
                    413:        }
                    414:        return (s);
                    415: }
                    416:
                    417: /*
                    418:  * Help command
                    419:  */
1.8       deraadt   420: void
1.26      moritz    421: help(int c)
1.1       deraadt   422: {
1.15      millert   423:        esctable_t *p;
1.1       deraadt   424:
                    425:        printf("%c\r\n", c);
                    426:        for (p = etable; p->e_char; p++) {
1.48      nicm      427:                printf("%2s", ctrl(vgetnum(ESCAPE)));
1.37      nicm      428:                printf("%-2s     %s\r\n", ctrl(p->e_char), p->e_help);
1.1       deraadt   429:        }
                    430: }
                    431:
                    432: /*
                    433:  * Set up the "remote" tty's state
                    434:  */
1.19      millert   435: int
1.25      deraadt   436: ttysetup(int speed)
1.1       deraadt   437: {
1.2       deraadt   438:        struct termios  cntrl;
1.1       deraadt   439:
1.19      millert   440:        if (tcgetattr(FD, &cntrl))
                    441:                return (-1);
                    442:        cfsetspeed(&cntrl, speed);
1.2       deraadt   443:        cntrl.c_cflag &= ~(CSIZE|PARENB);
                    444:        cntrl.c_cflag |= CS8;
1.48      nicm      445:        if (vgetnum(DC))
1.5       millert   446:                cntrl.c_cflag |= CLOCAL;
1.48      nicm      447:        if (vgetnum(HARDWAREFLOW))
1.25      deraadt   448:                cntrl.c_cflag |= CRTSCTS;
1.2       deraadt   449:        cntrl.c_iflag &= ~(ISTRIP|ICRNL);
                    450:        cntrl.c_oflag &= ~OPOST;
                    451:        cntrl.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
                    452:        cntrl.c_cc[VMIN] = 1;
                    453:        cntrl.c_cc[VTIME] = 0;
1.48      nicm      454:        if (vgetnum(TAND))
1.2       deraadt   455:                cntrl.c_iflag |= IXOFF;
1.19      millert   456:        return (tcsetattr(FD, TCSAFLUSH, &cntrl));
1.1       deraadt   457: }
                    458:
                    459: static char partab[0200];
                    460:
                    461: /*
                    462:  * Do a write to the remote machine with the correct parity.
                    463:  * We are doing 8 bit wide output, so we just generate a character
                    464:  * with the right parity and output it.
                    465:  */
1.8       deraadt   466: void
1.27      deraadt   467: parwrite(int fd, char *buf, size_t n)
1.1       deraadt   468: {
1.15      millert   469:        int i;
                    470:        char *bp;
1.1       deraadt   471:
                    472:        bp = buf;
                    473:        if (bits8 == 0)
                    474:                for (i = 0; i < n; i++) {
                    475:                        *bp = partab[(*bp) & 0177];
                    476:                        bp++;
                    477:                }
                    478:        if (write(fd, buf, n) < 0) {
                    479:                if (errno == EIO)
                    480:                        tipabort("Lost carrier.");
                    481:                /* this is questionable */
1.48      nicm      482:                abort();;//
1.1       deraadt   483:                perror("write");
                    484:        }
                    485: }
                    486:
                    487: /*
                    488:  * Build a parity table with appropriate high-order bit.
                    489:  */
1.8       deraadt   490: void
1.25      deraadt   491: setparity(char *defparity)
1.1       deraadt   492: {
1.15      millert   493:        int i, flip, clr, set;
1.1       deraadt   494:        char *parity;
1.4       millert   495:        extern const unsigned char evenpartab[];
1.1       deraadt   496:
1.48      nicm      497:        if (vgetstr(PARITY) == NULL)
                    498:                vsetstr(PARITY, defparity);
                    499:        parity = vgetstr(PARITY);
1.39      nicm      500:        if (strcmp(parity, "none") == 0) {
1.1       deraadt   501:                bits8 = 1;
                    502:                return;
                    503:        }
                    504:        bits8 = 0;
                    505:        flip = 0;
                    506:        clr = 0377;
                    507:        set = 0;
1.39      nicm      508:        if (strcmp(parity, "odd") == 0)
1.1       deraadt   509:                flip = 0200;                    /* reverse bit 7 */
1.39      nicm      510:        else if (strcmp(parity, "zero") == 0)
1.1       deraadt   511:                clr = 0177;                     /* turn off bit 7 */
1.39      nicm      512:        else if (strcmp(parity, "one") == 0)
1.1       deraadt   513:                set = 0200;                     /* turn on bit 7 */
1.39      nicm      514:        else if (strcmp(parity, "even") != 0) {
1.1       deraadt   515:                (void) fprintf(stderr, "%s: unknown parity value\r\n", parity);
                    516:                (void) fflush(stderr);
                    517:        }
                    518:        for (i = 0; i < 0200; i++)
1.18      hugh      519:                partab[i] = ((evenpartab[i] ^ flip) | set) & clr;
1.1       deraadt   520: }