Import OpenSSH-3.9p1 from openbsd.org
[dragonfly.git] / crypto / openssh-3.9p1 / openbsd-compat / bsd-openpty.c
1 /*
2  * Please note: this implementation of openpty() is far from complete.
3  * it is just enough for portable OpenSSH's needs.
4  */
5
6 /*
7  * Copyright (c) 2004 Damien Miller <djm@mindrot.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21
22 /*
23  * Author: Tatu Ylonen <ylo@cs.hut.fi>
24  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
25  *                    All rights reserved
26  * Allocating a pseudo-terminal, and making it the controlling tty.
27  *
28  * As far as I am concerned, the code I have written for this software
29  * can be used freely for any purpose.  Any derived versions of this
30  * software must be clearly marked as such, and if the derived work is
31  * incompatible with the protocol description in the RFC file, it must be
32  * called by a name other than "ssh" or "Secure Shell".
33  */
34
35 #include "includes.h"
36 #if !defined(HAVE_OPENPTY)
37
38 #ifdef HAVE_UTIL_H
39 # include <util.h>
40 #endif /* HAVE_UTIL_H */
41
42 #ifdef HAVE_PTY_H
43 # include <pty.h>
44 #endif
45 #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H)
46 # include <sys/stropts.h>
47 #endif
48
49 #ifndef O_NOCTTY
50 #define O_NOCTTY 0
51 #endif
52
53 int
54 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
55    struct winsize *winp)
56 {
57 #if defined(HAVE__GETPTY)
58         /*
59          * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
60          * pty's automagically when needed
61          */
62         char *slave;
63
64         if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
65                 return (-1);
66
67         /* Open the slave side. */
68         if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
69                 close(*amaster);
70                 return (-1);
71         }
72         return (0);
73
74 #elif defined(HAVE_DEV_PTMX)
75         /*
76          * This code is used e.g. on Solaris 2.x.  (Note that Solaris 2.3
77          * also has bsd-style ptys, but they simply do not work.)
78          */
79         int ptm;
80         char *pts;
81         mysig_t old_signal;
82
83         if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1)
84                 return (-1);
85
86         /* XXX: need to close ptm on error? */
87         old_signal = signal(SIGCHLD, SIG_DFL);
88         if (grantpt(ptm) < 0)
89                 return (-1);
90         signal(SIGCHLD, old_signal);
91
92         if (unlockpt(ptm) < 0)
93                 return (-1);
94
95         if ((pts = ptsname(ptm)) == NULL)
96                 return (-1);
97         *amaster = ptm;
98
99         /* Open the slave side. */
100         if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) {
101                 close(*amaster);
102                 return (-1);
103         }
104
105 #ifndef HAVE_CYGWIN
106         /*
107          * Try to push the appropriate streams modules, as described 
108          * in Solaris pts(7).
109          */
110         ioctl(*aslave, I_PUSH, "ptem");
111         ioctl(*aslave, I_PUSH, "ldterm");
112 # ifndef __hpux
113         ioctl(*aslave, I_PUSH, "ttcompat");
114 # endif /* __hpux */
115 #endif /* HAVE_CYGWIN */
116
117         return (0);
118
119 #elif defined(HAVE_DEV_PTS_AND_PTC)
120         /* AIX-style pty code. */
121         const char *ttname;
122
123         if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1)
124                 return (-1);
125         if ((ttname = ttyname(*amaster)) == NULL)
126                 return (-1);
127         if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) {
128                 close(*amaster);
129                 return (-1);
130         }
131         return (0);
132
133 #elif defined(_UNICOS)
134         char ptbuf[64], ttbuf[64];
135         int i;
136         int highpty;
137
138         highpty = 128;
139 #ifdef _SC_CRAY_NPTY
140         if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1)
141                 highpty = 128;
142 #endif /* _SC_CRAY_NPTY */
143
144         for (i = 0; i < highpty; i++) {
145                 snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i);
146                 snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i);
147                 if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1)
148                         continue;
149                 /* Open the slave side. */
150                 if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) {
151                         close(*amaster);
152                         return (-1);
153                 }
154                 return (0);
155         }
156         return (-1);
157
158 #else
159         /* BSD-style pty code. */
160         char ptbuf[64], ttbuf[64];
161         int i;
162         const char *ptymajors = "pqrstuvwxyzabcdefghijklmno"
163             "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
164         const char *ptyminors = "0123456789abcdef";
165         int num_minors = strlen(ptyminors);
166         int num_ptys = strlen(ptymajors) * num_minors;
167         struct termios tio;
168
169         for (i = 0; i < num_ptys; i++) {
170                 snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", 
171                     ptymajors[i / num_minors], ptyminors[i % num_minors]);
172                 snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c",
173                     ptymajors[i / num_minors], ptyminors[i % num_minors]);
174
175                 if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) {
176                         /* Try SCO style naming */
177                         snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i);
178                         snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i);
179                         if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1)
180                                 continue;
181                 }
182
183                 /* Open the slave side. */
184                 if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) {
185                         close(*amaster);
186                         return (-1);
187                 }
188                 /* set tty modes to a sane state for broken clients */
189                 if (tcgetattr(*amaster, &tio) != -1) {
190                         tio.c_lflag |= (ECHO | ISIG | ICANON);
191                         tio.c_oflag |= (OPOST | ONLCR);
192                         tio.c_iflag |= ICRNL;
193                         tcsetattr(*amaster, TCSANOW, &tio);
194                 }
195
196                 return (0);
197         }
198         return (-1);
199 #endif
200 }
201
202 #endif /* !defined(HAVE_OPENPTY) */
203