ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libptytty/src/ptytty.C
Revision: 1.49
Committed: Wed Jan 18 20:05:13 2012 UTC (12 years, 5 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
Changes since 1.48: +1 -1 lines
Log Message:
Fix compilation on solaris.

File Contents

# User Rev Content
1 root 1.8 /*----------------------------------------------------------------------*
2 root 1.1 * File: ptytty.C
3     *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
7 sf-exg 1.38 * Copyright (c) 2004-2006 Marc Lehmann <schmorp@schmorp.de>
8 root 1.12 * Copyright (c) 2006 Emanuele Giaquinta <e.giaquinta@glauco.it>
9 root 1.1 *
10     * This program is free software; you can redistribute it and/or modify
11     * it under the terms of the GNU General Public License as published by
12     * the Free Software Foundation; either version 2 of the License, or
13     * (at your option) any later version.
14     *
15     * This program is distributed in the hope that it will be useful,
16     * but WITHOUT ANY WARRANTY; without even the implied warranty of
17     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     * GNU General Public License for more details.
19     *
20     * You should have received a copy of the GNU General Public License
21     * along with this program; if not, write to the Free Software
22     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23     *---------------------------------------------------------------------*/
24    
25 sf-exg 1.36 #include "config.h"
26 root 1.1
27 root 1.3 #include "ptytty.h"
28    
29 sf-exg 1.49 #include <stdlib.h>
30 sf-exg 1.46 #include <cstdio>
31 root 1.2 #include <cstring>
32    
33     #include <sys/types.h>
34 ayin 1.34 #include <sys/stat.h>
35 root 1.2 #include <unistd.h>
36     #include <fcntl.h>
37    
38 root 1.1 #ifdef HAVE_SYS_IOCTL_H
39     # include <sys/ioctl.h>
40     #endif
41 sf-exg 1.40 #if defined(HAVE_SYS_STROPTS_H)
42 root 1.1 # include <sys/stropts.h> /* for I_PUSH */
43     #endif
44 root 1.35 #if defined(HAVE_ISASTREAM) && defined(HAVE_STROPTS_H)
45 root 1.1 # include <stropts.h>
46     #endif
47 root 1.2 #if defined(HAVE_PTY_H)
48 root 1.1 # include <pty.h>
49 root 1.2 #elif defined(HAVE_LIBUTIL_H)
50 root 1.1 # include <libutil.h>
51 root 1.2 #elif defined(HAVE_UTIL_H)
52 root 1.1 # include <util.h>
53     #endif
54 root 1.2 #ifdef TTY_GID_SUPPORT
55     #include <grp.h>
56     #endif
57 root 1.1
58 sf-exg 1.47 #ifndef O_NOCTTY
59     # define O_NOCTTY 0
60     #endif
61    
62 root 1.2 /////////////////////////////////////////////////////////////////////////////
63 root 1.1
64     /* ------------------------------------------------------------------------- *
65     * GET PSEUDO TELETYPE - MASTER AND SLAVE *
66     * ------------------------------------------------------------------------- */
67     /*
68 ayin 1.26 * Returns pty file descriptor, or -1 on failure
69 root 1.1 * If successful, ttydev is set to the name of the slave device.
70     * fd_tty _may_ also be set to an open fd to the slave device
71     */
72 root 1.2 #if defined(UNIX98_PTY)
73 root 1.25
74     static int
75     get_pty (int *fd_tty, char **ttydev)
76     {
77     int pfd;
78 root 1.1
79 root 1.2 # if defined(HAVE_GETPT)
80 sf-exg 1.43 pfd = getpt ();
81 root 1.2 # elif defined(HAVE_POSIX_OPENPT)
82 sf-exg 1.41 pfd = posix_openpt (O_RDWR | O_NOCTTY);
83 root 1.2 # else
84 sf-exg 1.40 # ifdef _AIX
85     pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0);
86     # else
87     pfd = open ("/dev/ptmx", O_RDWR | O_NOCTTY, 0);
88     # endif
89 root 1.2 # endif
90 root 1.1
91 root 1.25 if (pfd >= 0)
92     {
93     if (grantpt (pfd) == 0 /* change slave permissions */
94     && unlockpt (pfd) == 0)
95 ayin 1.32 {
96     /* slave now unlocked */
97 root 1.25 *ttydev = strdup (ptsname (pfd)); /* get slave's name */
98     return pfd;
99     }
100    
101     close (pfd);
102     }
103    
104     return -1;
105     }
106 root 1.2
107     #elif defined(HAVE_OPENPTY)
108 root 1.1
109 root 1.25 static int
110     get_pty (int *fd_tty, char **ttydev)
111     {
112     int pfd;
113     int res;
114 ayin 1.26
115 ayin 1.29 res = openpty (&pfd, fd_tty, NULL, NULL, NULL);
116 root 1.25
117     if (res != -1)
118     {
119 ayin 1.29 *ttydev = strdup (ttyname (*fd_tty));
120 root 1.25 return pfd;
121     }
122    
123     return -1;
124     }
125    
126 root 1.2 #elif defined(HAVE__GETPTY)
127    
128 root 1.25 static int
129     get_pty (int *fd_tty, char **ttydev)
130     {
131     int pfd;
132 ayin 1.30 char *slave;
133 root 1.25
134 sf-exg 1.42 slave = _getpty (&pfd, O_RDWR | O_NOCTTY, 0622, 0);
135 root 1.25
136 ayin 1.33 if (slave != NULL)
137     {
138     *ttydev = strdup (slave);
139     return pfd;
140     }
141 root 1.25
142     return -1;
143     }
144 root 1.1
145 root 1.2 #else
146 root 1.1
147 root 1.25 /* Based on the code in openssh/openbsd-compat/bsd-openpty.c */
148     static int
149     get_pty (int *fd_tty, char **ttydev)
150     {
151     int pfd;
152     int i;
153     char pty_name[32];
154     char tty_name[32];
155     const char *majors = "pqrstuvwxyzabcde";
156     const char *minors = "0123456789abcdef";
157    
158     for (i = 0; i < 256; i++)
159     {
160 sf-exg 1.43 snprintf (pty_name, 32, "/dev/pty%c%c", majors[i / 16], minors[i % 16]);
161     snprintf (tty_name, 32, "/dev/tty%c%c", majors[i / 16], minors[i % 16]);
162 root 1.25
163     if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1)
164     {
165 sf-exg 1.43 snprintf (pty_name, 32, "/dev/ptyp%d", i);
166     snprintf (tty_name, 32, "/dev/ttyp%d", i);
167 root 1.25 if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1)
168     continue;
169     }
170    
171     if (access (tty_name, R_OK | W_OK) == 0)
172     {
173     *ttydev = strdup (tty_name);
174     return pfd;
175     }
176    
177     close (pfd);
178     }
179    
180     return -1;
181     }
182 ayin 1.24
183 root 1.1 #endif
184    
185     /*----------------------------------------------------------------------*/
186     /*
187 ayin 1.26 * Returns tty file descriptor, or -1 on failure
188 root 1.1 */
189     static int
190     get_tty (char *ttydev)
191     {
192     return open (ttydev, O_RDWR | O_NOCTTY, 0);
193     }
194    
195     /*----------------------------------------------------------------------*/
196     /*
197     * Make our tty a controlling tty so that /dev/tty points to us
198     */
199     static int
200 root 1.2 control_tty (int fd_tty)
201 root 1.1 {
202 ayin 1.28 int fd;
203    
204 root 1.1 setsid ();
205    
206 ayin 1.27 #ifdef TIOCSCTTY
207 root 1.2 ioctl (fd_tty, TIOCSCTTY, NULL);
208 ayin 1.27 #else
209 ayin 1.28 fd = open (ttyname (fd_tty), O_RDWR);
210 ayin 1.27 if (fd >= 0)
211     close (fd);
212     #endif
213 root 1.2
214 ayin 1.28 fd = open ("/dev/tty", O_WRONLY);
215 root 1.1 if (fd < 0)
216 root 1.10 return -1; /* fatal */
217 root 1.2
218 root 1.1 close (fd);
219    
220     return 0;
221     }
222    
223 root 1.2 void
224 root 1.4 ptytty::close_tty ()
225 root 1.2 {
226     if (tty < 0)
227     return;
228    
229     close (tty);
230     tty = -1;
231     }
232    
233     bool
234 root 1.4 ptytty::make_controlling_tty ()
235 root 1.2 {
236     return control_tty (tty) >= 0;
237     }
238    
239     void
240 root 1.4 ptytty::set_utf8_mode (bool on)
241 root 1.2 {
242     #ifdef IUTF8
243     if (pty < 0)
244     return;
245    
246     struct termios tio;
247    
248     if (tcgetattr (pty, &tio) != -1)
249     {
250     tcflag_t new_cflag = tio.c_iflag;
251    
252     if (on)
253     new_cflag |= IUTF8;
254     else
255     new_cflag &= ~IUTF8;
256    
257     if (new_cflag != tio.c_iflag)
258     {
259     tio.c_iflag = new_cflag;
260     tcsetattr (pty, TCSANOW, &tio);
261     }
262     }
263     #endif
264     }
265    
266 root 1.1 static struct ttyconf {
267     gid_t gid;
268     mode_t mode;
269    
270     ttyconf ()
271     {
272     #ifdef TTY_GID_SUPPORT
273     struct group *gr = getgrnam ("tty");
274    
275     if (gr)
276 ayin 1.32 {
277     /* change group ownership of tty to "tty" */
278 root 1.1 mode = S_IRUSR | S_IWUSR | S_IWGRP;
279     gid = gr->gr_gid;
280     }
281     else
282 ayin 1.31 #endif /* TTY_GID_SUPPORT */
283 root 1.1 {
284     mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
285 root 1.2 gid = 0;
286 root 1.1 }
287     }
288     } ttyconf;
289    
290 root 1.4 ptytty_unix::ptytty_unix ()
291 root 1.1 {
292     name = 0;
293 root 1.2 #if UTMP_SUPPORT
294     cmd_pid = 0;
295 root 1.1 #endif
296     }
297    
298 root 1.4 ptytty_unix::~ptytty_unix ()
299 root 1.1 {
300 root 1.2 #if UTMP_SUPPORT
301     logout ();
302     #endif
303 root 1.1 put ();
304     }
305    
306     void
307 root 1.4 ptytty_unix::put ()
308 root 1.2 {
309 root 1.25 if (name)
310     {
311     chmod (name, RESTORE_TTY_MODE);
312     chown (name, 0, ttyconf.gid);
313     }
314 root 1.1
315 root 1.2 close_tty ();
316 root 1.1
317 root 1.2 if (pty >= 0)
318     close (pty);
319 root 1.1
320     free (name);
321    
322     pty = tty = -1;
323     name = 0;
324     }
325    
326     bool
327 root 1.4 ptytty_unix::get ()
328 root 1.1 {
329     /* get master (pty) */
330     if ((pty = get_pty (&tty, &name)) < 0)
331     return false;
332    
333     /* get slave (tty) */
334     if (tty < 0)
335     {
336     #ifndef NO_SETOWNER_TTYDEV
337 root 1.2 chown (name, getuid (), ttyconf.gid); /* fail silently */
338     chmod (name, ttyconf.mode);
339     # ifdef HAVE_REVOKE
340     revoke (name);
341     # endif
342 root 1.1 #endif
343    
344     if ((tty = get_tty (name)) < 0)
345     {
346     put ();
347     return false;
348     }
349     }
350    
351 sf-exg 1.40 #if defined(I_PUSH)
352 sf-exg 1.39 /*
353     * Push STREAMS modules:
354     * ptem: pseudo-terminal hardware emulation module.
355     * ldterm: standard terminal line discipline.
356     * ttcompat: V7, 4BSD and XENIX STREAMS compatibility module.
357     *
358     * After we push the STREAMS modules, the first open () on the slave side
359     * should make the "ptem" (or "ldterm" depending upon either which OS
360     * version or which set of manual pages you have) module give us a
361     * controlling terminal. We must already have close ()d the master side
362     * fd in this child process before we push STREAMS modules on because the
363     * documentation is really unclear about whether it is any close () on
364     * the master side or the last close () - i.e. a proper STREAMS dismantling
365     * close () - on the master side which causes a hang up to be sent
366     * through - Geoff Wing
367     */
368     #if defined(HAVE_ISASTREAM) && defined(HAVE_STROPTS_H)
369     if (isastream (tty) == 1)
370     # endif
371     {
372     ioctl (tty, I_PUSH, "ptem");
373     ioctl (tty, I_PUSH, "ldterm");
374     ioctl (tty, I_PUSH, "ttcompat");
375     }
376     #endif
377    
378 sf-exg 1.44 #if UTMP_SUPPORT
379     # if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID)
380     int fd_stdin = dup (STDIN_FILENO);
381     dup2 (tty, STDIN_FILENO);
382    
383     utmp_pos = ttyslot ();
384    
385     dup2 (fd_stdin, STDIN_FILENO);
386     close (fd_stdin);
387     # endif
388     #endif
389    
390 root 1.1 return true;
391     }
392