diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/fork-child.c | 22 | ||||
-rw-r--r-- | gdb/m3-nat.c | 2 | ||||
-rw-r--r-- | gdb/procfs.c | 105 |
4 files changed, 96 insertions, 41 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 798dbb0..da5fe2e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +Sat Jan 22 08:30:42 1994 Jim Kingdon (kingdon@deneb.cygnus.com) + + * fork-child.c, inferior.h (fork_inferior): New argument shell_file. + * procfs.c (procfs_create_inferior), inftarg.c (child_create_inferior), + m3-nat.c (m3_create_inferior): Pass it. + * procfs.c: Remove ptrace function. It was declared in a way which + conflicted with the prototype in unistd.h on Solaris. + Sat Jan 22 01:37:40 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) * sparc-tdep.c (frame_saved_pc): Get the pc from the saved pc diff --git a/gdb/fork-child.c b/gdb/fork-child.c index f4a5a59..4fd5ee3 100644 --- a/gdb/fork-child.c +++ b/gdb/fork-child.c @@ -38,26 +38,28 @@ extern int original_stack_limit; extern char **environ; -/* Start an inferior Unix child process and sets inferior_pid 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. Errors reported with error(). */ - #ifndef SHELL_FILE #define SHELL_FILE "/bin/sh" #endif +/* Start an inferior Unix child process and sets inferior_pid 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(). */ + void -fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) +fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun, + shell_file) char *exec_file; char *allargs; char **env; void (*traceme_fun) PARAMS ((void)); void (*init_trace_fun) PARAMS ((int)); + char *shell_file; { int pid; char *shell_command; - char *shell_file; static char default_shell_file[] = SHELL_FILE; int len; /* Set debug_fork then attach to the child while it sleeps, to debug. */ @@ -76,8 +78,10 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) 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-maybe, we might want a "set shell" command so the user can change - the shell from within GDB. */ - shell_file = getenv ("SHELL"); + the shell from within GDB (if so, change callers which pass in a non-NULL + shell_file too). */ + if (shell_file == NULL) + shell_file = getenv ("SHELL"); if (shell_file == NULL) shell_file = default_shell_file; diff --git a/gdb/m3-nat.c b/gdb/m3-nat.c index 66bd679..90cddb0 100644 --- a/gdb/m3-nat.c +++ b/gdb/m3-nat.c @@ -3879,7 +3879,7 @@ m3_create_inferior (exec_file, allargs, env) char *allargs; char **env; { - fork_inferior (exec_file, allargs, env, m3_trace_m3, m3_trace_him); + fork_inferior (exec_file, allargs, env, m3_trace_m3, m3_trace_him, NULL); /* We are at the first instruction we care about. */ /* Pedal to the metal... */ proceed ((CORE_ADDR) -1, 0, 0); diff --git a/gdb/procfs.c b/gdb/procfs.c index c9e0d8f..0d7aee8 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -34,6 +34,7 @@ regardless of whether or not the actual target has floating point hardware. #include "defs.h" +#include <sys/types.h> #include <time.h> #include <sys/procfs.h> #include <fcntl.h> @@ -41,6 +42,8 @@ regardless of whether or not the actual target has floating point hardware. #include <string.h> #include <stropts.h> #include <poll.h> +#include <unistd.h> +#include <sys/stat.h> #include "inferior.h" #include "target.h" @@ -1206,36 +1209,6 @@ init_syscall_table () /* -GLOBAL FUNCTION - - ptrace -- override library version to force errors for /proc version - -SYNOPSIS - - int ptrace (int request, int pid, PTRACE_ARG3_TYPE arg3, int arg4) - -DESCRIPTION - - When gdb is configured to use /proc, it should not be calling - or otherwise attempting to use ptrace. In order to catch errors - where use of /proc is configured, but some routine is still calling - ptrace, we provide a local version of a function with that name - that does nothing but issue an error message. -*/ - -int -ptrace (request, pid, arg3, arg4) - int request; - int pid; - PTRACE_ARG3_TYPE arg3; - int arg4; -{ - error ("internal error - there is a call to ptrace() somewhere"); - /*NOTREACHED*/ -} - -/* - LOCAL FUNCTION procfs_kill_inferior - kill any currently inferior @@ -3448,8 +3421,78 @@ procfs_create_inferior (exec_file, allargs, env) char *allargs; char **env; { + char *shell_file = getenv ("SHELL"); + char *tryname; + if (shell_file != NULL && strchr (shell_file, '/') == NULL) + { + + /* We will be looking down the PATH to find shell_file. If we + just do this the normal way (via execlp, which operates by + attempting an exec for each element of the PATH until it + finds one which succeeds), then there will be an exec for + each failed attempt, each of which will cause a PR_SYSEXIT + stop, and we won't know how to distinguish the PR_SYSEXIT's + for these failed execs with the ones for successful execs + (whether the exec has succeeded is stored at that time in the + carry bit or some such architecture-specific and + non-ABI-specified place). + + So I can't think of anything better than to search the PATH + now. This has several disadvantages: (1) There is a race + condition; if we find a file now and it is deleted before we + exec it, we lose, even if the deletion leaves a valid file + further down in the PATH, (2) there is no way to know exactly + what an executable (in the sense of "capable of being + exec'd") file is. Using access() loses because it may lose + if the caller is the superuser; failing to use it loses if + there are ACLs or some such. */ + + char *p; + char *p1; + /* FIXME-maybe: might want "set path" command to replace putenv hack + in set_in_environ. */ + char *path = getenv ("PATH"); + int len; + struct stat statbuf; + + if (path == NULL) + path = "/bin:/usr/bin"; + + tryname = alloca (strlen (path) + strlen (shell_file) + 2); + for (p = path; p != NULL; p = p1 ? p1 + 1: NULL) + { + p1 = strchr (p, ':'); + if (p1 != NULL) + len = p1 - p; + else + len = strlen (p); + strncpy (tryname, p, len); + tryname[len] = '\0'; + strcat (tryname, "/"); + strcat (tryname, shell_file); + if (access (tryname, X_OK) < 0) + continue; + if (stat (tryname, &statbuf) < 0) + continue; + if (!S_ISREG (statbuf.st_mode)) + /* We certainly need to reject directories. I'm not quite + as sure about FIFOs, sockets, etc., but I kind of doubt + that people want to exec() these things. */ + continue; + break; + } + if (p == NULL) + /* Not found. This must be an error rather than merely passing + the file to execlp(), because execlp() would try all the + exec()s, causing GDB to get confused. */ + error ("Can't find shell %s in PATH", shell_file); + + shell_file = tryname; + } + fork_inferior (exec_file, allargs, env, - proc_set_exec_trap, procfs_init_inferior); + proc_set_exec_trap, procfs_init_inferior, shell_file); + /* We are at the first instruction we care about. */ /* Pedal to the metal... */ |