ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libptytty/src/ptytty.C
Revision: 1.44
Committed: Fri Dec 2 08:45:45 2011 UTC (12 years, 7 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
Changes since 1.43: +12 -0 lines
Log Message:
Fix writing of bsd login and logout utmp entry when close_tty is called
before login and delete respectively.

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     #include <cstring>
34 root 1.19 #include <csignal>
35 root 1.2
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     #include <cstdio>
62 root 1.2
63     /////////////////////////////////////////////////////////////////////////////
64 root 1.1
65     /* ------------------------------------------------------------------------- *
66     * GET PSEUDO TELETYPE - MASTER AND SLAVE *
67     * ------------------------------------------------------------------------- */
68     /*
69 ayin 1.26 * Returns pty file descriptor, or -1 on failure
70 root 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 root 1.2 #if defined(UNIX98_PTY)
74 root 1.25
75     static int
76     get_pty (int *fd_tty, char **ttydev)
77     {
78     int pfd;
79 root 1.1
80 root 1.2 # if defined(HAVE_GETPT)
81 sf-exg 1.43 pfd = getpt ();
82 root 1.2 # elif defined(HAVE_POSIX_OPENPT)
83 sf-exg 1.41 pfd = posix_openpt (O_RDWR | O_NOCTTY);
84 root 1.2 # else
85 sf-exg 1.40 # ifdef _AIX
86     pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0);
87     # else
88     pfd = open ("/dev/ptmx", O_RDWR | O_NOCTTY, 0);
89     # endif
90 root 1.2 # endif
91 root 1.1
92 root 1.25 if (pfd >= 0)
93     {
94     if (grantpt (pfd) == 0 /* change slave permissions */
95     && unlockpt (pfd) == 0)
96 ayin 1.32 {
97     /* slave now unlocked */
98 root 1.25 *ttydev = strdup (ptsname (pfd)); /* get slave's name */
99     return pfd;
100     }
101    
102     close (pfd);
103     }
104    
105     return -1;
106     }
107 root 1.2
108     #elif defined(HAVE_OPENPTY)
109 root 1.1
110 root 1.25 static int
111     get_pty (int *fd_tty, char **ttydev)
112     {
113     int pfd;
114     int res;
115 ayin 1.26
116 ayin 1.29 res = openpty (&pfd, fd_tty, NULL, NULL, NULL);
117 root 1.25
118     if (res != -1)
119     {
120 ayin 1.29 *ttydev = strdup (ttyname (*fd_tty));
121 root 1.25 return pfd;
122     }
123    
124     return -1;
125     }
126    
127 root 1.2 #elif defined(HAVE__GETPTY)
128    
129 root 1.25 static int
130     get_pty (int *fd_tty, char **ttydev)
131     {
132     int pfd;
133 ayin 1.30 char *slave;
134 root 1.25
135 sf-exg 1.42 slave = _getpty (&pfd, O_RDWR | O_NOCTTY, 0622, 0);
136 root 1.25
137 ayin 1.33 if (slave != NULL)
138     {
139     *ttydev = strdup (slave);
140     return pfd;
141     }
142 root 1.25
143     return -1;
144     }
145 root 1.1
146 root 1.2 #else
147 root 1.1
148 root 1.25 /* Based on the code in openssh/openbsd-compat/bsd-openpty.c */
149     static int
150     get_pty (int *fd_tty, char **ttydev)
151     {
152     int pfd;
153     int i;
154     char pty_name[32];
155     char tty_name[32];
156     const char *majors = "pqrstuvwxyzabcde";
157     const char *minors = "0123456789abcdef";
158    
159     for (i = 0; i < 256; i++)
160     {
161 sf-exg 1.43 snprintf (pty_name, 32, "/dev/pty%c%c", majors[i / 16], minors[i % 16]);
162     snprintf (tty_name, 32, "/dev/tty%c%c", majors[i / 16], minors[i % 16]);
163 root 1.25
164     if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1)
165     {
166 sf-exg 1.43 snprintf (pty_name, 32, "/dev/ptyp%d", i);
167     snprintf (tty_name, 32, "/dev/ttyp%d", i);
168 root 1.25 if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1)
169     continue;
170     }
171    
172     if (access (tty_name, R_OK | W_OK) == 0)
173     {
174     *ttydev = strdup (tty_name);
175     return pfd;
176     }
177    
178     close (pfd);
179     }
180    
181     return -1;
182     }
183 ayin 1.24
184 root 1.1 #endif
185    
186     /*----------------------------------------------------------------------*/
187     /*
188 ayin 1.26 * Returns tty file descriptor, or -1 on failure
189 root 1.1 */
190     static int
191     get_tty (char *ttydev)
192     {
193     return open (ttydev, O_RDWR | O_NOCTTY, 0);
194     }
195    
196     /*----------------------------------------------------------------------*/
197     /*
198     * Make our tty a controlling tty so that /dev/tty points to us
199     */
200     static int
201 root 1.2 control_tty (int fd_tty)
202 root 1.1 {
203 ayin 1.28 int fd;
204    
205 root 1.1 setsid ();
206    
207 ayin 1.27 #ifdef TIOCSCTTY
208 root 1.2 ioctl (fd_tty, TIOCSCTTY, NULL);
209 ayin 1.27 #else
210 ayin 1.28 fd = open (ttyname (fd_tty), O_RDWR);
211 ayin 1.27 if (fd >= 0)
212     close (fd);
213     #endif
214 root 1.2
215 ayin 1.28 fd = open ("/dev/tty", O_WRONLY);
216 root 1.1 if (fd < 0)
217 root 1.10 return -1; /* fatal */
218 root 1.2
219 root 1.1 close (fd);
220    
221     return 0;
222     }
223    
224 root 1.2 void
225 root 1.4 ptytty::close_tty ()
226 root 1.2 {
227     if (tty < 0)
228     return;
229    
230     close (tty);
231     tty = -1;
232     }
233    
234     bool
235 root 1.4 ptytty::make_controlling_tty ()
236 root 1.2 {
237     return control_tty (tty) >= 0;
238     }
239    
240     void
241 root 1.4 ptytty::set_utf8_mode (bool on)
242 root 1.2 {
243     #ifdef IUTF8
244     if (pty < 0)
245     return;
246    
247     struct termios tio;
248    
249     if (tcgetattr (pty, &tio) != -1)
250     {
251     tcflag_t new_cflag = tio.c_iflag;
252    
253     if (on)
254     new_cflag |= IUTF8;
255     else
256     new_cflag &= ~IUTF8;
257    
258     if (new_cflag != tio.c_iflag)
259     {
260     tio.c_iflag = new_cflag;
261     tcsetattr (pty, TCSANOW, &tio);
262     }
263     }
264     #endif
265     }
266    
267 root 1.1 static struct ttyconf {
268     gid_t gid;
269     mode_t mode;
270    
271     ttyconf ()
272     {
273     #ifdef TTY_GID_SUPPORT
274     struct group *gr = getgrnam ("tty");
275    
276     if (gr)
277 ayin 1.32 {
278     /* change group ownership of tty to "tty" */
279 root 1.1 mode = S_IRUSR | S_IWUSR | S_IWGRP;
280     gid = gr->gr_gid;
281     }
282     else
283 ayin 1.31 #endif /* TTY_GID_SUPPORT */
284 root 1.1 {
285     mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
286 root 1.2 gid = 0;
287 root 1.1 }
288     }
289     } ttyconf;
290    
291 root 1.4 ptytty_unix::ptytty_unix ()
292 root 1.1 {
293     name = 0;
294 root 1.2 #if UTMP_SUPPORT
295     cmd_pid = 0;
296 root 1.1 #endif
297     }
298    
299 root 1.4 ptytty_unix::~ptytty_unix ()
300 root 1.1 {
301 root 1.2 #if UTMP_SUPPORT
302     logout ();
303     #endif
304 root 1.1 put ();
305     }
306    
307     void
308 root 1.4 ptytty_unix::put ()
309 root 1.2 {
310 root 1.25 if (name)
311     {
312     chmod (name, RESTORE_TTY_MODE);
313     chown (name, 0, ttyconf.gid);
314     }
315 root 1.1
316 root 1.2 close_tty ();
317 root 1.1
318 root 1.2 if (pty >= 0)
319     close (pty);
320 root 1.1
321     free (name);
322    
323     pty = tty = -1;
324     name = 0;
325     }
326    
327     bool
328 root 1.4 ptytty_unix::get ()
329 root 1.1 {
330     /* get master (pty) */
331     if ((pty = get_pty (&tty, &name)) < 0)
332     return false;
333    
334     fcntl (pty, F_SETFL, O_NONBLOCK);
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