/* This file works under BSD, System V, minix, and Posix systems. It does
not implement job control. */
-/* Copyright (C) 1987-2019 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
#include <signal.h>
#include <errno.h>
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
+#include "input.h"
/* Need to include this up here for *_TTY_DRIVER definitions. */
#include "shtty.h"
extern int errno;
#endif /* !errno */
-extern void set_original_signal __P((int, SigHandler *));
+extern void set_original_signal (int, SigHandler *);
volatile pid_t last_made_pid = NO_PID;
volatile pid_t last_asynchronous_pid = NO_PID;
static long child_max = -1L;
-static void alloc_pid_list __P((void));
-static int find_proc_slot __P((pid_t));
-static int find_index_by_pid __P((pid_t));
-static int find_status_by_pid __P((pid_t));
-static int process_exit_status __P((WAIT));
-static int find_termsig_by_pid __P((pid_t));
-static int get_termsig __P((WAIT));
-static void set_pid_status __P((pid_t, WAIT));
-static void set_pid_flags __P((pid_t, int));
-static void unset_pid_flags __P((pid_t, int));
-static int get_pid_flags __P((pid_t));
-static void add_pid __P((pid_t, int));
-static void mark_dead_jobs_as_notified __P((int));
-
-static sighandler wait_sigint_handler __P((int));
-static char *j_strsignal __P((int));
+static void alloc_pid_list (void);
+static int find_proc_slot (pid_t);
+static int find_index_by_pid (pid_t);
+static int find_status_by_pid (pid_t);
+static int process_exit_status (WAIT);
+static int find_termsig_by_pid (pid_t);
+static int get_termsig (WAIT);
+static void set_pid_status (pid_t, WAIT);
+static void set_pid_flags (pid_t, int);
+static void unset_pid_flags (pid_t, int);
+static int get_pid_flags (pid_t);
+static void add_pid (pid_t, int);
+static void mark_dead_jobs_as_notified (int);
+
+static sighandler wait_sigint_handler (int);
+static char *j_strsignal (int);
#if defined (HAVE_WAITPID)
-static void reap_zombie_children __P((void));
+static void reap_zombie_children (void);
#endif
#if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
-static int siginterrupt __P((int, int));
+static int siginterrupt (int, int);
#endif
-static void restore_sigint_handler __P((void));
+static void restore_sigint_handler (void);
/* Allocate new, or grow existing PID_LIST. */
static void
-alloc_pid_list ()
+alloc_pid_list (void)
{
register int i;
int old = pid_list_size;
/* Return the offset within the PID_LIST array of an empty slot. This can
create new slots if all of the existing slots are taken. */
static int
-find_proc_slot (pid)
- pid_t pid;
+find_proc_slot (pid_t pid)
{
register int i;
/* Return the offset within the PID_LIST array of a slot containing PID,
or the value NO_PID if the pid wasn't found. */
static int
-find_index_by_pid (pid)
- pid_t pid;
+find_index_by_pid (pid_t pid)
{
register int i;
/* Return the status of PID as looked up in the PID_LIST array. A
return value of PROC_BAD indicates that PID wasn't found. */
static int
-find_status_by_pid (pid)
- pid_t pid;
+find_status_by_pid (pid_t pid)
{
int i;
}
static int
-process_exit_status (status)
- WAIT status;
+process_exit_status (WAIT status)
{
if (WIFSIGNALED (status))
return (128 + WTERMSIG (status));
/* Return the status of PID as looked up in the PID_LIST array. A
return value of PROC_BAD indicates that PID wasn't found. */
static int
-find_termsig_by_pid (pid)
- pid_t pid;
+find_termsig_by_pid (pid_t pid)
{
int i;
up PID in the pid array and set LAST_COMMAND_EXIT_SIGNAL appropriately
depending on its flags and exit status. */
static int
-get_termsig (status)
- WAIT status;
+get_termsig (WAIT status)
{
if (WIFSTOPPED (status) == 0 && WIFSIGNALED (status))
return (WTERMSIG (status));
/* Give PID the status value STATUS in the PID_LIST array. */
static void
-set_pid_status (pid, status)
- pid_t pid;
- WAIT status;
+set_pid_status (pid_t pid, WAIT status)
{
int slot;
/* Give PID the flags FLAGS in the PID_LIST array. */
static void
-set_pid_flags (pid, flags)
- pid_t pid;
- int flags;
+set_pid_flags (pid_t pid, int flags)
{
int slot;
/* Unset FLAGS for PID in the pid list */
static void
-unset_pid_flags (pid, flags)
- pid_t pid;
- int flags;
+unset_pid_flags (pid_t pid, int flags)
{
int slot;
/* Return the flags corresponding to PID in the PID_LIST array. */
static int
-get_pid_flags (pid)
- pid_t pid;
+get_pid_flags (pid_t pid)
{
int slot;
}
static void
-add_pid (pid, async)
- pid_t pid;
- int async;
+add_pid (pid_t pid, int async)
{
int slot;
}
static void
-mark_dead_jobs_as_notified (force)
- int force;
+mark_dead_jobs_as_notified (int force)
{
register int i, ndead;
/* Remove all dead, notified jobs from the pid_list. */
int
-cleanup_dead_jobs ()
+cleanup_dead_jobs (void)
{
register int i;
}
void
-reap_dead_jobs ()
+reap_dead_jobs (void)
{
mark_dead_jobs_as_notified (0);
cleanup_dead_jobs ();
/* Initialize the job control mechanism, and set up the tty stuff. */
int
-initialize_job_control (force)
- int force;
+initialize_job_control (int force)
{
shell_tty = fileno (stderr);
/* Setup this shell to handle C-C, etc. */
void
-initialize_job_signals ()
+initialize_job_signals (void)
{
set_signal_handler (SIGINT, sigint_sighandler);
/* Collect the status of all zombie children so that their system
resources can be deallocated. */
static void
-reap_zombie_children ()
+reap_zombie_children (void)
{
# if defined (WNOHANG)
pid_t pid;
#endif
static int
-siginterrupt (sig, flag)
- int sig, flag;
+siginterrupt (int sig, int flag)
{
struct sigaction act;
anything else with it. ASYNC_P says what to do with the tty. If
non-zero, then don't give it away. */
pid_t
-make_child (command, flags)
- char *command;
- int flags;
+make_child (char *command, int flags)
{
pid_t pid;
int async_p, forksleep;
async_p = (flags & FORK_ASYNC);
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 */
/* Block SIGTERM here and unblock in child after fork resets the
set of pending signals */
if (pid == 0)
{
-#if defined (BUFFERED_INPUT)
unset_bash_input (0);
-#endif /* BUFFERED_INPUT */
CLRINTERRUPT; /* XXX - children have their own interrupt state */
last_asynchronous_pid = getpid ();
#endif
+ subshell_environment |= SUBSHELL_IGNTRAP;
+
default_tty_job_signals ();
}
else
}
void
-ignore_tty_job_signals ()
+ignore_tty_job_signals (void)
{
#if defined (SIGTSTP)
set_signal_handler (SIGTSTP, SIG_IGN);
}
void
-default_tty_job_signals ()
+default_tty_job_signals (void)
{
#if defined (SIGTSTP)
if (signal_is_trapped (SIGTSTP) == 0 && signal_is_hard_ignored (SIGTSTP))
/* Called once in a parent process. */
void
-get_original_tty_job_signals ()
+get_original_tty_job_signals (void)
{
static int fetched = 0;
/* Wait for a single pid (PID) and return its exit status. Called by
the wait builtin. */
int
-wait_for_single_pid (pid, flags)
- pid_t pid;
- int flags;
+wait_for_single_pid (pid_t pid, int flags)
{
pid_t got_pid;
WAIT status;
if (pstatus == PROC_BAD)
{
internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
- return (127);
+ return (257);
}
if (pstatus != PROC_STILL_ALIVE)
/* Wait for all of the shell's children to exit. Called by the `wait'
builtin. */
-void
-wait_for_background_pids (ps)
- struct procstat *ps;
+int
+wait_for_background_pids (struct procstat *ps)
{
pid_t got_pid;
WAIT status;
+ int njobs;
/* 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. */
+ njobs = 0;
siginterrupt (SIGINT, 1);
/* Wait for ECHILD */
while ((got_pid = WAITPID (-1, &status, 0)) != -1)
{
waiting_for_child = 0;
+ njobs++;
set_pid_status (got_pid, status);
if (ps)
{
mark_dead_jobs_as_notified (1);
cleanup_dead_jobs ();
+
+ return njobs;
}
void
-wait_sigint_cleanup ()
+wait_sigint_cleanup (void)
{
}
static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
static void
-restore_sigint_handler ()
+restore_sigint_handler (void)
{
if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
{
All interrupts are effectively ignored by the shell, but allowed to
kill a running job. */
static sighandler
-wait_sigint_handler (sig)
- int sig;
+wait_sigint_handler (int sig)
{
SigHandler *sigint_handler;
{
last_command_exit_value = 128+SIGINT;
restore_sigint_handler ();
- interrupt_immediately = 0;
trap_handler (SIGINT); /* set pending_traps[SIGINT] */
wait_signal_received = SIGINT;
SIGRETURN (0);
}
- 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;
+j_strsignal (int s)
{
static char retcode_name_buffer[64] = { '\0' };
char *x;
/* Wait for pid (one of our children) to terminate. This is called only
by the execution code in execute_cmd.c. */
int
-wait_for (pid, flags)
- pid_t pid;
- int flags;
+wait_for (pid_t pid, int flags)
{
int return_val, pstatus;
pid_t got_pid;
/* 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. */
int
-kill_pid (pid, signal, group)
- pid_t pid;
- int signal, group;
+kill_pid (pid_t pid, int signal, int group)
{
int result;
/* Fill the contents of shell_tty_info with the current tty info. */
int
-get_tty_state ()
+get_tty_state (void)
{
int tty;
/* Make the current tty use the state in shell_tty_info. */
int
-set_tty_state ()
+set_tty_state (void)
{
int tty;
/* Give the terminal to PGRP. */
int
-give_terminal_to (pgrp, force)
- pid_t pgrp;
- int force;
+give_terminal_to (pid_t pgrp, int force)
{
return 0;
}
/* Stop a pipeline. */
int
-stop_pipeline (async, ignore)
- int async;
- COMMAND *ignore;
+stop_pipeline (int async, COMMAND *ignore)
{
already_making_children = 0;
return 0;
}
void
-start_pipeline ()
+start_pipeline (void)
{
already_making_children = 1;
}
void
-stop_making_children ()
+stop_making_children (void)
{
already_making_children = 0;
}
/* The name is kind of a misnomer, but it's what the job control code uses. */
void
-without_job_control ()
+without_job_control (void)
{
stop_making_children ();
last_made_pid = NO_PID; /* XXX */
}
int
-get_job_by_pid (pid, block, ignore)
- pid_t pid;
- int block;
- PROCESS **ignore;
+get_job_by_pid (pid_t pid, int block, PROCESS **ignore)
{
int i;
/* Print descriptive information about the job with leader pid PID. */
void
-describe_pid (pid)
- pid_t pid;
+describe_pid (pid_t pid)
{
fprintf (stderr, "%ld\n", (long) pid);
}
int
-freeze_jobs_list ()
+freeze_jobs_list (void)
{
return 0;
}
-void
-unfreeze_jobs_list ()
+int
+unfreeze_jobs_list (void)
{
+ return 0;
}
void
-set_jobs_list_frozen (s)
- int s;
+set_jobs_list_frozen (int s)
+{
+}
+
+int
+jobs_list_frozen_status (void)
{
+ return 0;
+}
+
+int
+count_all_jobs (void)
+{
+ return 0;
}
int
-count_all_jobs ()
+job_control_active_p (void)
{
return 0;
}