📄 trap.c
字号:
retval = trap_saved_exit_value; running_trap = 0; return retval; }#if defined (ARRAY_VARS) restore_pipestatus_array (ps);#endif return (trap_saved_exit_value);}voidrun_trap_cleanup (sig) int sig;{ sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);}/* Run a trap command for SIG. SIG is one of the signals the shell treats specially. Returns the exit status of the executed trap command list. */static int_run_trap_internal (sig, tag) int sig; char *tag;{ char *trap_command, *old_trap; int trap_exit_value, *token_state; int save_return_catch_flag, function_code, flags; procenv_t save_return_catch; WORD_LIST *save_subst_varlist;#if defined (ARRAY_VARS) ARRAY *ps;#endif trap_exit_value = function_code = 0; /* Run the trap only if SIG is trapped and not ignored, and we are not currently executing in the trap handler. */ if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) && (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) && ((sigmodes[sig] & SIG_INPROGRESS) == 0)) { old_trap = trap_list[sig]; sigmodes[sig] |= SIG_INPROGRESS; sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */ trap_command = savestring (old_trap); running_trap = sig + 1; trap_saved_exit_value = last_command_exit_value;#if defined (ARRAY_VARS) ps = save_pipestatus_array ();#endif token_state = save_token_state (); save_subst_varlist = subst_assign_varlist; subst_assign_varlist = 0; /* If we're in a function, make sure return longjmps come here, too. */ save_return_catch_flag = return_catch_flag; if (return_catch_flag) { COPY_PROCENV (return_catch, save_return_catch); function_code = setjmp (return_catch); } flags = SEVAL_NONINT|SEVAL_NOHIST; if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP) flags |= SEVAL_RESETLINE; if (function_code == 0) parse_and_execute (trap_command, tag, flags); restore_token_state (token_state); free (token_state); subst_assign_varlist = save_subst_varlist; trap_exit_value = last_command_exit_value; last_command_exit_value = trap_saved_exit_value;#if defined (ARRAY_VARS) restore_pipestatus_array (ps);#endif running_trap = 0; sigmodes[sig] &= ~SIG_INPROGRESS; if (sigmodes[sig] & SIG_CHANGED) {#if 0 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in the places where they can be changed using unwind-protects. For example, look at execute_cmd.c:execute_function(). */ if (SPECIAL_TRAP (sig) == 0)#endif free (old_trap); sigmodes[sig] &= ~SIG_CHANGED; } if (save_return_catch_flag) { return_catch_flag = save_return_catch_flag; return_catch_value = trap_exit_value; COPY_PROCENV (save_return_catch, return_catch); if (function_code) longjmp (return_catch, 1); } } return trap_exit_value;}intrun_debug_trap (){ int trap_exit_value; pid_t save_pgrp; int save_pipe[2]; /* XXX - question: should the DEBUG trap inherit the RETURN trap? */ trap_exit_value = 0; if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0)) {#if defined (JOB_CONTROL) save_pgrp = pipeline_pgrp; pipeline_pgrp = 0; save_pipeline (1);# if defined (PGRP_PIPE) save_pgrp_pipe (save_pipe, 1);# endif stop_making_children ();#endif trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");#if defined (JOB_CONTROL) pipeline_pgrp = save_pgrp; restore_pipeline (1);# if defined (PGRP_PIPE) close_pgrp_pipe (); restore_pgrp_pipe (save_pipe);# endif if (pipeline_pgrp > 0) give_terminal_to (pipeline_pgrp, 1); notify_and_cleanup ();#endif #if defined (DEBUGGER) /* If we're in the debugger and the DEBUG trap returns 2 while we're in a function or sourced script, we force a `return'. */ if (debugging_mode && trap_exit_value == 2 && return_catch_flag) { return_catch_value = trap_exit_value; longjmp (return_catch, 1); }#endif } return trap_exit_value;}voidrun_error_trap (){ if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0) _run_trap_internal (ERROR_TRAP, "error trap");}voidrun_return_trap (){ int old_exit_value;#if 0 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS)) return;#endif if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0) { old_exit_value = last_command_exit_value; _run_trap_internal (RETURN_TRAP, "return trap"); last_command_exit_value = old_exit_value; }}/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and declared here to localize the trap functions. */voidrun_interrupt_trap (){ _run_trap_internal (SIGINT, "interrupt trap");}/* Free all the allocated strings in the list of traps and reset the trap values to the default. Intended to be called from subshells that want to complete work done by reset_signal_handlers upon execution of a subsequent `trap' command that changes a signal's disposition. */voidfree_trap_strings (){ register int i; for (i = 0; i < BASH_NSIG; i++) free_trap_string (i); trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;}/* Free a trap command string associated with SIG without changing signal disposition. Intended to be called from free_trap_strings() */static voidfree_trap_string (sig) int sig;{ change_signal (sig, (char *)DEFAULT_SIG); sigmodes[sig] &= ~SIG_TRAPPED;}/* Reset the handler for SIG to the original value but leave the trap string in place. */static voidreset_signal (sig) int sig;{ set_signal_handler (sig, original_signals[sig]); sigmodes[sig] &= ~SIG_TRAPPED;}/* Set the handler signal SIG to the original and free any trap command associated with it. */static voidrestore_signal (sig) int sig;{ set_signal_handler (sig, original_signals[sig]); change_signal (sig, (char *)DEFAULT_SIG); sigmodes[sig] &= ~SIG_TRAPPED;}static voidreset_or_restore_signal_handlers (reset) sh_resetsig_func_t *reset;{ register int i; /* Take care of the exit trap first */ if (sigmodes[EXIT_TRAP] & SIG_TRAPPED) { sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED; if (reset != reset_signal) { free_trap_command (EXIT_TRAP); trap_list[EXIT_TRAP] = (char *)NULL; } } for (i = 1; i < NSIG; i++) { if (sigmodes[i] & SIG_TRAPPED) { if (trap_list[i] == (char *)IGNORE_SIG) set_signal_handler (i, SIG_IGN); else (*reset) (i); } else if (sigmodes[i] & SIG_SPECIAL) (*reset) (i); } /* Command substitution and other child processes don't inherit the debug, error, or return traps. If we're in the debugger, and the `functrace' or `errtrace' options have been set, then let command substitutions inherit them. Let command substitution inherit the RETURN trap if we're in the debugger and tracing functions. */ if (function_trace_mode == 0) { sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED; sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED; } if (error_trace_mode == 0) sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;}/* Reset trapped signals to their original values, but don't free the trap strings. Called by the command substitution code and other places that create a "subshell environment". */voidreset_signal_handlers (){ reset_or_restore_signal_handlers (reset_signal);}/* Reset all trapped signals to their original values. Signals set to be ignored with trap '' SIGNAL should be ignored, so we make sure that they are. Called by child processes after they are forked. */voidrestore_original_signals (){ reset_or_restore_signal_handlers (restore_signal);}/* If a trap handler exists for signal SIG, then call it; otherwise just return failure. */intmaybe_call_trap_handler (sig) int sig;{ /* Call the trap handler for SIG if the signal is trapped and not ignored. */ if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0)) { switch (sig) { case SIGINT: run_interrupt_trap (); break; case EXIT_TRAP: run_exit_trap (); break; case DEBUG_TRAP: run_debug_trap (); break; case ERROR_TRAP: run_error_trap (); break; default: trap_handler (sig); break; } return (1); } else return (0);}intsignal_is_trapped (sig) int sig;{ return (sigmodes[sig] & SIG_TRAPPED);}intsignal_is_special (sig) int sig;{ return (sigmodes[sig] & SIG_SPECIAL);}intsignal_is_ignored (sig) int sig;{ return (sigmodes[sig] & SIG_IGNORED);}intsignal_is_hard_ignored (sig) int sig;{ return (sigmodes[sig] & SIG_HARD_IGNORE);}voidset_signal_ignored (sig) int sig;{ sigmodes[sig] |= SIG_HARD_IGNORE; original_signals[sig] = SIG_IGN;}intsignal_in_progress (sig) int sig;{ return (sigmodes[sig] & SIG_INPROGRESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -