/* Low level interface to ptrace, for GDB when running under Unix.
- Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Copyright 1986-87, 1989, 1991-92, 1995, 1998 Free Software Foundation, Inc.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "serial.h"
#include "terminal.h"
#include "target.h"
-#include "thread.h"
+#include "gdbthread.h"
+#include "gdb_string.h"
#include <signal.h>
#include <fcntl.h>
-
-#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY) && !defined (__GO32__)
-#define HAVE_SGTTY
-#endif
-
-#if defined (HAVE_TERMIOS)
-#include <termios.h>
-#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
#endif
#ifdef HAVE_TERMIOS
#define PROCESS_GROUP_TYPE pid_t
#endif
+#ifdef HAVE_TERMIO
+#define PROCESS_GROUP_TYPE int
+#endif
+
#ifdef HAVE_SGTTY
#ifdef SHORT_PGRP
/* This is only used for the ultra. Does it have pid_t? */
#endif
#endif /* sgtty */
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN)
+static void
+handle_sigio PARAMS ((int));
+#endif
+
+extern void _initialize_inflow PARAMS ((void));
+
+static void
+pass_signal PARAMS ((int));
+
static void
kill_command PARAMS ((char *, int));
inferior only. If we have job control, that takes care of it. If not,
we save our handlers in these two variables and set SIGINT and SIGQUIT
to SIG_IGN. */
+
static void (*sigint_ours) ();
static void (*sigquit_ours) ();
inferior's settings are in effect. Ignored if !gdb_has_a_terminal
(). */
-static int terminal_is_ours;
+int terminal_is_ours;
-enum {yes, no, have_not_checked} gdb_has_a_terminal_flag = have_not_checked;
+enum
+ {
+ yes, no, have_not_checked
+ }
+gdb_has_a_terminal_flag = have_not_checked;
/* Does GDB have a terminal (on stdin)? */
int
return 0;
case have_not_checked:
/* Get all the current tty settings (including whether we have a tty at
- all!). Can't do this in _initialize_inflow because SERIAL_FDOPEN
- won't work until the serial_ops_list is initialized. */
+ all!). Can't do this in _initialize_inflow because SERIAL_FDOPEN
+ won't work until the serial_ops_list is initialized. */
#ifdef F_GETFL
tflags_ours = fcntl (0, F_GETFL, 0);
#ifdef HAVE_TERMIOS
our_process_group = tcgetpgrp (0);
#endif
+#ifdef HAVE_TERMIO
+ our_process_group = getpgrp ();
+#endif
#ifdef HAVE_SGTTY
ioctl (0, TIOCGPGRP, &our_process_group);
#endif
before we actually run the inferior. */
void
-terminal_init_inferior ()
+terminal_init_inferior_with_pgrp (pgrp)
+ int pgrp;
{
if (gdb_has_a_terminal ())
{
/* We could just as well copy our_ttystate (if we felt like adding
- a new function SERIAL_COPY_TTY_STATE). */
+ a new function SERIAL_COPY_TTY_STATE). */
if (inferior_ttystate)
free (inferior_ttystate);
inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
+
#ifdef PROCESS_GROUP_TYPE
-#ifdef PIDGET
- /* This is for Lynx, and should be cleaned up by having Lynx be
- a separate debugging target with a version of
- target_terminal_init_inferior which passes in the process
- group to a generic routine which does all the work (and the
- non-threaded child_terminal_init_inferior can just pass in
- inferior_pid to the same routine). */
- inferior_process_group = PIDGET (inferior_pid);
-#else
- inferior_process_group = inferior_pid;
-#endif
+ inferior_process_group = pgrp;
#endif
/* Make sure that next time we call terminal_inferior (which will be
- before the program runs, as it needs to be), we install the new
- process group. */
+ before the program runs, as it needs to be), we install the new
+ process group. */
terminal_is_ours = 1;
}
}
+void
+terminal_init_inferior ()
+{
+#ifdef PROCESS_GROUP_TYPE
+ /* This is for Lynx, and should be cleaned up by having Lynx be a separate
+ debugging target with a version of target_terminal_init_inferior which
+ passes in the process group to a generic routine which does all the work
+ (and the non-threaded child_terminal_init_inferior can just pass in
+ inferior_pid to the same routine). */
+ /* We assume INFERIOR_PID is also the child's process group. */
+ terminal_init_inferior_with_pgrp (PIDGET (inferior_pid));
+#endif /* PROCESS_GROUP_TYPE */
+}
+
/* Put the inferior's terminal settings into effect.
This is preparation for starting or resuming the inferior. */
#ifdef F_GETFL
/* Is there a reason this is being done twice? It happens both
- places we use F_SETFL, so I'm inclined to think perhaps there
- is some reason, however perverse. Perhaps not though... */
+ places we use F_SETFL, so I'm inclined to think perhaps there
+ is some reason, however perverse. Perhaps not though... */
result = fcntl (0, F_SETFL, tflags_inferior);
result = fcntl (0, F_SETFL, tflags_inferior);
OOPSY ("fcntl F_SETFL");
#endif
/* Because we were careful to not change in or out of raw mode in
- terminal_ours, we will not change in our out of raw mode with
- this call, so we don't flush any input. */
+ terminal_ours, we will not change in our out of raw mode with
+ this call, so we don't flush any input. */
result = SERIAL_SET_TTY_STATE (stdin_serial, inferior_ttystate);
OOPSY ("setting tty state");
if (!job_control)
{
- sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN);
- sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+ sigint_ours = (void (*)()) signal (SIGINT, SIG_IGN);
+#ifdef SIGQUIT
+ sigquit_ours = (void (*)()) signal (SIGQUIT, SIG_IGN);
+#endif
}
/* If attach_flag is set, we don't know whether we are sharing a
- terminal with the inferior or not. (attaching a process
- without a terminal is one case where we do not; attaching a
- process which we ran from the same shell as GDB via `&' is
- one case where we do, I think (but perhaps this is not
- `sharing' in the sense that we need to save and restore tty
- state)). I don't know if there is any way to tell whether we
- are sharing a terminal. So what we do is to go through all
- the saving and restoring of the tty state, but ignore errors
- setting the process group, which will happen if we are not
- sharing a terminal). */
+ terminal with the inferior or not. (attaching a process
+ without a terminal is one case where we do not; attaching a
+ process which we ran from the same shell as GDB via `&' is
+ one case where we do, I think (but perhaps this is not
+ `sharing' in the sense that we need to save and restore tty
+ state)). I don't know if there is any way to tell whether we
+ are sharing a terminal. So what we do is to go through all
+ the saving and restoring of the tty state, but ignore errors
+ setting the process group, which will happen if we are not
+ sharing a terminal). */
if (job_control)
{
if (!terminal_is_ours)
{
/* Ignore this signal since it will happen when we try to set the
- pgrp. */
+ pgrp. */
void (*osigttou) ();
int result;
#ifdef SIGTTOU
if (job_control)
- osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN);
+ osigttou = (void (*)()) signal (SIGTTOU, SIG_IGN);
#endif
if (inferior_ttystate)
#ifdef HAVE_TERMIOS
inferior_process_group = tcgetpgrp (0);
#endif
+#ifdef HAVE_TERMIO
+ inferior_process_group = getpgrp ();
+#endif
#ifdef HAVE_SGTTY
ioctl (0, TIOCGPGRP, &inferior_process_group);
#endif
/* Here we used to set ICANON in our ttystate, but I believe this
- was an artifact from before when we used readline. Readline sets
- the tty state when it needs to.
- FIXME-maybe: However, query() expects non-raw mode and doesn't
- use readline. Maybe query should use readline (on the other hand,
- this only matters for HAVE_SGTTY, not termio or termios, I think). */
+ was an artifact from before when we used readline. Readline sets
+ the tty state when it needs to.
+ FIXME-maybe: However, query() expects non-raw mode and doesn't
+ use readline. Maybe query should use readline (on the other hand,
+ this only matters for HAVE_SGTTY, not termio or termios, I think). */
/* Set tty state to our_ttystate. We don't change in our out of raw
- mode, to avoid flushing input. We need to do the same thing
- regardless of output_only, because we don't have separate
- terminal_is_ours and terminal_is_ours_for_output flags. It's OK,
- though, since readline will deal with raw mode when/if it needs to.
- */
+ mode, to avoid flushing input. We need to do the same thing
+ regardless of output_only, because we don't have separate
+ terminal_is_ours and terminal_is_ours_for_output flags. It's OK,
+ though, since readline will deal with raw mode when/if it needs to.
+ */
SERIAL_NOFLUSH_SET_TTY_STATE (stdin_serial, our_ttystate,
inferior_ttystate);
such situations as well. */
if (result == -1)
fprintf_unfiltered (gdb_stderr, "[tcsetpgrp failed in terminal_ours: %s]\n",
- strerror (errno));
+ strerror (errno));
#endif
#endif /* termios */
if (!job_control)
{
signal (SIGINT, sigint_ours);
+#ifdef SIGQUIT
signal (SIGQUIT, sigquit_ours);
+#endif
}
#ifdef F_GETFL
tflags_inferior = fcntl (0, F_GETFL, 0);
/* Is there a reason this is being done twice? It happens both
- places we use F_SETFL, so I'm inclined to think perhaps there
- is some reason, however perverse. Perhaps not though... */
+ places we use F_SETFL, so I'm inclined to think perhaps there
+ is some reason, however perverse. Perhaps not though... */
result = fcntl (0, F_SETFL, tflags_ours);
result = fcntl (0, F_SETFL, tflags_ours);
#endif
- result = result; /* lint */
+ result = result; /* lint */
}
}
/* First the fcntl flags. */
{
int flags;
-
+
flags = tflags_inferior;
printf_filtered ("File descriptor flags = ");
/* (O_ACCMODE) parens are to avoid Ultrix header file bug */
switch (flags & (O_ACCMODE))
{
- case O_RDONLY: printf_filtered ("O_RDONLY"); break;
- case O_WRONLY: printf_filtered ("O_WRONLY"); break;
- case O_RDWR: printf_filtered ("O_RDWR"); break;
+ case O_RDONLY:
+ printf_filtered ("O_RDONLY");
+ break;
+ case O_WRONLY:
+ printf_filtered ("O_WRONLY");
+ break;
+ case O_RDWR:
+ printf_filtered ("O_RDWR");
+ break;
}
flags &= ~(O_ACCMODE);
#ifdef O_NONBLOCK
- if (flags & O_NONBLOCK)
+ if (flags & O_NONBLOCK)
printf_filtered (" | O_NONBLOCK");
flags &= ~O_NONBLOCK;
#endif
-
+
#if defined (O_NDELAY)
/* If O_NDELAY and O_NONBLOCK are defined to the same thing, we will
print it as O_NONBLOCK, which is good cause that is what POSIX
}
#ifdef PROCESS_GROUP_TYPE
- printf_filtered ("Process group = %d\n", inferior_process_group);
+ printf_filtered ("Process group = %d\n",
+ (int) inferior_process_group);
#endif
- SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate);
+ SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate, gdb_stdout);
}
\f
/* NEW_TTY_PREFORK is called before forking a new child process,
if (inferior_thisrun_terminal == 0)
return;
-#if !defined(__GO32__)
+#if !defined(__GO32__) && !defined(_WIN32)
#ifdef TIOCNOTTY
/* Disconnect the child process from our controlling terminal. On some
systems (SVR4 for example), this may cause a SIGTTOU, so temporarily
ignore SIGTTOU. */
- tty = open("/dev/tty", O_RDWR);
+ tty = open ("/dev/tty", O_RDWR);
if (tty > 0)
{
void (*osigttou) ();
- osigttou = (void (*)()) signal(SIGTTOU, SIG_IGN);
- ioctl(tty, TIOCNOTTY, 0);
- close(tty);
- signal(SIGTTOU, osigttou);
+ osigttou = (void (*)()) signal (SIGTTOU, SIG_IGN);
+ ioctl (tty, TIOCNOTTY, 0);
+ close (tty);
+ signal (SIGTTOU, osigttou);
}
#endif
/* Now open the specified new terminal. */
#ifdef USE_O_NOCTTY
- tty = open(inferior_thisrun_terminal, O_RDWR | O_NOCTTY);
+ tty = open (inferior_thisrun_terminal, O_RDWR | O_NOCTTY);
#else
- tty = open(inferior_thisrun_terminal, O_RDWR);
+ tty = open (inferior_thisrun_terminal, O_RDWR);
#endif
if (tty == -1)
{
print_sys_errmsg (inferior_thisrun_terminal, errno);
- _exit(1);
+ _exit (1);
}
/* Avoid use of dup2; doesn't exist on all systems. */
if (tty != 0)
- { close (0); dup (tty); }
+ {
+ close (0);
+ dup (tty);
+ }
if (tty != 1)
- { close (1); dup (tty); }
+ {
+ close (1);
+ dup (tty);
+ }
if (tty != 2)
- { close (2); dup (tty); }
+ {
+ close (2);
+ dup (tty);
+ }
if (tty > 2)
- close(tty);
-#endif /* !go32 */
+ close (tty);
+#endif /* !go32 && !win32 */
}
\f
/* Kill the inferior process. Make us have no inferior. */
char *arg;
int from_tty;
{
- /* Shouldn't this be target_has_execution? FIXME. */
+ /* FIXME: This should not really be inferior_pid (or target_has_execution).
+ It should be a distinct flag that indicates that a target is active, cuz
+ some targets don't have processes! */
+
if (inferior_pid == 0)
error ("The program is not being run.");
if (!query ("Kill the program being debugged? "))
error ("Not confirmed.");
target_kill ();
- init_thread_list(); /* Destroy thread info */
+ init_thread_list (); /* Destroy thread info */
/* Killing off the inferior can leave us with a core file. If so,
print the state we are left in. */
- if (target_has_stack) {
- printf_filtered ("In %s,\n", target_longname);
- if (selected_frame == NULL)
- fputs_filtered ("No selected stack frame.\n", gdb_stdout);
- else
- print_stack_frame (selected_frame, selected_frame_level, 1);
- }
+ if (target_has_stack)
+ {
+ printf_filtered ("In %s,\n", target_longname);
+ if (selected_frame == NULL)
+ fputs_filtered ("No selected stack frame.\n", gdb_stdout);
+ else
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ }
}
\f
/* Call set_sigint_trap when you need to pass a signal on to an attached
/* ARGSUSED */
static void
pass_signal (signo)
- int signo;
+ int signo;
{
- kill (inferior_pid, SIGINT);
+#ifndef _WIN32
+ kill (PIDGET (inferior_pid), SIGINT);
+#endif
}
-static void (*osig)();
+static void (*osig) ();
void
-set_sigint_trap()
+set_sigint_trap ()
{
- osig = (void (*) ()) signal (SIGINT, pass_signal);
+ if (attach_flag || inferior_thisrun_terminal)
+ {
+ osig = (void (*)()) signal (SIGINT, pass_signal);
+ }
}
void
-clear_sigint_trap()
+clear_sigint_trap ()
{
- signal (SIGINT, osig);
+ if (attach_flag || inferior_thisrun_terminal)
+ {
+ signal (SIGINT, osig);
+ }
}
\f
#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN)
numfds = select (target_activity_fd + 1, &readfds, NULL, NULL, NULL);
if (numfds >= 0 && FD_ISSET (target_activity_fd, &readfds))
{
+#ifndef _WIN32
if ((*target_activity_function) ())
kill (inferior_pid, SIGINT);
+#endif
}
}
{
if (target_activity_function)
{
- old_sigio = (void (*) ()) signal (SIGIO, handle_sigio);
- fcntl (target_activity_fd, F_SETOWN, getpid());
+ old_sigio = (void (*)()) signal (SIGIO, handle_sigio);
+ fcntl (target_activity_fd, F_SETOWN, getpid ());
old_fcntl_flags = fcntl (target_activity_fd, F_GETFL, 0);
fcntl (target_activity_fd, F_SETFL, old_fcntl_flags | FASYNC);
}
if (job_control)
{
-#if defined (NEED_POSIX_SETPGID) || defined (HAVE_TERMIOS)
- /* Do all systems with termios have setpgid? I hope so. */
+#if defined (NEED_POSIX_SETPGID) || (defined (HAVE_TERMIOS) && defined (HAVE_SETPGID))
/* setpgid (0, 0) is supposed to work and mean the same thing as
- this, but on Ultrix 4.2A it fails with EPERM (and
- setpgid (getpid (), getpid ()) succeeds). */
+ this, but on Ultrix 4.2A it fails with EPERM (and
+ setpgid (getpid (), getpid ()) succeeds). */
retval = setpgid (getpid (), getpid ());
#else
#if defined (TIOCGPGRP)
_initialize_inflow ()
{
add_info ("terminal", term_info,
- "Print inferior's saved terminal status.");
+ "Print inferior's saved terminal status.");
add_com ("kill", class_run, kill_command,
"Kill execution of program being debugged.");
#ifdef _POSIX_JOB_CONTROL
job_control = 1;
#else
+#ifdef _SC_JOB_CONTROL
job_control = sysconf (_SC_JOB_CONTROL);
-#endif
-#endif /* termios */
+#else
+ job_control = 0; /* have to assume the worst */
+#endif /* _SC_JOB_CONTROL */
+#endif /* _POSIX_JOB_CONTROL */
+#endif /* HAVE_TERMIOS */
#ifdef HAVE_SGTTY
#ifdef TIOCGPGRP