]> andersk Git - openssh.git/blob - openbsd-compat/bsd-openpty.c
- (dtucker) [openbsd-compat/strtonum.c] Include stdlib.h for strtoll,
[openssh.git] / 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 #include <sys/types.h>
39
40 #ifdef HAVE_SYS_STAT_H
41 # include <sys/stat.h>
42 #endif
43
44 #ifdef HAVE_FCNTL_H
45 # include <fcntl.h>
46 #endif
47
48 #ifdef HAVE_UTIL_H
49 # include <util.h>
50 #endif /* HAVE_UTIL_H */
51
52 #ifdef HAVE_PTY_H
53 # include <pty.h>
54 #endif
55 #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H)
56 # include <sys/stropts.h>
57 #endif
58
59 #include <signal.h>
60 #include <string.h>
61 #include <unistd.h>
62
63 #ifndef O_NOCTTY
64 #define O_NOCTTY 0
65 #endif
66
67 int
68 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
69    struct winsize *winp)
70 {
71 #if defined(HAVE__GETPTY)
72         /*
73          * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
74          * pty's automagically when needed
75          */
76         char *slave;
77
78         if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
79                 return (-1);
80
81         /* Open the slave side. */
82         if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
83                 close(*amaster);
84                 return (-1);
85         }
86         return (0);
87
88 #elif defined(HAVE_DEV_PTMX)
89         /*
90          * This code is used e.g. on Solaris 2.x.  (Note that Solaris 2.3
91          * also has bsd-style ptys, but they simply do not work.)
92          */
93         int ptm;
94         char *pts;
95         mysig_t old_signal;
96
97         if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1)
98                 return (-1);
99
100         /* XXX: need to close ptm on error? */
101         old_signal = signal(SIGCHLD, SIG_DFL);
102         if (grantpt(ptm) < 0)
103                 return (-1);
104         signal(SIGCHLD, old_signal);
105
106         if (unlockpt(ptm) < 0)
107                 return (-1);
108
109         if ((pts = ptsname(ptm)) == NULL)
110                 return (-1);
111         *amaster = ptm;
112
113         /* Open the slave side. */
114         if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) {
115                 close(*amaster);
116                 return (-1);
117         }
118
119         /*
120          * Try to push the appropriate streams modules, as described 
121          * in Solaris pts(7).
122          */
123         ioctl(*aslave, I_PUSH, "ptem");
124         ioctl(*aslave, I_PUSH, "ldterm");
125 # ifndef __hpux
126         ioctl(*aslave, I_PUSH, "ttcompat");
127 # endif /* __hpux */
128
129         return (0);
130
131 #elif defined(HAVE_DEV_PTS_AND_PTC)
132         /* AIX-style pty code. */
133         const char *ttname;
134
135         if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1)
136                 return (-1);
137         if ((ttname = ttyname(*amaster)) == NULL)
138                 return (-1);
139         if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) {
140                 close(*amaster);
141                 return (-1);
142         }
143         return (0);
144
145 #elif defined(_UNICOS)
146         char ptbuf[64], ttbuf[64];
147         int i;
148         int highpty;
149
150         highpty = 128;
151 #ifdef _SC_CRAY_NPTY
152         if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1)
153                 highpty = 128;
154 #endif /* _SC_CRAY_NPTY */
155
156         for (i = 0; i < highpty; i++) {
157                 snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i);
158                 snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i);
159                 if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1)
160                         continue;
161                 /* Open the slave side. */
162                 if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) {
163                         close(*amaster);
164                         return (-1);
165                 }
166                 return (0);
167         }
168         return (-1);
169
170 #else
171         /* BSD-style pty code. */
172         char ptbuf[64], ttbuf[64];
173         int i;
174         const char *ptymajors = "pqrstuvwxyzabcdefghijklmno"
175             "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
176         const char *ptyminors = "0123456789abcdef";
177         int num_minors = strlen(ptyminors);
178         int num_ptys = strlen(ptymajors) * num_minors;
179         struct termios tio;
180
181         for (i = 0; i < num_ptys; i++) {
182                 snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", 
183                     ptymajors[i / num_minors], ptyminors[i % num_minors]);
184                 snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c",
185                     ptymajors[i / num_minors], ptyminors[i % num_minors]);
186
187                 if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) {
188                         /* Try SCO style naming */
189                         snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i);
190                         snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i);
191                         if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1)
192                                 continue;
193                 }
194
195                 /* Open the slave side. */
196                 if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) {
197                         close(*amaster);
198                         return (-1);
199                 }
200                 /* set tty modes to a sane state for broken clients */
201                 if (tcgetattr(*amaster, &tio) != -1) {
202                         tio.c_lflag |= (ECHO | ISIG | ICANON);
203                         tio.c_oflag |= (OPOST | ONLCR);
204                         tio.c_iflag |= ICRNL;
205                         tcsetattr(*amaster, TCSANOW, &tio);
206                 }
207
208                 return (0);
209         }
210         return (-1);
211 #endif
212 }
213
214 #endif /* !defined(HAVE_OPENPTY) */
215
This page took 1.159809 seconds and 5 git commands to generate.