This commit was generated by cvs2svn to track changes on a CVS vendor
[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 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include "signals.h"
37 #include "gdb_string.h"
38
39 extern int (*ui_loop_hook) PARAMS ((int));
40
41 static int pipe_open PARAMS ((serial_t scb, const char *name));
42 static void pipe_raw PARAMS ((serial_t scb));
43 static int wait_for PARAMS ((serial_t scb, int timeout));
44 static int pipe_readchar PARAMS ((serial_t scb, int timeout));
45 static int pipe_setbaudrate PARAMS ((serial_t scb, int rate));
46 static int pipe_setstopbits PARAMS ((serial_t scb, int num));
47 static int pipe_write PARAMS ((serial_t scb, const char *str, int len));
48 /* FIXME: static void pipe_restore PARAMS ((serial_t scb)); */
49 static void pipe_close PARAMS ((serial_t scb));
50 static serial_ttystate pipe_get_tty_state PARAMS ((serial_t scb));
51 static int pipe_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
52 static int pipe_return_0 PARAMS ((serial_t));
53 static int pipe_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate,
54                                                serial_ttystate));
55 static void pipe_print_tty_state PARAMS ((serial_t, serial_ttystate));
56
57 extern void _initialize_ser_pipe PARAMS ((void));
58
59 #undef XMALLOC
60 #define XMALLOC(T) ((T*) xmalloc (sizeof (T)))
61
62
63 struct pipe_state
64   {
65     int pid;
66   };
67
68 /* Open up a raw pipe */
69
70 static int
71 pipe_open (scb, name)
72      serial_t scb;
73      const char *name;
74 {
75 #if !defined(O_NONBLOCK) || !defined(F_GETFL) || !defined(F_SETFL) || !HAVE_SOCKETPAIR
76   return -1;
77 #else
78   struct pipe_state *state;
79   /* This chunk: */
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
91   pid = vfork ();
92   
93   /* Error. */
94   if (pid == -1)
95     {
96       close (pdes[0]);
97       close (pdes[1]);
98       return -1;
99     }
100
101   /* Child. */
102   if (pid == 0)
103     {
104       /* re-wire pdes[1] to stdin/stdout */
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);
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
120       execl ("/bin/sh", "sh", "-c", name + 1, NULL);
121       _exit (127);
122     }
123
124   /* Parent. */
125   close (pdes[1]);
126   /* :end chunk */
127   state = XMALLOC (struct pipe_state);
128   state->pid = pid;
129   scb->fd = pdes[0];
130   scb->state = state;
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
149 static serial_ttystate
150 pipe_get_tty_state (scb)
151      serial_t scb;
152 {
153   /* return garbage */
154   return xmalloc (sizeof (int));
155 }
156
157 static int
158 pipe_set_tty_state (scb, ttystate)
159      serial_t scb;
160      serial_ttystate ttystate;
161 {
162   return 0;
163 }
164
165 static int
166 pipe_return_0 (scb)
167      serial_t scb;
168 {
169   return 0;
170 }
171
172 static void
173 pipe_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
186 static int
187 wait_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
230 static int
231 pipe_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
310 static int
311 pipe_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
319 static void
320 pipe_print_tty_state (scb, ttystate)
321      serial_t scb;
322      serial_ttystate ttystate;
323 {
324   /* Nothing to print.  */
325   return;
326 }
327
328 static int
329 pipe_setbaudrate (scb, rate)
330      serial_t scb;
331      int rate;
332 {
333   return 0;                     /* Never fails! */
334 }
335
336 static int
337 pipe_setstopbits (scb, num)
338      serial_t scb;
339      int num;
340 {
341   return 0;                     /* Never fails! */
342 }
343
344 static int
345 pipe_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
364 static void
365 pipe_close (scb)
366      serial_t scb;
367 {
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     }
379 }
380
381 static 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
402 void
403 _initialize_ser_pipe ()
404 {
405   serial_add_interface (&pipe_ops);
406 }