]> git.ipfire.org Git - thirdparty/bash.git/blame - nojobs.c
commit bash-20050817 snapshot
[thirdparty/bash.git] / nojobs.c
CommitLineData
726f6388
JA
1/* The thing that makes children, remembers them, and contains wait loops. */
2
ccc6cda3
JA
3/* This file works under BSD, System V, minix, and Posix systems. It does
4 not implement job control. */
726f6388
JA
5
6/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
7
8 This file is part of GNU Bash, the Bourne Again SHell.
9
10 Bash is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
bb70624e 12 Software Foundation; either version 2, or (at your option) any later
726f6388
JA
13 version.
14
15 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License along
21 with Bash; see the file COPYING. If not, write to the Free Software
bb70624e 22 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388 23
ccc6cda3
JA
24#include "config.h"
25
726f6388 26#include "bashtypes.h"
ccc6cda3
JA
27#include "filecntl.h"
28
29#if defined (HAVE_UNISTD_H)
30# include <unistd.h>
31#endif
32
33#include <stdio.h>
726f6388 34#include <signal.h>
726f6388
JA
35#include <errno.h>
36
726f6388
JA
37#if defined (BUFFERED_INPUT)
38# include "input.h"
39#endif
40
bb70624e
JA
41/* Need to include this up here for *_TTY_DRIVER definitions. */
42#include "shtty.h"
ccc6cda3 43
d166f048 44#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
ccc6cda3
JA
45/* For struct winsize on SCO */
46/* sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
d166f048
JA
47# if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
48# if defined (HAVE_SYS_STREAM_H)
49# include <sys/stream.h>
50# endif
51# include <sys/ptem.h>
52# endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
53#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
726f6388 54
5e13499c
CR
55#include "bashintl.h"
56
bb70624e
JA
57#include "shell.h"
58#include "jobs.h"
59
60#include "builtins/builtext.h" /* for wait_builtin */
61
7117c2d2 62#define DEFAULT_CHILD_MAX 32
bb70624e 63
ccc6cda3 64#if defined (_POSIX_VERSION) || !defined (HAVE_KILLPG)
726f6388
JA
65# define killpg(pg, sig) kill(-(pg),(sig))
66#endif /* USG || _POSIX_VERSION */
67
5e13499c 68#if !defined (HAVE_SIGINTERRUPT) && !defined (HAVE_POSIX_SIGNALS)
726f6388 69# define siginterrupt(sig, code)
5e13499c 70#endif /* !HAVE_SIGINTERRUPT && !HAVE_POSIX_SIGNALS */
726f6388 71
ccc6cda3 72#if defined (HAVE_WAITPID)
726f6388
JA
73# define WAITPID(pid, statusp, options) waitpid (pid, statusp, options)
74#else
75# define WAITPID(pid, statusp, options) wait (statusp)
ccc6cda3 76#endif /* !HAVE_WAITPID */
726f6388 77
d166f048
JA
78/* Return the fd from which we are actually getting input. */
79#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
80
726f6388
JA
81#if !defined (errno)
82extern int errno;
83#endif /* !errno */
84
d166f048 85#if defined (READLINE)
28ef6c31 86extern void rl_set_screen_size __P((int, int));
bb70624e 87#endif
d166f048 88
726f6388
JA
89extern int interactive, interactive_shell, login_shell;
90extern int subshell_environment;
d3a24ed2 91extern int last_command_exit_value, last_command_exit_signal;
bb70624e 92extern int interrupt_immediately;
f73dda09 93extern sh_builtin_func_t *this_shell_builtin;
ccc6cda3 94#if defined (HAVE_POSIX_SIGNALS)
726f6388
JA
95extern sigset_t top_level_mask;
96#endif
bb70624e 97extern procenv_t wait_intr_buf;
7117c2d2 98extern int wait_signal_received;
726f6388
JA
99
100pid_t last_made_pid = NO_PID;
101pid_t last_asynchronous_pid = NO_PID;
102
103/* Call this when you start making children. */
104int already_making_children = 0;
105
d166f048
JA
106/* The controlling tty for this shell. */
107int shell_tty = -1;
108
ccc6cda3
JA
109/* If this is non-zero, $LINES and $COLUMNS are reset after every process
110 exits from get_tty_state(). */
111int check_window_size;
112
bb70624e
JA
113/* STATUS and FLAGS are only valid if pid != NO_PID
114 STATUS is only valid if (flags & PROC_RUNNING) == 0 */
726f6388
JA
115struct proc_status {
116 pid_t pid;
117 int status; /* Exit status of PID or 128 + fatal signal number */
bb70624e 118 int flags;
726f6388
JA
119};
120
bb70624e
JA
121/* Values for proc_status.flags */
122#define PROC_RUNNING 0x01
123#define PROC_NOTIFIED 0x02
124#define PROC_ASYNC 0x04
d3a24ed2 125#define PROC_SIGNALED 0x10
bb70624e 126
bb70624e
JA
127/* Return values from find_status_by_pid */
128#define PROC_BAD -1
726f6388
JA
129#define PROC_STILL_ALIVE -2
130
f73dda09
JA
131static struct proc_status *pid_list = (struct proc_status *)NULL;
132static int pid_list_size;
133static int wait_sigint_received;
134
7117c2d2
JA
135static long child_max = -1L;
136
f73dda09
JA
137static void alloc_pid_list __P((void));
138static int find_proc_slot __P((void));
139static int find_index_by_pid __P((pid_t));
140static int find_status_by_pid __P((pid_t));
141static int process_exit_status __P((WAIT));
d3a24ed2
CR
142static int find_termsig_by_pid __P((pid_t));
143static int get_termsig __P((WAIT));
f73dda09
JA
144static void set_pid_status __P((pid_t, WAIT));
145static void set_pid_flags __P((pid_t, int));
146static void unset_pid_flags __P((pid_t, int));
d3a24ed2 147static int get_pid_flags __P((pid_t));
f73dda09
JA
148static void add_pid __P((pid_t, int));
149static void mark_dead_jobs_as_notified __P((int));
150
151static void get_new_window_size __P((int));
152static sighandler sigwinch_sighandler __P((int));
7117c2d2 153static sighandler wait_sigint_handler __P((int));
d3a24ed2 154static char *j_strsignal __P((int));
f73dda09
JA
155
156#if defined (HAVE_WAITPID)
157static void reap_zombie_children __P((void));
158#endif
159
5e13499c
CR
160#if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
161static int siginterrupt __P((int, int));
162#endif
163
f73dda09
JA
164static void restore_sigint_handler __P((void));
165
726f6388
JA
166/* Allocate new, or grow existing PID_LIST. */
167static void
168alloc_pid_list ()
169{
170 register int i;
171 int old = pid_list_size;
172
173 pid_list_size += 10;
f73dda09 174 pid_list = (struct proc_status *)xrealloc (pid_list, pid_list_size * sizeof (struct proc_status));
726f6388
JA
175
176 /* None of the newly allocated slots have process id's yet. */
177 for (i = old; i < pid_list_size; i++)
ccc6cda3 178 pid_list[i].pid = NO_PID;
726f6388
JA
179}
180
181/* Return the offset within the PID_LIST array of an empty slot. This can
182 create new slots if all of the existing slots are taken. */
183static int
184find_proc_slot ()
185{
186 register int i;
187
188 for (i = 0; i < pid_list_size; i++)
189 if (pid_list[i].pid == NO_PID)
190 return (i);
191
192 if (i == pid_list_size)
193 alloc_pid_list ();
194
195 return (i);
196}
197
198/* Return the offset within the PID_LIST array of a slot containing PID,
199 or the value NO_PID if the pid wasn't found. */
200static int
201find_index_by_pid (pid)
202 pid_t pid;
203{
204 register int i;
205
206 for (i = 0; i < pid_list_size; i++)
207 if (pid_list[i].pid == pid)
208 return (i);
209
210 return (NO_PID);
211}
212
213/* Return the status of PID as looked up in the PID_LIST array. A
214 return value of PROC_BAD indicates that PID wasn't found. */
215static int
216find_status_by_pid (pid)
217 pid_t pid;
218{
219 int i;
220
221 i = find_index_by_pid (pid);
222 if (i == NO_PID)
223 return (PROC_BAD);
bb70624e
JA
224 if (pid_list[i].flags & PROC_RUNNING)
225 return (PROC_STILL_ALIVE);
726f6388
JA
226 return (pid_list[i].status);
227}
228
bb70624e
JA
229static int
230process_exit_status (status)
231 WAIT status;
232{
233 if (WIFSIGNALED (status))
234 return (128 + WTERMSIG (status));
235 else
236 return (WEXITSTATUS (status));
237}
238
d3a24ed2
CR
239/* Return the status of PID as looked up in the PID_LIST array. A
240 return value of PROC_BAD indicates that PID wasn't found. */
241static int
242find_termsig_by_pid (pid)
243 pid_t pid;
244{
245 int i;
246
247 i = find_index_by_pid (pid);
248 if (i == NO_PID)
249 return (0);
250 if (pid_list[i].flags & PROC_RUNNING)
251 return (0);
252 return (get_termsig (pid_list[i].status));
253}
254
255/* Set LAST_COMMAND_EXIT_SIGNAL depending on STATUS. If STATUS is -1, look
256 up PID in the pid array and set LAST_COMMAND_EXIT_SIGNAL appropriately
257 depending on its flags and exit status. */
258static int
259get_termsig (status)
260 WAIT status;
261{
262 if (WIFSTOPPED (status) == 0 && WIFSIGNALED (status))
263 return (WTERMSIG (status));
264 else
265 return (0);
266}
267
726f6388
JA
268/* Give PID the status value STATUS in the PID_LIST array. */
269static void
270set_pid_status (pid, status)
271 pid_t pid;
272 WAIT status;
273{
274 int slot;
275
276 slot = find_index_by_pid (pid);
277 if (slot == NO_PID)
278 return;
279
bb70624e
JA
280 pid_list[slot].status = process_exit_status (status);
281 pid_list[slot].flags &= ~PROC_RUNNING;
d3a24ed2
CR
282 if (WIFSIGNALED (status))
283 pid_list[slot].flags |= PROC_SIGNALED;
bb70624e
JA
284 /* If it's not a background process, mark it as notified so it gets
285 cleaned up. */
286 if ((pid_list[slot].flags & PROC_ASYNC) == 0)
287 pid_list[slot].flags |= PROC_NOTIFIED;
288}
289
290/* Give PID the flags FLAGS in the PID_LIST array. */
291static void
292set_pid_flags (pid, flags)
293 pid_t pid;
294 int flags;
295{
296 int slot;
297
298 slot = find_index_by_pid (pid);
299 if (slot == NO_PID)
300 return;
301
302 pid_list[slot].flags |= flags;
303}
304
305/* Unset FLAGS for PID in the pid list */
306static void
307unset_pid_flags (pid, flags)
308 pid_t pid;
309 int flags;
310{
311 int slot;
312
313 slot = find_index_by_pid (pid);
314 if (slot == NO_PID)
315 return;
316
317 pid_list[slot].flags &= ~flags;
726f6388
JA
318}
319
d3a24ed2
CR
320/* Return the flags corresponding to PID in the PID_LIST array. */
321static int
322get_pid_flags (pid)
323 pid_t pid;
324{
325 int slot;
326
327 slot = find_index_by_pid (pid);
328 if (slot == NO_PID)
329 return 0;
330
331 return (pid_list[slot].flags);
332}
333
726f6388 334static void
bb70624e 335add_pid (pid, async)
726f6388 336 pid_t pid;
bb70624e 337 int async;
726f6388
JA
338{
339 int slot;
340
341 slot = find_proc_slot ();
bb70624e 342
726f6388 343 pid_list[slot].pid = pid;
bb70624e
JA
344 pid_list[slot].status = -1;
345 pid_list[slot].flags = PROC_RUNNING;
346 if (async)
347 pid_list[slot].flags |= PROC_ASYNC;
348}
349
350static void
351mark_dead_jobs_as_notified (force)
352 int force;
353{
354 register int i, ndead;
355
356 /* first, count the number of non-running async jobs if FORCE == 0 */
357 for (i = ndead = 0; force == 0 && i < pid_list_size; i++)
358 {
359 if (pid_list[i].pid == NO_PID)
360 continue;
361 if (((pid_list[i].flags & PROC_RUNNING) == 0) &&
362 (pid_list[i].flags & PROC_ASYNC))
28ef6c31 363 ndead++;
bb70624e
JA
364 }
365
7117c2d2
JA
366 if (child_max < 0)
367 child_max = getmaxchild ();
368 if (child_max < 0)
369 child_max = DEFAULT_CHILD_MAX;
370
371 if (force == 0 && ndead <= child_max)
bb70624e
JA
372 return;
373
374 /* If FORCE == 0, we just mark as many non-running async jobs as notified
375 to bring us under the CHILD_MAX limit. */
376 for (i = 0; i < pid_list_size; i++)
377 {
378 if (pid_list[i].pid == NO_PID)
379 continue;
380 if (((pid_list[i].flags & PROC_RUNNING) == 0) &&
381 pid_list[i].pid != last_asynchronous_pid)
382 {
383 pid_list[i].flags |= PROC_NOTIFIED;
7117c2d2 384 if (force == 0 && (pid_list[i].flags & PROC_ASYNC) && --ndead <= child_max)
bb70624e
JA
385 break;
386 }
387 }
726f6388
JA
388}
389
bb70624e 390/* Remove all dead, notified jobs from the pid_list. */
726f6388
JA
391int
392cleanup_dead_jobs ()
393{
394 register int i;
395
ccc6cda3 396#if defined (HAVE_WAITPID)
726f6388
JA
397 reap_zombie_children ();
398#endif
399
400 for (i = 0; i < pid_list_size; i++)
bb70624e
JA
401 {
402 if ((pid_list[i].flags & PROC_RUNNING) == 0 &&
403 (pid_list[i].flags & PROC_NOTIFIED))
404 pid_list[i].pid = NO_PID;
405 }
406
407 return 0;
408}
409
410void
411reap_dead_jobs ()
412{
413 mark_dead_jobs_as_notified (0);
414 cleanup_dead_jobs ();
726f6388
JA
415}
416
417/* Initialize the job control mechanism, and set up the tty stuff. */
d166f048
JA
418initialize_job_control (force)
419 int force;
726f6388 420{
d166f048
JA
421 shell_tty = fileno (stderr);
422
423 if (interactive)
424 get_tty_state ();
726f6388
JA
425}
426
ccc6cda3
JA
427#if defined (TIOCGWINSZ) && defined (SIGWINCH)
428static SigHandler *old_winch = (SigHandler *)SIG_DFL;
429
430static void
431get_new_window_size (from_sig)
432 int from_sig;
433{
434 struct winsize win;
435 int tty;
436
d166f048 437 tty = input_tty ();
ccc6cda3
JA
438 if (tty >= 0 && (ioctl (tty, TIOCGWINSZ, &win) == 0) &&
439 win.ws_row > 0 && win.ws_col > 0)
440 {
441#if defined (aixpc)
442 shell_tty_info.c_winsize = win; /* structure copying */
443#endif
28ef6c31 444 sh_set_lines_and_columns (win.ws_row, win.ws_col);
ccc6cda3 445#if defined (READLINE)
28ef6c31 446 rl_set_screen_size (win.ws_row, win.ws_col);
ccc6cda3
JA
447#endif
448 }
ccc6cda3 449}
726f6388
JA
450
451static sighandler
452sigwinch_sighandler (sig)
453 int sig;
454{
ccc6cda3 455#if defined (MUST_REINSTALL_SIGHANDLERS)
726f6388 456 set_signal_handler (SIGWINCH, sigwinch_sighandler);
ccc6cda3
JA
457#endif /* MUST_REINSTALL_SIGHANDLERS */
458 get_new_window_size (1);
459}
460#else
461static void
462get_new_window_size (from_sig)
463 int from_sig;
464{
465}
466#endif /* TIOCGWINSZ && SIGWINCH */
467
468void
469set_sigwinch_handler ()
470{
471#if defined (TIOCGWINSZ) && defined (SIGWINCH)
472 old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
473#endif
474}
475
476void
477unset_sigwinch_handler ()
478{
479#if defined (TIOCGWINSZ) && defined (SIGWINCH)
480 set_signal_handler (SIGWINCH, old_winch);
481#endif
726f6388 482}
726f6388
JA
483
484/* Setup this shell to handle C-C, etc. */
485void
486initialize_job_signals ()
487{
488 set_signal_handler (SIGINT, sigint_sighandler);
ccc6cda3 489 set_sigwinch_handler ();
726f6388
JA
490
491 /* If this is a login shell we don't wish to be disturbed by
492 stop signals. */
493 if (login_shell)
ccc6cda3 494 ignore_tty_job_signals ();
726f6388
JA
495}
496
ccc6cda3 497#if defined (HAVE_WAITPID)
726f6388
JA
498/* Collect the status of all zombie children so that their system
499 resources can be deallocated. */
500static void
501reap_zombie_children ()
502{
5e13499c 503# if defined (WNOHANG)
726f6388
JA
504 pid_t pid;
505 WAIT status;
506
507 while ((pid = waitpid (-1, (int *)&status, WNOHANG)) > 0)
508 set_pid_status (pid, status);
5e13499c
CR
509# endif /* WNOHANG */
510}
511#endif /* WAITPID */
512
513#if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
514static int
515siginterrupt (sig, flag)
516 int sig, flag;
517{
518 struct sigaction act;
519
520 sigaction (sig, (struct sigaction *)NULL, &act);
521
522 if (flag)
523 act.sa_flags &= ~SA_RESTART;
524 else
525 act.sa_flags |= SA_RESTART;
526
527 return (sigaction (sig, &act, (struct sigaction *)NULL));
726f6388 528}
5e13499c 529#endif /* !HAVE_SIGINTERRUPT && HAVE_POSIX_SIGNALS */
726f6388
JA
530
531/* Fork, handling errors. Returns the pid of the newly made child, or 0.
532 COMMAND is just for remembering the name of the command; we don't do
533 anything else with it. ASYNC_P says what to do with the tty. If
534 non-zero, then don't give it away. */
535pid_t
536make_child (command, async_p)
537 char *command;
538 int async_p;
539{
540 pid_t pid;
ccc6cda3 541#if defined (HAVE_WAITPID)
726f6388 542 int retry = 1;
ccc6cda3 543#endif /* HAVE_WAITPID */
726f6388
JA
544
545 /* Discard saved memory. */
ccc6cda3 546 if (command)
726f6388
JA
547 free (command);
548
549 start_pipeline ();
550
551#if defined (BUFFERED_INPUT)
552 /* If default_buffered_input is active, we are reading a script. If
553 the command is asynchronous, we have already duplicated /dev/null
554 as fd 0, but have not changed the buffered stream corresponding to
555 the old fd 0. We don't want to sync the stream in this case. */
cce855bc 556 if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
726f6388
JA
557 sync_buffered_stream (default_buffered_input);
558#endif /* BUFFERED_INPUT */
559
560 /* Create the child, handle severe errors. */
ccc6cda3 561#if defined (HAVE_WAITPID)
726f6388 562 retry_fork:
ccc6cda3 563#endif /* HAVE_WAITPID */
726f6388
JA
564
565 if ((pid = fork ()) < 0)
566 {
ccc6cda3 567#if defined (HAVE_WAITPID)
726f6388
JA
568 /* Posix systems with a non-blocking waitpid () system call available
569 get another chance after zombies are reaped. */
570 if (errno == EAGAIN && retry)
571 {
572 reap_zombie_children ();
573 retry = 0;
574 goto retry_fork;
575 }
ccc6cda3 576#endif /* HAVE_WAITPID */
726f6388 577
ccc6cda3 578 sys_error ("fork");
726f6388
JA
579
580 throw_to_top_level ();
581 }
ccc6cda3 582
726f6388
JA
583 if (pid == 0)
584 {
585#if defined (BUFFERED_INPUT)
cce855bc 586 unset_bash_input (0);
726f6388
JA
587#endif /* BUFFERED_INPUT */
588
ccc6cda3 589#if defined (HAVE_POSIX_SIGNALS)
726f6388
JA
590 /* Restore top-level signal mask. */
591 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
592#endif
593
594 /* Ignore INT and QUIT in asynchronous children. */
595 if (async_p)
ccc6cda3 596 last_asynchronous_pid = getpid ();
726f6388 597
ccc6cda3 598 default_tty_job_signals ();
726f6388
JA
599 }
600 else
601 {
602 /* In the parent. */
603
604 last_made_pid = pid;
605
606 if (async_p)
607 last_asynchronous_pid = pid;
608
bb70624e 609 add_pid (pid, async_p);
726f6388
JA
610 }
611 return (pid);
612}
613
ccc6cda3
JA
614void
615ignore_tty_job_signals ()
616{
617#if defined (SIGTSTP)
618 set_signal_handler (SIGTSTP, SIG_IGN);
619 set_signal_handler (SIGTTIN, SIG_IGN);
620 set_signal_handler (SIGTTOU, SIG_IGN);
621#endif
622}
623
624void
625default_tty_job_signals ()
626{
627#if defined (SIGTSTP)
628 set_signal_handler (SIGTSTP, SIG_DFL);
629 set_signal_handler (SIGTTIN, SIG_DFL);
630 set_signal_handler (SIGTTOU, SIG_DFL);
631#endif
632}
633
bb70624e
JA
634/* Wait for a single pid (PID) and return its exit status. Called by
635 the wait builtin. */
f73dda09 636int
726f6388
JA
637wait_for_single_pid (pid)
638 pid_t pid;
639{
640 pid_t got_pid;
641 WAIT status;
d3a24ed2 642 int pstatus, flags;
726f6388
JA
643
644 pstatus = find_status_by_pid (pid);
645
646 if (pstatus == PROC_BAD)
ccc6cda3 647 {
5e13499c 648 internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
ccc6cda3
JA
649 return (127);
650 }
726f6388
JA
651
652 if (pstatus != PROC_STILL_ALIVE)
d3a24ed2
CR
653 {
654 if (pstatus > 128)
655 last_command_exit_signal = find_termsig_by_pid (pid);
656 return (pstatus);
657 }
726f6388
JA
658
659 siginterrupt (SIGINT, 1);
660 while ((got_pid = WAITPID (pid, &status, 0)) != pid)
661 {
662 if (got_pid < 0)
663 {
664 if (errno != EINTR && errno != ECHILD)
665 {
666 siginterrupt (SIGINT, 0);
ccc6cda3 667 sys_error ("wait");
726f6388
JA
668 }
669 break;
670 }
671 else if (got_pid > 0)
28ef6c31 672 set_pid_status (got_pid, status);
726f6388
JA
673 }
674
7117c2d2
JA
675 if (got_pid > 0)
676 {
677 set_pid_status (got_pid, status);
678 set_pid_flags (got_pid, PROC_NOTIFIED);
679 }
bb70624e 680
726f6388
JA
681 siginterrupt (SIGINT, 0);
682 QUIT;
683
7117c2d2 684 return (got_pid > 0 ? process_exit_status (status) : -1);
726f6388
JA
685}
686
bb70624e
JA
687/* Wait for all of the shell's children to exit. Called by the `wait'
688 builtin. */
726f6388
JA
689void
690wait_for_background_pids ()
691{
692 pid_t got_pid;
693 WAIT status;
694
695 /* If we aren't using job control, we let the kernel take care of the
ccc6cda3 696 bookkeeping for us. wait () will return -1 and set errno to ECHILD
726f6388
JA
697 when there are no more unwaited-for child processes on both
698 4.2 BSD-based and System V-based systems. */
699
700 siginterrupt (SIGINT, 1);
701
702 /* Wait for ECHILD */
703 while ((got_pid = WAITPID (-1, &status, 0)) != -1)
704 set_pid_status (got_pid, status);
705
706 if (errno != EINTR && errno != ECHILD)
707 {
708 siginterrupt (SIGINT, 0);
ccc6cda3 709 sys_error("wait");
726f6388
JA
710 }
711
712 siginterrupt (SIGINT, 0);
713 QUIT;
bb70624e
JA
714
715 mark_dead_jobs_as_notified (1);
716 cleanup_dead_jobs ();
717}
718
719/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
720#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
721static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
722
723static void
724restore_sigint_handler ()
725{
726 if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
727 {
728 set_signal_handler (SIGINT, old_sigint_handler);
729 old_sigint_handler = INVALID_SIGNAL_HANDLER;
730 }
726f6388
JA
731}
732
733/* Handle SIGINT while we are waiting for children in a script to exit.
734 All interrupts are effectively ignored by the shell, but allowed to
735 kill a running job. */
736static sighandler
737wait_sigint_handler (sig)
738 int sig;
739{
bb70624e
JA
740 SigHandler *sigint_handler;
741
742 /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
743 what POSIX.2 says (see builtins/wait.def for more info). */
744 if (this_shell_builtin && this_shell_builtin == wait_builtin &&
745 signal_is_trapped (SIGINT) &&
746 ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
747 {
748 last_command_exit_value = EXECUTION_FAILURE;
749 restore_sigint_handler ();
750 interrupt_immediately = 0;
751 trap_handler (SIGINT); /* set pending_traps[SIGINT] */
7117c2d2 752 wait_signal_received = SIGINT;
bb70624e
JA
753 longjmp (wait_intr_buf, 1);
754 }
755
28ef6c31
JA
756 if (interrupt_immediately)
757 {
758 last_command_exit_value = EXECUTION_FAILURE;
759 restore_sigint_handler ();
760 ADDINTERRUPT;
761 QUIT;
762 }
726f6388 763
bb70624e
JA
764 wait_sigint_received = 1;
765
ccc6cda3 766 SIGRETURN (0);
726f6388
JA
767}
768
d3a24ed2
CR
769static char *
770j_strsignal (s)
771 int s;
772{
773 static char retcode_name_buffer[64] = { '\0' };
774 char *x;
775
776 x = strsignal (s);
777 if (x == 0)
778 {
779 x = retcode_name_buffer;
780 sprintf (x, "Signal %d", s);
781 }
782 return x;
783}
784
726f6388
JA
785/* Wait for pid (one of our children) to terminate. This is called only
786 by the execution code in execute_cmd.c. */
787int
788wait_for (pid)
789 pid_t pid;
790{
791 int return_val, pstatus;
792 pid_t got_pid;
793 WAIT status;
726f6388
JA
794
795 pstatus = find_status_by_pid (pid);
796
797 if (pstatus == PROC_BAD)
798 return (0);
799
800 if (pstatus != PROC_STILL_ALIVE)
d3a24ed2
CR
801 {
802 if (pstatus > 128)
803 last_command_exit_signal = find_termsig_by_pid (pid);
804 return (pstatus);
805 }
726f6388
JA
806
807 /* If we are running a script, ignore SIGINT while we're waiting for
808 a child to exit. The loop below does some of this, but not all. */
bb70624e
JA
809 wait_sigint_received = 0;
810 if (interactive_shell == 0)
726f6388
JA
811 old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
812
813 while ((got_pid = WAITPID (-1, &status, 0)) != pid) /* XXX was pid now -1 */
814 {
815 if (got_pid < 0 && errno == ECHILD)
816 {
817#if !defined (_POSIX_VERSION)
818 status.w_termsig = status.w_retcode = 0;
819#else
820 status = 0;
821#endif /* _POSIX_VERSION */
822 break;
823 }
824 else if (got_pid < 0 && errno != EINTR)
f73dda09 825 programming_error ("wait_for(%ld): %s", (long)pid, strerror(errno));
726f6388
JA
826 else if (got_pid > 0)
827 set_pid_status (got_pid, status);
828 }
829
7117c2d2
JA
830 if (got_pid > 0)
831 set_pid_status (got_pid, status);
726f6388 832
ccc6cda3 833#if defined (HAVE_WAITPID)
726f6388
JA
834 if (got_pid >= 0)
835 reap_zombie_children ();
ccc6cda3 836#endif /* HAVE_WAITPID */
726f6388 837
ccc6cda3 838 if (interactive_shell == 0)
726f6388 839 {
bb70624e
JA
840 SigHandler *temp_handler;
841
842 temp_handler = old_sigint_handler;
843 restore_sigint_handler ();
844
726f6388
JA
845 /* If the job exited because of SIGINT, make sure the shell acts as if
846 it had received one also. */
847 if (WIFSIGNALED (status) && (WTERMSIG (status) == SIGINT))
848 {
bb70624e 849
726f6388 850 if (maybe_call_trap_handler (SIGINT) == 0)
bb70624e
JA
851 {
852 if (temp_handler == SIG_DFL)
853 termination_unwind_protect (SIGINT);
854 else if (temp_handler != INVALID_SIGNAL_HANDLER && temp_handler != SIG_IGN)
855 (*temp_handler) (SIGINT);
856 }
726f6388
JA
857 }
858 }
ccc6cda3 859
726f6388
JA
860 /* Default return value. */
861 /* ``a full 8 bits of status is returned'' */
bb70624e 862 return_val = process_exit_status (status);
d3a24ed2 863 last_command_exit_signal = get_termsig (status);
ccc6cda3 864
d166f048
JA
865#if !defined (DONT_REPORT_SIGPIPE)
866 if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) &&
867 (WTERMSIG (status) != SIGINT))
868#else
869 if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) &&
870 (WTERMSIG (status) != SIGINT) && (WTERMSIG (status) != SIGPIPE))
871#endif
726f6388 872 {
d3a24ed2 873 fprintf (stderr, "%s", j_strsignal (WTERMSIG (status)));
726f6388
JA
874 if (WIFCORED (status))
875 fprintf (stderr, " (core dumped)");
876 fprintf (stderr, "\n");
877 }
878
ccc6cda3 879 if (interactive_shell && subshell_environment == 0)
726f6388
JA
880 {
881 if (WIFSIGNALED (status) || WIFSTOPPED (status))
882 set_tty_state ();
883 else
884 get_tty_state ();
885 }
886
887 return (return_val);
888}
889
890/* Give PID SIGNAL. This determines what job the pid belongs to (if any).
891 If PID does belong to a job, and the job is stopped, then CONTinue the
892 job after giving it SIGNAL. Returns -1 on failure. If GROUP is non-null,
893 then kill the process group associated with PID. */
894int
895kill_pid (pid, signal, group)
896 pid_t pid;
897 int signal, group;
898{
899 int result;
900
bb70624e 901 result = group ? killpg (pid, signal) : kill (pid, signal);
726f6388
JA
902 return (result);
903}
904
bb70624e 905static TTYSTRUCT shell_tty_info;
ccc6cda3 906static int got_tty_state;
726f6388
JA
907
908/* Fill the contents of shell_tty_info with the current tty info. */
909get_tty_state ()
910{
ccc6cda3
JA
911 int tty;
912
d166f048 913 tty = input_tty ();
726f6388
JA
914 if (tty != -1)
915 {
bb70624e 916 ttgetattr (tty, &shell_tty_info);
726f6388 917 got_tty_state = 1;
ccc6cda3
JA
918 if (check_window_size)
919 get_new_window_size (0);
726f6388
JA
920 }
921}
922
923/* Make the current tty use the state in shell_tty_info. */
b72432fd 924int
726f6388
JA
925set_tty_state ()
926{
ccc6cda3
JA
927 int tty;
928
d166f048 929 tty = input_tty ();
726f6388
JA
930 if (tty != -1)
931 {
ccc6cda3 932 if (got_tty_state == 0)
b72432fd 933 return 0;
bb70624e 934 ttsetattr (tty, &shell_tty_info);
726f6388 935 }
b72432fd 936 return 0;
726f6388
JA
937}
938
939/* Give the terminal to PGRP. */
28ef6c31 940give_terminal_to (pgrp, force)
726f6388 941 pid_t pgrp;
28ef6c31 942 int force;
726f6388
JA
943{
944}
945
946/* Stop a pipeline. */
f73dda09 947int
726f6388
JA
948stop_pipeline (async, ignore)
949 int async;
950 COMMAND *ignore;
951{
952 already_making_children = 0;
f73dda09 953 return 0;
726f6388
JA
954}
955
956void
957start_pipeline ()
958{
959 already_making_children = 1;
960}
961
f73dda09
JA
962void
963stop_making_children ()
964{
965 already_making_children = 0;
966}
967
d166f048
JA
968int
969get_job_by_pid (pid, block)
970 pid_t pid;
971 int block;
972{
973 int i;
974
975 i = find_index_by_pid (pid);
976 return ((i == NO_PID) ? PROC_BAD : i);
977}
978
726f6388
JA
979/* Print descriptive information about the job with leader pid PID. */
980void
981describe_pid (pid)
982 pid_t pid;
983{
f73dda09 984 fprintf (stderr, "%ld\n", (long) pid);
726f6388 985}
ccc6cda3
JA
986
987void
988unfreeze_jobs_list ()
989{
990}
bb70624e
JA
991
992int
993count_all_jobs ()
994{
995 return 0;
996}