2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 #ifdef VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermPrimGetPty-svr4.c /main/1 1996/04/21 19:17:39 drk $";
26 #endif /* VERBOSE_REV_INFO */
30 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
31 * (c) Copyright 1993, 1994 International Business Machines Corp. *
32 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
33 * (c) Copyright 1993, 1994 Novell, Inc. *
36 /**************************************************************************
38 * Note: This code is based on the pty allocation code from xview. It
39 * was basically taken intact as were the comments...
43 #include "TermPrimOSDepI.h"
44 #include "TermPrimDebug.h"
45 #include "TermHeader.h"
49 #include <sys/stream.h>
51 #include <sys/termios.h>
54 #undef USE_STREAMS_BUFMOD
57 #ifdef USE_STREAMS_BUFMOD
58 #include <sys/bufmod.h>
59 #endif /* USE_STREAMS_BUFMOD */
63 /* last ditch fallback. If the clone device is other than /dev/ptmx,
64 * it should have been set previously...
66 #ifndef PTY_CLONE_DEVICE
67 #define PTY_CLONE_DEVICE "/dev/ptmx"
68 #endif /* PTY_CLONE_DEVICE */
71 static int GetPty(char **ptySlave, char **ptyMaster)
76 extern char *ptsname(int fd);
78 *ptyMaster = malloc(strlen(PTY_CLONE_DEVICE) + 1);
79 (void) strcpy(*ptyMaster, PTY_CLONE_DEVICE);
81 if (isDebugFSet('p', 10)) {
88 if ((ptyFd = open(*ptyMaster, O_RDWR, 0)) >= 0) {
90 /* use grantpt to prevent other processes from grabbing the tty that
91 * goes with the pty master we have opened. It is a mandatory step
92 * in the SVR4 pty-tty initialization. Note that /dev must be
93 * mounted read/write...
95 Debug('T', timeStamp("_DtTermPrimGetPty() calling grantpt()"));
96 if (grantpt(ptyFd) == -1) {
97 (void) perror("grantpt");
102 /* Unlock the pty master/slave pair so the slave can be opened later */
103 Debug('T', timeStamp("_DtTermPrimGetPty() calling unlockpt()"));
104 if (unlockpt(ptyFd) == -1) {
105 (void) perror("unlockpt");
109 Debug('T', timeStamp("_DtTermPrimGetPty() unlockpt() finished"));
111 #ifdef USE_STREAMS_BUFMOD
112 if (ioctl(ptyFd, I_PUSH, "bufmod") == -1) {
113 (void) perror("I_PUSH bufmod");
115 /* We can't push bufmod. This means that we're probably running
116 * on a generic SVR4 system. We can ignore this error since
117 * bufmod is used for performance reasons only...
120 struct timeval timeval;
124 /* Note that we're not using SB_SEND_ON_WRITE | SB_DEFER_CHUNK.
125 * Turns out the shell (or someone down the pty) does an ioctl
126 * when sending out each prompt. Since this flushes any
127 * partially filled chunk automatically, we really don't need
131 chunk = SB_NO_DROPS | SB_NO_PROTO_CVT | SB_NO_HEADER;
133 cmd.ic_cmd = SBIOCSFLAGS;
134 cmd.ic_len = sizeof(u_long);
135 cmd.ic_dp = (char *) &chunk;
136 if (ioctl(ptyFd, I_STR, &cmd) < 0) {
137 (void) perror("SBIOCSFLAGS");
138 /* If we pushed bufmod, but this ioctl fails, it means we're
139 * most likely running on a system with old bufmod (i.e., for
140 * released OSs this must be Jupiter). We treat this error
141 * silently so developers and users of the Mars trees don't
142 * get confused. Treat it like bufmod wasn't there at all...
147 timeval.tv_usec = 50000;
149 cmd.ic_cmd = SBIOCSTIME;
151 cmd.ic_len = sizeof(timeval);
152 cmd.ic_dp = (char *) &timeval;
153 if (ioctl(ptyFd, I_STR, &cmd) < 0) {
154 /* These are legit errors. If we have new bufmod, this
155 * should have worked...
157 (void) perror("BSIOCSTIME");
161 /* I have made the chunk size the same as the buffer used in the
162 * ttysw. One could experiment here, but this works...
165 /* struct cbuf *sizeit; */
166 /* chunk = sizeof(sizeit->cb_buf); */
167 chunk = 2048; /* taken from xview source def of cbuf... */
170 cmd.ic_cmd = SBIOCSCHUNK;
171 cmd.ic_len = sizeof(int);
172 cmd.ic_dp = (char *) &chunk;
174 if (ioctl(ptyFd, I_STR, &cmd) < 0) {
175 (void) perror("SBIOCSCHUNK");
179 /* We certainly don't want to truncate any packets, so set the
180 * snap length to zero...
183 cmd.ic_cmd = SBIOCSSNAP;
184 cmd.ic_len = sizeof(int);
185 cmd.ic_dp = (char *) &chunk;
186 if (ioctl(ptyFd, I_STR, &cmd) < 0) {
187 (void) perror("SBIOCSSNAP");
195 /* Something didn't work out, so pull bofmod off the stream and
196 * continue as if it weren't there...
198 if (ioctl(ptyFd, I_POP, 0) == -1) {
199 /* bufmod not working or wrong version... */
200 (void) perror("I_POP bufmod");
204 #endif /* USE_STREAMS_BUFMOD */
206 /* get the pty slave name... */
207 if (c = ptsname(ptyFd)) {
208 *ptySlave = malloc(strlen(c) + 1);
209 (void) strcpy(*ptySlave, c);
215 if ((slaveFd = open(*ptySlave, O_RDWR, 0)) < 0) {
216 (void) perror(*ptySlave);
217 (void) fprintf(stderr, "it failed!\n");
218 (void) sprintf(buffer, "ls -l %s", *ptySlave);
219 (void) system(buffer);
221 (void) close(slaveFd);
227 /* ptsname on the pty master failed. This should not happen!... */
228 (void) perror("ptsname");
232 (void) perror(*ptyMaster);
237 /* this is a public wrapper around the previous function that runs the
238 * previous function setuid root...
241 _DtTermPrimGetPty(char **ptySlave, char **ptyMaster)
245 /* this function needs to be suid root... */
246 (void) _DtTermPrimToggleSuidRoot(True);
247 retValue = GetPty(ptySlave, ptyMaster);
248 /* we now need to turn off setuid root... */
249 (void) _DtTermPrimToggleSuidRoot(False);
256 SetupPty(char *ptySlave, int ptyFd)
259 * The following "pushes" were done at GetPty time, but
260 * they don't seem to stick after the file is closed on
261 * SVR4.2. Not sure where else this applies.
264 if (ioctl(ptyFd, I_PUSH, "ptem") == -1) {
265 (void) perror("Error pushing ptem");
266 /* exit the subprocess */
270 if (ioctl(ptyFd, I_PUSH, "ldterm") == -1) {
271 (void) perror("Error pushing ldterm");
272 /* exit the subprocess */
276 #ifdef USE_STREAMS_TTCOMPAT
277 if (ioctl(ptyFd, I_PUSH, "ttcompat") == -1) {
278 (void) perror("Error pushing ttcompat");
279 /* exit the subprocess */
282 #endif /* USE_STREAMS_TTCOMPAT */
286 chown(ptySlave, getuid(), getgid());
287 chmod(ptySlave, 0622);
295 _DtTermPrimSetupPty(char *ptySlave, int ptyFd)
299 /* this function needs to be suid root... */
300 (void) _DtTermPrimToggleSuidRoot(True);
301 retValue = SetupPty(ptySlave, ptyFd);
302 /* we now need to turn off setuid root... */
303 (void) _DtTermPrimToggleSuidRoot(False);
309 _DtTermPrimReleasePty(char *ptySlave)
311 /* dummy function for STREAMS... */
315 _DtTermPrimPtyCleanup()
317 /* dummy function for STREAMS... */