ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/ptytty.C
Revision: 1.11
Committed: Thu Apr 8 20:31:45 2004 UTC (20 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_5, rel-3_4, rel-3_3, rel-3_2, rel-2_8, rel-3_0
Changes since 1.10: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*--------------------------------*-C-*---------------------------------*
2 pcg 1.11 * File: ptytty.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
7 pcg 1.11 * Copyright (c) 2004 Marc Lehmann <pcg@goof.com>
8 pcg 1.1 *
9     * This program is free software; you can redistribute it and/or modify
10     * it under the terms of the GNU General Public License as published by
11     * the Free Software Foundation; either version 2 of the License, or
12     * (at your option) any later version.
13     *
14     * This program is distributed in the hope that it will be useful,
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     * GNU General Public License for more details.
18     *
19     * You should have received a copy of the GNU General Public License
20     * along with this program; if not, write to the Free Software
21     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22     *---------------------------------------------------------------------*/
23    
24     #include "../config.h" /* NECESSARY */
25    
26     /*
27     * Try to be self-contained except for the above autoconfig'd defines
28     */
29    
30 pcg 1.7 #if 0
31     #ifdef HAVE_GETPT
32     # define _GNU_SOURCE
33     #endif
34     #endif
35    
36 pcg 1.8 #include <cstdio>
37 pcg 1.1 #ifdef HAVE_STDLIB_H
38 pcg 1.8 # include <cstdlib>
39 pcg 1.1 #endif
40     #ifdef HAVE_SYS_TYPES_H
41     # include <sys/types.h>
42     #endif
43     #ifdef HAVE_UNISTD_H
44     # include <unistd.h>
45     #endif
46     #if defined(HAVE_STRING_H)
47 pcg 1.8 # include <cstring>
48 pcg 1.1 #endif
49     #ifdef HAVE_FCNTL_H
50     # include <fcntl.h>
51     #endif
52     #ifdef HAVE_SYS_IOCTL_H
53     # include <sys/ioctl.h>
54     #endif
55     #if defined(PTYS_ARE_PTMX) && !defined(__CYGWIN32__)
56     # include <sys/stropts.h> /* for I_PUSH */
57     #endif
58 pcg 1.10 #ifdef HAVE_ISASTREAM
59     # include <stropts.h>
60     #endif
61 pcg 1.1
62     #ifdef DEBUG_TTY
63     # define D_TTY(x) fprintf x ; fputc('\n', stderr) ; fflush(stderr)
64     #else
65     # define D_TTY(x)
66     #endif
67    
68     /* ------------------------------------------------------------------------- *
69     * GET PSEUDO TELETYPE - MASTER AND SLAVE *
70     * ------------------------------------------------------------------------- */
71     /*
72     * Returns pty file descriptor, or -1 on failure
73     * If successful, ttydev is set to the name of the slave device.
74     * fd_tty _may_ also be set to an open fd to the slave device
75     */
76     /* EXTPROTO */
77     int
78 pcg 1.6 rxvt_get_pty (int *fd_tty, const char **ttydev)
79 pcg 1.1 {
80 pcg 1.4 int pfd;
81 pcg 1.1
82     #ifdef PTYS_ARE_OPENPTY
83    
84 pcg 1.4 char tty_name[sizeof "/dev/pts/????\0"];
85    
86 pcg 1.6 if (openpty (&pfd, fd_tty, tty_name, NULL, NULL) != -1)
87 pcg 1.4 {
88 pcg 1.6 *ttydev = strdup (tty_name);
89 pcg 1.4 return pfd;
90 pcg 1.1 }
91     #endif
92    
93     #ifdef PTYS_ARE__GETPTY
94 pcg 1.6 *ttydev = _getpty (&pfd, O_RDWR | O_NONBLOCK | O_NOCTTY, 0622, 0);
95 pcg 1.4 if (*ttydev != NULL)
96     return pfd;
97 pcg 1.1 #endif
98    
99     #ifdef PTYS_ARE_GETPTY
100    
101 pcg 1.4 char *ptydev;
102    
103 pcg 1.6 while ((ptydev = getpty ()) != NULL)
104     if ((pfd = open (ptydev, O_RDWR | O_NOCTTY, 0)) >= 0)
105 pcg 1.4 {
106     *ttydev = ptydev;
107     return pfd;
108     }
109 pcg 1.1 #endif
110    
111     #if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT)
112     # if defined(PTYS_ARE_GETPT) || defined(PTYS_ARE_PTMX)
113 pcg 1.4
114     {
115 pcg 1.1 # ifdef PTYS_ARE_GETPT
116 pcg 1.6 pfd = getpt ();
117 pcg 1.1 # else
118 pcg 1.4
119 pcg 1.6 pfd = open ("/dev/ptmx", O_RDWR | O_NOCTTY, 0);
120 pcg 1.1 # endif
121 pcg 1.4
122     if (pfd >= 0)
123     {
124 pcg 1.6 if (grantpt (pfd) == 0 /* change slave permissions */
125     && unlockpt (pfd) == 0)
126 pcg 1.4 { /* slave now unlocked */
127 pcg 1.6 *ttydev = ptsname (pfd); /* get slave's name */
128 pcg 1.4 return pfd;
129     }
130 pcg 1.6 close (pfd);
131 pcg 1.4 }
132     }
133 pcg 1.1 # endif
134     #endif
135    
136     #ifdef PTYS_ARE_PTC
137 pcg 1.6 if ((pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0)) >= 0)
138 pcg 1.4 {
139 pcg 1.6 *ttydev = ttyname (pfd);
140 pcg 1.4 return pfd;
141 pcg 1.1 }
142     #endif
143    
144     #ifdef PTYS_ARE_CLONE
145 pcg 1.6 if ((pfd = open ("/dev/ptym/clone", O_RDWR | O_NOCTTY, 0)) >= 0)
146 pcg 1.4 {
147 pcg 1.6 *ttydev = ptsname (pfd);
148 pcg 1.4 return pfd;
149 pcg 1.1 }
150     #endif
151    
152     #ifdef PTYS_ARE_NUMERIC
153 pcg 1.4 {
154     int idx;
155     char *c1, *c2;
156     char pty_name[] = "/dev/ptyp???";
157     char tty_name[] = "/dev/ttyp???";
158    
159 pcg 1.6 c1 = & (pty_name[sizeof (pty_name) - 4]);
160     c2 = & (tty_name[sizeof (tty_name) - 4]);
161 pcg 1.4 for (idx = 0; idx < 256; idx++)
162     {
163 pcg 1.6 sprintf (c1, "%d", idx);
164     sprintf (c2, "%d", idx);
165     if (access (tty_name, F_OK) < 0)
166 pcg 1.4 {
167     idx = 256;
168     break;
169     }
170 pcg 1.6 if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) >= 0)
171 pcg 1.4 {
172 pcg 1.6 if (access (tty_name, R_OK | W_OK) == 0)
173 pcg 1.4 {
174 pcg 1.6 *ttydev = strdup (tty_name);
175 pcg 1.4 return pfd;
176     }
177 pcg 1.6 close (pfd);
178 pcg 1.4 }
179     }
180     }
181 pcg 1.1 #endif
182     #ifdef PTYS_ARE_SEARCHED
183 pcg 1.4 {
184     const char *c1, *c2;
185     char pty_name[] = "/dev/pty??";
186     char tty_name[] = "/dev/tty??";
187 pcg 1.1
188     # ifndef PTYCHAR1
189     # define PTYCHAR1 "pqrstuvwxyz"
190     # endif
191     # ifndef PTYCHAR2
192     # define PTYCHAR2 "0123456789abcdef"
193     # endif
194 pcg 1.4
195     for (c1 = PTYCHAR1; *c1; c1++)
196     {
197 pcg 1.6 pty_name[ (sizeof (pty_name) - 3)] =
198     tty_name[ (sizeof (pty_name) - 3)] = *c1;
199 pcg 1.4 for (c2 = PTYCHAR2; *c2; c2++)
200     {
201 pcg 1.6 pty_name[ (sizeof (pty_name) - 2)] =
202     tty_name[ (sizeof (pty_name) - 2)] = *c2;
203     if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) >= 0)
204 pcg 1.4 {
205 pcg 1.6 if (access (tty_name, R_OK | W_OK) == 0)
206 pcg 1.4 {
207 pcg 1.6 *ttydev = strdup (tty_name);
208 pcg 1.4 return pfd;
209     }
210 pcg 1.6 close (pfd);
211 pcg 1.4 }
212     }
213     }
214     }
215 pcg 1.1 #endif
216 pcg 1.4 return -1;
217 pcg 1.1 }
218    
219     /*----------------------------------------------------------------------*/
220     /*
221     * Returns tty file descriptor, or -1 on failure
222     */
223     /* EXTPROTO */
224     int
225 pcg 1.4 rxvt_get_tty (const char *ttydev)
226 pcg 1.1 {
227 pcg 1.4 return open (ttydev, O_RDWR | O_NOCTTY, 0);
228 pcg 1.1 }
229    
230     /*----------------------------------------------------------------------*/
231     /*
232     * Make our tty a controlling tty so that /dev/tty points to us
233     */
234     /* EXTPROTO */
235     int
236 pcg 1.4 rxvt_control_tty (int fd_tty, const char *ttydev)
237 pcg 1.1 {
238     #ifndef __QNX__
239 pcg 1.4 int fd;
240 pcg 1.1
241 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): pid: %d, tty fd: %d, dev: %s", getpid (), fd_tty, ttydev));
242 pcg 1.4 /* ---------------------------------------- */
243 pcg 1.1 # ifdef HAVE_SETSID
244 pcg 1.4 setsid ();
245 pcg 1.1 # endif
246     # if defined(HAVE_SETPGID)
247 pcg 1.4 setpgid (0, 0);
248 pcg 1.1 # elif defined(HAVE_SETPGRP)
249 pcg 1.4 setpgrp (0, 0);
250 pcg 1.1 # endif
251 pcg 1.4 /* ---------------------------------------- */
252 pcg 1.1 # ifdef TIOCNOTTY
253 pcg 1.4
254     fd = open ("/dev/tty", O_RDWR | O_NOCTTY);
255 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): Voiding tty associations: previous=%s", fd < 0 ? "no" : "yes"));
256 pcg 1.4 if (fd >= 0)
257     {
258     ioctl (fd, TIOCNOTTY, NULL); /* void tty associations */
259     close (fd);
260 pcg 1.1 }
261     # endif
262 pcg 1.4 /* ---------------------------------------- */
263     fd = open ("/dev/tty", O_RDWR | O_NOCTTY);
264 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): /dev/tty has controlling tty? %s", fd < 0 ? "no (good)" : "yes (bad)"));
265 pcg 1.4 if (fd >= 0)
266     close (fd); /* ouch: still have controlling tty */
267     /* ---------------------------------------- */
268 pcg 1.1 #if defined(PTYS_ARE_PTMX) && defined(I_PUSH)
269 pcg 1.4 /*
270     * Push STREAMS modules:
271     * ptem: pseudo-terminal hardware emulation module.
272     * ldterm: standard terminal line discipline.
273     * ttcompat: V7, 4BSD and XENIX STREAMS compatibility module.
274     *
275 pcg 1.6 * After we push the STREAMS modules, the first open () on the slave side
276 pcg 1.4 * (i.e. the next section between the dashes giving us "tty opened OK")
277     * should make the "ptem" (or "ldterm" depending upon either which OS
278     * version or which set of manual pages you have) module give us a
279 pcg 1.6 * controlling terminal. We must already have close ()d the master side
280 pcg 1.4 * fd in this child process before we push STREAMS modules on because the
281 pcg 1.6 * documentation is really unclear about whether it is any close () on
282     * the master side or the last close () - i.e. a proper STREAMS dismantling
283     * close () - on the master side which causes a hang up to be sent
284 pcg 1.4 * through - Geoff Wing
285     */
286 pcg 1.1 # ifdef HAVE_ISASTREAM
287 pcg 1.4 if (isastream (fd_tty) == 1)
288 pcg 1.1 # endif
289     {
290 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): Pushing STREAMS modules"));
291 pcg 1.4 ioctl (fd_tty, I_PUSH, "ptem");
292     ioctl (fd_tty, I_PUSH, "ldterm");
293     ioctl (fd_tty, I_PUSH, "ttcompat");
294 pcg 1.1 }
295     #endif
296 pcg 1.4 /* ---------------------------------------- */
297 pcg 1.1 # if defined(TIOCSCTTY)
298 pcg 1.4 fd = ioctl (fd_tty, TIOCSCTTY, NULL);
299 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): ioctl (..,TIOCSCTTY): %d", fd));
300 pcg 1.1 # elif defined(TIOCSETCTTY)
301 pcg 1.4 fd = ioctl (fd_tty, TIOCSETCTTY, NULL);
302 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): ioctl (..,TIOCSETCTTY): %d", fd));
303 pcg 1.1 # else
304 pcg 1.4 fd = open (ttydev, O_RDWR);
305 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): tty open%s", fd < 0 ? " failure" : "ed OK"));
306 pcg 1.4 if (fd >= 0)
307 pcg 1.6 close (fd);
308 pcg 1.1 # endif
309 pcg 1.4 /* ---------------------------------------- */
310     fd = open ("/dev/tty", O_WRONLY);
311 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): do we have controlling tty now: %s", fd < 0 ? "no (fatal)" : "yes (good)"));
312 pcg 1.4 if (fd < 0)
313     return -1; /* fatal */
314     close (fd);
315     /* ---------------------------------------- */
316 pcg 1.6 D_TTY ((stderr, "rxvt_control_tty (): tcgetpgrp (): %d getpgrp (): %d", tcgetpgrp (fd_tty), getpgrp ()));
317 pcg 1.4 /* ---------------------------------------- */
318 pcg 1.1 #endif /* ! __QNX__ */
319 pcg 1.4
320     return 0;
321 pcg 1.1 }
322     /*----------------------- end-of-file (C source) -----------------------*/