📄 trap.c
字号:
sighandlertrap_handler (sig) int sig;{ int oerrno; if ((sigmodes[sig] & SIG_TRAPPED) == 0) {#if defined (DEBUG) internal_warning ("trap_handler: signal %d: signal not trapped", sig);#endif SIGRETURN (0); } if ((sig >= NSIG) || (trap_list[sig] == (char *)DEFAULT_SIG) || (trap_list[sig] == (char *)IGNORE_SIG)) programming_error (_("trap_handler: bad signal %d"), sig); else { oerrno = errno;#if defined (MUST_REINSTALL_SIGHANDLERS)# if defined (JOB_CONTROL) && defined (SIGCHLD) if (sig != SIGCHLD)# endif /* JOB_CONTROL && SIGCHLD */ set_signal_handler (sig, trap_handler);#endif /* MUST_REINSTALL_SIGHANDLERS */ catch_flag = 1; pending_traps[sig]++; if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin)) { wait_signal_received = sig; longjmp (wait_intr_buf, 1); } if (interrupt_immediately) run_pending_traps (); errno = oerrno; } SIGRETURN (0);}#if defined (JOB_CONTROL) && defined (SIGCHLD)#ifdef INCLUDE_UNUSED/* Make COMMAND_STRING be executed when SIGCHLD is caught. */voidset_sigchld_trap (command_string) char *command_string;{ set_signal (SIGCHLD, command_string);}#endif/* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel to make sure that a SIGCHLD trap handler run via run_sigchld_trap can reset the disposition to the default and not have the original signal accidentally restored, undoing the user's command. */voidmaybe_set_sigchld_trap (command_string) char *command_string;{ if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER) set_signal (SIGCHLD, command_string);}/* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */voidset_impossible_sigchld_trap (){ restore_default_signal (SIGCHLD); change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER); sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */}#endif /* JOB_CONTROL && SIGCHLD */voidset_debug_trap (command) char *command;{ set_signal (DEBUG_TRAP, command);}voidset_error_trap (command) char *command;{ set_signal (ERROR_TRAP, command);}voidset_return_trap (command) char *command;{ set_signal (RETURN_TRAP, command);}#ifdef INCLUDE_UNUSEDvoidset_sigint_trap (command) char *command;{ set_signal (SIGINT, command);}#endif/* Reset the SIGINT handler so that subshells that are doing `shellsy' things, like waiting for command substitution or executing commands in explicit subshells ( ( cmd ) ), can catch interrupts properly. */SigHandler *set_sigint_handler (){ if (sigmodes[SIGINT] & SIG_HARD_IGNORE) return ((SigHandler *)SIG_IGN); else if (sigmodes[SIGINT] & SIG_IGNORED) return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */ else if (sigmodes[SIGINT] & SIG_TRAPPED) return ((SigHandler *)set_signal_handler (SIGINT, trap_handler)); /* The signal is not trapped, so set the handler to the shell's special interrupt handler. */ else if (interactive) /* XXX - was interactive_shell */ return (set_signal_handler (SIGINT, sigint_sighandler)); else return (set_signal_handler (SIGINT, termsig_sighandler));}/* Return the correct handler for signal SIG according to the values in sigmodes[SIG]. */SigHandler *trap_to_sighandler (sig) int sig;{ if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE)) return (SIG_IGN); else if (sigmodes[sig] & SIG_TRAPPED) return (trap_handler); else return (SIG_DFL);}/* Set SIG to call STRING as a command. */voidset_signal (sig, string) int sig; char *string;{ if (SPECIAL_TRAP (sig)) { change_signal (sig, savestring (string)); if (sig == EXIT_TRAP && interactive == 0) initialize_terminating_signals (); return; } /* A signal ignored on entry to the shell cannot be trapped or reset, but no error is reported when attempting to do so. -- Posix.2 */ if (sigmodes[sig] & SIG_HARD_IGNORE) return; /* Make sure we have original_signals[sig] if the signal has not yet been trapped. */ if ((sigmodes[sig] & SIG_TRAPPED) == 0) { /* If we aren't sure of the original value, check it. */ if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) GETORIGSIG (sig); if (original_signals[sig] == SIG_IGN) return; } /* Only change the system signal handler if SIG_NO_TRAP is not set. The trap command string is changed in either case. The shell signal handlers for SIGINT and SIGCHLD run the user specified traps in an environment in which it is safe to do so. */ if ((sigmodes[sig] & SIG_NO_TRAP) == 0) { set_signal_handler (sig, SIG_IGN); change_signal (sig, savestring (string)); set_signal_handler (sig, trap_handler); } else change_signal (sig, savestring (string));}static voidfree_trap_command (sig) int sig;{ if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] && (trap_list[sig] != (char *)IGNORE_SIG) && (trap_list[sig] != (char *)DEFAULT_SIG) && (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER)) free (trap_list[sig]);}/* If SIG has a string assigned to it, get rid of it. Then give it VALUE. */static voidchange_signal (sig, value) int sig; char *value;{ if ((sigmodes[sig] & SIG_INPROGRESS) == 0) free_trap_command (sig); trap_list[sig] = value; sigmodes[sig] |= SIG_TRAPPED; if (value == (char *)IGNORE_SIG) sigmodes[sig] |= SIG_IGNORED; else sigmodes[sig] &= ~SIG_IGNORED; if (sigmodes[sig] & SIG_INPROGRESS) sigmodes[sig] |= SIG_CHANGED;}static voidget_original_signal (sig) int sig;{ /* If we aren't sure the of the original value, then get it. */ if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER) GETORIGSIG (sig);}voidget_all_original_signals (){ register int i; for (i = 1; i < NSIG; i++) GET_ORIGINAL_SIGNAL (i);}voidset_original_signal (sig, handler) int sig; SigHandler *handler;{ if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER) SETORIGSIG (sig, handler);}/* Restore the default action for SIG; i.e., the action the shell would have taken before you used the trap command. This is called from trap_builtin (), which takes care to restore the handlers for the signals the shell treats specially. */voidrestore_default_signal (sig) int sig;{ if (SPECIAL_TRAP (sig)) { if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) || (sigmodes[sig] & SIG_INPROGRESS) == 0) free_trap_command (sig); trap_list[sig] = (char *)NULL; sigmodes[sig] &= ~SIG_TRAPPED; if (sigmodes[sig] & SIG_INPROGRESS) sigmodes[sig] |= SIG_CHANGED; return; } GET_ORIGINAL_SIGNAL (sig); /* A signal ignored on entry to the shell cannot be trapped or reset, but no error is reported when attempting to do so. Thanks Posix.2. */ if (sigmodes[sig] & SIG_HARD_IGNORE) return; /* If we aren't trapping this signal, don't bother doing anything else. */ if ((sigmodes[sig] & SIG_TRAPPED) == 0) return; /* Only change the signal handler for SIG if it allows it. */ if ((sigmodes[sig] & SIG_NO_TRAP) == 0) set_signal_handler (sig, original_signals[sig]); /* Change the trap command in either case. */ change_signal (sig, (char *)DEFAULT_SIG); /* Mark the signal as no longer trapped. */ sigmodes[sig] &= ~SIG_TRAPPED;}/* Make this signal be ignored. */voidignore_signal (sig) int sig;{ if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0)) { change_signal (sig, (char *)IGNORE_SIG); return; } GET_ORIGINAL_SIGNAL (sig); /* A signal ignored on entry to the shell cannot be trapped or reset. No error is reported when the user attempts to do so. */ if (sigmodes[sig] & SIG_HARD_IGNORE) return; /* If already trapped and ignored, no change necessary. */ if (sigmodes[sig] & SIG_IGNORED) return; /* Only change the signal handler for SIG if it allows it. */ if ((sigmodes[sig] & SIG_NO_TRAP) == 0) set_signal_handler (sig, SIG_IGN); /* Change the trap command in either case. */ change_signal (sig, (char *)IGNORE_SIG);}/* Handle the calling of "trap 0". The only sticky situation is when the command to be executed includes an "exit". This is why we have to provide our own place for top_level to jump to. */intrun_exit_trap (){ char *trap_command; int code, function_code, retval;#if defined (ARRAY_VARS) ARRAY *ps;#endif trap_saved_exit_value = last_command_exit_value;#if defined (ARRAY_VARS) ps = save_pipestatus_array ();#endif function_code = 0; /* Run the trap only if signal 0 is trapped and not ignored, and we are not currently running in the trap handler (call to exit in the list of commands given to trap 0). */ if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) && (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0) { trap_command = savestring (trap_list[EXIT_TRAP]); sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED; sigmodes[EXIT_TRAP] |= SIG_INPROGRESS; retval = trap_saved_exit_value; running_trap = 1; code = setjmp (top_level); /* If we're in a function, make sure return longjmps come here, too. */ if (return_catch_flag) function_code = setjmp (return_catch); if (code == 0 && function_code == 0) { reset_parser (); parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE); } else if (code == ERREXIT) retval = last_command_exit_value; else if (code == EXITPROG) retval = last_command_exit_value; else if (function_code != 0) retval = return_catch_value; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -