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

Annotation of src/usr.bin/ssh/pty.c, Revision 1.7

1.1       deraadt     1: /*
1.7     ! deraadt     2:  *
        !             3:  * pty.c
        !             4:  *
        !             5:  * Author: Tatu Ylonen <ylo@cs.hut.fi>
        !             6:  *
        !             7:  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
        !             8:  *                    All rights reserved
        !             9:  *
        !            10:  * Created: Fri Mar 17 04:37:25 1995 ylo
        !            11:  *
        !            12:  * Allocating a pseudo-terminal, and making it the controlling tty.
        !            13:  *
        !            14:  */
1.1       deraadt    15:
                     16: #include "includes.h"
1.7     ! deraadt    17: RCSID("$Id: pty.c,v 1.6 1999/11/23 22:25:54 markus Exp $");
1.1       deraadt    18:
                     19: #include "pty.h"
                     20: #include "ssh.h"
                     21:
                     22: /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
                     23: #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
                     24: #undef HAVE_DEV_PTMX
                     25: #endif
                     26:
                     27: #ifndef O_NOCTTY
                     28: #define O_NOCTTY 0
                     29: #endif
                     30:
                     31: /* Allocates and opens a pty.  Returns 0 if no pty could be allocated,
                     32:    or nonzero if a pty was successfully allocated.  On success, open file
1.6       markus     33:    descriptors for the pty and tty sides and the name of the tty side are
1.1       deraadt    34:    returned (the buffer must be able to hold at least 64 characters). */
                     35:
1.6       markus     36: int
                     37: pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
1.1       deraadt    38: {
                     39: #ifdef HAVE_OPENPTY
1.6       markus     40:        /* openpty(3) exists in OSF/1 and some other os'es */
                     41:        int i;
1.1       deraadt    42:
1.6       markus     43:        i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
                     44:        if (i < 0) {
                     45:                error("openpty: %.100s", strerror(errno));
                     46:                return 0;
                     47:        }
                     48:        return 1;
1.1       deraadt    49: #else /* HAVE_OPENPTY */
                     50: #ifdef HAVE__GETPTY
1.6       markus     51:        /* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates
                     52:           more pty's automagically when needed */
                     53:        char *slave;
                     54:
                     55:        slave = _getpty(ptyfd, O_RDWR, 0622, 0);
                     56:        if (slave == NULL) {
                     57:                error("_getpty: %.100s", strerror(errno));
                     58:                return 0;
                     59:        }
                     60:        strcpy(namebuf, slave);
                     61:        /* Open the slave side. */
                     62:        *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
                     63:        if (*ttyfd < 0) {
                     64:                error("%.200s: %.100s", namebuf, strerror(errno));
                     65:                close(*ptyfd);
                     66:                return 0;
                     67:        }
                     68:        return 1;
1.1       deraadt    69: #else /* HAVE__GETPTY */
                     70: #ifdef HAVE_DEV_PTMX
1.6       markus     71:        /* This code is used e.g. on Solaris 2.x.  (Note that Solaris 2.3
                     72:           also has bsd-style ptys, but they simply do not work.) */
                     73:        int ptm;
                     74:        char *pts;
                     75:
                     76:        ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
                     77:        if (ptm < 0) {
                     78:                error("/dev/ptmx: %.100s", strerror(errno));
                     79:                return 0;
                     80:        }
                     81:        if (grantpt(ptm) < 0) {
                     82:                error("grantpt: %.100s", strerror(errno));
                     83:                return 0;
                     84:        }
                     85:        if (unlockpt(ptm) < 0) {
                     86:                error("unlockpt: %.100s", strerror(errno));
                     87:                return 0;
                     88:        }
                     89:        pts = ptsname(ptm);
                     90:        if (pts == NULL)
                     91:                error("Slave pty side name could not be obtained.");
                     92:        strcpy(namebuf, pts);
                     93:        *ptyfd = ptm;
                     94:
                     95:        /* Open the slave side. */
                     96:        *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
                     97:        if (*ttyfd < 0) {
                     98:                error("%.100s: %.100s", namebuf, strerror(errno));
                     99:                close(*ptyfd);
                    100:                return 0;
                    101:        }
                    102:        /* Push the appropriate streams modules, as described in Solaris
                    103:           pts(7). */
                    104:        if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
                    105:                error("ioctl I_PUSH ptem: %.100s", strerror(errno));
                    106:        if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
                    107:                error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
                    108:        if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
                    109:                error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
                    110:        return 1;
1.1       deraadt   111: #else /* HAVE_DEV_PTMX */
                    112: #ifdef HAVE_DEV_PTS_AND_PTC
1.6       markus    113:        /* AIX-style pty code. */
                    114:        const char *name;
1.1       deraadt   115:
1.6       markus    116:        *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
                    117:        if (*ptyfd < 0) {
                    118:                error("Could not open /dev/ptc: %.100s", strerror(errno));
                    119:                return 0;
                    120:        }
                    121:        name = ttyname(*ptyfd);
                    122:        if (!name)
                    123:                fatal("Open of /dev/ptc returns device for which ttyname fails.");
                    124:        strcpy(namebuf, name);
                    125:        *ttyfd = open(name, O_RDWR | O_NOCTTY);
                    126:        if (*ttyfd < 0) {
                    127:                error("Could not open pty slave side %.100s: %.100s",
                    128:                      name, strerror(errno));
                    129:                close(*ptyfd);
                    130:                return 0;
                    131:        }
                    132:        return 1;
1.1       deraadt   133: #else /* HAVE_DEV_PTS_AND_PTC */
1.6       markus    134:        /* BSD-style pty code. */
                    135:        char buf[64];
                    136:        int i;
                    137:        const char *ptymajors =
                    138:        "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
                    139:        const char *ptyminors = "0123456789abcdef";
                    140:        int num_minors = strlen(ptyminors);
                    141:        int num_ptys = strlen(ptymajors) * num_minors;
                    142:
                    143:        for (i = 0; i < num_ptys; i++) {
                    144:                snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
                    145:                         ptyminors[i % num_minors]);
                    146:                *ptyfd = open(buf, O_RDWR | O_NOCTTY);
                    147:                if (*ptyfd < 0)
                    148:                        continue;
                    149:                snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
                    150:                         ptyminors[i % num_minors]);
                    151:
                    152:                /* Open the slave side. */
                    153:                *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
                    154:                if (*ttyfd < 0) {
                    155:                        error("%.100s: %.100s", namebuf, strerror(errno));
                    156:                        close(*ptyfd);
                    157:                        return 0;
                    158:                }
                    159:                return 1;
                    160:        }
                    161:        return 0;
1.1       deraadt   162: #endif /* HAVE_DEV_PTS_AND_PTC */
                    163: #endif /* HAVE_DEV_PTMX */
                    164: #endif /* HAVE__GETPTY */
                    165: #endif /* HAVE_OPENPTY */
                    166: }
                    167:
1.6       markus    168: /* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
1.1       deraadt   169:
1.6       markus    170: void
                    171: pty_release(const char *ttyname)
1.1       deraadt   172: {
1.6       markus    173:        if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0)
                    174:                debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
                    175:        if (chmod(ttyname, (mode_t) 0666) < 0)
                    176:                debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
1.1       deraadt   177: }
                    178:
                    179: /* Makes the tty the processes controlling tty and sets it to sane modes. */
                    180:
1.6       markus    181: void
                    182: pty_make_controlling_tty(int *ttyfd, const char *ttyname)
1.1       deraadt   183: {
1.6       markus    184:        int fd;
1.1       deraadt   185:
1.6       markus    186:        /* First disconnect from the old controlling tty. */
1.1       deraadt   187: #ifdef TIOCNOTTY
1.6       markus    188:        fd = open("/dev/tty", O_RDWR | O_NOCTTY);
                    189:        if (fd >= 0) {
                    190:                (void) ioctl(fd, TIOCNOTTY, NULL);
                    191:                close(fd);
                    192:        }
1.1       deraadt   193: #endif /* TIOCNOTTY */
1.6       markus    194:        if (setsid() < 0)
                    195:                error("setsid: %.100s", strerror(errno));
1.1       deraadt   196:
1.6       markus    197:        /* Verify that we are successfully disconnected from the
                    198:           controlling tty. */
                    199:        fd = open("/dev/tty", O_RDWR | O_NOCTTY);
                    200:        if (fd >= 0) {
                    201:                error("Failed to disconnect from controlling tty.");
                    202:                close(fd);
                    203:        }
                    204:        /* Make it our controlling tty. */
1.1       deraadt   205: #ifdef TIOCSCTTY
1.6       markus    206:        debug("Setting controlling tty using TIOCSCTTY.");
                    207:        /* We ignore errors from this, because HPSUX defines TIOCSCTTY,
                    208:           but returns EINVAL with these arguments, and there is
                    209:           absolutely no documentation. */
                    210:        ioctl(*ttyfd, TIOCSCTTY, NULL);
1.1       deraadt   211: #endif /* TIOCSCTTY */
1.6       markus    212:        fd = open(ttyname, O_RDWR);
                    213:        if (fd < 0)
                    214:                error("%.100s: %.100s", ttyname, strerror(errno));
                    215:        else
                    216:                close(fd);
                    217:
                    218:        /* Verify that we now have a controlling tty. */
                    219:        fd = open("/dev/tty", O_WRONLY);
                    220:        if (fd < 0)
                    221:                error("open /dev/tty failed - could not set controlling tty: %.100s",
                    222:                      strerror(errno));
                    223:        else {
                    224:                close(fd);
                    225:        }
1.1       deraadt   226: }
                    227:
                    228: /* Changes the window size associated with the pty. */
                    229:
1.6       markus    230: void
                    231: pty_change_window_size(int ptyfd, int row, int col,
                    232:                       int xpixel, int ypixel)
1.1       deraadt   233: {
1.6       markus    234:        struct winsize w;
                    235:        w.ws_row = row;
                    236:        w.ws_col = col;
                    237:        w.ws_xpixel = xpixel;
                    238:        w.ws_ypixel = ypixel;
                    239:        (void) ioctl(ptyfd, TIOCSWINSZ, &w);
1.1       deraadt   240: }