ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/ptytty.C
Revision: 1.72
Committed: Mon May 30 21:24:42 2011 UTC (12 years, 11 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.71: +0 -0 lines
State: FILE REMOVED
Log Message:
Embed libptytty.

File Contents

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