/* Fork a Unix child process, and set up to debug it, for GDB and GDBserver.
- Copyright (C) 1990-2017 Free Software Foundation, Inc.
+ Copyright (C) 1990-2019 Free Software Foundation, Inc.
This file is part of GDB.
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 "common-defs.h"
+#include "gdbsupport/common-defs.h"
#include "fork-inferior.h"
#include "target/waitstatus.h"
-#include "filestuff.h"
+#include "gdbsupport/filestuff.h"
#include "target/target.h"
-#include "common-inferior.h"
-#include "common-gdbthread.h"
-#include "signals-state-save-restore.h"
+#include "gdbsupport/common-inferior.h"
+#include "gdbsupport/common-gdbthread.h"
+#include "gdbsupport/pathstuff.h"
+#include "gdbsupport/signals-state-save-restore.h"
+#include "gdbsupport/gdb_tilde_expand.h"
#include <vector>
extern char **environ;
-/* Default shell file to be used if 'startup-with-shell' is set but
- $SHELL is not. */
-#define SHELL_FILE "/bin/sh"
-
/* Build the argument vector for execv(3). */
class execv_argv
}
private:
- /* Disable copying. */
- execv_argv (const execv_argv &) = delete;
- void operator= (const execv_argv &) = delete;
+ DISABLE_COPY_AND_ASSIGN (execv_argv);
/* Helper methods for constructing the argument vector. */
m_argv.push_back (NULL);
}
-/* Return the shell that must be used to startup the inferior. The
- first attempt is the environment variable SHELL; if it is not set,
- then we default to SHELL_FILE. */
-
-static const char *
-get_startup_shell ()
-{
- static const char *ret;
-
- ret = getenv ("SHELL");
- if (ret == NULL)
- ret = SHELL_FILE;
-
- return ret;
-}
-
/* See nat/fork-inferior.h. */
pid_t
char **save_our_env;
int i;
int save_errno;
+ const char *inferior_cwd;
+ std::string expanded_inferior_cwd;
/* If no exec file handed to us, get it from the exec-file command
-- with a good, common error message if none is specified. */
/* Figure out what shell to start up the user program under. */
if (shell_file == NULL)
- shell_file = get_startup_shell ();
+ shell_file = get_shell ();
gdb_assert (shell_file != NULL);
}
the parent and child flushing the same data after the fork. */
gdb_flush_out_err ();
+ /* Check if the user wants to set a different working directory for
+ the inferior. */
+ inferior_cwd = get_inferior_cwd ();
+
+ if (inferior_cwd != NULL)
+ {
+ /* Expand before forking because between fork and exec, the child
+ process may only execute async-signal-safe operations. */
+ expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
+ inferior_cwd = expanded_inferior_cwd.c_str ();
+ }
+
/* If there's any initialization of the target layers that must
happen to prepare to handle the child we're about fork, do it
now... */
UIs. */
close_most_fds ();
+ /* Change to the requested working directory if the user
+ requested it. */
+ if (inferior_cwd != NULL)
+ {
+ if (chdir (inferior_cwd) < 0)
+ trace_start_error_with_name (inferior_cwd);
+ }
+
if (debug_fork)
sleep (debug_fork);
for (i = 1; argv[i] != NULL; i++)
warning (" %s", argv[i]);
- warning ("Error: %s\n", safe_strerror (save_errno));
+ warning ("Error: %s", safe_strerror (save_errno));
_exit (0177);
}
}
if (target_supports_multi_process ())
- resume_ptid = pid_to_ptid (pid);
+ resume_ptid = ptid_t (pid);
else
resume_ptid = minus_one_ptid;
break;
case TARGET_WAITKIND_SIGNALLED:
- target_terminal_ours ();
+ target_terminal::ours ();
target_mourn_inferior (event_ptid);
error (_("During startup program terminated with signal %s, %s."),
gdb_signal_to_name (ws.value.sig),
return resume_ptid;
case TARGET_WAITKIND_EXITED:
- target_terminal_ours ();
+ target_terminal::ours ();
target_mourn_inferior (event_ptid);
if (ws.value.integer)
error (_("During startup program exited with code %d."),
/* Set up the "saved terminal modes" of the inferior
based on what modes we are starting it with. */
- target_terminal_init ();
+ target_terminal::init ();
/* Install inferior's terminal modes. */
- target_terminal_inferior ();
+ target_terminal::inferior ();
terminal_initted = 1;
}