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

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