1/* Serial interface for a pipe to a separate program 2 Copyright (C) 1999-2020 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 "gdbsupport/gdb_sys_time.h" 31#include <fcntl.h> 32#include "gdbsupport/filestuff.h" 33 34#include <signal.h> 35 36static int pipe_open (struct serial *scb, const char *name); 37static void pipe_close (struct serial *scb); 38 39struct pipe_state 40 { 41 int pid; 42 }; 43 44/* Open up a raw pipe. */ 45 46static int 47pipe_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 146static void 147pipe_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 188int 189gdb_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 206static 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 231void _initialize_ser_pipe (); 232void 233_initialize_ser_pipe () 234{ 235 serial_add_interface (&pipe_ops); 236} 237