Fix latest ChangeLog entry (forgot to give credit to reporter)
[deliverable/binutils-gdb.git] / gdb / ser-pipe.c
CommitLineData
daf3f280 1/* Serial interface for a pipe to a separate program
7b6bb8da 2 Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010, 2011
0fb0cc75 3 Free Software Foundation, Inc.
daf3f280
JM
4
5 Contributed by Cygnus Solutions.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
daf3f280
JM
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
daf3f280
JM
21
22#include "defs.h"
23#include "serial.h"
3eb25fda 24#include "ser-base.h"
c2c6d25f
JM
25#include "ser-unix.h"
26
74c1b268
AC
27#include "gdb_vfork.h"
28
daf3f280 29#include <sys/types.h>
daf3f280
JM
30#include <sys/socket.h>
31#include <sys/time.h>
32#include <fcntl.h>
27b82ed2 33#include "gdb_string.h"
0a4f61e3 34#include "gdb_wait.h"
daf3f280 35
042be3a9 36#include <signal.h>
daf3f280 37
819cc324
AC
38static int pipe_open (struct serial *scb, const char *name);
39static void pipe_close (struct serial *scb);
adf40b2e 40
c2c6d25f 41extern void _initialize_ser_pipe (void);
adf40b2e
JM
42
43struct pipe_state
44 {
45 int pid;
46 };
47
c378eb4e 48/* Open up a raw pipe. */
daf3f280
JM
49
50static int
819cc324 51pipe_open (struct serial *scb, const char *name)
daf3f280 52{
2acceee2 53#if !HAVE_SOCKETPAIR
daf3f280
JM
54 return -1;
55#else
adf40b2e 56 struct pipe_state *state;
daf3f280 57 /* This chunk: */
daf3f280
JM
58 /* Copyright (c) 1988, 1993
59 * The Regents of the University of California. All rights reserved.
60 *
61 * This code is derived from software written by Ken Arnold and
62 * published in UNIX Review, Vol. 6, No. 8.
63 */
64 int pdes[2];
65cc4390 65 int err_pdes[2];
daf3f280 66 int pid;
433759f7 67
daf3f280
JM
68 if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
69 return -1;
65cc4390 70 if (socketpair (AF_UNIX, SOCK_STREAM, 0, err_pdes) < 0)
ff9f22f1
DE
71 {
72 close (pdes[0]);
73 close (pdes[1]);
74 return -1;
75 }
daf3f280 76
7700434b
KB
77 /* Create the child process to run the command in. Note that the
78 apparent call to vfork() below *might* actually be a call to
79 fork() due to the fact that autoconf will ``#define vfork fork''
80 on certain platforms. */
adf40b2e
JM
81 pid = vfork ();
82
c378eb4e 83 /* Error. */
adf40b2e 84 if (pid == -1)
daf3f280 85 {
daf3f280
JM
86 close (pdes[0]);
87 close (pdes[1]);
65cc4390
VP
88 close (err_pdes[0]);
89 close (err_pdes[1]);
daf3f280 90 return -1;
adf40b2e
JM
91 }
92
65cc4390
VP
93 if (fcntl (err_pdes[0], F_SETFL, O_NONBLOCK) == -1)
94 {
95 close (err_pdes[0]);
96 close (err_pdes[1]);
97 err_pdes[0] = err_pdes[1] = -1;
98 }
99
c378eb4e 100 /* Child. */
adf40b2e
JM
101 if (pid == 0)
102 {
e34838f0
DE
103 /* We don't want ^c to kill the connection. */
104#ifdef HAVE_SETSID
105 pid_t sid = setsid ();
106 if (sid == -1)
107 signal (SIGINT, SIG_IGN);
108#else
109 signal (SIGINT, SIG_IGN);
110#endif
111
c378eb4e 112 /* Re-wire pdes[1] to stdin/stdout. */
daf3f280
JM
113 close (pdes[0]);
114 if (pdes[1] != STDOUT_FILENO)
115 {
116 dup2 (pdes[1], STDOUT_FILENO);
117 close (pdes[1]);
118 }
119 dup2 (STDOUT_FILENO, STDIN_FILENO);
65cc4390
VP
120
121 if (err_pdes[0] != -1)
122 {
123 close (err_pdes[0]);
124 dup2 (err_pdes[1], STDERR_FILENO);
125 close (err_pdes[1]);
126 }
adf40b2e 127#if 0
c378eb4e 128 /* close any stray FD's - FIXME - how? */
adf40b2e
JM
129 /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
130 from previous popen() calls that remain open in the
c378eb4e 131 parent process are closed in the new child process. */
adf40b2e 132 for (old = pidlist; old; old = old->next)
c378eb4e 133 close (fileno (old->fp)); /* Don't allow a flush. */
adf40b2e 134#endif
36662fde 135 execl ("/bin/sh", "sh", "-c", name, (char *) 0);
daf3f280
JM
136 _exit (127);
137 }
138
c378eb4e 139 /* Parent. */
daf3f280 140 close (pdes[1]);
ff9f22f1
DE
141 if (err_pdes[1] != -1)
142 close (err_pdes[1]);
adf40b2e
JM
143 /* :end chunk */
144 state = XMALLOC (struct pipe_state);
145 state->pid = pid;
daf3f280 146 scb->fd = pdes[0];
65cc4390 147 scb->error_fd = err_pdes[0];
adf40b2e 148 scb->state = state;
daf3f280 149
daf3f280
JM
150 /* If we don't do this, GDB simply exits when the remote side dies. */
151 signal (SIGPIPE, SIG_IGN);
152 return 0;
153#endif
154}
155
daf3f280 156static void
819cc324 157pipe_close (struct serial *scb)
daf3f280 158{
adf40b2e 159 struct pipe_state *state = scb->state;
433759f7 160
58f07bae
PA
161 close (scb->fd);
162 scb->fd = -1;
163
adf40b2e
JM
164 if (state != NULL)
165 {
0a4f61e3 166 int status;
58f07bae 167 kill (state->pid, SIGTERM);
0a4f61e3
DJ
168#ifdef HAVE_WAITPID
169 /* Assume the program will exit after SIGTERM. Might be
170 useful to print any remaining stderr output from
171 scb->error_fd while waiting. */
172 waitpid (state->pid, &status, 0);
173#endif
ff9f22f1
DE
174 if (scb->error_fd != -1)
175 close (scb->error_fd);
176 scb->error_fd = -1;
b8c9b27d 177 xfree (state);
adf40b2e 178 scb->state = NULL;
adf40b2e 179 }
daf3f280
JM
180}
181
58f07bae
PA
182int
183gdb_pipe (int pdes[2])
184{
185#if !HAVE_SOCKETPAIR
186 errno = ENOSYS;
187 return -1;
188#else
189
190 if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
191 return -1;
192
193 /* If we don't do this, GDB simply exits when the remote side
194 dies. */
195 signal (SIGPIPE, SIG_IGN);
196 return 0;
197#endif
198}
199
daf3f280 200void
c2c6d25f 201_initialize_ser_pipe (void)
daf3f280 202{
c2c6d25f 203 struct serial_ops *ops = XMALLOC (struct serial_ops);
433759f7 204
2fdbdd39 205 memset (ops, 0, sizeof (struct serial_ops));
c2c6d25f
JM
206 ops->name = "pipe";
207 ops->next = 0;
208 ops->open = pipe_open;
209 ops->close = pipe_close;
b4505029 210 ops->readchar = ser_base_readchar;
dd5da072
MM
211 ops->write = ser_base_write;
212 ops->flush_output = ser_base_flush_output;
213 ops->flush_input = ser_base_flush_input;
214 ops->send_break = ser_base_send_break;
215 ops->go_raw = ser_base_raw;
216 ops->get_tty_state = ser_base_get_tty_state;
1e182ce8 217 ops->copy_tty_state = ser_base_copy_tty_state;
dd5da072
MM
218 ops->set_tty_state = ser_base_set_tty_state;
219 ops->print_tty_state = ser_base_print_tty_state;
220 ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
221 ops->setbaudrate = ser_base_setbaudrate;
222 ops->setstopbits = ser_base_setstopbits;
223 ops->drain_output = ser_base_drain_output;
224 ops->async = ser_base_async;
b4505029
MM
225 ops->read_prim = ser_unix_read_prim;
226 ops->write_prim = ser_unix_write_prim;
c2c6d25f 227 serial_add_interface (ops);
daf3f280 228}
This page took 1.448642 seconds and 4 git commands to generate.