xref: /dflybsd-src/contrib/gdb-7/gdb/ser-pipe.c (revision cf7f2e2d389e8012d562650bd94d7e433f449d6e)
15796c8dcSSimon Schubert /* Serial interface for a pipe to a separate program
2*cf7f2e2dSJohn Marino    Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010
35796c8dcSSimon Schubert    Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    Contributed by Cygnus Solutions.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This file is part of GDB.
85796c8dcSSimon Schubert 
95796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert    (at your option) any later version.
135796c8dcSSimon Schubert 
145796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175796c8dcSSimon Schubert    GNU General Public License for more details.
185796c8dcSSimon Schubert 
195796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
215796c8dcSSimon Schubert 
225796c8dcSSimon Schubert #include "defs.h"
235796c8dcSSimon Schubert #include "serial.h"
245796c8dcSSimon Schubert #include "ser-base.h"
255796c8dcSSimon Schubert #include "ser-unix.h"
265796c8dcSSimon Schubert 
275796c8dcSSimon Schubert #include "gdb_vfork.h"
285796c8dcSSimon Schubert 
295796c8dcSSimon Schubert #include <sys/types.h>
305796c8dcSSimon Schubert #include <sys/socket.h>
315796c8dcSSimon Schubert #include <sys/time.h>
325796c8dcSSimon Schubert #include <fcntl.h>
335796c8dcSSimon Schubert #include "gdb_string.h"
345796c8dcSSimon Schubert 
355796c8dcSSimon Schubert #include <signal.h>
365796c8dcSSimon Schubert 
375796c8dcSSimon Schubert static int pipe_open (struct serial *scb, const char *name);
385796c8dcSSimon Schubert static void pipe_close (struct serial *scb);
395796c8dcSSimon Schubert 
405796c8dcSSimon Schubert extern void _initialize_ser_pipe (void);
415796c8dcSSimon Schubert 
425796c8dcSSimon Schubert struct pipe_state
435796c8dcSSimon Schubert   {
445796c8dcSSimon Schubert     int pid;
455796c8dcSSimon Schubert   };
465796c8dcSSimon Schubert 
475796c8dcSSimon Schubert /* Open up a raw pipe */
485796c8dcSSimon Schubert 
495796c8dcSSimon Schubert static int
505796c8dcSSimon Schubert pipe_open (struct serial *scb, const char *name)
515796c8dcSSimon Schubert {
525796c8dcSSimon Schubert #if !HAVE_SOCKETPAIR
535796c8dcSSimon Schubert   return -1;
545796c8dcSSimon Schubert #else
555796c8dcSSimon Schubert   struct pipe_state *state;
565796c8dcSSimon Schubert   /* This chunk: */
575796c8dcSSimon Schubert   /* Copyright (c) 1988, 1993
585796c8dcSSimon Schubert    *      The Regents of the University of California.  All rights reserved.
595796c8dcSSimon Schubert    *
605796c8dcSSimon Schubert    * This code is derived from software written by Ken Arnold and
615796c8dcSSimon Schubert    * published in UNIX Review, Vol. 6, No. 8.
625796c8dcSSimon Schubert    */
635796c8dcSSimon Schubert   int pdes[2];
645796c8dcSSimon Schubert   int err_pdes[2];
655796c8dcSSimon Schubert   int pid;
66*cf7f2e2dSJohn Marino 
675796c8dcSSimon Schubert   if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
685796c8dcSSimon Schubert     return -1;
695796c8dcSSimon Schubert   if (socketpair (AF_UNIX, SOCK_STREAM, 0, err_pdes) < 0)
70*cf7f2e2dSJohn Marino     {
71*cf7f2e2dSJohn Marino       close (pdes[0]);
72*cf7f2e2dSJohn Marino       close (pdes[1]);
735796c8dcSSimon Schubert       return -1;
74*cf7f2e2dSJohn Marino     }
755796c8dcSSimon Schubert 
765796c8dcSSimon Schubert   /* Create the child process to run the command in.  Note that the
775796c8dcSSimon Schubert      apparent call to vfork() below *might* actually be a call to
785796c8dcSSimon Schubert      fork() due to the fact that autoconf will ``#define vfork fork''
795796c8dcSSimon Schubert      on certain platforms.  */
805796c8dcSSimon Schubert   pid = vfork ();
815796c8dcSSimon Schubert 
825796c8dcSSimon Schubert   /* Error. */
835796c8dcSSimon Schubert   if (pid == -1)
845796c8dcSSimon Schubert     {
855796c8dcSSimon Schubert       close (pdes[0]);
865796c8dcSSimon Schubert       close (pdes[1]);
875796c8dcSSimon Schubert       close (err_pdes[0]);
885796c8dcSSimon Schubert       close (err_pdes[1]);
895796c8dcSSimon Schubert       return -1;
905796c8dcSSimon Schubert     }
915796c8dcSSimon Schubert 
925796c8dcSSimon Schubert   if (fcntl (err_pdes[0], F_SETFL, O_NONBLOCK) == -1)
935796c8dcSSimon Schubert     {
945796c8dcSSimon Schubert       close (err_pdes[0]);
955796c8dcSSimon Schubert       close (err_pdes[1]);
965796c8dcSSimon Schubert       err_pdes[0] = err_pdes[1] = -1;
975796c8dcSSimon Schubert     }
985796c8dcSSimon Schubert 
995796c8dcSSimon Schubert   /* Child. */
1005796c8dcSSimon Schubert   if (pid == 0)
1015796c8dcSSimon Schubert     {
102*cf7f2e2dSJohn Marino       /* We don't want ^c to kill the connection.  */
103*cf7f2e2dSJohn Marino #ifdef HAVE_SETSID
104*cf7f2e2dSJohn Marino       pid_t sid = setsid ();
105*cf7f2e2dSJohn Marino       if (sid == -1)
106*cf7f2e2dSJohn Marino 	signal (SIGINT, SIG_IGN);
107*cf7f2e2dSJohn Marino #else
108*cf7f2e2dSJohn Marino       signal (SIGINT, SIG_IGN);
109*cf7f2e2dSJohn Marino #endif
110*cf7f2e2dSJohn Marino 
1115796c8dcSSimon Schubert       /* re-wire pdes[1] to stdin/stdout */
1125796c8dcSSimon Schubert       close (pdes[0]);
1135796c8dcSSimon Schubert       if (pdes[1] != STDOUT_FILENO)
1145796c8dcSSimon Schubert 	{
1155796c8dcSSimon Schubert 	  dup2 (pdes[1], STDOUT_FILENO);
1165796c8dcSSimon Schubert 	  close (pdes[1]);
1175796c8dcSSimon Schubert 	}
1185796c8dcSSimon Schubert       dup2 (STDOUT_FILENO, STDIN_FILENO);
1195796c8dcSSimon Schubert 
1205796c8dcSSimon Schubert       if (err_pdes[0] != -1)
1215796c8dcSSimon Schubert 	{
1225796c8dcSSimon Schubert 	  close (err_pdes[0]);
1235796c8dcSSimon Schubert 	  dup2 (err_pdes[1], STDERR_FILENO);
1245796c8dcSSimon Schubert 	  close (err_pdes[1]);
1255796c8dcSSimon Schubert 	}
1265796c8dcSSimon Schubert #if 0
1275796c8dcSSimon Schubert       /* close any stray FD's - FIXME - how? */
1285796c8dcSSimon Schubert       /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
1295796c8dcSSimon Schubert          from previous popen() calls that remain open in the
1305796c8dcSSimon Schubert          parent process are closed in the new child process. */
1315796c8dcSSimon Schubert       for (old = pidlist; old; old = old->next)
1325796c8dcSSimon Schubert 	close (fileno (old->fp));	/* don't allow a flush */
1335796c8dcSSimon Schubert #endif
1345796c8dcSSimon Schubert       execl ("/bin/sh", "sh", "-c", name, (char *) 0);
1355796c8dcSSimon Schubert       _exit (127);
1365796c8dcSSimon Schubert     }
1375796c8dcSSimon Schubert 
1385796c8dcSSimon Schubert   /* Parent. */
1395796c8dcSSimon Schubert   close (pdes[1]);
140*cf7f2e2dSJohn Marino   if (err_pdes[1] != -1)
141*cf7f2e2dSJohn Marino     close (err_pdes[1]);
1425796c8dcSSimon Schubert   /* :end chunk */
1435796c8dcSSimon Schubert   state = XMALLOC (struct pipe_state);
1445796c8dcSSimon Schubert   state->pid = pid;
1455796c8dcSSimon Schubert   scb->fd = pdes[0];
1465796c8dcSSimon Schubert   scb->error_fd = err_pdes[0];
1475796c8dcSSimon Schubert   scb->state = state;
1485796c8dcSSimon Schubert 
1495796c8dcSSimon Schubert   /* If we don't do this, GDB simply exits when the remote side dies.  */
1505796c8dcSSimon Schubert   signal (SIGPIPE, SIG_IGN);
1515796c8dcSSimon Schubert   return 0;
1525796c8dcSSimon Schubert #endif
1535796c8dcSSimon Schubert }
1545796c8dcSSimon Schubert 
1555796c8dcSSimon Schubert static void
1565796c8dcSSimon Schubert pipe_close (struct serial *scb)
1575796c8dcSSimon Schubert {
1585796c8dcSSimon Schubert   struct pipe_state *state = scb->state;
159*cf7f2e2dSJohn Marino 
1605796c8dcSSimon Schubert   if (state != NULL)
1615796c8dcSSimon Schubert     {
1625796c8dcSSimon Schubert       int pid = state->pid;
1635796c8dcSSimon Schubert       close (scb->fd);
1645796c8dcSSimon Schubert       scb->fd = -1;
165*cf7f2e2dSJohn Marino       if (scb->error_fd != -1)
166*cf7f2e2dSJohn Marino 	close (scb->error_fd);
167*cf7f2e2dSJohn Marino       scb->error_fd = -1;
1685796c8dcSSimon Schubert       xfree (state);
1695796c8dcSSimon Schubert       scb->state = NULL;
1705796c8dcSSimon Schubert       kill (pid, SIGTERM);
171*cf7f2e2dSJohn Marino       /* Might be useful to check that the child does die,
172*cf7f2e2dSJohn Marino 	 and while we're waiting for it to die print any remaining
173*cf7f2e2dSJohn Marino 	 stderr output.  */
1745796c8dcSSimon Schubert     }
1755796c8dcSSimon Schubert }
1765796c8dcSSimon Schubert 
1775796c8dcSSimon Schubert void
1785796c8dcSSimon Schubert _initialize_ser_pipe (void)
1795796c8dcSSimon Schubert {
1805796c8dcSSimon Schubert   struct serial_ops *ops = XMALLOC (struct serial_ops);
181*cf7f2e2dSJohn Marino 
1825796c8dcSSimon Schubert   memset (ops, 0, sizeof (struct serial_ops));
1835796c8dcSSimon Schubert   ops->name = "pipe";
1845796c8dcSSimon Schubert   ops->next = 0;
1855796c8dcSSimon Schubert   ops->open = pipe_open;
1865796c8dcSSimon Schubert   ops->close = pipe_close;
1875796c8dcSSimon Schubert   ops->readchar = ser_base_readchar;
1885796c8dcSSimon Schubert   ops->write = ser_base_write;
1895796c8dcSSimon Schubert   ops->flush_output = ser_base_flush_output;
1905796c8dcSSimon Schubert   ops->flush_input = ser_base_flush_input;
1915796c8dcSSimon Schubert   ops->send_break = ser_base_send_break;
1925796c8dcSSimon Schubert   ops->go_raw = ser_base_raw;
1935796c8dcSSimon Schubert   ops->get_tty_state = ser_base_get_tty_state;
1945796c8dcSSimon Schubert   ops->set_tty_state = ser_base_set_tty_state;
1955796c8dcSSimon Schubert   ops->print_tty_state = ser_base_print_tty_state;
1965796c8dcSSimon Schubert   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
1975796c8dcSSimon Schubert   ops->setbaudrate = ser_base_setbaudrate;
1985796c8dcSSimon Schubert   ops->setstopbits = ser_base_setstopbits;
1995796c8dcSSimon Schubert   ops->drain_output = ser_base_drain_output;
2005796c8dcSSimon Schubert   ops->async = ser_base_async;
2015796c8dcSSimon Schubert   ops->read_prim = ser_unix_read_prim;
2025796c8dcSSimon Schubert   ops->write_prim = ser_unix_write_prim;
2035796c8dcSSimon Schubert   serial_add_interface (ops);
2045796c8dcSSimon Schubert }
205