* inflow.c (pass_signal): Signal handlers take one int arg;

supply an unused one to make it type compatible as an arg to
	signal().
This commit is contained in:
Fred Fish 1993-08-05 01:33:45 +00:00
parent c2b781a26e
commit a88797b5ea
2 changed files with 219 additions and 268 deletions

View File

@ -1,3 +1,9 @@
Wed Aug 4 18:32:12 1993 Fred Fish (fnf@cygnus.com)
* inflow.c (pass_signal): Signal handlers take one int arg;
supply an unused one to make it type compatible as an arg to
signal().
Tue Aug 3 18:34:14 1993 Ian Lance Taylor (ian@cygnus.com) Tue Aug 3 18:34:14 1993 Ian Lance Taylor (ian@cygnus.com)
* config/mips/tm-mips.h: Include bfd.h before coff/sym.h. * config/mips/tm-mips.h: Include bfd.h before coff/sym.h.

View File

@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "inferior.h" #include "inferior.h"
#include "command.h" #include "command.h"
#include "signals.h" #include "signals.h"
#include "terminal.h" #include "serial.h"
#include "target.h" #include "target.h"
#ifdef USG #ifdef USG
@ -42,8 +42,6 @@ kill_command PARAMS ((char *, int));
static void static void
terminal_ours_1 PARAMS ((int)); terminal_ours_1 PARAMS ((int));
extern struct target_ops child_ops;
/* Nonzero if we are debugging an attached outside process /* Nonzero if we are debugging an attached outside process
rather than an inferior. */ rather than an inferior. */
@ -52,42 +50,28 @@ int attach_flag;
/* Record terminal status separately for debugger and inferior. */ /* Record terminal status separately for debugger and inferior. */
/* Does GDB have a terminal (on stdin)? */ static serial_t stdin_serial;
int gdb_has_a_terminal;
#if !defined(__GO32__) /* TTY state for the inferior. We save it whenever the inferior stops, and
static TERMINAL sg_inferior; restore it when it resumes. */
static TERMINAL sg_ours; static serial_ttystate inferior_ttystate;
#endif
/* Our own tty state, which we restore every time we need to deal with the
terminal. We only set it once, when GDB first starts. The settings of
flags which readline saves and restores and unimportant. */
static serial_ttystate our_ttystate;
/* fcntl flags for us and the inferior. Saved and restored just like
{our,inferior}_ttystate. */
static int tflags_inferior; static int tflags_inferior;
static int tflags_ours; static int tflags_ours;
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) /* While the inferior is running, we want SIGINT and SIGQUIT to go to the
static struct tchars tc_inferior; inferior only. If we have job control, that takes care of it. If not,
static struct tchars tc_ours; we save our handlers in these two variables and set SIGINT and SIGQUIT
#endif to SIG_IGN. */
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN)
static struct ltchars ltc_inferior;
static struct ltchars ltc_ours;
#endif
#ifdef TIOCLGET
static int lmode_inferior;
static int lmode_ours;
#endif
#ifdef TIOCGPGRP
# ifdef SHORT_PGRP
static short pgrp_inferior;
static short pgrp_ours;
# else /* not def SHORT_PGRP */
static int pgrp_inferior;
static int pgrp_ours;
# endif /* not def SHORT_PGRP */
#else /* not def TIOCGPGRP */
static void (*sigint_ours) (); static void (*sigint_ours) ();
static void (*sigquit_ours) (); static void (*sigquit_ours) ();
#endif /* TIOCGPGRP */
/* The name of the tty (from the `tty' command) that we gave to the inferior /* The name of the tty (from the `tty' command) that we gave to the inferior
when it was last started. */ when it was last started. */
@ -99,6 +83,38 @@ static char *inferior_thisrun_terminal;
static int terminal_is_ours; static int terminal_is_ours;
enum {yes, no, have_not_checked} gdb_has_a_terminal_flag = have_not_checked;
/* Does GDB have a terminal (on stdin)? */
int
gdb_has_a_terminal ()
{
switch (gdb_has_a_terminal_flag)
{
case yes:
return 1;
case no:
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. */
tflags_ours = fcntl (0, F_GETFL, 0);
gdb_has_a_terminal_flag = no;
stdin_serial = SERIAL_FDOPEN (0);
if (stdin_serial != NULL)
{
our_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
if (our_ttystate != NULL)
gdb_has_a_terminal_flag = yes;
}
return gdb_has_a_terminal_flag == yes;
}
}
/* Macro for printing errors from ioctl operations */ /* Macro for printing errors from ioctl operations */
#define OOPSY(what) \ #define OOPSY(what) \
@ -106,7 +122,7 @@ static int terminal_is_ours;
fprintf(stderr, "[%s failed in terminal_inferior: %s]\n", \ fprintf(stderr, "[%s failed in terminal_inferior: %s]\n", \
what, strerror (errno)) what, strerror (errno))
static void terminal_ours_1 (); static void terminal_ours_1 PARAMS ((int));
/* Initialize the terminal settings we record for the inferior, /* Initialize the terminal settings we record for the inferior,
before we actually run the inferior. */ before we actually run the inferior. */
@ -114,26 +130,19 @@ static void terminal_ours_1 ();
void void
terminal_init_inferior () terminal_init_inferior ()
{ {
#if !defined(__GO32__) /* Make sure that our_ttystate (etc) are initialized. */
sg_inferior = sg_ours; gdb_has_a_terminal ();
tflags_inferior = tflags_ours;
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) /* We could just as well copy our_ttystate (if we felt like adding
tc_inferior = tc_ours; a new function SERIAL_COPY_TTY_STATE). */
#endif if (inferior_ttystate)
free (inferior_ttystate);
inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
SERIAL_SET_PROCESS_GROUP (stdin_serial, inferior_ttystate, inferior_pid);
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) /* Make sure that next time we call terminal_inferior (which will be
ltc_inferior = ltc_ours; before the program runs, as it needs to be), we install the new
#endif process group. */
#ifdef TIOCLGET
lmode_inferior = lmode_ours;
#endif
#ifdef TIOCGPGRP
pgrp_inferior = inferior_pid;
#endif /* TIOCGPGRP */
#endif
terminal_is_ours = 1; terminal_is_ours = 1;
} }
@ -143,44 +152,44 @@ terminal_init_inferior ()
void void
terminal_inferior () terminal_inferior ()
{ {
#if !defined(__GO32__) if (gdb_has_a_terminal () && terminal_is_ours
int result; && inferior_thisrun_terminal == 0)
if (gdb_has_a_terminal && terminal_is_ours && inferior_thisrun_terminal == 0)
{ {
int result;
/* 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... */
result = fcntl (0, F_SETFL, tflags_inferior); result = fcntl (0, F_SETFL, tflags_inferior);
result = fcntl (0, F_SETFL, tflags_inferior); result = fcntl (0, F_SETFL, tflags_inferior);
OOPSY ("fcntl F_SETFL"); OOPSY ("fcntl F_SETFL");
result = ioctl (0, TIOCSETN, &sg_inferior);
OOPSY ("ioctl TIOCSETN");
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) /* Because we were careful to not change in or out of raw mode in
result = ioctl (0, TIOCSETC, &tc_inferior); terminal_ours, we will not change in our out of raw mode with
OOPSY ("ioctl TIOCSETC"); this call, so we don't flush any input. */
#endif result = SERIAL_SET_TTY_STATE (stdin_serial, inferior_ttystate);
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN)
result = ioctl (0, TIOCSLTC, &ltc_inferior);
OOPSY ("ioctl TIOCSLTC");
#endif
#ifdef TIOCLGET
result = ioctl (0, TIOCLSET, &lmode_inferior);
OOPSY ("ioctl TIOCLSET");
#endif
#ifdef TIOCGPGRP /* If attach_flag is set, we don't know whether we are sharing a
result = ioctl (0, TIOCSPGRP, &pgrp_inferior); terminal with the inferior or not. (attaching a process
/* If we attached to the process, we might or might not be sharing without a terminal is one case where we do not; attaching a
a terminal. Avoid printing error msg if we are unable to set our process which we ran from the same shell as GDB via `&' is
terminal's process group to his process group ID. */ one case where we do, I think (but perhaps this is not
if (!attach_flag) { `sharing' in the sense that we need to save and restore tty
OOPSY ("ioctl TIOCSPGRP"); 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
#else the saving and restoring of terminal state, but ignore errors
sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN); (which will occur, in tcsetpgrp, if we are not sharing a
sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN); terminal). */
#endif /* TIOCGPGRP */
if (!attach_flag)
OOPSY ("setting tty state");
if (!job_control)
{
sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN);
sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN);
}
} }
#endif
terminal_is_ours = 0; terminal_is_ours = 0;
} }
@ -208,86 +217,73 @@ terminal_ours ()
terminal_ours_1 (0); terminal_ours_1 (0);
} }
/* output_only is not used, and should not be used unless we introduce
separate terminal_is_ours and terminal_is_ours_for_output
flags. */
static void static void
terminal_ours_1 (output_only) terminal_ours_1 (output_only)
int output_only; int output_only;
{ {
#if !defined(__GO32__)
int result;
#ifdef TIOCGPGRP
/* Ignore this signal since it will happen when we try to set the pgrp. */
void (*osigttou) ();
#endif /* TIOCGPGRP */
/* Checking inferior_thisrun_terminal is necessary so that /* Checking inferior_thisrun_terminal is necessary so that
if GDB is running in the background, it won't block trying if GDB is running in the background, it won't block trying
to do the ioctl()'s below. Checking gdb_has_a_terminal to do the ioctl()'s below. Checking gdb_has_a_terminal
avoids attempting all the ioctl's when running in batch. */ avoids attempting all the ioctl's when running in batch. */
if (inferior_thisrun_terminal != 0 || gdb_has_a_terminal == 0) if (inferior_thisrun_terminal != 0 || gdb_has_a_terminal () == 0)
return; return;
if (!terminal_is_ours) if (!terminal_is_ours)
{ {
/* Ignore this signal since it will happen when we try to set the
pgrp. */
void (*osigttou) ();
int result;
terminal_is_ours = 1; terminal_is_ours = 1;
#ifdef TIOCGPGRP #ifdef SIGTTOU
osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN); if (job_control)
osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN);
#endif
result = ioctl (0, TIOCGPGRP, &pgrp_inferior); if (inferior_ttystate)
result = ioctl (0, TIOCSPGRP, &pgrp_ours); free (inferior_ttystate);
inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
signal (SIGTTOU, osigttou); /* Here we used to set ICANON in our ttystate, but I believe this
#else was an artifact from before when we used readline. Readline sets
signal (SIGINT, sigint_ours); the tty state when it needs to. */
signal (SIGQUIT, sigquit_ours);
#endif /* TIOCGPGRP */ /* 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.
*/
SERIAL_NOFLUSH_SET_TTY_STATE (stdin_serial, our_ttystate,
inferior_ttystate);
#ifdef SIGTTOU
if (job_control)
signal (SIGTTOU, osigttou);
#endif
if (!job_control)
{
signal (SIGINT, sigint_ours);
signal (SIGQUIT, sigquit_ours);
}
tflags_inferior = fcntl (0, F_GETFL, 0); tflags_inferior = fcntl (0, F_GETFL, 0);
result = ioctl (0, TIOCGETP, &sg_inferior);
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) /* Is there a reason this is being done twice? It happens both
result = ioctl (0, TIOCGETC, &tc_inferior); places we use F_SETFL, so I'm inclined to think perhaps there
#endif is some reason, however perverse. Perhaps not though... */
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) result = fcntl (0, F_SETFL, tflags_ours);
result = ioctl (0, TIOCGLTC, &ltc_inferior); result = fcntl (0, F_SETFL, tflags_ours);
#endif
#ifdef TIOCLGET result = result; /* lint */
result = ioctl (0, TIOCLGET, &lmode_inferior);
#endif
} }
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
if (output_only && !(sg_inferior.c_lflag & ICANON))
sg_ours.c_lflag &= ~ICANON;
#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
if (output_only)
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
#endif /* not HAVE_TERMIO */
result = fcntl (0, F_SETFL, tflags_ours);
result = fcntl (0, F_SETFL, tflags_ours);
result = ioctl (0, TIOCSETN, &sg_ours);
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
result = ioctl (0, TIOCSETC, &tc_ours);
#endif
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN)
result = ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
result = ioctl (0, TIOCLSET, &lmode_ours);
#endif
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
#endif /* not HAVE_TERMIO */
result = result; /* lint */
#endif
} }
/* ARGSUSED */ /* ARGSUSED */
@ -305,58 +301,65 @@ child_terminal_info (args, from_tty)
char *args; char *args;
int from_tty; int from_tty;
{ {
register int i; if (!gdb_has_a_terminal ())
{
printf_filtered ("This GDB does not control a terminal.\n");
return;
}
if (!gdb_has_a_terminal) {
printf_filtered ("This GDB does not control a terminal.\n");
return;
}
#if !defined(__GO32__)
#ifdef TIOCGPGRP
printf_filtered ("Inferior's terminal status (currently saved by GDB):\n"); printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
printf_filtered ("owner pgrp = %d, fcntl flags = 0x%x.\n", /* First the fcntl flags. */
pgrp_inferior, tflags_inferior); {
#endif /* TIOCGPGRP */ int flags;
flags = tflags_inferior;
#ifdef HAVE_TERMIO printf_filtered ("File descriptor flags = ");
printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n", #ifndef O_ACCMODE
sg_inferior.c_iflag, sg_inferior.c_oflag); #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", #endif
sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line); /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
printf_filtered ("c_cc: "); switch (flags & (O_ACCMODE))
for (i = 0; (i < NCC); i += 1) {
printf_filtered ("0x%x ", sg_inferior.c_cc[i]); case O_RDONLY: printf_filtered ("O_RDONLY"); break;
printf_filtered ("\n"); case O_WRONLY: printf_filtered ("O_WRONLY"); break;
case O_RDWR: printf_filtered ("O_RDWR"); break;
}
flags &= ~(O_ACCMODE);
#else /* not HAVE_TERMIO */ #ifdef O_NONBLOCK
if (flags & O_NONBLOCK)
printf_filtered ("sgttyb.sg_flags = 0x%x.\n", sg_inferior.sg_flags); printf_filtered (" | O_NONBLOCK");
flags &= ~O_NONBLOCK;
#endif /* not HAVE_TERMIO */ #endif
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) #if defined (O_NDELAY)
printf_filtered ("tchars: "); /* If O_NDELAY and O_NONBLOCK are defined to the same thing, we will
for (i = 0; i < (int)sizeof (struct tchars); i++) print it as O_NONBLOCK, which is good cause that is what POSIX
printf_filtered ("0x%x ", ((unsigned char *)&tc_inferior)[i]); has, and the flag will already be cleared by the time we get here. */
printf_filtered ("\n"); if (flags & O_NDELAY)
printf_filtered (" | O_NDELAY");
flags &= ~O_NDELAY;
#endif #endif
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) if (flags & O_APPEND)
printf_filtered ("ltchars: "); printf_filtered (" | O_APPEND");
for (i = 0; i < (int)sizeof (struct ltchars); i++) flags &= ~O_APPEND;
printf_filtered ("0x%x ", ((unsigned char *)&ltc_inferior)[i]);
printf_filtered ("\n"); #if defined (O_BINARY)
#endif if (flags & O_BINARY)
printf_filtered (" | O_BINARY");
#ifdef TIOCLGET flags &= ~O_BINARY;
printf_filtered ("lmode: 0x%x\n", lmode_inferior);
#endif
#else
printf_filtered("This is a DOS machine; there is no terminal state\n");
#endif #endif
if (flags)
printf_filtered (" | 0x%x", flags);
printf_filtered ("\n");
}
SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate);
} }
/* NEW_TTY_PREFORK is called before forking a new child process, /* NEW_TTY_PREFORK is called before forking a new child process,
@ -396,7 +399,7 @@ new_tty ()
osigttou = (void (*)()) signal(SIGTTOU, SIG_IGN); osigttou = (void (*)()) signal(SIGTTOU, SIG_IGN);
ioctl(tty, TIOCNOTTY, 0); ioctl(tty, TIOCNOTTY, 0);
close(tty); close(tty);
(void) signal(SIGTTOU, osigttou); signal(SIGTTOU, osigttou);
} }
#endif #endif
@ -422,7 +425,7 @@ new_tty ()
{ close (2); dup (tty); } { close (2); dup (tty); }
if (tty > 2) if (tty > 2)
close(tty); close(tty);
#endif /* !go32*/o #endif /* !go32 */
} }
/* Kill the inferior process. Make us have no inferior. */ /* Kill the inferior process. Make us have no inferior. */
@ -433,9 +436,10 @@ kill_command (arg, from_tty)
char *arg; char *arg;
int from_tty; int from_tty;
{ {
/* Shouldn't this be target_has_execution? FIXME. */
if (inferior_pid == 0) if (inferior_pid == 0)
error ("The program is not being run."); error ("The program is not being run.");
if (!query ("Kill the inferior process? ")) if (!query ("Kill the program being debugged? "))
error ("Not confirmed."); error ("Not confirmed.");
target_kill (); target_kill ();
@ -478,101 +482,42 @@ generic_mourn_inferior ()
from previous runs of the inferior. So clear them. */ from previous runs of the inferior. So clear them. */
breakpoint_clear_ignore_counts (); breakpoint_clear_ignore_counts ();
} }
void
child_mourn_inferior ()
{
unpush_target (&child_ops);
generic_mourn_inferior ();
}
#if 0 /* Call set_sigint_trap when you need to pass a signal on to an attached
/* This function is just for testing, and on some systems (Sony NewsOS process when handling SIGINT */
3.2) <sys/user.h> also includes <sys/time.h> which leads to errors
(since on this system at least sys/time.h is not protected against
multiple inclusion). */
/* ARGSUSED */ /* ARGSUSED */
static void static void
try_writing_regs_command (arg, from_tty) pass_signal (signo)
char *arg; int signo;
int from_tty;
{ {
register int i; kill (inferior_pid, SIGINT);
register int value; }
if (inferior_pid == 0) static void (*osig)();
error ("There is no inferior process now.");
void
/* A Sun 3/50 or 3/60 (at least) running SunOS 4.0.3 will have a set_sigint_trap()
kernel panic if we try to write past the end of the user area. {
Presumably Sun will fix this bug (it has been reported), but it osig = (void (*) ()) signal (SIGINT, pass_signal);
is tacky to crash the system, so at least on SunOS4 we need to }
stop writing when we hit the end of the user area. */
for (i = 0; i < sizeof (struct user); i += 2) void
{ clear_sigint_trap()
QUIT; {
errno = 0; signal (SIGINT, osig);
value = call_ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) i, 0);
call_ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) i, value);
if (errno == 0)
{
printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
i, value, value);
}
else if ((i & 0377) == 0)
printf (" Failed at 0x%x.\n", i);
}
} }
#endif
void void
_initialize_inflow () _initialize_inflow ()
{ {
int result;
add_info ("terminal", term_info, add_info ("terminal", term_info,
"Print inferior's saved terminal status."); "Print inferior's saved terminal status.");
#if 0
add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
"Try writing all locations in inferior's system block.\n\
Report which ones can be written.");
#endif
add_com ("kill", class_run, kill_command, add_com ("kill", class_run, kill_command,
"Kill execution of program being debugged."); "Kill execution of program being debugged.");
inferior_pid = 0; inferior_pid = 0;
/* Get all the current tty settings (including whether we have a tty at
all!). */
#if !defined(__GO32__)
tflags_ours = fcntl (0, F_GETFL, 0);
result = ioctl (0, TIOCGETP, &sg_ours);
if (result == 0) {
gdb_has_a_terminal = 1;
/* Get the rest of the tty settings, then... */
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCGETC, &tc_ours);
#endif
#if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN)
ioctl (0, TIOCGLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_ours);
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCGPGRP, &pgrp_ours);
#endif /* TIOCGPGRP */
} else {
gdb_has_a_terminal = 0;
}
#else
gdb_has_a_terminal = 0;
#endif
terminal_is_ours = 1; terminal_is_ours = 1;
} }