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

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