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