ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libptytty/src/ptytty.C
Revision: 1.47
Committed: Wed Dec 21 11:07:22 2011 UTC (12 years, 6 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-9_14, rel-1_5
Changes since 1.46: +4 -0 lines
Log Message:
Define O_NOCTTY to 0 if it is not defined.

File Contents

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