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