|  | /* Fork a Unix child process, and set up to debug it, for GDBserver. | 
|  | Copyright (C) 1989-2021 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "server.h" | 
|  | #include "gdbsupport/job-control.h" | 
|  | #include "nat/fork-inferior.h" | 
|  | #ifdef HAVE_SIGNAL_H | 
|  | #include <signal.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef SIGTTOU | 
|  | /* A file descriptor for the controlling terminal.  */ | 
|  | static int terminal_fd; | 
|  |  | 
|  | /* TERMINAL_FD's original foreground group.  */ | 
|  | static pid_t old_foreground_pgrp; | 
|  |  | 
|  | /* Hand back terminal ownership to the original foreground group.  */ | 
|  |  | 
|  | static void | 
|  | restore_old_foreground_pgrp (void) | 
|  | { | 
|  | tcsetpgrp (terminal_fd, old_foreground_pgrp); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* See nat/fork-inferior.h.  */ | 
|  |  | 
|  | void | 
|  | prefork_hook (const char *args) | 
|  | { | 
|  | client_state &cs = get_client_state (); | 
|  | if (debug_threads) | 
|  | { | 
|  | debug_printf ("args: %s\n", args); | 
|  | debug_flush (); | 
|  | } | 
|  |  | 
|  | #ifdef SIGTTOU | 
|  | signal (SIGTTOU, SIG_DFL); | 
|  | signal (SIGTTIN, SIG_DFL); | 
|  | #endif | 
|  |  | 
|  | /* Clear this so the backend doesn't get confused, thinking | 
|  | CONT_THREAD died, and it needs to resume all threads.  */ | 
|  | cs.cont_thread = null_ptid; | 
|  | } | 
|  |  | 
|  | /* See nat/fork-inferior.h.  */ | 
|  |  | 
|  | void | 
|  | postfork_hook (pid_t pid) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* See nat/fork-inferior.h.  */ | 
|  |  | 
|  | void | 
|  | postfork_child_hook () | 
|  | { | 
|  | /* This is set to the result of setpgrp, which if vforked, will be | 
|  | visible to you in the parent process.  It's only used by humans | 
|  | for debugging.  */ | 
|  | static int debug_setpgrp = 657473; | 
|  |  | 
|  | debug_setpgrp = gdb_setpgid (); | 
|  | if (debug_setpgrp == -1) | 
|  | perror (_("setpgrp failed in child")); | 
|  | } | 
|  |  | 
|  | /* See nat/fork-inferior.h.  */ | 
|  |  | 
|  | void | 
|  | gdb_flush_out_err () | 
|  | { | 
|  | fflush (stdout); | 
|  | fflush (stderr); | 
|  | } | 
|  |  | 
|  | /* See server.h.  */ | 
|  |  | 
|  | void | 
|  | post_fork_inferior (int pid, const char *program) | 
|  | { | 
|  | client_state &cs = get_client_state (); | 
|  | #ifdef SIGTTOU | 
|  | signal (SIGTTOU, SIG_IGN); | 
|  | signal (SIGTTIN, SIG_IGN); | 
|  | terminal_fd = fileno (stderr); | 
|  | old_foreground_pgrp = tcgetpgrp (terminal_fd); | 
|  | tcsetpgrp (terminal_fd, pid); | 
|  | atexit (restore_old_foreground_pgrp); | 
|  | #endif | 
|  |  | 
|  | startup_inferior (the_target, pid, | 
|  | START_INFERIOR_TRAPS_EXPECTED, | 
|  | &cs.last_status, &cs.last_ptid); | 
|  | current_thread->last_resume_kind = resume_stop; | 
|  | current_thread->last_status = cs.last_status; | 
|  | signal_pid = pid; | 
|  | target_post_create_inferior (); | 
|  | fprintf (stderr, "Process %s created; pid = %d\n", program, pid); | 
|  | fflush (stderr); | 
|  | } |