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 #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 }