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

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