Imported from ../bash-3.1.tar.gz.
[platform/upstream/bash.git] / builtins / jobs.def
index 8a293da..4c3ba6a 100644 (file)
@@ -1,13 +1,13 @@
 This file is jobs.def, from which is created jobs.c.
-It implements the builtin "jobs" in Bash.
+It implements the builtins "jobs" and "disown" in Bash.
 
-Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+Copyright (C) 1987-2005 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 1, or (at your option) any later
+Software Foundation; either version 2, or (at your option) any later
 version.
 
 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -17,34 +17,48 @@ for more details.
 
 You should have received a copy of the GNU General Public License along
 with Bash; see the file COPYING.  If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
 
 $PRODUCES jobs.c
 
 $BUILTIN jobs
 $FUNCTION jobs_builtin
 $DEPENDS_ON JOB_CONTROL
-$SHORT_DOC jobs [-lnp] [jobspec ...] | jobs -x command [args]
+$SHORT_DOC jobs [-lnprs] [jobspec ...] or jobs -x command [args]
 Lists the active jobs.  The -l option lists process id's in addition
 to the normal information; the -p option lists process id's only.
 If -n is given, only processes that have changed status since the last
-notification are printed.  JOBSPEC restricts output to that job.
-If -x is given, COMMAND is run after all job specifications that appear
-in ARGS have been replaced with the process ID of that job's process group
-leader.
+notification are printed.  JOBSPEC restricts output to that job.  The
+-r and -s options restrict output to running and stopped jobs only,
+respectively.  Without options, the status of all active jobs is
+printed.  If -x is given, COMMAND is run after all job specifications
+that appear in ARGS have been replaced with the process ID of that job's
+process group leader.
 $END
 
-#include "../shell.h"
+#include <config.h>
 
 #if defined (JOB_CONTROL)
-#include <sys/types.h>
+#include "../bashtypes.h"
 #include <signal.h>
-#include "../jobs.h"
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
 
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "../jobs.h"
+#include "../execute_cmd.h"
 #include "bashgetopt.h"
+#include "common.h"
+
+#define JSTATE_ANY     0x0
+#define JSTATE_RUNNING 0x1
+#define JSTATE_STOPPED 0x2
 
-extern int job_control, interactive_shell;
-static int execute_list_with_replacements ();
+static int execute_list_with_replacements __P((WORD_LIST *));
 
 /* The `jobs' command.  Prints outs a list of active jobs.  If the
    argument `-l' is given, then the process id's are printed also.
@@ -52,20 +66,21 @@ static int execute_list_with_replacements ();
    pid only.  If `-n' is given, only processes that have changed
    status since the last notification are printed.  If -x is given,
    replace all job specs with the pid of the appropriate process
-   group leader and execute the command. */
+   group leader and execute the command.  The -r and -s options mean
+   to print info about running and stopped jobs only, respectively. */
 int
 jobs_builtin (list)
      WORD_LIST *list;
 {
-  int form = JLIST_STANDARD, execute = 0;
-  int opt;
-  int any_failed = 0;
+  int form, execute, state, opt, any_failed, job;
+  sigset_t set, oset;
 
-  if (!job_control && !interactive_shell)
-    return (EXECUTION_SUCCESS);
+  execute = any_failed = 0;
+  form = JLIST_STANDARD;
+  state = JSTATE_ANY;
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "lpnx")) != -1)
+  while ((opt = internal_getopt (list, "lpnxrs")) != -1)
     {
       switch (opt)
        {
@@ -81,14 +96,20 @@ jobs_builtin (list)
        case 'x':
          if (form != JLIST_STANDARD)
            {
-             builtin_error ("Other options not allowed with `-x'");
+             builtin_error (_("no other options allowed with `-x'"));
              return (EXECUTION_FAILURE);
            }
          execute++;
          break;
+       case 'r':
+         state = JSTATE_RUNNING;
+         break;
+       case 's':
+         state = JSTATE_STOPPED;
+         break;
 
        default:
-         builtin_error ("usage: jobs [-lpn [jobspec]] [-x command [args]]");
+         builtin_usage ();
          return (EX_USAGE);
        }
     }
@@ -100,21 +121,29 @@ jobs_builtin (list)
 
   if (!list)
     {
-      list_jobs (form);
+      switch (state)
+       {
+       case JSTATE_ANY:
+         list_all_jobs (form);
+         break;
+       case JSTATE_RUNNING:
+         list_running_jobs (form);
+         break;
+       case JSTATE_STOPPED:
+         list_stopped_jobs (form);
+         break;
+       }
       return (EXECUTION_SUCCESS);
     }
 
   while (list)
     {
-      int job;
-      sigset_t set, oset;
-
       BLOCK_CHILD (set, oset);
       job = get_job_spec (list);
 
-      if ((job == NO_JOB) || !jobs || !jobs[job])
+      if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
        {
-         builtin_error ("No such job %s", list->word->word);
+         sh_badjob (list->word->word);
          any_failed++;
        }
       else if (job != DUP_JOB)
@@ -132,6 +161,8 @@ execute_list_with_replacements (list)
 {
   register WORD_LIST *l;
   int job, result;
+  COMMAND *command;
+  JOB *j;
 
   /* First do the replacement of job specifications with pids. */
   for (l = list; l; l = l->next)
@@ -141,31 +172,109 @@ execute_list_with_replacements (list)
          job = get_job_spec (l);
 
          /* A bad job spec is not really a job spec! Pass it through. */
-         if (job < 0 || job >= job_slots || !jobs[job])
+         if (INVALID_JOB (job))
            continue;
 
+         j = get_job_by_jid (job);
          free (l->word->word);
-         l->word->word = itos (jobs[job]->pgrp);
+         l->word->word = itos (j->pgrp);
        }
     }
 
   /* Next make a new simple command and execute it. */
   begin_unwind_frame ("jobs_builtin");
-  {
-    COMMAND *command = (COMMAND *)NULL;
-
-    add_unwind_protect (dispose_command, command);
 
-    command = make_bare_simple_command ();
-    command->value.Simple->words = copy_word_list (list);
-    command->value.Simple->redirects = (REDIRECT *)NULL;
-    command->flags |= CMD_INHIBIT_EXPANSION;
-    command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
+  command = make_bare_simple_command ();
+  command->value.Simple->words = copy_word_list (list);
+  command->value.Simple->redirects = (REDIRECT *)NULL;
+  command->flags |= CMD_INHIBIT_EXPANSION;
+  command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
 
-    result = execute_command (command);
-  }
+  add_unwind_protect (dispose_command, command);
+  result = execute_command (command);
+  dispose_command (command);
 
-  run_unwind_frame ("jobs_builtin");
+  discard_unwind_frame ("jobs_builtin");
   return (result);
 }
 #endif /* JOB_CONTROL */
+
+$BUILTIN disown
+$FUNCTION disown_builtin
+$DEPENDS_ON JOB_CONTROL
+$SHORT_DOC disown [-h] [-ar] [jobspec ...]
+By default, removes each JOBSPEC argument from the table of active jobs.
+If the -h option is given, the job is not removed from the table, but is
+marked so that SIGHUP is not sent to the job if the shell receives a
+SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
+jobs from the job table; the -r option means to remove only running jobs.
+$END
+
+#if defined (JOB_CONTROL)
+int
+disown_builtin (list)
+     WORD_LIST *list;
+{
+  int opt, job, retval, nohup_only, running_jobs, all_jobs;
+  sigset_t set, oset;
+  intmax_t pid_value;
+
+  nohup_only = running_jobs = all_jobs = 0;
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "ahr")) != -1)
+    {
+      switch (opt)
+       {
+       case 'a':
+         all_jobs = 1;
+         break;
+       case 'h':
+         nohup_only = 1;
+         break;
+       case 'r':
+         running_jobs = 1;
+         break;
+       default:
+         builtin_usage ();
+         return (EX_USAGE);
+       }
+    }
+  list = loptend;
+  retval = EXECUTION_SUCCESS;
+
+  /* `disown -a' or `disown -r' */
+  if (list == 0 && (all_jobs || running_jobs))
+    {
+      if (nohup_only)
+       nohup_all_jobs (running_jobs);
+      else
+       delete_all_jobs (running_jobs);
+      return (EXECUTION_SUCCESS);
+    }
+
+  do
+    {
+      BLOCK_CHILD (set, oset);
+      job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
+               ? get_job_by_pid ((pid_t) pid_value, 0)
+               : get_job_spec (list);
+
+      if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
+       {
+         sh_badjob (list ? list->word->word : "current");
+         retval = EXECUTION_FAILURE;
+       }
+      else if (nohup_only)
+       nohup_job (job);
+      else
+       delete_job (job, 1);
+      UNBLOCK_CHILD (oset);
+
+      if (list)
+       list = list->next;
+    }
+  while (list);
+
+  return (retval);
+}
+#endif /* JOB_CONTROL */