⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trap.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 3 页
字号:
/* trap.c -- Not the trap command, but useful functions for manipulating   those objects.  The trap command is in builtins/trap.def. *//* Copyright (C) 1987-2010 Free Software Foundation, Inc.   This file is part of GNU Bash, the Bourne Again SHell.   Bash 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 3 of the License, or   (at your option) any later version.   Bash 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 Bash.  If not, see <http://www.gnu.org/licenses/>.*/#include "config.h"#if defined (HAVE_UNISTD_H)#  include <unistd.h>#endif#include "bashtypes.h"#include "bashansi.h"#include <stdio.h>#include <errno.h>#include "bashintl.h"#include "trap.h"#include "shell.h"#include "flags.h"#include "input.h"	/* for save_token_state, restore_token_state */#include "jobs.h"#include "signames.h"#include "builtins.h"#include "builtins/common.h"#include "builtins/builtext.h"#ifndef errnoextern int errno;#endif/* Flags which describe the current handling state of a signal. */#define SIG_INHERITED   0x0	/* Value inherited from parent. */#define SIG_TRAPPED     0x1	/* Currently trapped. */#define SIG_HARD_IGNORE 0x2	/* Signal was ignored on shell entry. */#define SIG_SPECIAL     0x4	/* Treat this signal specially. */#define SIG_NO_TRAP     0x8	/* Signal cannot be trapped. */#define SIG_INPROGRESS	0x10	/* Signal handler currently executing. */#define SIG_CHANGED	0x20	/* Trap value changed in trap handler. */#define SIG_IGNORED	0x40	/* The signal is currently being ignored. */#define SPECIAL_TRAP(s)	((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)/* An array of such flags, one for each signal, describing what the   shell will do with a signal.  DEBUG_TRAP == NSIG; some code below   assumes this. */static int sigmodes[BASH_NSIG];static void free_trap_command __P((int));static void change_signal __P((int, char *));static void get_original_signal __P((int));static int _run_trap_internal __P((int, char *));static void free_trap_string __P((int));static void reset_signal __P((int));static void restore_signal __P((int));static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));/* Variables used here but defined in other files. */extern int last_command_exit_value;extern int line_number;extern char *this_command_name;extern sh_builtin_func_t *this_shell_builtin;extern procenv_t wait_intr_buf;extern int return_catch_flag, return_catch_value;extern int subshell_level;extern WORD_LIST *subst_assign_varlist;/* The list of things to do originally, before we started trapping. */SigHandler *original_signals[NSIG];/* For each signal, a slot for a string, which is a command to be   executed when that signal is recieved.  The slot can also contain   DEFAULT_SIG, which means do whatever you were going to do before   you were so rudely interrupted, or IGNORE_SIG, which says ignore   this signal. */char *trap_list[BASH_NSIG];/* A bitmap of signals received for which we have trap handlers. */int pending_traps[NSIG];/* Set to the number of the signal we're running the trap for + 1.   Used in execute_cmd.c and builtins/common.c to clean up when   parse_and_execute does not return normally after executing the   trap command (e.g., when `return' is executed in the trap command). */int running_trap;/* Set to last_command_exit_value before running a trap. */int trap_saved_exit_value;/* The (trapped) signal received while executing in the `wait' builtin */int wait_signal_received;#define GETORIGSIG(sig) \  do { \    original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \    set_signal_handler (sig, original_signals[sig]); \    if (original_signals[sig] == SIG_IGN) \      sigmodes[sig] |= SIG_HARD_IGNORE; \  } while (0)#define SETORIGSIG(sig,handler) \  do { \    original_signals[sig] = handler; \    if (original_signals[sig] == SIG_IGN) \      sigmodes[sig] |= SIG_HARD_IGNORE; \  } while (0)#define GET_ORIGINAL_SIGNAL(sig) \  if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \    GETORIGSIG(sig)voidinitialize_traps (){  register int i;  initialize_signames();  trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;  sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;  original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;  for (i = 1; i < NSIG; i++)    {      pending_traps[i] = 0;      trap_list[i] = (char *)DEFAULT_SIG;      sigmodes[i] = SIG_INHERITED;	/* XXX - only set, not used */      original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;    }  /* Show which signals are treated specially by the shell. */#if defined (SIGCHLD)  GETORIGSIG (SIGCHLD);  sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);#endif /* SIGCHLD */  GETORIGSIG (SIGINT);  sigmodes[SIGINT] |= SIG_SPECIAL;#if defined (__BEOS__)  /* BeOS sets SIGINT to SIG_IGN! */  original_signals[SIGINT] = SIG_DFL;  sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;#endif  GETORIGSIG (SIGQUIT);  sigmodes[SIGQUIT] |= SIG_SPECIAL;  if (interactive)    {      GETORIGSIG (SIGTERM);      sigmodes[SIGTERM] |= SIG_SPECIAL;    }}#ifdef INCLUDE_UNUSED/* Return a printable representation of the trap handler for SIG. */static char *trap_handler_string (sig)     int sig;{  if (trap_list[sig] == (char *)DEFAULT_SIG)    return "DEFAULT_SIG";  else if (trap_list[sig] == (char *)IGNORE_SIG)    return "IGNORE_SIG";  else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)    return "IMPOSSIBLE_TRAP_HANDLER";  else if (trap_list[sig])    return trap_list[sig];  else    return "NULL";}#endif/* Return the print name of this signal. */char *signal_name (sig)     int sig;{  char *ret;  /* on cygwin32, signal_names[sig] could be null */  ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)	? _("invalid signal number")	: signal_names[sig];  return ret;}/* Turn a string into a signal number, or a number into   a signal number.  If STRING is "2", "SIGINT", or "INT",   then (int)2 is returned.  Return NO_SIG if STRING doesn't   contain a valid signal descriptor. */intdecode_signal (string, flags)     char *string;     int flags;{  intmax_t sig;  char *name;  if (legal_number (string, &sig))    return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);  /* A leading `SIG' may be omitted. */  for (sig = 0; sig < BASH_NSIG; sig++)    {      name = signal_names[sig];      if (name == 0 || name[0] == '\0')	continue;      /* Check name without the SIG prefix first case sensitivly or	 insensitively depending on whether flags includes DSIG_NOCASE */      if (STREQN (name, "SIG", 3))	{	  name += 3;	  if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)	    return ((int)sig);	  else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)	    return ((int)sig);	  /* If we can't use the `SIG' prefix to match, punt on this	     name now. */	  else if ((flags & DSIG_SIGPREFIX) == 0)	    continue;	}      /* Check name with SIG prefix case sensitively or insensitively	 depending on whether flags includes DSIG_NOCASE */      name = signal_names[sig];      if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)	return ((int)sig);      else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)	return ((int)sig);    }  return (NO_SIG);}/* Non-zero when we catch a trapped signal. */static int catch_flag;voidrun_pending_traps (){  register int sig;  int old_exit_value, *token_state;  WORD_LIST *save_subst_varlist;#if defined (ARRAY_VARS)  ARRAY *ps;#endif  if (catch_flag == 0)		/* simple optimization */    return;  catch_flag = 0;  /* Preserve $? when running trap. */  old_exit_value = last_command_exit_value;#if defined (ARRAY_VARS)  ps = save_pipestatus_array ();#endif  for (sig = 1; sig < NSIG; sig++)    {      /* XXX this could be made into a counter by using	 while (pending_traps[sig]--) instead of the if statement. */      if (pending_traps[sig])	{#if defined (HAVE_POSIX_SIGNALS)	  sigset_t set, oset;	  sigemptyset (&set);	  sigemptyset (&oset);	  sigaddset (&set, sig);	  sigprocmask (SIG_BLOCK, &set, &oset);#else#  if defined (HAVE_BSD_SIGNALS)	  int oldmask = sigblock (sigmask (sig));#  endif#endif /* HAVE_POSIX_SIGNALS */	  if (sig == SIGINT)	    {	      run_interrupt_trap ();	      CLRINTERRUPT;	    }#if defined (JOB_CONTROL) && defined (SIGCHLD)	  else if (sig == SIGCHLD &&		   trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&		   (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)	    {	      run_sigchld_trap (pending_traps[sig]);	/* use as counter */	    }#endif	  else if (trap_list[sig] == (char *)DEFAULT_SIG ||		   trap_list[sig] == (char *)IGNORE_SIG ||		   trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)	    {	      /* This is possible due to a race condition.  Say a bash		 process has SIGTERM trapped.  A subshell is spawned		 using { list; } & and the parent does something and kills		 the subshell with SIGTERM.  It's possible for the subshell		 to set pending_traps[SIGTERM] to 1 before the code in		 execute_cmd.c eventually calls restore_original_signals		 to reset the SIGTERM signal handler in the subshell.  The		 next time run_pending_traps is called, pending_traps[SIGTERM]		 will be 1, but the trap handler in trap_list[SIGTERM] will		 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).		 Unless we catch this, the subshell will dump core when		 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is		 usually 0x0. */	      internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),				sig, trap_list[sig]);	      if (trap_list[sig] == (char *)DEFAULT_SIG)		{		  internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));		  kill (getpid (), sig);		}	    }	  else	    {	      token_state = save_token_state ();	      save_subst_varlist = subst_assign_varlist;	      subst_assign_varlist = 0;	      parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);	      restore_token_state (token_state);	      free (token_state);	      subst_assign_varlist = save_subst_varlist;	    }	  pending_traps[sig] = 0;#if defined (HAVE_POSIX_SIGNALS)	  sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);#else#  if defined (HAVE_BSD_SIGNALS)	  sigsetmask (oldmask);#  endif#endif /* POSIX_VERSION */	}    }#if defined (ARRAY_VARS)  restore_pipestatus_array (ps);#endif  last_command_exit_value = old_exit_value;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -