diff options
author | Chet Ramey <chet.ramey@case.edu> | 2011-11-28 14:41:26 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2011-11-28 14:41:26 -0500 |
commit | d3a24ed242e91e6afb53b2cbf38b89667637168d (patch) | |
tree | b67e38d2eca8abd31da74e1dcbe69dd1bfa679a3 /jobs.c | |
parent | 7117c2d221b2aed4ede8600f6a36b7c1454b4f55 (diff) | |
download | bash-d3a24ed242e91e6afb53b2cbf38b89667637168d.tar.gz |
Initial devel branch import from bash-3.0-alpha
Diffstat (limited to 'jobs.c')
-rw-r--r-- | jobs.c | 96 |
1 files changed, 79 insertions, 17 deletions
@@ -3,7 +3,7 @@ /* This file works with both POSIX and BSD systems. It implements job control. */ -/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1989-2003 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -39,7 +39,10 @@ # include <sys/resource.h> #endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */ -#include <sys/file.h> +#if defined (HAVE_SYS_FILE_H) +# include <sys/file.h> +#endif + #include "filecntl.h" #include <sys/ioctl.h> #include <sys/param.h> @@ -127,6 +130,8 @@ extern int errno; /* Some systems let waitpid(2) tell callers about stopped children. */ #if !defined (WCONTINUED) # define WCONTINUED 0 +#endif +#if !defined (WIFCONTINUED) # define WIFCONTINUED(s) (0) #endif @@ -142,7 +147,8 @@ extern void rl_set_screen_size __P((int, int)); /* Variables used here but defined in other files. */ extern int subshell_environment, line_number; extern int posixly_correct, shell_level; -extern int interrupt_immediately, last_command_exit_value; +extern int interrupt_immediately; +extern int last_command_exit_value, last_command_exit_signal; extern int loop_level, breaking; extern int sourcelevel; extern sh_builtin_func_t *this_shell_builtin; @@ -223,6 +229,7 @@ static PROCESS *find_pipeline __P((pid_t, int, int *)); static char *current_working_directory __P((void)); static char *job_working_directory __P((void)); +static char *j_strsignal __P((int)); static char *printable_job_status __P((int, PROCESS *, int)); static pid_t find_last_pid __P((int, int)); @@ -235,7 +242,9 @@ static int most_recent_job_in_state __P((int, JOB_STATE)); static int find_job __P((pid_t, int)); static int print_job __P((JOB *, int, int, int)); static int process_exit_status __P((WAIT)); +static int process_exit_signal __P((WAIT)); static int job_exit_status __P((int)); +static int job_exit_signal __P((int)); static int set_job_status_and_cleanup __P((int)); static WAIT raw_job_exit_status __P((int)); @@ -994,6 +1003,21 @@ describe_pid (pid) } static char * +j_strsignal (s) + int s; +{ + char *x; + + x = strsignal (s); + if (x == 0) + { + x = retcode_name_buffer; + sprintf (x, "Signal %d", s); + } + return x; +} + +static char * printable_job_status (j, p, format) int j; PROCESS *p; @@ -1019,9 +1043,9 @@ printable_job_status (j, p, format) else { if (WIFSTOPPED (p->status)) - temp = strsignal (WSTOPSIG (p->status)); + temp = j_strsignal (WSTOPSIG (p->status)); else if (WIFSIGNALED (p->status)) - temp = strsignal (WTERMSIG (p->status)); + temp = j_strsignal (WTERMSIG (p->status)); else if (WIFEXITED (p->status)) { temp = retcode_name_buffer; @@ -1725,6 +1749,13 @@ wait_sigint_handler (sig) } static int +process_exit_signal (status) + WAIT status; +{ + return (WIFSIGNALED (status) ? WTERMSIG (status) : 0); +} + +static int process_exit_status (status) WAIT status; { @@ -1743,6 +1774,16 @@ raw_job_exit_status (job) int job; { register PROCESS *p; + int fail; + + if (pipefail_opt) + { + fail = 0; + for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next) + if (p->status != EXECUTION_SUCCESS) fail = p->status; + return fail; + } + for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next) ; return (p->status); @@ -1758,6 +1799,13 @@ job_exit_status (job) return (process_exit_status (raw_job_exit_status (job))); } +static int +job_exit_signal (job) + int job; +{ + return (process_exit_signal (raw_job_exit_status (job))); +} + #define FIND_CHILD(pid, child) \ do \ { \ @@ -1885,11 +1933,12 @@ wait_for (pid) /* The exit state of the command is either the termination state of the child, or the termination state of the job. If a job, the status - of the last child in the pipeline is the significant one. */ - if (job != NO_JOB) - termination_state = job_exit_status (job); - else - termination_state = process_exit_status (child->status); + of the last child in the pipeline is the significant one. If the command + or job was terminated by a signal, note that value also. */ + termination_state = (job != NO_JOB) ? job_exit_status (job) + : process_exit_status (child->status); + last_command_exit_signal = (job != NO_JOB) ? job_exit_signal (job) + : process_exit_signal (child->status); if (job == NO_JOB || IS_JOBCONTROL (job)) { @@ -1949,7 +1998,7 @@ if (job == NO_JOB) /* If the current job was stopped or killed by a signal, and the user has requested it, get a possibly new window size */ - if (check_window_size && job == current_job) + if (check_window_size && (job == current_job || IS_FOREGROUND (job))) get_new_window_size (0); } else @@ -2243,7 +2292,7 @@ start_job (job, foreground) if (foreground == 0 && already_running) { - internal_error ("%s: bg background job?", this_command_name); + internal_error ("%s: job %%%d already in background", this_command_name, job + 1); UNBLOCK_CHILD (oset); return (-1); } @@ -2733,6 +2782,7 @@ run_sigchld_trap (nchild) begin_unwind_frame ("SIGCHLD trap"); unwind_protect_int (last_command_exit_value); + unwind_protect_int (last_command_exit_signal); unwind_protect_var (last_made_pid); unwind_protect_int (interrupt_immediately); unwind_protect_int (jobs_list_frozen); @@ -2742,8 +2792,8 @@ run_sigchld_trap (nchild) /* We have to add the commands this way because they will be run in reverse order of adding. We don't want maybe_set_sigchld_trap () to reference freed memory. */ - add_unwind_protect ((Function *)xfree, trap_command); - add_unwind_protect ((Function *)maybe_set_sigchld_trap, trap_command); + add_unwind_protect (xfree, trap_command); + add_unwind_protect (maybe_set_sigchld_trap, trap_command); subst_assign_varlist = (WORD_LIST *)NULL; the_pipeline = (PROCESS *)NULL; @@ -2753,7 +2803,7 @@ run_sigchld_trap (nchild) for (i = 0; i < nchild; i++) { interrupt_immediately = 1; - parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST); + parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE); } run_unwind_frame ("SIGCHLD trap"); @@ -2800,11 +2850,21 @@ notify_of_job_status () ((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job))) continue; +#if 0 /* If job control is disabled, don't print the status messages. Mark dead jobs as notified so that they get cleaned up. If startup_state == 2, we were started to run `-c command', so don't print anything. */ if ((job_control == 0 && interactive_shell) || startup_state == 2) +#else + /* If job control is disabled, don't print the status messages. + Mark dead jobs as notified so that they get cleaned up. If + startup_state == 2 and subshell_environment has the + SUBSHELL_COMSUB bit turned on, we were started to run a command + substitution, so don't print anything. */ + if ((job_control == 0 && interactive_shell) || + (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB))) +#endif { /* POSIX.2 compatibility: if the shell is not interactive, hang onto the job corresponding to the last asynchronous @@ -2828,7 +2888,8 @@ notify_of_job_status () #endif signal_is_trapped (termsig) == 0) { - fprintf (stderr, "%s: line %d: ", get_name_for_error (), line_number); + /* Don't print `0' for a line number. */ + fprintf (stderr, "%s: line %d: ", get_name_for_error (), (line_number == 0) ? 1 : line_number); pretty_print_job (job, JLIST_NONINTERACTIVE, stderr); } else if (IS_FOREGROUND (job)) @@ -2839,7 +2900,7 @@ notify_of_job_status () if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE) #endif { - fprintf (stderr, "%s", strsignal (termsig)); + fprintf (stderr, "%s", j_strsignal (termsig)); if (WIFCORED (s)) fprintf (stderr, " (core dumped)"); @@ -2851,6 +2912,7 @@ notify_of_job_status () { if (dir == 0) dir = current_working_directory (); +itrace("calling pretty_print_job: startup_state == %d, subshell_environment = %d", startup_state, subshell_environment); pretty_print_job (job, JLIST_STANDARD, stderr); if (dir && strcmp (dir, jobs[job]->wd) != 0) fprintf (stderr, |