source: trunk/third/bash/nojobs.c @ 21276

Revision 21276, 22.6 KB checked in by zacheiss, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21275, which included commits to RCS files with non-trunk default branches.
RevLine 
[12958]1/* The thing that makes children, remembers them, and contains wait loops. */
2
3/* This file works under BSD, System V, minix, and Posix systems.  It does
4   not implement job control. */
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
[16806]12   Software Foundation; either version 2, or (at your option) any later
[12958]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
[16806]22   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
[12958]23
24#include "config.h"
25
26#include "bashtypes.h"
27#include "filecntl.h"
28
29#if defined (HAVE_UNISTD_H)
30#  include <unistd.h>
31#endif
32
33#include <stdio.h>
34#include <signal.h>
35#include <errno.h>
36
37#if defined (BUFFERED_INPUT)
38#  include "input.h"
39#endif
40
[16806]41/* Need to include this up here for *_TTY_DRIVER definitions. */
42#include "shtty.h"
[12958]43
44#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
45/* For struct winsize on SCO */
46/*   sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
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 */
54
[21275]55#include "bashintl.h"
56
[16806]57#include "shell.h"
58#include "jobs.h"
59
60#include "builtins/builtext.h"  /* for wait_builtin */
61
[18289]62#define DEFAULT_CHILD_MAX 32
[16806]63
[12958]64#if defined (_POSIX_VERSION) || !defined (HAVE_KILLPG)
65#  define killpg(pg, sig)               kill(-(pg),(sig))
66#endif /* USG || _POSIX_VERSION */
67
[21275]68#if !defined (HAVE_SIGINTERRUPT) && !defined (HAVE_POSIX_SIGNALS)
[12958]69#  define siginterrupt(sig, code)
[21275]70#endif /* !HAVE_SIGINTERRUPT && !HAVE_POSIX_SIGNALS */
[12958]71
72#if defined (HAVE_WAITPID)
73#  define WAITPID(pid, statusp, options) waitpid (pid, statusp, options)
74#else
75#  define WAITPID(pid, statusp, options) wait (statusp)
76#endif /* !HAVE_WAITPID */
77
78/* Return the fd from which we are actually getting input. */
79#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
80
81#if !defined (errno)
82extern int errno;
83#endif /* !errno */
84
85#if defined (READLINE)
[16806]86extern void rl_set_screen_size __P((int, int));
87#endif
[12958]88
89extern int interactive, interactive_shell, login_shell;
90extern int subshell_environment;
[21275]91extern int last_command_exit_value, last_command_exit_signal;
[16806]92extern int interrupt_immediately;
[18289]93extern sh_builtin_func_t *this_shell_builtin;
[12958]94#if defined (HAVE_POSIX_SIGNALS)
95extern sigset_t top_level_mask;
96#endif
[16806]97extern procenv_t wait_intr_buf;
[18289]98extern int wait_signal_received;
[12958]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
106/* The controlling tty for this shell. */
107int shell_tty = -1;
108
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
[16806]113/* STATUS and FLAGS are only valid if pid != NO_PID
114   STATUS is only valid if (flags & PROC_RUNNING) == 0 */
[12958]115struct proc_status {
116  pid_t pid;
117  int status;   /* Exit status of PID or 128 + fatal signal number */
[16806]118  int flags;
[12958]119};
120
[16806]121/* Values for proc_status.flags */
122#define PROC_RUNNING    0x01
123#define PROC_NOTIFIED   0x02
124#define PROC_ASYNC      0x04
[21275]125#define PROC_SIGNALED   0x10
[16806]126
127/* Return values from find_status_by_pid */
128#define PROC_BAD         -1
[12958]129#define PROC_STILL_ALIVE -2
130
[18289]131static struct proc_status *pid_list = (struct proc_status *)NULL;
132static int pid_list_size;
133static int wait_sigint_received;
134
135static long child_max = -1L;
136
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));
[21275]142static int find_termsig_by_pid __P((pid_t));
143static int get_termsig __P((WAIT));
[18289]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));
[21275]147static int get_pid_flags __P((pid_t));
[18289]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));
153static sighandler wait_sigint_handler __P((int));
[21275]154static char *j_strsignal __P((int));
[18289]155
156#if defined (HAVE_WAITPID)
157static void reap_zombie_children __P((void));
158#endif
159
[21275]160#if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
161static int siginterrupt __P((int, int));
162#endif
163
[18289]164static void restore_sigint_handler __P((void));
165
[12958]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;
[18289]174  pid_list = (struct proc_status *)xrealloc (pid_list, pid_list_size * sizeof (struct proc_status));
[12958]175
176  /* None of the newly allocated slots have process id's yet. */
177  for (i = old; i < pid_list_size; i++)
178    pid_list[i].pid = NO_PID;
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);
[16806]224  if (pid_list[i].flags & PROC_RUNNING)
225    return (PROC_STILL_ALIVE);
[12958]226  return (pid_list[i].status);
227}
228
[16806]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
[21275]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
[12958]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
[16806]280  pid_list[slot].status = process_exit_status (status);
281  pid_list[slot].flags &= ~PROC_RUNNING;
[21275]282  if (WIFSIGNALED (status))
283    pid_list[slot].flags |= PROC_SIGNALED;
[16806]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;
[12958]288}
289
[16806]290/* Give PID the flags FLAGS in the PID_LIST array. */
[12958]291static void
[16806]292set_pid_flags (pid, flags)
[12958]293     pid_t pid;
[16806]294     int flags;
[12958]295{
296  int slot;
297
[16806]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;
318}
319
[21275]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
[16806]334static void
335add_pid (pid, async)
336     pid_t pid;
337     int async;
338{
339  int slot;
340
[12958]341  slot = find_proc_slot ();
[16806]342
[12958]343  pid_list[slot].pid = pid;
[16806]344  pid_list[slot].status = -1;
345  pid_list[slot].flags = PROC_RUNNING;
346  if (async)
347    pid_list[slot].flags |= PROC_ASYNC;
[12958]348}
349
[16806]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))
363        ndead++;
364    }
365
[18289]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)
[16806]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;
[18289]384          if (force == 0 && (pid_list[i].flags & PROC_ASYNC) && --ndead <= child_max)
[16806]385            break;
386        }
387    }
388}
389
390/* Remove all dead, notified jobs from the pid_list. */
[12958]391int
392cleanup_dead_jobs ()
393{
394  register int i;
395
396#if defined (HAVE_WAITPID)
397  reap_zombie_children ();
398#endif
399
400  for (i = 0; i < pid_list_size; i++)
[16806]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;
[12958]408}
409
[16806]410void
411reap_dead_jobs ()
412{
413  mark_dead_jobs_as_notified (0);
414  cleanup_dead_jobs ();
415}
416
[12958]417/* Initialize the job control mechanism, and set up the tty stuff. */
418initialize_job_control (force)
419     int force;
420{
421  shell_tty = fileno (stderr);
422
423  if (interactive)
424    get_tty_state ();
425}
426
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
437  tty = input_tty ();
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
[16806]444      sh_set_lines_and_columns (win.ws_row, win.ws_col);
[12958]445#if defined (READLINE)
[16806]446      rl_set_screen_size (win.ws_row, win.ws_col);
[12958]447#endif
448    }
449}
450
451static sighandler
452sigwinch_sighandler (sig)
453     int sig;
454{
455#if defined (MUST_REINSTALL_SIGHANDLERS)
456  set_signal_handler (SIGWINCH, sigwinch_sighandler);
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
482}
483
484/* Setup this shell to handle C-C, etc. */
485void
486initialize_job_signals ()
487{
488  set_signal_handler (SIGINT, sigint_sighandler);
489  set_sigwinch_handler ();
490
491  /* If this is a login shell we don't wish to be disturbed by
492     stop signals. */
493  if (login_shell)
494    ignore_tty_job_signals ();
495}
496
497#if defined (HAVE_WAITPID)
498/* Collect the status of all zombie children so that their system
499   resources can be deallocated. */
500static void
501reap_zombie_children ()
502{
[21275]503#  if defined (WNOHANG)
[12958]504  pid_t pid;
505  WAIT status;
506
507  while ((pid = waitpid (-1, (int *)&status, WNOHANG)) > 0)
508    set_pid_status (pid, status);
[21275]509#  endif /* WNOHANG */
[12958]510}
[21275]511#endif /* WAITPID */
[12958]512
[21275]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));
528}
529#endif /* !HAVE_SIGINTERRUPT && HAVE_POSIX_SIGNALS */
530
[12958]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;
541#if defined (HAVE_WAITPID)
542  int retry = 1;
543#endif /* HAVE_WAITPID */
544
545  /* Discard saved memory. */
546  if (command)
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. */
556  if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
557    sync_buffered_stream (default_buffered_input);
558#endif /* BUFFERED_INPUT */
559
560  /* Create the child, handle severe errors. */
561#if defined (HAVE_WAITPID)
562  retry_fork:
563#endif /* HAVE_WAITPID */
564
565  if ((pid = fork ()) < 0)
566    {
567#if defined (HAVE_WAITPID)
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        }
576#endif /* HAVE_WAITPID */
577
578      sys_error ("fork");
579
580      throw_to_top_level ();
581    }
582
583  if (pid == 0)
584    {
585#if defined (BUFFERED_INPUT)
586      unset_bash_input (0);
587#endif /* BUFFERED_INPUT */
588
589#if defined (HAVE_POSIX_SIGNALS)
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)
596        last_asynchronous_pid = getpid ();
597
598      default_tty_job_signals ();
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
[16806]609      add_pid (pid, async_p);
[12958]610    }
611  return (pid);
612}
613
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
[16806]634/* Wait for a single pid (PID) and return its exit status.  Called by
635   the wait builtin. */
[18289]636int
[12958]637wait_for_single_pid (pid)
638     pid_t pid;
639{
640  pid_t got_pid;
641  WAIT status;
[21275]642  int pstatus, flags;
[12958]643
644  pstatus = find_status_by_pid (pid);
645
646  if (pstatus == PROC_BAD)
647    {
[21275]648      internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
[12958]649      return (127);
650    }
651
652  if (pstatus != PROC_STILL_ALIVE)
[21275]653    {
654      if (pstatus > 128)
655        last_command_exit_signal = find_termsig_by_pid (pid);
656      return (pstatus);
657    }
[12958]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);
667              sys_error ("wait");
668            }
669          break;
670        }
671      else if (got_pid > 0)
[16806]672        set_pid_status (got_pid, status);
[12958]673    }
674
[18289]675  if (got_pid > 0)
676    {
677      set_pid_status (got_pid, status);
678      set_pid_flags (got_pid, PROC_NOTIFIED);
679    }
[16806]680
[12958]681  siginterrupt (SIGINT, 0);
682  QUIT;
683
[18289]684  return (got_pid > 0 ? process_exit_status (status) : -1);
[12958]685}
686
[16806]687/* Wait for all of the shell's children to exit.  Called by the `wait'
688   builtin. */
[12958]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
696     bookkeeping for us.  wait () will return -1 and set errno to ECHILD
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);
709      sys_error("wait");
710    }
711
712  siginterrupt (SIGINT, 0);
713  QUIT;
[16806]714
715  mark_dead_jobs_as_notified (1);
716  cleanup_dead_jobs ();
[12958]717}
718
[16806]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    }
731}
732
[12958]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{
[16806]740  SigHandler *sigint_handler;
[12958]741
[16806]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] */
[18289]752      wait_signal_received = SIGINT;
[16806]753      longjmp (wait_intr_buf, 1);
754    }
755
756  if (interrupt_immediately)
757    {
758      last_command_exit_value = EXECUTION_FAILURE;
759      restore_sigint_handler ();
760      ADDINTERRUPT;
761      QUIT;
762    }
763
764  wait_sigint_received = 1;
765
[12958]766  SIGRETURN (0);
767}
768
[21275]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
[12958]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;
794
795  pstatus = find_status_by_pid (pid);
796
797  if (pstatus == PROC_BAD)
798    return (0);
799
800  if (pstatus != PROC_STILL_ALIVE)
[21275]801    {
802      if (pstatus > 128)
803        last_command_exit_signal = find_termsig_by_pid (pid);
804      return (pstatus);
805    }
[12958]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. */
[16806]809  wait_sigint_received = 0;
810  if (interactive_shell == 0)
[12958]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)
[18289]825        programming_error ("wait_for(%ld): %s", (long)pid, strerror(errno));
[12958]826      else if (got_pid > 0)
827        set_pid_status (got_pid, status);
828    }
829
[18289]830  if (got_pid > 0)
831    set_pid_status (got_pid, status);
[12958]832
833#if defined (HAVE_WAITPID)
834  if (got_pid >= 0)
835    reap_zombie_children ();
836#endif /* HAVE_WAITPID */
837
838  if (interactive_shell == 0)
839    {
[16806]840      SigHandler *temp_handler;
841
842      temp_handler = old_sigint_handler;
843      restore_sigint_handler ();
844
[12958]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        {
[16806]849
[12958]850          if (maybe_call_trap_handler (SIGINT) == 0)
[16806]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            }
[12958]857        }
858    }
859
860  /* Default return value. */
861  /* ``a full 8 bits of status is returned'' */
[16806]862  return_val = process_exit_status (status);
[21275]863  last_command_exit_signal = get_termsig (status);
[12958]864
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
872    {
[21275]873      fprintf (stderr, "%s", j_strsignal (WTERMSIG (status)));
[12958]874      if (WIFCORED (status))
875        fprintf (stderr, " (core dumped)");
876      fprintf (stderr, "\n");
877    }
878
879  if (interactive_shell && subshell_environment == 0)
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
[16806]901  result = group ? killpg (pid, signal) : kill (pid, signal);
[12958]902  return (result);
903}
904
[16806]905static TTYSTRUCT shell_tty_info;
[12958]906static int got_tty_state;
907
908/* Fill the contents of shell_tty_info with the current tty info. */
909get_tty_state ()
910{
911  int tty;
912
913  tty = input_tty ();
914  if (tty != -1)
915    {
[16806]916      ttgetattr (tty, &shell_tty_info);
[12958]917      got_tty_state = 1;
918      if (check_window_size)
919        get_new_window_size (0);
920    }
921}
922
923/* Make the current tty use the state in shell_tty_info. */
924int
925set_tty_state ()
926{
927  int tty;
928
929  tty = input_tty ();
930  if (tty != -1)
931    {
932      if (got_tty_state == 0)
933        return 0;
[16806]934      ttsetattr (tty, &shell_tty_info);
[12958]935    }
936  return 0;
937}
938
939/* Give the terminal to PGRP.  */
[16806]940give_terminal_to (pgrp, force)
[12958]941     pid_t pgrp;
[16806]942     int force;
[12958]943{
944}
945
946/* Stop a pipeline. */
[18289]947int
[12958]948stop_pipeline (async, ignore)
949     int async;
950     COMMAND *ignore;
951{
952  already_making_children = 0;
[18289]953  return 0;
[12958]954}
955
956void
957start_pipeline ()
958{
959  already_making_children = 1;
960}
961
[18289]962void
963stop_making_children ()
964{
965  already_making_children = 0;
966}
967
[12958]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
979/* Print descriptive information about the job with leader pid PID. */
980void
981describe_pid (pid)
982     pid_t pid;
983{
[18289]984  fprintf (stderr, "%ld\n", (long) pid);
[12958]985}
986
987void
988unfreeze_jobs_list ()
989{
990}
[16806]991
992int
993count_all_jobs ()
994{
995  return 0;
996}
Note: See TracBrowser for help on using the repository browser.