Fix minor bug in last change.
[deliverable/binutils-gdb.git] / gdb / ser-pipe.c
CommitLineData
daf3f280
JM
1/* Serial interface for a pipe to a separate program
2 Copyright 1999 Free Software Foundation, Inc.
3
4 Contributed by Cygnus Solutions.
5
6 This file is part of GDB.
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., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23#include "defs.h"
24#include "serial.h"
25#include <sys/types.h>
96baa820 26#ifdef HAVE_SYS_WAIT_H
daf3f280 27#include <sys/wait.h>
96baa820 28#endif
daf3f280
JM
29#include <sys/socket.h>
30#include <sys/time.h>
31#include <fcntl.h>
32#ifdef HAVE_UNISTD_H
33#include <unistd.h>
34#endif
35
36#include "signals.h"
37#include "gdb_string.h"
38
39extern int (*ui_loop_hook) PARAMS ((int));
40
41static int pipe_open PARAMS ((serial_t scb, const char *name));
42static void pipe_raw PARAMS ((serial_t scb));
43static int wait_for PARAMS ((serial_t scb, int timeout));
44static int pipe_readchar PARAMS ((serial_t scb, int timeout));
45static int pipe_setbaudrate PARAMS ((serial_t scb, int rate));
46static int pipe_setstopbits PARAMS ((serial_t scb, int num));
47static int pipe_write PARAMS ((serial_t scb, const char *str, int len));
48/* FIXME: static void pipe_restore PARAMS ((serial_t scb)); */
49static void pipe_close PARAMS ((serial_t scb));
50static serial_ttystate pipe_get_tty_state PARAMS ((serial_t scb));
51static int pipe_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
52static int pipe_return_0 PARAMS ((serial_t));
53static int pipe_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate,
54 serial_ttystate));
55static void pipe_print_tty_state PARAMS ((serial_t, serial_ttystate));
56
57extern void _initialize_ser_pipe PARAMS ((void));
58
adf40b2e
JM
59#undef XMALLOC
60#define XMALLOC(T) ((T*) xmalloc (sizeof (T)))
61
62
63struct pipe_state
64 {
65 int pid;
66 };
67
daf3f280
JM
68/* Open up a raw pipe */
69
70static int
71pipe_open (scb, name)
72 serial_t scb;
73 const char *name;
74{
96baa820 75#if !defined(O_NONBLOCK) || !defined(F_GETFL) || !defined(F_SETFL) || !HAVE_SOCKETPAIR
daf3f280
JM
76 return -1;
77#else
adf40b2e 78 struct pipe_state *state;
daf3f280 79 /* This chunk: */
daf3f280
JM
80 /* Copyright (c) 1988, 1993
81 * The Regents of the University of California. All rights reserved.
82 *
83 * This code is derived from software written by Ken Arnold and
84 * published in UNIX Review, Vol. 6, No. 8.
85 */
86 int pdes[2];
87 int pid;
88 if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
89 return -1;
90
adf40b2e
JM
91 pid = vfork ();
92
93 /* Error. */
94 if (pid == -1)
daf3f280 95 {
daf3f280
JM
96 close (pdes[0]);
97 close (pdes[1]);
98 return -1;
adf40b2e
JM
99 }
100
101 /* Child. */
102 if (pid == 0)
103 {
104 /* re-wire pdes[1] to stdin/stdout */
daf3f280
JM
105 close (pdes[0]);
106 if (pdes[1] != STDOUT_FILENO)
107 {
108 dup2 (pdes[1], STDOUT_FILENO);
109 close (pdes[1]);
110 }
111 dup2 (STDOUT_FILENO, STDIN_FILENO);
adf40b2e
JM
112#if 0
113 /* close any stray FD's - FIXME - how? */
114 /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
115 from previous popen() calls that remain open in the
116 parent process are closed in the new child process. */
117 for (old = pidlist; old; old = old->next)
118 close (fileno (old->fp)); /* don't allow a flush */
119#endif
daf3f280
JM
120 execl ("/bin/sh", "sh", "-c", name + 1, NULL);
121 _exit (127);
122 }
123
adf40b2e 124 /* Parent. */
daf3f280 125 close (pdes[1]);
adf40b2e
JM
126 /* :end chunk */
127 state = XMALLOC (struct pipe_state);
128 state->pid = pid;
daf3f280 129 scb->fd = pdes[0];
adf40b2e 130 scb->state = state;
daf3f280
JM
131
132 /* Make it non-blocking */
133 {
134 int flags = fcntl (scb->fd, F_GETFL, 0);
135 if (fcntl (scb->fd, F_SETFL, flags | O_NONBLOCK) < 0)
136 {
137 perror ("ser-pipe");
138 pipe_close (scb);
139 return -1;
140 }
141 }
142
143 /* If we don't do this, GDB simply exits when the remote side dies. */
144 signal (SIGPIPE, SIG_IGN);
145 return 0;
146#endif
147}
148
149static serial_ttystate
150pipe_get_tty_state (scb)
151 serial_t scb;
152{
153 /* return garbage */
154 return xmalloc (sizeof (int));
155}
156
157static int
158pipe_set_tty_state (scb, ttystate)
159 serial_t scb;
160 serial_ttystate ttystate;
161{
162 return 0;
163}
164
165static int
166pipe_return_0 (scb)
167 serial_t scb;
168{
169 return 0;
170}
171
172static void
173pipe_raw (scb)
174 serial_t scb;
175{
176 return; /* Always in raw mode */
177}
178
179/* Wait for input on scb, with timeout seconds. Returns 0 on success,
180 otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
181
182 For termio{s}, we actually just setup VTIME if necessary, and let the
183 timeout occur in the read() in pipe_read().
184 */
185
186static int
187wait_for (scb, timeout)
188 serial_t scb;
189 int timeout;
190{
191 int numfds;
192 struct timeval tv;
193 fd_set readfds, exceptfds;
194
195 FD_ZERO (&readfds);
196 FD_ZERO (&exceptfds);
197
198 tv.tv_sec = timeout;
199 tv.tv_usec = 0;
200
201 FD_SET (scb->fd, &readfds);
202 FD_SET (scb->fd, &exceptfds);
203
204 while (1)
205 {
206 if (timeout >= 0)
207 numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
208 else
209 numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
210
211 if (numfds <= 0)
212 {
213 if (numfds == 0)
214 return SERIAL_TIMEOUT;
215 else if (errno == EINTR)
216 continue;
217 else
218 return SERIAL_ERROR; /* Got an error from select or poll */
219 }
220
221 return 0;
222 }
223}
224
225/* Read a character with user-specified timeout. TIMEOUT is number of seconds
226 to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
227 char if successful. Returns -2 if timeout expired, EOF if line dropped
228 dead, or -3 for any other error (see errno in that case). */
229
230static int
231pipe_readchar (scb, timeout)
232 serial_t scb;
233 int timeout;
234{
235 int status;
236 int delta;
237
238 if (scb->bufcnt-- > 0)
239 return *scb->bufp++;
240
241 /* We have to be able to keep the GUI alive here, so we break the original
242 timeout into steps of 1 second, running the "keep the GUI alive" hook
243 each time through the loop.
244
245 Also, timeout = 0 means to poll, so we just set the delta to 0, so we
246 will only go through the loop once. */
247
248 delta = (timeout == 0 ? 0 : 1);
249 while (1)
250 {
251
252 /* N.B. The UI may destroy our world (for instance by calling
253 remote_stop,) in which case we want to get out of here as
254 quickly as possible. It is not safe to touch scb, since
255 someone else might have freed it. The ui_loop_hook signals that
256 we should exit by returning 1. */
257
258 if (ui_loop_hook)
259 {
260 if (ui_loop_hook (0))
261 return SERIAL_TIMEOUT;
262 }
263
264 status = wait_for (scb, delta);
265 timeout -= delta;
266
267 /* If we got a character or an error back from wait_for, then we can
268 break from the loop before the timeout is completed. */
269
270 if (status != SERIAL_TIMEOUT)
271 {
272 break;
273 }
274
275 /* If we have exhausted the original timeout, then generate
276 a SERIAL_TIMEOUT, and pass it out of the loop. */
277
278 else if (timeout == 0)
279 {
280 status == SERIAL_TIMEOUT;
281 break;
282 }
283 }
284
285 if (status < 0)
286 return status;
287
288 while (1)
289 {
290 scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ);
291 if (scb->bufcnt != -1 || errno != EINTR)
292 break;
293 }
294
295 if (scb->bufcnt <= 0)
296 {
297 if (scb->bufcnt == 0)
298 return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to
299 distinguish between EOF & timeouts
300 someday] */
301 else
302 return SERIAL_ERROR; /* Got an error from read */
303 }
304
305 scb->bufcnt--;
306 scb->bufp = scb->buf;
307 return *scb->bufp++;
308}
309
310static int
311pipe_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
312 serial_t scb;
313 serial_ttystate new_ttystate;
314 serial_ttystate old_ttystate;
315{
316 return 0;
317}
318
319static void
320pipe_print_tty_state (scb, ttystate)
321 serial_t scb;
322 serial_ttystate ttystate;
323{
324 /* Nothing to print. */
325 return;
326}
327
328static int
329pipe_setbaudrate (scb, rate)
330 serial_t scb;
331 int rate;
332{
333 return 0; /* Never fails! */
334}
335
336static int
337pipe_setstopbits (scb, num)
338 serial_t scb;
339 int num;
340{
341 return 0; /* Never fails! */
342}
343
344static int
345pipe_write (scb, str, len)
346 serial_t scb;
347 const char *str;
348 int len;
349{
350 int cc;
351
352 while (len > 0)
353 {
354 cc = write (scb->fd, str, len);
355
356 if (cc < 0)
357 return 1;
358 len -= cc;
359 str += cc;
360 }
361 return 0;
362}
363
364static void
365pipe_close (scb)
366 serial_t scb;
367{
adf40b2e
JM
368 struct pipe_state *state = scb->state;
369 if (state != NULL)
370 {
371 int pid = state->pid;
372 close (scb->fd);
373 scb->fd = -1;
374 free (state);
375 scb->state = NULL;
376 kill (pid, SIGTERM);
377 /* Might be useful to check that the child does die. */
378 }
daf3f280
JM
379}
380
381static struct serial_ops pipe_ops =
382{
383 "pipe",
384 0,
385 pipe_open,
386 pipe_close,
387 pipe_readchar,
388 pipe_write,
389 pipe_return_0, /* flush output */
390 pipe_return_0, /* flush input */
391 pipe_return_0, /* send break */
392 pipe_raw,
393 pipe_get_tty_state,
394 pipe_set_tty_state,
395 pipe_print_tty_state,
396 pipe_noflush_set_tty_state,
397 pipe_setbaudrate,
398 pipe_setstopbits,
399 pipe_return_0, /* wait for output to drain */
400};
401
402void
403_initialize_ser_pipe ()
404{
405 serial_add_interface (&pipe_ops);
406}
This page took 0.040094 seconds and 4 git commands to generate.