📄 nojobs.c
字号:
char *command; int async_p;{ pid_t pid; int forksleep; /* Discard saved memory. */ if (command) free (command); start_pipeline ();#if defined (BUFFERED_INPUT) /* If default_buffered_input is active, we are reading a script. If the command is asynchronous, we have already duplicated /dev/null as fd 0, but have not changed the buffered stream corresponding to the old fd 0. We don't want to sync the stream in this case. */ if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0)) sync_buffered_stream (default_buffered_input);#endif /* BUFFERED_INPUT */ /* Create the child, handle severe errors. Retry on EAGAIN. */ forksleep = 1; while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX) { sys_error ("fork: retry");#if defined (HAVE_WAITPID) /* Posix systems with a non-blocking waitpid () system call available get another chance after zombies are reaped. */ reap_zombie_children (); if (forksleep > 1 && sleep (forksleep) != 0) break;#else if (sleep (forksleep) != 0) break;#endif /* HAVE_WAITPID */ forksleep <<= 1; } if (pid < 0) { sys_error ("fork"); throw_to_top_level (); } if (pid == 0) {#if defined (BUFFERED_INPUT) unset_bash_input (0);#endif /* BUFFERED_INPUT */#if defined (HAVE_POSIX_SIGNALS) /* Restore top-level signal mask. */ sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);#endif#if 0 /* Ignore INT and QUIT in asynchronous children. */ if (async_p) last_asynchronous_pid = getpid ();#endif default_tty_job_signals (); } else { /* In the parent. */ last_made_pid = pid; if (async_p) last_asynchronous_pid = pid; add_pid (pid, async_p); } return (pid);}voidignore_tty_job_signals (){#if defined (SIGTSTP) set_signal_handler (SIGTSTP, SIG_IGN); set_signal_handler (SIGTTIN, SIG_IGN); set_signal_handler (SIGTTOU, SIG_IGN);#endif}voiddefault_tty_job_signals (){#if defined (SIGTSTP) set_signal_handler (SIGTSTP, SIG_DFL); set_signal_handler (SIGTTIN, SIG_DFL); set_signal_handler (SIGTTOU, SIG_DFL);#endif}/* Wait for a single pid (PID) and return its exit status. Called by the wait builtin. */intwait_for_single_pid (pid) pid_t pid;{ pid_t got_pid; WAIT status; int pstatus, flags; pstatus = find_status_by_pid (pid); if (pstatus == PROC_BAD) { internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid); return (127); } if (pstatus != PROC_STILL_ALIVE) { if (pstatus > 128) last_command_exit_signal = find_termsig_by_pid (pid); return (pstatus); } siginterrupt (SIGINT, 1); while ((got_pid = WAITPID (pid, &status, 0)) != pid) { CHECK_TERMSIG; if (got_pid < 0) { if (errno != EINTR && errno != ECHILD) { siginterrupt (SIGINT, 0); sys_error ("wait"); } break; } else if (got_pid > 0) set_pid_status (got_pid, status); } if (got_pid > 0) { set_pid_status (got_pid, status); set_pid_flags (got_pid, PROC_NOTIFIED); } siginterrupt (SIGINT, 0); QUIT; return (got_pid > 0 ? process_exit_status (status) : -1);}/* Wait for all of the shell's children to exit. Called by the `wait' builtin. */voidwait_for_background_pids (){ pid_t got_pid; WAIT status; /* If we aren't using job control, we let the kernel take care of the bookkeeping for us. wait () will return -1 and set errno to ECHILD when there are no more unwaited-for child processes on both 4.2 BSD-based and System V-based systems. */ siginterrupt (SIGINT, 1); /* Wait for ECHILD */ while ((got_pid = WAITPID (-1, &status, 0)) != -1) set_pid_status (got_pid, status); if (errno != EINTR && errno != ECHILD) { siginterrupt (SIGINT, 0); sys_error("wait"); } siginterrupt (SIGINT, 0); QUIT; mark_dead_jobs_as_notified (1); cleanup_dead_jobs ();}/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pidsstatic SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;static voidrestore_sigint_handler (){ if (old_sigint_handler != INVALID_SIGNAL_HANDLER) { set_signal_handler (SIGINT, old_sigint_handler); old_sigint_handler = INVALID_SIGNAL_HANDLER; }}/* Handle SIGINT while we are waiting for children in a script to exit. All interrupts are effectively ignored by the shell, but allowed to kill a running job. */static sighandlerwait_sigint_handler (sig) int sig;{ SigHandler *sigint_handler; /* If we got a SIGINT while in `wait', and SIGINT is trapped, do what POSIX.2 says (see builtins/wait.def for more info). */ if (this_shell_builtin && this_shell_builtin == wait_builtin && signal_is_trapped (SIGINT) && ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler)) { last_command_exit_value = EXECUTION_FAILURE; restore_sigint_handler (); interrupt_immediately = 0; trap_handler (SIGINT); /* set pending_traps[SIGINT] */ wait_signal_received = SIGINT; longjmp (wait_intr_buf, 1); } if (interrupt_immediately) { last_command_exit_value = EXECUTION_FAILURE; restore_sigint_handler (); ADDINTERRUPT; QUIT; } wait_sigint_received = 1; SIGRETURN (0);}static char *j_strsignal (s) int s;{ static char retcode_name_buffer[64] = { '\0' }; char *x; x = strsignal (s); if (x == 0) { x = retcode_name_buffer; sprintf (x, "Signal %d", s); } return x;}/* Wait for pid (one of our children) to terminate. This is called only by the execution code in execute_cmd.c. */intwait_for (pid) pid_t pid;{ int return_val, pstatus; pid_t got_pid; WAIT status; pstatus = find_status_by_pid (pid); if (pstatus == PROC_BAD) return (0); if (pstatus != PROC_STILL_ALIVE) { if (pstatus > 128) last_command_exit_signal = find_termsig_by_pid (pid); return (pstatus); } /* If we are running a script, ignore SIGINT while we're waiting for a child to exit. The loop below does some of this, but not all. */ wait_sigint_received = 0; if (interactive_shell == 0) old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler); while ((got_pid = WAITPID (-1, &status, 0)) != pid) /* XXX was pid now -1 */ { CHECK_TERMSIG; if (got_pid < 0 && errno == ECHILD) {#if !defined (_POSIX_VERSION) status.w_termsig = status.w_retcode = 0;#else status = 0;#endif /* _POSIX_VERSION */ break; } else if (got_pid < 0 && errno != EINTR) programming_error ("wait_for(%ld): %s", (long)pid, strerror(errno)); else if (got_pid > 0) set_pid_status (got_pid, status); } if (got_pid > 0) set_pid_status (got_pid, status);#if defined (HAVE_WAITPID) if (got_pid >= 0) reap_zombie_children ();#endif /* HAVE_WAITPID */ if (interactive_shell == 0) { SigHandler *temp_handler; temp_handler = old_sigint_handler; restore_sigint_handler (); /* If the job exited because of SIGINT, make sure the shell acts as if it had received one also. */ if (WIFSIGNALED (status) && (WTERMSIG (status) == SIGINT)) { if (maybe_call_trap_handler (SIGINT) == 0) { if (temp_handler == SIG_DFL) termsig_handler (SIGINT); else if (temp_handler != INVALID_SIGNAL_HANDLER && temp_handler != SIG_IGN) (*temp_handler) (SIGINT); } } } /* Default return value. */ /* ``a full 8 bits of status is returned'' */ return_val = process_exit_status (status); last_command_exit_signal = get_termsig (status);#if !defined (DONT_REPORT_SIGPIPE) if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) && (WTERMSIG (status) != SIGINT))#else if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) && (WTERMSIG (status) != SIGINT) && (WTERMSIG (status) != SIGPIPE))#endif { fprintf (stderr, "%s", j_strsignal (WTERMSIG (status))); if (WIFCORED (status)) fprintf (stderr, _(" (core dumped)")); fprintf (stderr, "\n"); } if (interactive_shell && subshell_environment == 0) { if (WIFSIGNALED (status) || WIFSTOPPED (status)) set_tty_state (); else get_tty_state (); } return (return_val);}/* Send PID SIGNAL. Returns -1 on failure, 0 on success. If GROUP is non-zero, or PID is less than -1, then kill the process group associated with PID. */intkill_pid (pid, signal, group) pid_t pid; int signal, group;{ int result; if (pid < -1) { pid = -pid; group = 1; } result = group ? killpg (pid, signal) : kill (pid, signal); return (result);}static TTYSTRUCT shell_tty_info;static int got_tty_state;/* Fill the contents of shell_tty_info with the current tty info. */get_tty_state (){ int tty; tty = input_tty (); if (tty != -1) { ttgetattr (tty, &shell_tty_info); got_tty_state = 1; if (check_window_size) get_new_window_size (0, (int *)0, (int *)0); }}/* Make the current tty use the state in shell_tty_info. */intset_tty_state (){ int tty; tty = input_tty (); if (tty != -1) { if (got_tty_state == 0) return 0; ttsetattr (tty, &shell_tty_info); } return 0;}/* Give the terminal to PGRP. */give_terminal_to (pgrp, force) pid_t pgrp; int force;{}/* Stop a pipeline. */intstop_pipeline (async, ignore) int async; COMMAND *ignore;{ already_making_children = 0; return 0;}voidstart_pipeline (){ already_making_children = 1;}voidstop_making_children (){ already_making_children = 0;}intget_job_by_pid (pid, block) pid_t pid; int block;{ int i; i = find_index_by_pid (pid); return ((i == NO_PID) ? PROC_BAD : i);}/* Print descriptive information about the job with leader pid PID. */voiddescribe_pid (pid) pid_t pid;{ fprintf (stderr, "%ld\n", (long) pid);}voidfreeze_jobs_list (){}voidunfreeze_jobs_list (){}intcount_all_jobs (){ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -