ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/ptytty.C
Revision: 1.10
Committed: Fri Apr 2 20:41:01 2004 UTC (20 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_7
Changes since 1.8: +3 -0 lines
Log Message:
*** empty log message ***

File Contents

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