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