224 lines
		
	
	
	
		
			5.5 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
	
		
			5.5 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
This file is wait.def, from which is created wait.c.
 | 
						|
It implements the builtin "wait" in Bash.
 | 
						|
 | 
						|
Copyright (C) 1987-2015 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Bash, the Bourne Again SHell.
 | 
						|
 | 
						|
Bash is free software: you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation, either version 3 of the License, or
 | 
						|
(at your option) any later version.
 | 
						|
 | 
						|
Bash is distributed in the hope that it will be useful,
 | 
						|
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
GNU General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
$BUILTIN wait
 | 
						|
$FUNCTION wait_builtin
 | 
						|
$DEPENDS_ON JOB_CONTROL
 | 
						|
$PRODUCES wait.c
 | 
						|
$SHORT_DOC wait [-n] [id ...]
 | 
						|
Wait for job completion and return exit status.
 | 
						|
 | 
						|
Waits for each process identified by an ID, which may be a process ID or a
 | 
						|
job specification, and reports its termination status.  If ID is not
 | 
						|
given, waits for all currently active child processes, and the return
 | 
						|
status is zero.  If ID is a a job specification, waits for all processes
 | 
						|
in that job's pipeline.
 | 
						|
 | 
						|
If the -n option is supplied, waits for the next job to terminate and
 | 
						|
returns its exit status.
 | 
						|
 | 
						|
Exit Status:
 | 
						|
Returns the status of the last ID; fails if ID is invalid or an invalid
 | 
						|
option is given.
 | 
						|
$END
 | 
						|
 | 
						|
$BUILTIN wait
 | 
						|
$FUNCTION wait_builtin
 | 
						|
$DEPENDS_ON !JOB_CONTROL
 | 
						|
$SHORT_DOC wait [pid ...]
 | 
						|
Wait for process completion and return exit status.
 | 
						|
 | 
						|
Waits for each process specified by a PID and reports its termination status.
 | 
						|
If PID is not given, waits for all currently active child processes,
 | 
						|
and the return status is zero.  PID must be a process ID.
 | 
						|
 | 
						|
Exit Status:
 | 
						|
Returns the status of the last PID; fails if PID is invalid or an invalid
 | 
						|
option is given.
 | 
						|
$END
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
 | 
						|
#include "../bashtypes.h"
 | 
						|
#include <signal.h>
 | 
						|
 | 
						|
#if defined (HAVE_UNISTD_H)
 | 
						|
#  include <unistd.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <chartypes.h>
 | 
						|
 | 
						|
#include "../bashansi.h"
 | 
						|
 | 
						|
#include "../shell.h"
 | 
						|
#include "../jobs.h"
 | 
						|
#include "common.h"
 | 
						|
#include "bashgetopt.h"
 | 
						|
 | 
						|
extern int wait_signal_received;
 | 
						|
extern int last_command_exit_signal;
 | 
						|
 | 
						|
procenv_t wait_intr_buf;
 | 
						|
int wait_intr_flag;
 | 
						|
 | 
						|
/* Wait for the pid in LIST to stop or die.  If no arguments are given, then
 | 
						|
   wait for all of the active background processes of the shell and return
 | 
						|
   0.  If a list of pids or job specs are given, return the exit status of
 | 
						|
   the last one waited for. */
 | 
						|
 | 
						|
#define WAIT_RETURN(s) \
 | 
						|
  do \
 | 
						|
    { \
 | 
						|
      interrupt_immediately = old_interrupt_immediately;\
 | 
						|
      wait_signal_received = 0; \
 | 
						|
      wait_intr_flag = 0; \
 | 
						|
      return (s);\
 | 
						|
    } \
 | 
						|
  while (0)
 | 
						|
 | 
						|
int
 | 
						|
wait_builtin (list)
 | 
						|
     WORD_LIST *list;
 | 
						|
{
 | 
						|
  int status, code, opt, nflag;
 | 
						|
  volatile int old_interrupt_immediately;
 | 
						|
 | 
						|
  USE_VAR(list);
 | 
						|
 | 
						|
  nflag = 0;
 | 
						|
  reset_internal_getopt ();
 | 
						|
  while ((opt = internal_getopt (list, "n")) != -1)
 | 
						|
    {
 | 
						|
      switch (opt)
 | 
						|
	{
 | 
						|
#if defined (JOB_CONTROL)
 | 
						|
	case 'n':
 | 
						|
	  nflag = 1;
 | 
						|
	  break;
 | 
						|
#endif
 | 
						|
	CASE_HELPOPT;
 | 
						|
	default:
 | 
						|
	  builtin_usage ();
 | 
						|
	  return (EX_USAGE);
 | 
						|
	}
 | 
						|
    }
 | 
						|
  list = loptend;
 | 
						|
 | 
						|
  old_interrupt_immediately = interrupt_immediately;
 | 
						|
#if 0
 | 
						|
  interrupt_immediately++;
 | 
						|
#endif
 | 
						|
 | 
						|
  /* POSIX.2 says:  When the shell is waiting (by means of the wait utility)
 | 
						|
     for asynchronous commands to complete, the reception of a signal for
 | 
						|
     which a trap has been set shall cause the wait utility to return
 | 
						|
     immediately with an exit status greater than 128, after which the trap
 | 
						|
     associated with the signal shall be taken.
 | 
						|
 | 
						|
     We handle SIGINT here; it's the only one that needs to be treated
 | 
						|
     specially (I think), since it's handled specially in {no,}jobs.c. */
 | 
						|
  wait_intr_flag = 1;
 | 
						|
  code = setjmp_sigs (wait_intr_buf);
 | 
						|
 | 
						|
  if (code)
 | 
						|
    {
 | 
						|
      last_command_exit_signal = wait_signal_received;
 | 
						|
      status = 128 + wait_signal_received;
 | 
						|
      wait_sigint_cleanup ();
 | 
						|
      WAIT_RETURN (status);
 | 
						|
    }
 | 
						|
 | 
						|
  /* We support jobs or pids.
 | 
						|
     wait <pid-or-job> [pid-or-job ...] */
 | 
						|
 | 
						|
#if defined (JOB_CONTROL)
 | 
						|
  if (nflag)
 | 
						|
    {
 | 
						|
      status = wait_for_any_job ();
 | 
						|
      if (status < 0)
 | 
						|
	status = 127;
 | 
						|
      WAIT_RETURN (status);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
      
 | 
						|
  /* But wait without any arguments means to wait for all of the shell's
 | 
						|
     currently active background processes. */
 | 
						|
  if (list == 0)
 | 
						|
    {
 | 
						|
      wait_for_background_pids ();
 | 
						|
      WAIT_RETURN (EXECUTION_SUCCESS);
 | 
						|
    }
 | 
						|
 | 
						|
  status = EXECUTION_SUCCESS;
 | 
						|
  while (list)
 | 
						|
    {
 | 
						|
      pid_t pid;
 | 
						|
      char *w;
 | 
						|
      intmax_t pid_value;
 | 
						|
 | 
						|
      w = list->word->word;
 | 
						|
      if (DIGIT (*w))
 | 
						|
	{
 | 
						|
	  if (legal_number (w, &pid_value) && pid_value == (pid_t)pid_value)
 | 
						|
	    {
 | 
						|
	      pid = (pid_t)pid_value;
 | 
						|
	      status = wait_for_single_pid (pid, 1);
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      sh_badpid (w);
 | 
						|
	      WAIT_RETURN (EXECUTION_FAILURE);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
#if defined (JOB_CONTROL)
 | 
						|
      else if (*w && *w == '%')
 | 
						|
	/* Must be a job spec.  Check it out. */
 | 
						|
	{
 | 
						|
	  int job;
 | 
						|
	  sigset_t set, oset;
 | 
						|
 | 
						|
	  BLOCK_CHILD (set, oset);
 | 
						|
	  job = get_job_spec (list);
 | 
						|
 | 
						|
	  if (INVALID_JOB (job))
 | 
						|
	    {
 | 
						|
	      if (job != DUP_JOB)
 | 
						|
		sh_badjob (list->word->word);
 | 
						|
	      UNBLOCK_CHILD (oset);
 | 
						|
	      status = 127;	/* As per Posix.2, section 4.70.2 */
 | 
						|
	      list = list->next;
 | 
						|
	      continue;
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* Job spec used.  Wait for the last pid in the pipeline. */
 | 
						|
	  UNBLOCK_CHILD (oset);
 | 
						|
	  status = wait_for_job (job);
 | 
						|
	}
 | 
						|
#endif /* JOB_CONTROL */
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  sh_badpid (w);
 | 
						|
	  status = EXECUTION_FAILURE;
 | 
						|
	}
 | 
						|
      list = list->next;
 | 
						|
    }
 | 
						|
 | 
						|
  WAIT_RETURN (status);
 | 
						|
}
 |