#include "target.h"
#include "wait.h"
#include "gdbcore.h"
-#include "serial.h" /* For job_control. */
-#include "terminal.h" /* For new_tty */
+#include "terminal.h"
+#include "thread.h"
#include <signal.h>
char *shell_file;
static char default_shell_file[] = SHELL_FILE;
int len;
- int pending_execs;
/* Set debug_fork then attach to the child while it sleeps, to debug. */
static int debug_fork = 0;
/* This is set to the result of setpgrp, which if vforked, will be visible
/* The user might want tilde-expansion, and in general probably wants
the program to behave the same way as if run from
his/her favorite shell. So we let the shell run it for us.
- FIXME, this should probably search the local environment (as
- modified by the setenv command), not the env gdb inherited. */
+ FIXME-maybe, we might want a "set shell" command so the user can change
+ the shell from within GDB. */
shell_file = getenv ("SHELL");
if (shell_file == NULL)
shell_file = default_shell_file;
#endif
strcat (shell_command, "exec ");
- /* Now add exec_file, quoting as necessary. Quoting in this style is
- said to work with all shells. */
+ /* Now add exec_file, quoting as necessary. */
{
char *p;
+ int need_to_quote;
- strcat (shell_command, "'");
- for (p = exec_file; *p != '\0'; ++p)
+ /* Quoting in this style is said to work with all shells. But csh
+ on IRIX 4.0.1 can't deal with it. So we only quote it if we need
+ to. */
+ p = exec_file;
+ while (1)
{
- if (*p == '\'')
- strcat (shell_command, "'\\''");
- else
- strncat (shell_command, p, 1);
+ switch (*p)
+ {
+ case '\'':
+ case '"':
+ case '(':
+ case ')':
+ case '$':
+ case '&':
+ case ';':
+ case '<':
+ case '>':
+ case ' ':
+ case '\n':
+ case '\t':
+ need_to_quote = 1;
+ goto end_scan;
+
+ case '\0':
+ need_to_quote = 0;
+ goto end_scan;
+
+ default:
+ break;
+ }
+ ++p;
+ }
+ end_scan:
+ if (need_to_quote)
+ {
+ strcat (shell_command, "'");
+ for (p = exec_file; *p != '\0'; ++p)
+ {
+ if (*p == '\'')
+ strcat (shell_command, "'\\''");
+ else
+ strncat (shell_command, p, 1);
+ }
+ strcat (shell_command, "'");
}
- strcat (shell_command, "'");
+ else
+ strcat (shell_command, exec_file);
}
strcat (shell_command, " ");
output prior to doing a fork, to avoid the possibility of both the
parent and child flushing the same data after the fork. */
- fflush (stdout);
- fflush (stderr);
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
#if defined(USG) && !defined(HAVE_VFORK)
pid = fork ();
environ = env;
execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
- fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
+ fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
safe_strerror (errno));
- fflush (stderr);
+ gdb_flush (gdb_stderr);
_exit (0177);
}
/* Restore our environment in case a vforked child clob'd it. */
environ = save_our_env;
+ init_thread_list();
+
+ inferior_pid = pid; /* Needed for wait_for_inferior stuff below */
+
/* Now that we have a child process, make it our target, and
initialize anything target-vector-specific that needs initializing. */
(*init_trace_fun)(pid);
-#ifdef CREATE_INFERIOR_HOOK
- CREATE_INFERIOR_HOOK (pid);
-#endif
-
-/* The process was started by the fork that created it,
- but it will have stopped one instruction after execing the shell.
- Here we must get it up to actual execution of the real program. */
+ /* We are now in the child process of interest, having exec'd the
+ correct program, and are poised at the first instruction of the
+ new program. */
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+ SOLIB_CREATE_INFERIOR_HOOK (pid);
+#endif
+}
- inferior_pid = pid; /* Needed for wait_for_inferior stuff below */
+/* Accept NTRAPS traps from the inferior. */
- clear_proceed_status ();
+void
+startup_inferior (ntraps)
+ int ntraps;
+{
+ int pending_execs = ntraps;
+ int terminal_initted;
- /* We will get a trace trap after one instruction.
- Continue it automatically. Eventually (after shell does an exec)
- it will get another trace trap. Then insert breakpoints and continue. */
+ /* The process was started by the fork that created it,
+ but it will have stopped one instruction after execing the shell.
+ Here we must get it up to actual execution of the real program. */
-#ifdef START_INFERIOR_TRAPS_EXPECTED
- pending_execs = START_INFERIOR_TRAPS_EXPECTED;
-#else
- pending_execs = 2;
-#endif
+ clear_proceed_status ();
init_wait_for_inferior ();
- /* Set up the "saved terminal modes" of the inferior
- based on what modes we are starting it with. */
- target_terminal_init ();
-
- /* Install inferior's terminal modes. */
- target_terminal_inferior ();
+ terminal_initted = 0;
while (1)
{
stop_soon_quietly = 1; /* Make wait_for_inferior be quiet */
wait_for_inferior ();
- if (stop_signal != SIGTRAP)
+ if (stop_signal != TARGET_SIGNAL_TRAP)
{
/* Let shell child handle its own signals in its own way */
/* FIXME, what if child has exit()ed? Must exit loop somehow */
else
{
/* We handle SIGTRAP, however; it means child did an exec. */
+ if (!terminal_initted)
+ {
+ /* Now that the child has exec'd we know it has already set its
+ process group. On POSIX systems, tcsetpgrp will fail with
+ EPERM if we try it before the child's setpgid. */
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ terminal_initted = 1;
+ }
if (0 == --pending_execs)
break;
- resume (0, 0); /* Just make it go on */
+ resume (0, TARGET_SIGNAL_0); /* Just make it go on */
}
}
stop_soon_quietly = 0;
-
- /* We are now in the child process of interest, having exec'd the
- correct program, and are poised at the first instruction of the
- new program. */
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
- SOLIB_CREATE_INFERIOR_HOOK (pid);
-#endif
}