* fork-child.c: Update copyright year. Fix coding style.
This commit is contained in:
parent
982526a134
commit
74a4fe3270
2 changed files with 103 additions and 104 deletions
|
@ -1,3 +1,7 @@
|
|||
2004-09-30 Mark Kettenis <kettenis@chello.nl>
|
||||
|
||||
* fork-child.c: Update copyright year. Fix coding style.
|
||||
|
||||
2004-09-29 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* defs.h (msavestring, mstrsave): Remove prototypes.
|
||||
|
|
203
gdb/fork-child.c
203
gdb/fork-child.c
|
@ -1,6 +1,8 @@
|
|||
/* Fork a Unix child process, and set up to debug it, for GDB.
|
||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
|
||||
2001 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
|
||||
2000, 2001, 2004 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB.
|
||||
|
@ -34,19 +36,18 @@
|
|||
|
||||
#include <signal.h>
|
||||
|
||||
/* This just gets used as a default if we can't find SHELL */
|
||||
/* This just gets used as a default if we can't find SHELL. */
|
||||
#ifndef SHELL_FILE
|
||||
#define SHELL_FILE "/bin/sh"
|
||||
#endif
|
||||
|
||||
extern char **environ;
|
||||
|
||||
/* This function breaks up an argument string into an argument
|
||||
* vector suitable for passing to execvp().
|
||||
* E.g., on "run a b c d" this routine would get as input
|
||||
* the string "a b c d", and as output it would fill in argv with
|
||||
* the four arguments "a", "b", "c", "d".
|
||||
*/
|
||||
/* Break up SCRATCH into an argument vector suitable for passing to
|
||||
execvp and store it in ARGV. E.g., on "run a b c d" this routine
|
||||
would get as input the string "a b c d", and as output it would
|
||||
fill in ARGV with the four arguments "a", "b", "c", "d". */
|
||||
|
||||
static void
|
||||
breakup_args (char *scratch, char **argv)
|
||||
{
|
||||
|
@ -54,49 +55,45 @@ breakup_args (char *scratch, char **argv)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
/* Scan past leading separators */
|
||||
while (*cp == ' ' || *cp == '\t' || *cp == '\n')
|
||||
{
|
||||
cp++;
|
||||
}
|
||||
cp++;
|
||||
|
||||
/* Break if at end of string */
|
||||
/* Break if at end of string. */
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
|
||||
/* Take an arg */
|
||||
/* Take an arg. */
|
||||
*argv++ = cp;
|
||||
|
||||
/* Scan for next arg separator */
|
||||
/* Scan for next arg separator. */
|
||||
cp = strchr (cp, ' ');
|
||||
if (cp == NULL)
|
||||
cp = strchr (cp, '\t');
|
||||
if (cp == NULL)
|
||||
cp = strchr (cp, '\n');
|
||||
|
||||
/* No separators => end of string => break */
|
||||
/* No separators => end of string => break. */
|
||||
if (cp == NULL)
|
||||
break;
|
||||
|
||||
/* Replace the separator with a terminator */
|
||||
/* Replace the separator with a terminator. */
|
||||
*cp++ = '\0';
|
||||
}
|
||||
|
||||
/* execv requires a null-terminated arg vector */
|
||||
/* Null-terminate the vector. */
|
||||
*argv = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* When executing a command under the given shell, return non-zero
|
||||
if the '!' character should be escaped when embedded in a quoted
|
||||
/* When executing a command under the given shell, return non-zero if
|
||||
the '!' character should be escaped when embedded in a quoted
|
||||
command-line argument. */
|
||||
|
||||
static int
|
||||
escape_bang_in_quoted_argument (const char *shell_file)
|
||||
{
|
||||
const int shell_file_len = strlen (shell_file);
|
||||
|
||||
|
||||
/* Bang should be escaped only in C Shells. For now, simply check
|
||||
that the shell name ends with 'csh', which covers at least csh
|
||||
and tcsh. This should be good enough for now. */
|
||||
|
@ -112,14 +109,14 @@ escape_bang_in_quoted_argument (const char *shell_file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Start an inferior Unix child process and sets inferior_ptid to its pid.
|
||||
EXEC_FILE is the file to run.
|
||||
ALLARGS is a string containing the arguments to the program.
|
||||
ENV is the environment vector to pass. SHELL_FILE is the shell file,
|
||||
or NULL if we should pick one. Errors reported with error(). */
|
||||
/* Start an inferior Unix child process and sets inferior_ptid to its
|
||||
pid. EXEC_FILE is the file to run. ALLARGS is a string containing
|
||||
the arguments to the program. ENV is the environment vector to
|
||||
pass. SHELL_FILE is the shell file, or NULL if we should pick
|
||||
one. */
|
||||
|
||||
/* This function is NOT-REENTRANT. Some of the variables have been
|
||||
made static to ensure that they survive the vfork() call. */
|
||||
/* This function is NOT reentrant. Some of the variables have been
|
||||
made static to ensure that they survive the vfork call. */
|
||||
|
||||
void
|
||||
fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
||||
|
@ -141,20 +138,19 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
int shell = 0;
|
||||
static char **argv;
|
||||
|
||||
/* If no exec file handed to us, get it from the exec-file command -- with
|
||||
a good, common error message if none is specified. */
|
||||
/* If no exec file handed to us, get it from the exec-file command
|
||||
-- with a good, common error message if none is specified. */
|
||||
exec_file = exec_file_arg;
|
||||
if (exec_file == 0)
|
||||
exec_file = get_exec_file (1);
|
||||
|
||||
/* STARTUP_WITH_SHELL is defined in inferior.h.
|
||||
* If 0, we'll just do a fork/exec, no shell, so don't
|
||||
* bother figuring out what shell.
|
||||
*/
|
||||
/* STARTUP_WITH_SHELL is defined in inferior.h. If 0,e we'll just
|
||||
do a fork/exec, no shell, so don't bother figuring out what
|
||||
shell. */
|
||||
shell_file = shell_file_arg;
|
||||
if (STARTUP_WITH_SHELL)
|
||||
{
|
||||
/* Figure out what shell to start up the user program under. */
|
||||
/* Figure out what shell to start up the user program under. */
|
||||
if (shell_file == NULL)
|
||||
shell_file = getenv ("SHELL");
|
||||
if (shell_file == NULL)
|
||||
|
@ -162,9 +158,9 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
shell = 1;
|
||||
}
|
||||
|
||||
/* Multiplying the length of exec_file by 4 is to account for the fact
|
||||
that it may expand when quoted; it is a worst-case number based on
|
||||
every character being '. */
|
||||
/* Multiplying the length of exec_file by 4 is to account for the
|
||||
fact that it may expand when quoted; it is a worst-case number
|
||||
based on every character being '. */
|
||||
len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
|
||||
/* If desired, concat something onto the front of ALLARGS.
|
||||
SHELL_COMMAND is the result. */
|
||||
|
@ -178,17 +174,18 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
|
||||
if (!shell)
|
||||
{
|
||||
/* We're going to call execvp. Create argv */
|
||||
/* Largest case: every other character is a separate arg */
|
||||
argv = (char **) xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) * sizeof (*argv));
|
||||
/* We're going to call execvp. Create argument vector.
|
||||
Calculate an upper bound on the length of the vector by
|
||||
assuming that every other character is a separate
|
||||
argument. */
|
||||
int argc = (strlen (allargs) + 1) / 2 + 2;
|
||||
argv = (char **) xmalloc (argc * sizeof (*argv));
|
||||
argv[0] = exec_file;
|
||||
breakup_args (allargs, &argv[1]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* We're going to call a shell */
|
||||
/* We're going to call a shell. */
|
||||
|
||||
/* Now add exec_file, quoting as necessary. */
|
||||
|
||||
|
@ -198,9 +195,9 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
|
||||
strcat (shell_command, "exec ");
|
||||
|
||||
/* 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. */
|
||||
/* 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)
|
||||
{
|
||||
|
@ -251,32 +248,29 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
|
||||
strcat (shell_command, " ");
|
||||
strcat (shell_command, allargs);
|
||||
|
||||
}
|
||||
|
||||
/* exec is said to fail if the executable is open. */
|
||||
/* On some systems an exec will fail if the executable is open. */
|
||||
close_exec_file ();
|
||||
|
||||
/* Retain a copy of our environment variables, since the child will
|
||||
replace the value of environ and if we're vforked, we have to
|
||||
replace the value of environ and if we're vforked, we have to
|
||||
restore it. */
|
||||
save_our_env = environ;
|
||||
|
||||
/* Tell the terminal handling subsystem what tty we plan to run on;
|
||||
it will just record the information for later. */
|
||||
|
||||
new_tty_prefork (inferior_io_terminal);
|
||||
|
||||
/* It is generally good practice to flush any possible pending stdio
|
||||
output prior to doing a fork, to avoid the possibility of both the
|
||||
parent and child flushing the same data after the fork. */
|
||||
|
||||
output prior to doing a fork, to avoid the possibility of both
|
||||
the parent and child flushing the same data after the fork. */
|
||||
gdb_flush (gdb_stdout);
|
||||
gdb_flush (gdb_stderr);
|
||||
|
||||
/* 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...
|
||||
*/
|
||||
/* 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... */
|
||||
if (pre_trace_fun != NULL)
|
||||
(*pre_trace_fun) ();
|
||||
|
||||
|
@ -301,9 +295,9 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
if (debug_setpgrp == -1)
|
||||
perror ("setpgrp failed in child");
|
||||
|
||||
/* Ask the tty subsystem to switch to the one we specified earlier
|
||||
(or to share the current terminal, if none was specified). */
|
||||
|
||||
/* Ask the tty subsystem to switch to the one we specified
|
||||
earlier (or to share the current terminal, if none was
|
||||
specified). */
|
||||
new_tty ();
|
||||
|
||||
/* Changing the signal handlers for the inferior after
|
||||
|
@ -314,14 +308,15 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
|
||||
/* "Trace me, Dr. Memory!" */
|
||||
(*traceme_fun) ();
|
||||
|
||||
/* The call above set this process (the "child") as debuggable
|
||||
* by the original gdb process (the "parent"). Since processes
|
||||
* (unlike people) can have only one parent, if you are
|
||||
* debugging gdb itself (and your debugger is thus _already_ the
|
||||
* controller/parent for this child), code from here on out
|
||||
* is undebuggable. Indeed, you probably got an error message
|
||||
* saying "not parent". Sorry--you'll have to use print statements!
|
||||
*/
|
||||
by the original gdb process (the "parent"). Since processes
|
||||
(unlike people) can have only one parent, if you are debugging
|
||||
gdb itself (and your debugger is thus _already_ the
|
||||
controller/parent for this child), code from here on out is
|
||||
undebuggable. Indeed, you probably got an error message
|
||||
saying "not parent". Sorry; you'll have to use print
|
||||
statements! */
|
||||
|
||||
/* There is no execlpe call, so we have to set the environment
|
||||
for our child in the global variable. If we've vforked, this
|
||||
|
@ -330,19 +325,17 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
path to find $SHELL. Rich Pixley says so, and I agree. */
|
||||
environ = env;
|
||||
|
||||
/* If we decided above to start up with a shell,
|
||||
* we exec the shell,
|
||||
* "-c" says to interpret the next arg as a shell command
|
||||
* to execute, and this command is "exec <target-program> <args>".
|
||||
* "-f" means "fast startup" to the c-shell, which means
|
||||
* don't do .cshrc file. Doing .cshrc may cause fork/exec
|
||||
* events which will confuse debugger start-up code.
|
||||
*/
|
||||
/* If we decided above to start up with a shell, we exec the
|
||||
shell, "-c" says to interpret the next arg as a shell command
|
||||
to execute, and this command is "exec <target-program>
|
||||
<args>". "-f" means "fast startup" to the c-shell, which
|
||||
means don't do .cshrc file. Doing .cshrc may cause fork/exec
|
||||
events which will confuse debugger start-up code. */
|
||||
if (shell)
|
||||
{
|
||||
execlp (shell_file, shell_file, "-c", shell_command, (char *) 0);
|
||||
|
||||
/* If we get here, it's an error */
|
||||
/* If we get here, it's an error. */
|
||||
fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
|
||||
safe_strerror (errno));
|
||||
gdb_flush (gdb_stderr);
|
||||
|
@ -350,13 +343,14 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we directly exec the target program with execvp. */
|
||||
/* Otherwise, we directly exec the target program with
|
||||
execvp. */
|
||||
int i;
|
||||
char *errstring;
|
||||
|
||||
execvp (exec_file, argv);
|
||||
|
||||
/* If we get here, it's an error */
|
||||
/* If we get here, it's an error. */
|
||||
errstring = safe_strerror (errno);
|
||||
fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file);
|
||||
|
||||
|
@ -369,9 +363,10 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
i++;
|
||||
}
|
||||
fprintf_unfiltered (gdb_stderr, ".\n");
|
||||
/* This extra info seems to be useless
|
||||
fprintf_unfiltered (gdb_stderr, "Got error %s.\n", errstring);
|
||||
*/
|
||||
#if 0
|
||||
/* This extra info seems to be useless. */
|
||||
fprintf_unfiltered (gdb_stderr, "Got error %s.\n", errstring);
|
||||
#endif
|
||||
gdb_flush (gdb_stderr);
|
||||
_exit (0177);
|
||||
}
|
||||
|
@ -382,20 +377,21 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
|||
|
||||
init_thread_list ();
|
||||
|
||||
inferior_ptid = pid_to_ptid (pid); /* Needed for wait_for_inferior stuff below */
|
||||
/* Needed for wait_for_inferior stuff below. */
|
||||
inferior_ptid = pid_to_ptid (pid);
|
||||
|
||||
/* Now that we have a child process, make it our target, and
|
||||
initialize anything target-vector-specific that needs initializing. */
|
||||
|
||||
initialize anything target-vector-specific that needs
|
||||
initializing. */
|
||||
(*init_trace_fun) (pid);
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* Allow target dependent code to play with the new process. This might be
|
||||
used to have target-specific code initialize a variable in the new process
|
||||
prior to executing the first instruction. */
|
||||
/* Allow target dependent code to play with the new process. This
|
||||
might be used to have target-specific code initialize a variable
|
||||
in the new process prior to executing the first instruction. */
|
||||
TARGET_CREATE_INFERIOR_HOOK (pid);
|
||||
|
||||
#ifdef SOLIB_CREATE_INFERIOR_HOOK
|
||||
|
@ -409,18 +405,16 @@ void
|
|||
startup_inferior (int ntraps)
|
||||
{
|
||||
int pending_execs = ntraps;
|
||||
int terminal_initted;
|
||||
int terminal_initted = 0;
|
||||
|
||||
/* 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. */
|
||||
/* 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. */
|
||||
|
||||
clear_proceed_status ();
|
||||
|
||||
init_wait_for_inferior ();
|
||||
|
||||
terminal_initted = 0;
|
||||
|
||||
if (STARTUP_WITH_SHELL)
|
||||
inferior_ignoring_startup_exec_events = ntraps;
|
||||
else
|
||||
|
@ -430,13 +424,14 @@ startup_inferior (int ntraps)
|
|||
|
||||
while (1)
|
||||
{
|
||||
/* Make wait_for_inferior be quiet */
|
||||
/* Make wait_for_inferior be quiet. */
|
||||
stop_soon = STOP_QUIETLY;
|
||||
wait_for_inferior ();
|
||||
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 */
|
||||
/* Let shell child handle its own signals in its own way.
|
||||
FIXME: what if child has exited? Must exit loop
|
||||
somehow. */
|
||||
resume (0, stop_signal);
|
||||
}
|
||||
else
|
||||
|
@ -444,9 +439,10 @@ startup_inferior (int ntraps)
|
|||
/* 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. */
|
||||
/* 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. */
|
||||
|
@ -458,11 +454,10 @@ startup_inferior (int ntraps)
|
|||
terminal_initted = 1;
|
||||
}
|
||||
|
||||
pending_execs = pending_execs - 1;
|
||||
if (0 == pending_execs)
|
||||
if (--pending_execs == 0)
|
||||
break;
|
||||
|
||||
resume (0, TARGET_SIGNAL_0); /* Just make it go on */
|
||||
resume (0, TARGET_SIGNAL_0); /* Just make it go on. */
|
||||
}
|
||||
}
|
||||
stop_soon = NO_STOP_QUIETLY;
|
||||
|
|
Loading…
Reference in a new issue