Do not include a couple of missing files under linux.
[oweals/cde.git] / cde / lib / DtTerm / TermPrim / TermPrimGetPty-svr4.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 #ifndef lint
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 */
27 #endif  /* lint */
28
29 /*                                                                      *
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.                                *
34  */
35
36 /**************************************************************************
37  *
38  *  Note: This code is based on the pty allocation code from xview.  It
39  *        was basically taken intact as were the comments...
40  */
41
42 #include "TermPrimOSDepI.h"
43 #include "TermPrimDebug.h"
44 #include "TermHeader.h"
45 #include <stropts.h>
46 #if !defined(linux)
47 #include <sys/conf.h>
48 #include <sys/stream.h>
49 #endif
50 #include <sys/termios.h>
51 #ifdef  USE_STREAMS_BUFMOD
52 #include <sys/bufmod.h>
53 #endif  /* USE_STREAMS_BUFMOD */
54 #include <errno.h>
55
56 /* last ditch fallback.  If the clone device is other than /dev/ptmx,
57  * it should have been set previously...
58  */
59 #ifndef PTY_CLONE_DEVICE
60 #define PTY_CLONE_DEVICE        "/dev/ptmx"
61 #endif  /* PTY_CLONE_DEVICE */
62
63
64 int _DtTermPrimGetPty(char **ptySlave, char **ptyMaster)
65 {
66     char *c;
67     int ptyFd;
68     int ttyFd;
69     extern char *ptsname(int fd);
70
71     *ptyMaster = malloc(strlen(PTY_CLONE_DEVICE) + 1);
72     (void) strcpy(*ptyMaster, PTY_CLONE_DEVICE);
73
74     if (isDebugFSet('p', 10)) {
75 #ifdef  BBA
76 #pragma BBA_IGNORE
77 #endif  /*BBA*/
78         return(-1);
79     }
80
81     if ((ptyFd = open(*ptyMaster, O_RDWR, 0)) >= 0) {
82
83         /* use grantpt to prevent other processes from grabbing the tty that
84          * goes with the pty master we have opened.  It is a mandatory step
85          * in the SVR4 pty-tty initialization.  Note that /dev must be
86          * mounted read/write...
87          */
88         Debug('T', timeStamp("_DtTermPrimGetPty() calling grantpt()"));
89         if (grantpt(ptyFd) == -1) {
90             (void) perror("grantpt");
91             (void) close(ptyFd);
92             return(-1);
93         }
94
95         /* Unlock the pty master/slave pair so the slave can be opened later */
96         Debug('T', timeStamp("_DtTermPrimGetPty() calling unlockpt()"));
97         if (unlockpt(ptyFd) == -1) {
98             (void) perror("unlockpt");
99             (void) close(ptyFd);
100             return(-1);
101         }
102         Debug('T', timeStamp("_DtTermPrimGetPty() unlockpt() finished"));
103
104 #ifdef  USE_STREAMS_BUFMOD
105         if (ioctl(ptyFd, I_PUSH, "bufmod") == -1) {
106             (void) perror("I_PUSH bufmod");
107
108             /* We can't push bufmod.  This means that we're probably running
109              * on a generic SVR4 system.  We can ignore this error since
110              * bufmod is used for performance reasons only...
111              */
112         } else {
113             struct timeval timeval;
114             struct strioctl cmd;
115             unsigned int chunk;
116
117             /* Note that we're not using SB_SEND_ON_WRITE | SB_DEFER_CHUNK.
118              * Turns out the shell (or someone down the pty) does an ioctl
119              * when sending out each prompt.  Since this flushes any
120              * partially filled chunk automatically, we really don't need
121              * to do this...
122              */
123
124             chunk = SB_NO_DROPS | SB_NO_PROTO_CVT | SB_NO_HEADER;
125             cmd.ic_timout = 0;
126             cmd.ic_cmd = SBIOCSFLAGS;
127             cmd.ic_len = sizeof(u_long);
128             cmd.ic_dp = (char *) &chunk;
129             if (ioctl(ptyFd, I_STR, &cmd) < 0) {
130                 (void) perror("SBIOCSFLAGS");
131                 /* If we pushed bufmod, but this ioctl fails, it means we're
132                  * most likely running on a system with old bufmod (i.e., for
133                  * released OSs this must be Jupiter).  We treat this error
134                  * silently so developers and users of the Mars trees don't
135                  * get confused.  Treat it like bufmod wasn't there at all...
136                  */
137                 goto backoff;
138             }
139
140             timeval.tv_usec = 50000;
141             timeval.tv_sec = 0;
142             cmd.ic_cmd = SBIOCSTIME;
143             cmd.ic_timout = 0;
144             cmd.ic_len = sizeof(timeval);
145             cmd.ic_dp = (char *) &timeval;
146             if (ioctl(ptyFd, I_STR, &cmd) < 0) {
147                 /* These are legit errors.  If we have new bufmod, this
148                  * should have worked...
149                  */
150                 (void) perror("BSIOCSTIME");
151                 goto backoff;
152             }
153
154             /* I have made the chunk size the same as the buffer used in the
155              * ttysw.  One could experiment here, but this works...
156              */
157             {
158                 /* struct cbuf *sizeit; */
159                 /* chunk = sizeof(sizeit->cb_buf); */
160                 chunk = 2048; /* taken from xview source def of cbuf... */
161             }
162
163             cmd.ic_cmd = SBIOCSCHUNK;
164             cmd.ic_len = sizeof(int);
165             cmd.ic_dp = (char *) &chunk;
166
167             if (ioctl(ptyFd, I_STR, &cmd) < 0) {
168                 (void) perror("SBIOCSCHUNK");
169                 goto backoff;
170             }
171
172             /* We certainly don't want to truncate any packets, so set the
173              * snap length to zero...
174              */
175             chunk = 0;
176             cmd.ic_cmd = SBIOCSSNAP;
177             cmd.ic_len = sizeof(int);
178             cmd.ic_dp = (char *) &chunk;
179             if (ioctl(ptyFd, I_STR, &cmd) < 0) {
180                 (void) perror("SBIOCSSNAP");
181                 goto backoff;
182             }
183
184             goto ok;
185         }
186
187 backoff:
188         /* Something didn't work out, so pull bofmod off the stream and
189          * continue as if it weren't there...
190          */
191         if (ioctl(ptyFd, I_POP, 0) == -1) {
192             /* bufmod not working or wrong version... */
193             (void) perror("I_POP bufmod");
194         }
195
196 ok:
197 #endif  /* USE_STREAMS_BUFMOD */
198
199         /* get the pty slave name... */
200         if (c = ptsname(ptyFd)) {
201             *ptySlave = malloc(strlen(c) + 1);
202             (void) strcpy(*ptySlave, c);
203 #ifdef  NOTDEF
204             {
205                 int slaveFd;
206                 char buffer[BUFSIZ];
207
208                 if ((slaveFd = open(*ptySlave, O_RDWR, 0)) < 0) {
209                     (void) perror(*ptySlave);
210                     (void) fprintf(stderr, "it failed!\n");
211                     (void) sprintf(buffer, "ls -l %s", *ptySlave);
212                     (void) system(buffer);
213                 } else {
214                     (void) close(slaveFd);
215                 }
216             }
217 #endif  /* NOTDEF */
218             return(ptyFd);
219         } else {
220             /* ptsname on the pty master failed.  This should not happen!... */
221             (void) perror("ptsname");
222             (void) close(ptyFd);
223         }
224     } else {
225         (void) perror(*ptyMaster);
226     }
227     return(-1);
228 }
229
230 int
231 _DtTermPrimSetupPty(char *ptySlave, int ptyFd)
232 {
233     /*
234      * The following "pushes" were done at GetPty time, but
235      * they don't seem to stick after the file is closed on
236      * SVR4.2.  Not sure where else this applies.
237      */
238     if (ioctl(ptyFd, I_PUSH, "ptem") == -1) {
239             (void) perror("Error pushing ptem");
240             /* exit the subprocess */
241             return(1);
242     }
243
244     if (ioctl(ptyFd, I_PUSH, "ldterm") == -1) {
245             (void) perror("Error pushing ldterm");
246             /* exit the subprocess */
247             return(1);
248     }
249
250 #ifdef  USE_STREAMS_TTCOMPAT
251     if (ioctl(ptyFd, I_PUSH, "ttcompat") == -1) {
252             (void) perror("Error pushing ttcompat");
253             /* exit the subprocess */
254             return(1);
255     }
256 #endif  /* USE_STREAMS_TTCOMPAT */
257
258     /* success... */
259     return(0);
260 }
261
262 void
263 _DtTermPrimReleasePty(char *ptySlave)
264 {
265     /* dummy function for STREAMS... */
266 }
267
268 void
269 _DtTermPrimPtyCleanup()
270 {
271     /* dummy function for STREAMS... */
272     return;
273 }