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