Separate out execution-info window
[external/binutils.git] / gdb / ser-pipe.c
1 /* Serial interface for a pipe to a separate program
2    Copyright (C) 1999-2019 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 3 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, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "serial.h"
23 #include "ser-base.h"
24 #include "ser-unix.h"
25
26 #include "gdb_vfork.h"
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include "common/gdb_sys_time.h"
31 #include <fcntl.h>
32 #include "common/filestuff.h"
33
34 #include <signal.h>
35
36 static int pipe_open (struct serial *scb, const char *name);
37 static void pipe_close (struct serial *scb);
38
39 struct pipe_state
40   {
41     int pid;
42   };
43
44 /* Open up a raw pipe.  */
45
46 static int
47 pipe_open (struct serial *scb, const char *name)
48 {
49 #if !HAVE_SOCKETPAIR
50   return -1;
51 #else
52   struct pipe_state *state;
53   /* This chunk: */
54   /* Copyright (c) 1988, 1993
55    *      The Regents of the University of California.  All rights reserved.
56    *
57    * This code is derived from software written by Ken Arnold and
58    * published in UNIX Review, Vol. 6, No. 8.
59    */
60   int pdes[2];
61   int err_pdes[2];
62   int pid;
63
64   if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
65     return -1;
66   if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, err_pdes) < 0)
67     {
68       close (pdes[0]);
69       close (pdes[1]);
70       return -1;
71     }
72
73   /* Create the child process to run the command in.  Note that the
74      apparent call to vfork() below *might* actually be a call to
75      fork() due to the fact that autoconf will ``#define vfork fork''
76      on certain platforms.  */
77   pid = vfork ();
78   
79   /* Error.  */
80   if (pid == -1)
81     {
82       close (pdes[0]);
83       close (pdes[1]);
84       close (err_pdes[0]);
85       close (err_pdes[1]);
86       return -1;
87     }
88
89   if (fcntl (err_pdes[0], F_SETFL, O_NONBLOCK) == -1)
90     {
91       close (err_pdes[0]);
92       close (err_pdes[1]);
93       err_pdes[0] = err_pdes[1] = -1;
94     }
95
96   /* Child.  */
97   if (pid == 0)
98     {
99       /* We don't want ^c to kill the connection.  */
100 #ifdef HAVE_SETSID
101       pid_t sid = setsid ();
102       if (sid == -1)
103         signal (SIGINT, SIG_IGN);
104 #else
105       signal (SIGINT, SIG_IGN);
106 #endif
107
108       /* Re-wire pdes[1] to stdin/stdout.  */
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
117       if (err_pdes[0] != -1)
118         {
119           close (err_pdes[0]);
120           dup2 (err_pdes[1], STDERR_FILENO);
121           close (err_pdes[1]);
122         }
123
124       close_most_fds ();
125       execl ("/bin/sh", "sh", "-c", name, (char *) 0);
126       _exit (127);
127     }
128
129   /* Parent.  */
130   close (pdes[1]);
131   if (err_pdes[1] != -1)
132     close (err_pdes[1]);
133   /* :end chunk */
134   state = XNEW (struct pipe_state);
135   state->pid = pid;
136   scb->fd = pdes[0];
137   scb->error_fd = err_pdes[0];
138   scb->state = state;
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 void
147 pipe_close (struct serial *scb)
148 {
149   struct pipe_state *state = (struct pipe_state *) scb->state;
150
151   close (scb->fd);
152   scb->fd = -1;
153
154   if (state != NULL)
155     {
156       int wait_result, status;
157
158       /* Don't kill the task right away, give it a chance to shut down cleanly.
159          But don't wait forever though.  */
160 #define PIPE_CLOSE_TIMEOUT 5
161
162       /* Assume the program will exit after SIGTERM.  Might be
163          useful to print any remaining stderr output from
164          scb->error_fd while waiting.  */
165 #define SIGTERM_TIMEOUT INT_MAX
166
167       wait_result = -1;
168 #ifdef HAVE_WAITPID
169       wait_result = wait_to_die_with_timeout (state->pid, &status,
170                                               PIPE_CLOSE_TIMEOUT);
171 #endif
172       if (wait_result == -1)
173         {
174           kill (state->pid, SIGTERM);
175 #ifdef HAVE_WAITPID
176           wait_to_die_with_timeout (state->pid, &status, SIGTERM_TIMEOUT);
177 #endif
178         }
179
180       if (scb->error_fd != -1)
181         close (scb->error_fd);
182       scb->error_fd = -1;
183       xfree (state);
184       scb->state = NULL;
185     }
186 }
187
188 int
189 gdb_pipe (int pdes[2])
190 {
191 #if !HAVE_SOCKETPAIR
192   errno = ENOSYS;
193   return -1;
194 #else
195
196   if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
197     return -1;
198
199   /* If we don't do this, GDB simply exits when the remote side
200      dies.  */
201   signal (SIGPIPE, SIG_IGN);
202   return 0;
203 #endif
204 }
205
206 static const struct serial_ops pipe_ops =
207 {
208   "pipe",
209   pipe_open,
210   pipe_close,
211   NULL,
212   ser_base_readchar,
213   ser_base_write,
214   ser_base_flush_output,
215   ser_base_flush_input,
216   ser_base_send_break,
217   ser_base_raw,
218   ser_base_get_tty_state,
219   ser_base_copy_tty_state,
220   ser_base_set_tty_state,
221   ser_base_print_tty_state,
222   ser_base_setbaudrate,
223   ser_base_setstopbits,
224   ser_base_setparity,
225   ser_base_drain_output,
226   ser_base_async,
227   ser_unix_read_prim,
228   ser_unix_write_prim
229 };
230
231 void
232 _initialize_ser_pipe (void)
233 {
234   serial_add_interface (&pipe_ops);
235 }