Initial checkin. I created this by combining the XBoard 4.2.6 and
[xboard.git] / childio.c
1 /*
2  * childio.c -- set up communication with child processes $Id:
3  * childio.c,v 1.2 1994/11/12 19:31:41 mann Exp mann $
4  *
5  * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
6  * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
7  *
8  * The following terms apply to Digital Equipment Corporation's copyright
9  * interest in XBoard:
10  * ------------------------------------------------------------------------
11  * All Rights Reserved
12  *
13  * Permission to use, copy, modify, and distribute this software and its
14  * documentation for any purpose and without fee is hereby granted,
15  * provided that the above copyright notice appear in all copies and that
16  * both that copyright notice and this permission notice appear in
17  * supporting documentation, and that the name of Digital not be
18  * used in advertising or publicity pertaining to distribution of the
19  * software without specific, written prior permission.
20  *
21  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27  * SOFTWARE.
28  * ------------------------------------------------------------------------
29  *
30  * The following terms apply to the enhanced version of XBoard distributed
31  * by the Free Software Foundation:
32  * ------------------------------------------------------------------------
33  * This program is free software; you can redistribute it and/or modify
34  * it under the terms of the GNU General Public License as published by
35  * the Free Software Foundation; either version 2 of the License, or
36  * (at your option) any later version.
37  *
38  * This program is distributed in the hope that it will be useful,
39  * but WITHOUT ANY WARRANTY; without even the implied warranty of
40  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
41  * GNU General Public License for more details.
42  *
43  * You should have received a copy of the GNU General Public License
44  * along with this program; if not, write to the Free Software
45  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46  * ------------------------------------------------------------------------
47  *
48  * See the file ChangeLog for a revision history.  */
49
50 /* This file splits into two entirely different pieces of code
51    depending on whether USE_PTYS is 1.  The whole reason for all
52    the pty nonsense is that select() does not work on pipes in System-V
53    derivatives (at least some of them).  This is a problem because
54    XtAppAddInput works by adding its argument to a select that is done
55    deep inside Xlib.
56 */
57
58 #include "config.h"
59
60 #include <signal.h>
61 #if HAVE_UNISTD_H
62 # include <unistd.h>
63 #endif
64
65 #include "common.h"
66 #include "frontend.h"
67
68 #if !USE_PTYS
69 /* This code is for systems where pipes work properly */
70
71 void SetUpChildIO(to_prog, from_prog)
72      int to_prog[2], from_prog[2];
73 {
74     signal(SIGPIPE, SIG_IGN);
75     pipe(to_prog);
76     pipe(from_prog);
77 }
78
79 #else /* USE_PTYS == 1 */
80 /* This code is for all systems where we must use ptys */
81
82 #include <errno.h>
83 #include <sys/stat.h>
84 #include <sys/ioctl.h>
85 #if HAVE_STROPTS_H
86 # include <stropts.h>
87 #endif /* HAVE_STROPTS_H */
88 #if HAVE_SYS_FCNTL_H
89 # include <sys/fcntl.h>
90 #else /* not HAVE_SYS_FCNTL_H */
91 # if HAVE_FCNTL_H
92 #  include <fcntl.h>
93 # endif /* HAVE_FCNTL_H */
94 #endif /* not HAVE_SYS_FCNTL_H */
95
96 int PseudoTTY P((char pty_name[]));
97
98 int SetUpChildIO(to_prog, from_prog)
99      int to_prog[2], from_prog[2];
100 {
101     char pty_name[MSG_SIZ];
102
103     if ((to_prog[1] = PseudoTTY(pty_name)) == -1) {
104         DisplayFatalError("Can't open pseudo-tty", errno, 1);
105         ExitEvent(1);
106     }
107     from_prog[0] = to_prog[1];
108     to_prog[0] = from_prog[1] = open(pty_name, O_RDWR, 0);
109
110 #if HAVE_STROPTS_H /* do we really need this??  pipe-like behavior is fine */
111     if (ioctl (to_prog[0], I_PUSH, "ptem") == -1 ||
112         ioctl (to_prog[0], I_PUSH, "ldterm") == -1 ||
113         ioctl (to_prog[0], I_PUSH, "ttcompat") == -1) {
114 # ifdef NOTDEF /* seems some systems don't have or need ptem and ttcompat */
115         DisplayFatalError("Can't ioctl pseudo-tty", errno, 1);
116         ExitEvent(1);
117 # endif /*NOTDEF*/
118     }
119 #endif /* HAVE_STROPTS_H */
120
121 }
122
123 #if HAVE_GRANTPT
124 /* This code is for SVR4 */
125
126 int PseudoTTY(pty_name)
127      char pty_name[];
128 {
129     extern char *ptsname();
130     char *ptss;
131     int fd;
132     
133     fd = open("/dev/ptmx", O_RDWR);
134     if (fd < 0) return fd;
135     if (grantpt(fd) == -1) return -1;
136     if (unlockpt(fd) == -1) return -1;
137     if (!(ptss = ptsname(fd))) return -1;
138     strcpy(pty_name, ptss);
139     return fd;
140 }
141
142 #else /* not HAVE_GRANTPT */
143 #if HAVE__GETPTY
144 /* This code is for IRIX */
145
146 int PseudoTTY(pty_name)
147      char pty_name[];
148 {
149     int fd;
150     char *ptyn;
151
152     ptyn = _getpty(&fd, O_RDWR, 0600, 0);
153     if (ptyn == NULL) return -1;
154     strcpy(pty_name, ptyn);
155     return fd;
156 }
157
158 #else /* not HAVE__GETPTY */
159 #if HAVE_LIBSEQ
160 /* This code is for Sequent DYNIX/ptx.  Untested. --tpm */
161
162 int PseudoTTY(pty_name)
163      char pty_name[];
164 {
165     int fd;
166     char *slave, *master;
167
168     fd = getpseudotty(&slave, &master);
169     if (fd < 0) return fd;
170     strcpy(pty_name, slave);
171     return fd;
172 }
173
174 #else /* not HAVE_LIBSEQ */
175 /* This code is for all other systems */
176 /* The code is adapted from GNU Emacs 19.24 */
177
178 #ifndef FIRST_PTY_LETTER
179 #define FIRST_PTY_LETTER 'p'
180 #endif
181 #ifndef LAST_PTY_LETTER
182 #define LAST_PTY_LETTER 'z'
183 #endif
184
185 int PseudoTTY(pty_name)
186      char pty_name[];
187 {
188   struct stat stb;
189   register c, i;
190   int fd;
191
192   /* Some systems name their pseudoterminals so that there are gaps in
193      the usual sequence - for example, on HP9000/S700 systems, there
194      are no pseudoterminals with names ending in 'f'.  So we wait for
195      three failures in a row before deciding that we've reached the
196      end of the ptys.  */
197   int failed_count = 0;
198
199 #ifdef PTY_ITERATION
200   PTY_ITERATION
201 #else
202   for (c = FIRST_PTY_LETTER; c <= LAST_PTY_LETTER; c++)
203     for (i = 0; i < 16; i++)
204 #endif
205       {
206 #ifdef PTY_NAME_SPRINTF
207         PTY_NAME_SPRINTF
208 #else
209         sprintf (pty_name, "/dev/pty%c%x", c, i);
210 #endif /* no PTY_NAME_SPRINTF */
211
212 #ifdef PTY_OPEN
213         PTY_OPEN;
214 #else /* no PTY_OPEN */
215         if (stat (pty_name, &stb) < 0)
216           {
217             failed_count++;
218             if (failed_count >= 3)
219               return -1;
220           }
221         else
222           failed_count = 0;
223         fd = open (pty_name, O_RDWR, 0);
224 #endif /* no PTY_OPEN */
225
226         if (fd >= 0)
227           {
228             /* check to make certain that both sides are available
229                this avoids a nasty yet stupid bug in rlogins */
230 #ifdef PTY_TTY_NAME_SPRINTF
231             PTY_TTY_NAME_SPRINTF
232 #else
233             sprintf (pty_name, "/dev/tty%c%x", c, i);
234 #endif /* no PTY_TTY_NAME_SPRINTF */
235 #ifndef UNIPLUS
236             if (access (pty_name, 6) != 0)
237               {
238                 close (fd);
239                 continue;
240               }
241 #endif /* not UNIPLUS */
242 #ifdef IBMRTAIX
243               /* On AIX, the parent gets SIGHUP when a pty attached
244                  child dies.  So, we ignore SIGHUP once we've started
245                  a child on a pty.  Note that this may cause xboard
246                  not to die when it should, i.e., when its own
247                  controlling tty goes away.
248               */
249               signal(SIGHUP, SIG_IGN);
250 #endif /* IBMRTAIX */
251             return fd;
252           }
253       }
254   return -1;
255 }
256
257 #endif /* not HAVE_LIBSEQ */
258 #endif /* not HAVE__GETPTY */
259 #endif /* not HAVE_GRANTPT */
260 #endif /* USE_PTYS */