1/* Fork a Unix child process, and set up to debug it, for GDBserver.
2   Copyright (C) 1989-2023 Free Software Foundation, Inc.
3
4   This file is part of GDB.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19#include "server.h"
20#include "gdbsupport/job-control.h"
21#include "gdbsupport/scoped_restore.h"
22#include "nat/fork-inferior.h"
23#ifdef HAVE_SIGNAL_H
24#include <signal.h>
25#endif
26
27#ifdef SIGTTOU
28/* A file descriptor for the controlling terminal.  */
29static int terminal_fd;
30
31/* TERMINAL_FD's original foreground group.  */
32static pid_t old_foreground_pgrp;
33
34/* Hand back terminal ownership to the original foreground group.  */
35
36static void
37restore_old_foreground_pgrp (void)
38{
39  tcsetpgrp (terminal_fd, old_foreground_pgrp);
40}
41#endif
42
43/* See nat/fork-inferior.h.  */
44
45void
46prefork_hook (const char *args)
47{
48  client_state &cs = get_client_state ();
49  threads_debug_printf ("args: %s", args);
50
51#ifdef SIGTTOU
52  signal (SIGTTOU, SIG_DFL);
53  signal (SIGTTIN, SIG_DFL);
54#endif
55
56  /* Clear this so the backend doesn't get confused, thinking
57     CONT_THREAD died, and it needs to resume all threads.  */
58  cs.cont_thread = null_ptid;
59}
60
61/* See nat/fork-inferior.h.  */
62
63void
64postfork_hook (pid_t pid)
65{
66}
67
68/* See nat/fork-inferior.h.  */
69
70void
71postfork_child_hook ()
72{
73  /* This is set to the result of setpgrp, which if vforked, will be
74     visible to you in the parent process.  It's only used by humans
75     for debugging.  */
76  static int debug_setpgrp = 657473;
77
78  debug_setpgrp = gdb_setpgid ();
79  if (debug_setpgrp == -1)
80    perror (_("setpgrp failed in child"));
81}
82
83/* See nat/fork-inferior.h.  */
84
85void
86gdb_flush_out_err ()
87{
88  fflush (stdout);
89  fflush (stderr);
90}
91
92/* See server.h.  */
93
94void
95post_fork_inferior (int pid, const char *program)
96{
97  client_state &cs = get_client_state ();
98#ifdef SIGTTOU
99  signal (SIGTTOU, SIG_IGN);
100  signal (SIGTTIN, SIG_IGN);
101  terminal_fd = fileno (stderr);
102  old_foreground_pgrp = tcgetpgrp (terminal_fd);
103  tcsetpgrp (terminal_fd, pid);
104  atexit (restore_old_foreground_pgrp);
105#endif
106
107  process_info *proc = find_process_pid (pid);
108
109  /* If the inferior fails to start, startup_inferior mourns the
110     process (which deletes it), and then throws an error.  This means
111     that on exception return, we don't need or want to clear this
112     flag back, as PROC won't exist anymore.  Thus, we don't use a
113     scoped_restore.  */
114  proc->starting_up = true;
115
116  startup_inferior (the_target, pid,
117		    START_INFERIOR_TRAPS_EXPECTED,
118		    &cs.last_status, &cs.last_ptid);
119
120  /* If we get here, the process was successfully started.  */
121  proc->starting_up = false;
122
123  current_thread->last_resume_kind = resume_stop;
124  current_thread->last_status = cs.last_status;
125  signal_pid = pid;
126  target_post_create_inferior ();
127  fprintf (stderr, "Process %s created; pid = %d\n", program, pid);
128  fflush (stderr);
129}
130