xref: /dflybsd-src/contrib/gdb-7/gdb/ser-pipe.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* Serial interface for a pipe to a separate program
2*ef5ccd6cSJohn Marino    Copyright (C) 1999-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert 
45796c8dcSSimon Schubert    Contributed by Cygnus Solutions.
55796c8dcSSimon Schubert 
65796c8dcSSimon Schubert    This file is part of GDB.
75796c8dcSSimon Schubert 
85796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
95796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
105796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
115796c8dcSSimon Schubert    (at your option) any later version.
125796c8dcSSimon Schubert 
135796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
145796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
155796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
165796c8dcSSimon Schubert    GNU General Public License for more details.
175796c8dcSSimon Schubert 
185796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
195796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert #include "defs.h"
225796c8dcSSimon Schubert #include "serial.h"
235796c8dcSSimon Schubert #include "ser-base.h"
245796c8dcSSimon Schubert #include "ser-unix.h"
255796c8dcSSimon Schubert 
265796c8dcSSimon Schubert #include "gdb_vfork.h"
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert #include <sys/types.h>
295796c8dcSSimon Schubert #include <sys/socket.h>
305796c8dcSSimon Schubert #include <sys/time.h>
315796c8dcSSimon Schubert #include <fcntl.h>
325796c8dcSSimon Schubert #include "gdb_string.h"
335796c8dcSSimon Schubert 
345796c8dcSSimon Schubert #include <signal.h>
355796c8dcSSimon Schubert 
365796c8dcSSimon Schubert static int pipe_open (struct serial *scb, const char *name);
375796c8dcSSimon Schubert static void pipe_close (struct serial *scb);
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert extern void _initialize_ser_pipe (void);
405796c8dcSSimon Schubert 
415796c8dcSSimon Schubert struct pipe_state
425796c8dcSSimon Schubert   {
435796c8dcSSimon Schubert     int pid;
445796c8dcSSimon Schubert   };
455796c8dcSSimon Schubert 
46c50c785cSJohn Marino /* Open up a raw pipe.  */
475796c8dcSSimon Schubert 
485796c8dcSSimon Schubert static int
pipe_open(struct serial * scb,const char * name)495796c8dcSSimon Schubert pipe_open (struct serial *scb, const char *name)
505796c8dcSSimon Schubert {
515796c8dcSSimon Schubert #if !HAVE_SOCKETPAIR
525796c8dcSSimon Schubert   return -1;
535796c8dcSSimon Schubert #else
545796c8dcSSimon Schubert   struct pipe_state *state;
555796c8dcSSimon Schubert   /* This chunk: */
565796c8dcSSimon Schubert   /* Copyright (c) 1988, 1993
575796c8dcSSimon Schubert    *      The Regents of the University of California.  All rights reserved.
585796c8dcSSimon Schubert    *
595796c8dcSSimon Schubert    * This code is derived from software written by Ken Arnold and
605796c8dcSSimon Schubert    * published in UNIX Review, Vol. 6, No. 8.
615796c8dcSSimon Schubert    */
625796c8dcSSimon Schubert   int pdes[2];
635796c8dcSSimon Schubert   int err_pdes[2];
645796c8dcSSimon Schubert   int pid;
65cf7f2e2dSJohn Marino 
665796c8dcSSimon Schubert   if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
675796c8dcSSimon Schubert     return -1;
685796c8dcSSimon Schubert   if (socketpair (AF_UNIX, SOCK_STREAM, 0, err_pdes) < 0)
69cf7f2e2dSJohn Marino     {
70cf7f2e2dSJohn Marino       close (pdes[0]);
71cf7f2e2dSJohn Marino       close (pdes[1]);
725796c8dcSSimon Schubert       return -1;
73cf7f2e2dSJohn Marino     }
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert   /* Create the child process to run the command in.  Note that the
765796c8dcSSimon Schubert      apparent call to vfork() below *might* actually be a call to
775796c8dcSSimon Schubert      fork() due to the fact that autoconf will ``#define vfork fork''
785796c8dcSSimon Schubert      on certain platforms.  */
795796c8dcSSimon Schubert   pid = vfork ();
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert   /* Error.  */
825796c8dcSSimon Schubert   if (pid == -1)
835796c8dcSSimon Schubert     {
845796c8dcSSimon Schubert       close (pdes[0]);
855796c8dcSSimon Schubert       close (pdes[1]);
865796c8dcSSimon Schubert       close (err_pdes[0]);
875796c8dcSSimon Schubert       close (err_pdes[1]);
885796c8dcSSimon Schubert       return -1;
895796c8dcSSimon Schubert     }
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert   if (fcntl (err_pdes[0], F_SETFL, O_NONBLOCK) == -1)
925796c8dcSSimon Schubert     {
935796c8dcSSimon Schubert       close (err_pdes[0]);
945796c8dcSSimon Schubert       close (err_pdes[1]);
955796c8dcSSimon Schubert       err_pdes[0] = err_pdes[1] = -1;
965796c8dcSSimon Schubert     }
975796c8dcSSimon Schubert 
985796c8dcSSimon Schubert   /* Child.  */
995796c8dcSSimon Schubert   if (pid == 0)
1005796c8dcSSimon Schubert     {
101cf7f2e2dSJohn Marino       /* We don't want ^c to kill the connection.  */
102cf7f2e2dSJohn Marino #ifdef HAVE_SETSID
103cf7f2e2dSJohn Marino       pid_t sid = setsid ();
104cf7f2e2dSJohn Marino       if (sid == -1)
105cf7f2e2dSJohn Marino 	signal (SIGINT, SIG_IGN);
106cf7f2e2dSJohn Marino #else
107cf7f2e2dSJohn Marino       signal (SIGINT, SIG_IGN);
108cf7f2e2dSJohn Marino #endif
109cf7f2e2dSJohn Marino 
110c50c785cSJohn Marino       /* Re-wire pdes[1] to stdin/stdout.  */
1115796c8dcSSimon Schubert       close (pdes[0]);
1125796c8dcSSimon Schubert       if (pdes[1] != STDOUT_FILENO)
1135796c8dcSSimon Schubert 	{
1145796c8dcSSimon Schubert 	  dup2 (pdes[1], STDOUT_FILENO);
1155796c8dcSSimon Schubert 	  close (pdes[1]);
1165796c8dcSSimon Schubert 	}
1175796c8dcSSimon Schubert       dup2 (STDOUT_FILENO, STDIN_FILENO);
1185796c8dcSSimon Schubert 
1195796c8dcSSimon Schubert       if (err_pdes[0] != -1)
1205796c8dcSSimon Schubert 	{
1215796c8dcSSimon Schubert 	  close (err_pdes[0]);
1225796c8dcSSimon Schubert 	  dup2 (err_pdes[1], STDERR_FILENO);
1235796c8dcSSimon Schubert 	  close (err_pdes[1]);
1245796c8dcSSimon Schubert 	}
1255796c8dcSSimon Schubert #if 0
1265796c8dcSSimon Schubert       /* close any stray FD's - FIXME - how?  */
1275796c8dcSSimon Schubert       /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
1285796c8dcSSimon Schubert          from previous popen() calls that remain open in the
1295796c8dcSSimon Schubert          parent process are closed in the new child process.  */
1305796c8dcSSimon Schubert       for (old = pidlist; old; old = old->next)
131c50c785cSJohn Marino 	close (fileno (old->fp));	/* Don't allow a flush.  */
1325796c8dcSSimon Schubert #endif
1335796c8dcSSimon Schubert       execl ("/bin/sh", "sh", "-c", name, (char *) 0);
1345796c8dcSSimon Schubert       _exit (127);
1355796c8dcSSimon Schubert     }
1365796c8dcSSimon Schubert 
1375796c8dcSSimon Schubert   /* Parent.  */
1385796c8dcSSimon Schubert   close (pdes[1]);
139cf7f2e2dSJohn Marino   if (err_pdes[1] != -1)
140cf7f2e2dSJohn Marino     close (err_pdes[1]);
1415796c8dcSSimon Schubert   /* :end chunk */
1425796c8dcSSimon Schubert   state = XMALLOC (struct pipe_state);
1435796c8dcSSimon Schubert   state->pid = pid;
1445796c8dcSSimon Schubert   scb->fd = pdes[0];
1455796c8dcSSimon Schubert   scb->error_fd = err_pdes[0];
1465796c8dcSSimon Schubert   scb->state = state;
1475796c8dcSSimon Schubert 
1485796c8dcSSimon Schubert   /* If we don't do this, GDB simply exits when the remote side dies.  */
1495796c8dcSSimon Schubert   signal (SIGPIPE, SIG_IGN);
1505796c8dcSSimon Schubert   return 0;
1515796c8dcSSimon Schubert #endif
1525796c8dcSSimon Schubert }
1535796c8dcSSimon Schubert 
1545796c8dcSSimon Schubert static void
pipe_close(struct serial * scb)1555796c8dcSSimon Schubert pipe_close (struct serial *scb)
1565796c8dcSSimon Schubert {
1575796c8dcSSimon Schubert   struct pipe_state *state = scb->state;
158cf7f2e2dSJohn Marino 
1595796c8dcSSimon Schubert   close (scb->fd);
1605796c8dcSSimon Schubert   scb->fd = -1;
161c50c785cSJohn Marino 
162c50c785cSJohn Marino   if (state != NULL)
163c50c785cSJohn Marino     {
164*ef5ccd6cSJohn Marino       int wait_result, status;
165*ef5ccd6cSJohn Marino 
166*ef5ccd6cSJohn Marino       /* Don't kill the task right away, give it a chance to shut down cleanly.
167*ef5ccd6cSJohn Marino 	 But don't wait forever though.  */
168*ef5ccd6cSJohn Marino #define PIPE_CLOSE_TIMEOUT 5
169*ef5ccd6cSJohn Marino 
170c50c785cSJohn Marino       /* Assume the program will exit after SIGTERM.  Might be
171c50c785cSJohn Marino 	 useful to print any remaining stderr output from
172c50c785cSJohn Marino 	 scb->error_fd while waiting.  */
173*ef5ccd6cSJohn Marino #define SIGTERM_TIMEOUT INT_MAX
174*ef5ccd6cSJohn Marino 
175*ef5ccd6cSJohn Marino       wait_result = -1;
176*ef5ccd6cSJohn Marino #ifdef HAVE_WAITPID
177*ef5ccd6cSJohn Marino       wait_result = wait_to_die_with_timeout (state->pid, &status,
178*ef5ccd6cSJohn Marino 					      PIPE_CLOSE_TIMEOUT);
179c50c785cSJohn Marino #endif
180*ef5ccd6cSJohn Marino       if (wait_result == -1)
181*ef5ccd6cSJohn Marino 	{
182*ef5ccd6cSJohn Marino 	  kill (state->pid, SIGTERM);
183*ef5ccd6cSJohn Marino #ifdef HAVE_WAITPID
184*ef5ccd6cSJohn Marino 	  wait_to_die_with_timeout (state->pid, &status, SIGTERM_TIMEOUT);
185*ef5ccd6cSJohn Marino #endif
186*ef5ccd6cSJohn Marino 	}
187*ef5ccd6cSJohn Marino 
188cf7f2e2dSJohn Marino       if (scb->error_fd != -1)
189cf7f2e2dSJohn Marino 	close (scb->error_fd);
190cf7f2e2dSJohn Marino       scb->error_fd = -1;
1915796c8dcSSimon Schubert       xfree (state);
1925796c8dcSSimon Schubert       scb->state = NULL;
1935796c8dcSSimon Schubert     }
1945796c8dcSSimon Schubert }
1955796c8dcSSimon Schubert 
196c50c785cSJohn Marino int
gdb_pipe(int pdes[2])197c50c785cSJohn Marino gdb_pipe (int pdes[2])
198c50c785cSJohn Marino {
199c50c785cSJohn Marino #if !HAVE_SOCKETPAIR
200c50c785cSJohn Marino   errno = ENOSYS;
201c50c785cSJohn Marino   return -1;
202c50c785cSJohn Marino #else
203c50c785cSJohn Marino 
204c50c785cSJohn Marino   if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
205c50c785cSJohn Marino     return -1;
206c50c785cSJohn Marino 
207c50c785cSJohn Marino   /* If we don't do this, GDB simply exits when the remote side
208c50c785cSJohn Marino      dies.  */
209c50c785cSJohn Marino   signal (SIGPIPE, SIG_IGN);
210c50c785cSJohn Marino   return 0;
211c50c785cSJohn Marino #endif
212c50c785cSJohn Marino }
213c50c785cSJohn Marino 
2145796c8dcSSimon Schubert void
_initialize_ser_pipe(void)2155796c8dcSSimon Schubert _initialize_ser_pipe (void)
2165796c8dcSSimon Schubert {
2175796c8dcSSimon Schubert   struct serial_ops *ops = XMALLOC (struct serial_ops);
218cf7f2e2dSJohn Marino 
2195796c8dcSSimon Schubert   memset (ops, 0, sizeof (struct serial_ops));
2205796c8dcSSimon Schubert   ops->name = "pipe";
2215796c8dcSSimon Schubert   ops->next = 0;
2225796c8dcSSimon Schubert   ops->open = pipe_open;
2235796c8dcSSimon Schubert   ops->close = pipe_close;
2245796c8dcSSimon Schubert   ops->readchar = ser_base_readchar;
2255796c8dcSSimon Schubert   ops->write = ser_base_write;
2265796c8dcSSimon Schubert   ops->flush_output = ser_base_flush_output;
2275796c8dcSSimon Schubert   ops->flush_input = ser_base_flush_input;
2285796c8dcSSimon Schubert   ops->send_break = ser_base_send_break;
2295796c8dcSSimon Schubert   ops->go_raw = ser_base_raw;
2305796c8dcSSimon Schubert   ops->get_tty_state = ser_base_get_tty_state;
231c50c785cSJohn Marino   ops->copy_tty_state = ser_base_copy_tty_state;
2325796c8dcSSimon Schubert   ops->set_tty_state = ser_base_set_tty_state;
2335796c8dcSSimon Schubert   ops->print_tty_state = ser_base_print_tty_state;
2345796c8dcSSimon Schubert   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
2355796c8dcSSimon Schubert   ops->setbaudrate = ser_base_setbaudrate;
2365796c8dcSSimon Schubert   ops->setstopbits = ser_base_setstopbits;
2375796c8dcSSimon Schubert   ops->drain_output = ser_base_drain_output;
2385796c8dcSSimon Schubert   ops->async = ser_base_async;
2395796c8dcSSimon Schubert   ops->read_prim = ser_unix_read_prim;
2405796c8dcSSimon Schubert   ops->write_prim = ser_unix_write_prim;
2415796c8dcSSimon Schubert   serial_add_interface (ops);
2425796c8dcSSimon Schubert }
243