commit bash-20040422 snapshot
authorChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 17:56:49 +0000 (12:56 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 17:56:49 +0000 (12:56 -0500)
51 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
builtins/alias.def
builtins/common.c
builtins/common.c~
builtins/common.h
builtins/common.h~ [new file with mode: 0644]
builtins/jobs.def
builtins/jobs.def.save1 [new file with mode: 0644]
builtins/jobs.def~ [new file with mode: 0644]
builtins/kill.def
builtins/kill.def.save1 [new file with mode: 0644]
builtins/kill.def~ [new file with mode: 0644]
builtins/wait.def
builtins/wait.def.save1 [new file with mode: 0644]
builtins/wait.def~ [new file with mode: 0644]
doc/bash.0
doc/bash.1
doc/bash.html
doc/bash.ps
doc/bashref.dvi
doc/bashref.html
doc/bashref.info
doc/bashref.log
doc/bashref.ps
doc/bashref.texi
doc/bashref.texi~
doc/builtins.0
doc/builtins.ps
doc/rbash.0
doc/rbash.ps
doc/version.texi
jobs.c
jobs.c~
lib/readline/doc/rluser.texi
lib/readline/doc/rluser.texi~ [new file with mode: 0644]
njobs.c [new file with mode: 0644]
po/bash.pot
po/bash.pot~ [new file with mode: 0644]
po/en@boldquot.po
po/en@quot.po
subst.c
subst.c.save1
subst.c~
support/bashbug.sh
support/bashbug.sh.orig [new file with mode: 0644]
support/bashbug.sh~ [new file with mode: 0644]
tests/jobs.right
tests/jobs.right~ [new file with mode: 0644]
tests/jobs.tests
tests/jobs.tests~ [new file with mode: 0644]

index 7b16815..df2936c 100644 (file)
@@ -9367,3 +9367,29 @@ builtins/alias.def
 include/shmbutil.h
        - include <config.h> for definition of HANDLE_MULTIBYTE rather than
          duplicating logic
+
+                                  4/20
+                                  ----
+
+doc/{bash.1,bashref.texi}
+       - make sure $0 is consistently referred to as a `special parameter'
+       - document which characters are now not allowed in alias names
+
+                                  4/23
+                                  ----
+
+builtins/{jobs,kill,wait}.def
+       - removed requirement that job control be enabled to use job control
+         notation, as SUSv3 implies
+
+subst.c
+       - based on a message from David Korn, change param_expand to not call
+         string_list_dollar_star if the only quoting is Q_HERE_DOCUMENT --
+         quoted here documents are like double quoting, but not exactly
+       - analogous changes to list_remove_pattern and pos_params
+
+                                  4/24
+                                  ----
+lib/readline/doc/rluser.texi
+       - fix error in description of emacs-mode C-xC-e command (uses $VISUAL
+         instead of $FCEDIT)
index 126cd0c..ea7dd1e 100644 (file)
@@ -9362,3 +9362,28 @@ builtins/alias.def
        - call legal_alias_name to make sure alias name is valid before
          calling add_alias from alias_builtin
 
+                                  4/19
+                                  ----
+include/shmbutil.h
+       - include <config.h> for definition of HANDLE_MULTIBYTE rather than
+         duplicating logic
+
+                                  4/20
+                                  ----
+
+doc/{bash.1,bashref.texi}
+       - make sure $0 is consistently referred to as a `special parameter'
+       - document which characters are now not allowed in alias names
+
+                                  4/23
+                                  ----
+
+builtins/{jobs,kill,wait}.def
+       - removed requirement that job control be enabled to use job control
+         notation, as SUSv3 implies
+
+subst.c
+       - based on a message from David Korn, change param_expand to not call
+         string_list_dollar_star if the only quoting is Q_HERE_DOCUMENT --
+         quoted here documents are like double quoting, but not exactly
+       - analogous changes to list_remove_pattern and pos_params
index ec83d0b..572910b 100644 (file)
@@ -1,7 +1,7 @@
 This file is alias.def, from which is created alias.c
 It implements the builtins "alias" and "unalias" in Bash.
 
-Copyright (C) 1987-2002 Free Software Foundation, Inc.
+Copyright (C) 1987-2004 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -44,6 +44,7 @@ $END
 #endif
 
 #  include "../bashansi.h"
+#  include "../bashintl.h"
 
 #  include <stdio.h>
 #  include "../shell.h"
@@ -120,7 +121,7 @@ alias_builtin (list)
 
          if (legal_alias_name (name, 0) == 0)
            {
-             builtin_error ("%s: invalid alias name", name);
+             builtin_error (_("`%s': invalid alias name"), name);
              any_failed++;
            }
          else
index 7fd9155..bf0e14f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -573,11 +573,7 @@ get_job_spec (list)
   word = list->word->word;
 
   if (*word == '\0')
-#if 0
-    return (current_job);
-#else
     return (NO_JOB);
-#endif
 
   if (*word == '%')
     word++;
index 4a56480..1542ffa 100644 (file)
@@ -573,11 +573,7 @@ get_job_spec (list)
   word = list->word->word;
 
   if (*word == '\0')
-#if 0
-    return (current_job);
-#else
     return (NO_JOB);
-#endif
 
   if (*word == '%')
     word++;
@@ -585,11 +581,7 @@ get_job_spec (list)
   if (DIGIT (*word) && all_digits (word))
     {
       job = atoi (word);
-#if 0
-      return (job >= job_slots ? NO_JOB : job - 1);
-#else
       return (job > job_slots ? NO_JOB : job - 1);
-#endif
     }
 
   jflags = 0;
index 309bb6d..411ce1e 100644 (file)
@@ -1,6 +1,6 @@
 /* common.h -- extern declarations for functions defined in common.c. */
 
-/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
diff --git a/builtins/common.h~ b/builtins/common.h~
new file mode 100644 (file)
index 0000000..309bb6d
--- /dev/null
@@ -0,0 +1,161 @@
+/* common.h -- extern declarations for functions defined in common.c. */
+
+/* Copyright (C) 1993-2002 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 2, 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; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if  !defined (__COMMON_H)
+#  define __COMMON_H
+
+#include "stdc.h"
+
+#define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c)
+
+/* Flag values for parse_and_execute () */
+#define SEVAL_NONINT   0x001
+#define SEVAL_INTERACT 0x002
+#define SEVAL_NOHIST   0x004
+#define SEVAL_NOFREE   0x008
+#define SEVAL_RESETLINE        0x010
+
+/* Flags for describe_command, shared between type.def and command.def */
+#define CDESC_ALL              0x001   /* type -a */
+#define CDESC_SHORTDESC                0x002   /* command -V */
+#define CDESC_REUSABLE         0x004   /* command -v */
+#define CDESC_TYPE             0x008   /* type -t */
+#define CDESC_PATH_ONLY                0x010   /* type -p */
+#define CDESC_FORCE_PATH       0x020   /* type -ap or type -P */
+#define CDESC_NOFUNCS          0x040   /* type -f */
+
+/* Flags for get_job_by_name */
+#define JM_PREFIX              0x01    /* prefix of job name */
+#define JM_SUBSTRING           0x02    /* substring of job name */
+#define JM_EXACT               0x04    /* match job name exactly */
+#define JM_STOPPED             0x08    /* match stopped jobs only */
+#define JM_FIRSTMATCH          0x10    /* return first matching job */
+
+/* Flags for remember_args and value of changed_dollar_vars */
+#define ARGS_NONE              0x0
+#define ARGS_INVOC             0x01
+#define ARGS_FUNC              0x02
+#define ARGS_SETBLTIN          0x04
+
+/* Functions from common.c */
+extern void builtin_error __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
+extern void builtin_usage __P((void));
+extern void no_args __P((WORD_LIST *));
+extern int no_options __P((WORD_LIST *));
+
+/* common error message functions */
+extern void sh_needarg __P((char *));
+extern void sh_neednumarg __P((char *));
+extern void sh_notfound __P((char *));
+extern void sh_invalidopt __P((char *));
+extern void sh_invalidoptname __P((char *));
+extern void sh_invalidid __P((char *));
+extern void sh_invalidnum __P((char *));
+extern void sh_invalidsig __P((char *));
+extern void sh_erange __P((char *, char *));
+extern void sh_badpid __P((char *));
+extern void sh_badjob __P((char *));
+extern void sh_readonly __P((const char *));
+extern void sh_nojobs __P((char *));
+extern void sh_restricted __P((char *));
+extern void sh_notbuiltin __P((char *));
+
+extern char **make_builtin_argv __P((WORD_LIST *, int *));
+extern void remember_args __P((WORD_LIST *, int));
+
+extern int dollar_vars_changed __P((void));
+extern void set_dollar_vars_unchanged __P((void));
+extern void set_dollar_vars_changed __P((void));
+
+extern intmax_t get_numeric_arg __P((WORD_LIST *, int));
+extern int get_exitstat __P((WORD_LIST *));
+extern int read_octal __P((char *));
+
+/* Keeps track of the current working directory. */
+extern char *the_current_working_directory;
+extern char *get_working_directory __P((char *));
+extern void set_working_directory __P((char *));
+
+#if defined (JOB_CONTROL)
+extern int get_job_by_name __P((const char *, int));
+extern int get_job_spec __P((WORD_LIST *));
+#endif
+extern int display_signal_list __P((WORD_LIST *, int));
+
+/* It's OK to declare a function as returning a Function * without
+   providing a definition of what a `Function' is. */
+extern struct builtin *builtin_address_internal __P((char *, int));
+extern sh_builtin_func_t *find_shell_builtin __P((char *));
+extern sh_builtin_func_t *builtin_address __P((char *));
+extern sh_builtin_func_t *find_special_builtin __P((char *));
+extern void initialize_shell_builtins __P((void));
+
+/* Functions from exit.def */
+extern void bash_logout __P((void));
+
+/* Functions from getopts.def */
+extern void getopts_reset __P((int));
+
+/* Functions from set.def */
+extern int minus_o_option_value __P((char *));
+extern void list_minus_o_opts __P((int, int));
+extern char **get_minus_o_opts __P((void));
+extern int set_minus_o_option __P((int, char *));
+
+extern void set_shellopts __P((void));
+extern void parse_shellopts __P((char *));
+extern void initialize_shell_options __P((int));
+
+extern void reset_shell_options __P((void));
+
+/* Functions from shopt.def */
+extern void reset_shopt_options __P((void));
+extern char **get_shopt_options __P((void));
+
+extern int shopt_setopt __P((char *, int));
+extern int shopt_listopt __P((char *, int));
+
+extern int set_login_shell __P((int));
+
+/* Functions from type.def */
+extern int describe_command __P((char *, int));
+
+/* Functions from setattr.def */
+extern int set_or_show_attributes __P((WORD_LIST *, int, int));
+extern int show_var_attributes __P((SHELL_VAR *, int, int));
+extern int show_name_attributes __P((char *, int));
+extern void set_var_attribute __P((char *, int, int));
+
+/* Functions from pushd.def */
+extern char *get_dirstack_from_string __P((char *));
+extern char *get_dirstack_element __P((intmax_t, int));
+extern void set_dirstack_element __P((intmax_t, int, char *));
+extern WORD_LIST *get_directory_stack __P((void));
+
+/* Functions from evalstring.c */
+extern int parse_and_execute __P((char *, const char *, int));
+extern void parse_and_execute_cleanup __P((void));
+
+/* Functions from evalfile.c */
+extern int maybe_execute_file __P((const char *, int));
+extern int source_file __P((const char *, int));
+extern int fc_execute_file __P((const char *));
+
+#endif /* !__COMMON_H */
index a1f75ae..76d1957 100644 (file)
@@ -1,7 +1,7 @@
 This file is jobs.def, from which is created jobs.c.
 It implements the builtins "jobs" and "disown" in Bash.
 
-Copyright (C) 1987-2003 Free Software Foundation, Inc.
+Copyright (C) 1987-2004 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -75,9 +75,6 @@ jobs_builtin (list)
   int form, execute, state, opt, any_failed, job;
   sigset_t set, oset;
 
-  if (job_control == 0 && interactive_shell == 0)
-    return (EXECUTION_SUCCESS);
-
   execute = any_failed = 0;
   form = JLIST_STANDARD;
   state = JSTATE_ANY;
diff --git a/builtins/jobs.def.save1 b/builtins/jobs.def.save1
new file mode 100644 (file)
index 0000000..a1f75ae
--- /dev/null
@@ -0,0 +1,281 @@
+This file is jobs.def, from which is created jobs.c.
+It implements the builtins "jobs" and "disown" in Bash.
+
+Copyright (C) 1987-2003 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 2, 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; see the file COPYING.  If not, write to the Free Software
+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 [-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.  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 <config.h>
+
+#if defined (JOB_CONTROL)
+#include "../bashtypes.h"
+#include <signal.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
+
+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.
+   If the argument `-p' is given, print the process group leader's
+   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.  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, execute, state, opt, any_failed, job;
+  sigset_t set, oset;
+
+  if (job_control == 0 && interactive_shell == 0)
+    return (EXECUTION_SUCCESS);
+
+  execute = any_failed = 0;
+  form = JLIST_STANDARD;
+  state = JSTATE_ANY;
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "lpnxrs")) != -1)
+    {
+      switch (opt)
+       {
+       case 'l':
+         form = JLIST_LONG;
+         break;
+       case 'p':
+         form = JLIST_PID_ONLY;
+         break;
+       case 'n':
+         form = JLIST_CHANGED_ONLY;
+         break;
+       case 'x':
+         if (form != JLIST_STANDARD)
+           {
+             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_usage ();
+         return (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  if (execute)
+    return (execute_list_with_replacements (list));
+
+  if (!list)
+    {
+      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)
+    {
+      BLOCK_CHILD (set, oset);
+      job = get_job_spec (list);
+
+      if ((job == NO_JOB) || !jobs || !jobs[job])
+       {
+         sh_badjob (list->word->word);
+         any_failed++;
+       }
+      else if (job != DUP_JOB)
+       list_one_job ((JOB *)NULL, form, 0, job);
+
+      UNBLOCK_CHILD (oset);
+      list = list->next;
+    }
+  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
+
+static int
+execute_list_with_replacements (list)
+     WORD_LIST *list;
+{
+  register WORD_LIST *l;
+  int job, result;
+  COMMAND *command;
+
+  /* First do the replacement of job specifications with pids. */
+  for (l = list; l; l = l->next)
+    {
+      if (l->word->word[0] == '%')     /* we have a winner */
+       {
+         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])
+           continue;
+
+         free (l->word->word);
+         l->word->word = itos (jobs[job]->pgrp);
+       }
+    }
+
+  /* Next make a new simple command and execute it. */
+  begin_unwind_frame ("jobs_builtin");
+
+  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;
+
+  add_unwind_protect (dispose_command, command);
+  result = execute_command (command);
+  dispose_command (command);
+
+  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 || job < 0 || job >= job_slots || jobs[job] == 0)
+       {
+         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 */
diff --git a/builtins/jobs.def~ b/builtins/jobs.def~
new file mode 100644 (file)
index 0000000..38e2232
--- /dev/null
@@ -0,0 +1,283 @@
+This file is jobs.def, from which is created jobs.c.
+It implements the builtins "jobs" and "disown" in Bash.
+
+Copyright (C) 1987-2003 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 2, 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; see the file COPYING.  If not, write to the Free Software
+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 [-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.  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 <config.h>
+
+#if defined (JOB_CONTROL)
+#include "../bashtypes.h"
+#include <signal.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
+
+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.
+   If the argument `-p' is given, print the process group leader's
+   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.  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, execute, state, opt, any_failed, job;
+  sigset_t set, oset;
+
+#if 0
+  if (job_control == 0 && interactive_shell == 0)
+    return (EXECUTION_SUCCESS);
+#endif
+
+  execute = any_failed = 0;
+  form = JLIST_STANDARD;
+  state = JSTATE_ANY;
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "lpnxrs")) != -1)
+    {
+      switch (opt)
+       {
+       case 'l':
+         form = JLIST_LONG;
+         break;
+       case 'p':
+         form = JLIST_PID_ONLY;
+         break;
+       case 'n':
+         form = JLIST_CHANGED_ONLY;
+         break;
+       case 'x':
+         if (form != JLIST_STANDARD)
+           {
+             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_usage ();
+         return (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  if (execute)
+    return (execute_list_with_replacements (list));
+
+  if (!list)
+    {
+      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)
+    {
+      BLOCK_CHILD (set, oset);
+      job = get_job_spec (list);
+
+      if ((job == NO_JOB) || !jobs || !jobs[job])
+       {
+         sh_badjob (list->word->word);
+         any_failed++;
+       }
+      else if (job != DUP_JOB)
+       list_one_job ((JOB *)NULL, form, 0, job);
+
+      UNBLOCK_CHILD (oset);
+      list = list->next;
+    }
+  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
+
+static int
+execute_list_with_replacements (list)
+     WORD_LIST *list;
+{
+  register WORD_LIST *l;
+  int job, result;
+  COMMAND *command;
+
+  /* First do the replacement of job specifications with pids. */
+  for (l = list; l; l = l->next)
+    {
+      if (l->word->word[0] == '%')     /* we have a winner */
+       {
+         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])
+           continue;
+
+         free (l->word->word);
+         l->word->word = itos (jobs[job]->pgrp);
+       }
+    }
+
+  /* Next make a new simple command and execute it. */
+  begin_unwind_frame ("jobs_builtin");
+
+  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;
+
+  add_unwind_protect (dispose_command, command);
+  result = execute_command (command);
+  dispose_command (command);
+
+  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 || job < 0 || job >= job_slots || jobs[job] == 0)
+       {
+         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 */
index fcd5f46..d1b9f6d 100644 (file)
@@ -1,7 +1,7 @@
 This file is kill.def, from which is created kill.c.
 It implements the builtin "kill" in Bash.
 
-Copyright (C) 1987-2003 Free Software Foundation, Inc.
+Copyright (C) 1987-2004 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -187,7 +187,7 @@ kill_builtin (list)
          builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
          CONTINUE_OR_FAIL;
        }
-      else if (*word && (interactive || job_control))
+      else if (*word)
        /* Posix.2 says you can kill without job control active (4.32.4) */
        {                       /* Must be a job spec.  Check it out. */
          int job;
diff --git a/builtins/kill.def.save1 b/builtins/kill.def.save1
new file mode 100644 (file)
index 0000000..fcd5f46
--- /dev/null
@@ -0,0 +1,250 @@
+This file is kill.def, from which is created kill.c.
+It implements the builtin "kill" in Bash.
+
+Copyright (C) 1987-2003 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 2, 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; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+$PRODUCES kill.c
+
+$BUILTIN kill
+$FUNCTION kill_builtin
+$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
+Send the processes named by PID (or JOB) the signal SIGSPEC.  If
+SIGSPEC is not present, then SIGTERM is assumed.  An argument of `-l'
+lists the signal names; if arguments follow `-l' they are assumed to
+be signal numbers for which names should be listed.  Kill is a shell
+builtin for two reasons: it allows job IDs to be used instead of
+process IDs, and, if you have reached the limit on processes that
+you can create, you don't have to start a process to kill another one.
+$END
+
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "../trap.h"
+#include "../jobs.h"
+#include "common.h"
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int posixly_correct;
+
+static void kill_error __P((pid_t, int));
+
+#if !defined (CONTINUE_AFTER_KILL_ERROR)
+#  define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
+#else
+#  define CONTINUE_OR_FAIL goto continue_killing
+#endif /* CONTINUE_AFTER_KILL_ERROR */
+
+/* Here is the kill builtin.  We only have it so that people can type
+   kill -KILL %1?  No, if you fill up the process table this way you
+   can still kill some. */
+int
+kill_builtin (list)
+     WORD_LIST *list;
+{
+  int sig, any_succeeded, listing, saw_signal, dflags;
+  char *sigspec, *word;
+  pid_t pid;
+  intmax_t pid_value;
+
+  if (list == 0)
+    {
+      builtin_usage ();
+      return (EXECUTION_FAILURE);
+    }
+
+  any_succeeded = listing = saw_signal = 0;
+  sig = SIGTERM;
+  sigspec = "TERM";
+
+  dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
+  /* Process options. */
+  while (list)
+    {
+      word = list->word->word;
+
+      if (ISOPTION (word, 'l'))
+       {
+         listing++;
+         list = list->next;
+       }
+      else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
+       {
+         list = list->next;
+         if (list)
+           {
+             sigspec = list->word->word;
+             if (sigspec[0] == '0' && sigspec[1] == '\0')
+               sig = 0;
+             else
+               sig = decode_signal (sigspec, dflags);
+             list = list->next;
+           }
+         else
+           {
+             sh_needarg (word);
+             return (EXECUTION_FAILURE);
+           }
+       }
+      else if (ISOPTION (word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else if (ISOPTION (word, '?'))
+       {
+         builtin_usage ();
+         return (EXECUTION_SUCCESS);
+       }
+      /* If this is a signal specification then process it.  We only process
+        the first one seen; other arguments may signify process groups (e.g,
+        -num == process group num). */
+      else if ((*word == '-') && !saw_signal)
+       {
+         sigspec = word + 1;
+         sig = decode_signal (sigspec, dflags);
+         saw_signal++;
+         list = list->next;
+       }
+      else
+       break;
+    }
+
+  if (listing)
+    return (display_signal_list (list, 0));
+
+  /* OK, we are killing processes. */
+  if (sig == NO_SIG)
+    {
+      sh_invalidsig (sigspec);
+      return (EXECUTION_FAILURE);
+    }
+
+  if (list == 0)
+    {
+      builtin_usage ();
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      word = list->word->word;
+
+      if (*word == '-')
+       word++;
+
+      /* Use the entire argument in case of minus sign presence. */
+      if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
+       {
+         pid = (pid_t) pid_value;
+
+         if ((pid < -1 ? kill_pid (-pid, sig, 1) : kill_pid (pid, sig, 0)) < 0)
+           {
+             if (errno == EINVAL)
+               sh_invalidsig (sigspec);
+             else
+               kill_error (pid, errno);
+             CONTINUE_OR_FAIL;
+           }
+         else
+           any_succeeded++;
+       }
+#if defined (JOB_CONTROL)
+      else if (*list->word->word && *list->word->word != '%')
+       {
+         builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
+         CONTINUE_OR_FAIL;
+       }
+      else if (*word && (interactive || job_control))
+       /* Posix.2 says you can kill without job control active (4.32.4) */
+       {                       /* Must be a job spec.  Check it out. */
+         int job;
+         sigset_t set, oset;
+
+         BLOCK_CHILD (set, oset);
+         job = get_job_spec (list);
+
+         if (job < 0 || job >= job_slots || !jobs[job])
+           {
+             if (job != DUP_JOB)
+               sh_badjob (list->word->word);
+             UNBLOCK_CHILD (oset);
+             CONTINUE_OR_FAIL;
+           }
+
+         /* Job spec used.  Kill the process group. If the job was started
+            without job control, then its pgrp == shell_pgrp, so we have
+            to be careful.  We take the pid of the first job in the pipeline
+            in that case. */
+         pid = IS_JOBCONTROL (job) ? jobs[job]->pgrp : jobs[job]->pipe->pid;
+
+         UNBLOCK_CHILD (oset);
+
+         if (kill_pid (pid, sig, 1) < 0)
+           {
+             if (errno == EINVAL)
+               sh_invalidsig (sigspec);
+             else
+               kill_error (pid, errno);
+             CONTINUE_OR_FAIL;
+           }
+         else
+           any_succeeded++;
+       }
+#endif /* !JOB_CONTROL */
+      else
+       {
+         sh_badpid (list->word->word);
+         CONTINUE_OR_FAIL;
+       }
+    continue_killing:
+      list = list->next;
+    }
+
+  return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+}
+
+static void
+kill_error (pid, e)
+     pid_t pid;
+     int e;
+{
+  char *x;
+
+  x = strerror (e);
+  if (x == 0)
+    x = _("Unknown error");
+  builtin_error ("(%ld) - %s", (long)pid, x);
+}
diff --git a/builtins/kill.def~ b/builtins/kill.def~
new file mode 100644 (file)
index 0000000..77f52af
--- /dev/null
@@ -0,0 +1,250 @@
+This file is kill.def, from which is created kill.c.
+It implements the builtin "kill" in Bash.
+
+Copyright (C) 1987-2003 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 2, 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; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+$PRODUCES kill.c
+
+$BUILTIN kill
+$FUNCTION kill_builtin
+$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
+Send the processes named by PID (or JOB) the signal SIGSPEC.  If
+SIGSPEC is not present, then SIGTERM is assumed.  An argument of `-l'
+lists the signal names; if arguments follow `-l' they are assumed to
+be signal numbers for which names should be listed.  Kill is a shell
+builtin for two reasons: it allows job IDs to be used instead of
+process IDs, and, if you have reached the limit on processes that
+you can create, you don't have to start a process to kill another one.
+$END
+
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "../trap.h"
+#include "../jobs.h"
+#include "common.h"
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int posixly_correct;
+
+static void kill_error __P((pid_t, int));
+
+#if !defined (CONTINUE_AFTER_KILL_ERROR)
+#  define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
+#else
+#  define CONTINUE_OR_FAIL goto continue_killing
+#endif /* CONTINUE_AFTER_KILL_ERROR */
+
+/* Here is the kill builtin.  We only have it so that people can type
+   kill -KILL %1?  No, if you fill up the process table this way you
+   can still kill some. */
+int
+kill_builtin (list)
+     WORD_LIST *list;
+{
+  int sig, any_succeeded, listing, saw_signal, dflags;
+  char *sigspec, *word;
+  pid_t pid;
+  intmax_t pid_value;
+
+  if (list == 0)
+    {
+      builtin_usage ();
+      return (EXECUTION_FAILURE);
+    }
+
+  any_succeeded = listing = saw_signal = 0;
+  sig = SIGTERM;
+  sigspec = "TERM";
+
+  dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
+  /* Process options. */
+  while (list)
+    {
+      word = list->word->word;
+
+      if (ISOPTION (word, 'l'))
+       {
+         listing++;
+         list = list->next;
+       }
+      else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
+       {
+         list = list->next;
+         if (list)
+           {
+             sigspec = list->word->word;
+             if (sigspec[0] == '0' && sigspec[1] == '\0')
+               sig = 0;
+             else
+               sig = decode_signal (sigspec, dflags);
+             list = list->next;
+           }
+         else
+           {
+             sh_needarg (word);
+             return (EXECUTION_FAILURE);
+           }
+       }
+      else if (ISOPTION (word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else if (ISOPTION (word, '?'))
+       {
+         builtin_usage ();
+         return (EXECUTION_SUCCESS);
+       }
+      /* If this is a signal specification then process it.  We only process
+        the first one seen; other arguments may signify process groups (e.g,
+        -num == process group num). */
+      else if ((*word == '-') && !saw_signal)
+       {
+         sigspec = word + 1;
+         sig = decode_signal (sigspec, dflags);
+         saw_signal++;
+         list = list->next;
+       }
+      else
+       break;
+    }
+
+  if (listing)
+    return (display_signal_list (list, 0));
+
+  /* OK, we are killing processes. */
+  if (sig == NO_SIG)
+    {
+      sh_invalidsig (sigspec);
+      return (EXECUTION_FAILURE);
+    }
+
+  if (list == 0)
+    {
+      builtin_usage ();
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      word = list->word->word;
+
+      if (*word == '-')
+       word++;
+
+      /* Use the entire argument in case of minus sign presence. */
+      if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
+       {
+         pid = (pid_t) pid_value;
+
+         if ((pid < -1 ? kill_pid (-pid, sig, 1) : kill_pid (pid, sig, 0)) < 0)
+           {
+             if (errno == EINVAL)
+               sh_invalidsig (sigspec);
+             else
+               kill_error (pid, errno);
+             CONTINUE_OR_FAIL;
+           }
+         else
+           any_succeeded++;
+       }
+#if defined (JOB_CONTROL)
+      else if (*list->word->word && *list->word->word != '%')
+       {
+         builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
+         CONTINUE_OR_FAIL;
+       }
+      else if (*word)
+       /* Posix.2 says you can kill without job control active (4.32.4) */
+       {                       /* Must be a job spec.  Check it out. */
+         int job;
+         sigset_t set, oset;
+
+         BLOCK_CHILD (set, oset);
+         job = get_job_spec (list);
+
+         if (job < 0 || job >= job_slots || !jobs[job])
+           {
+             if (job != DUP_JOB)
+               sh_badjob (list->word->word);
+             UNBLOCK_CHILD (oset);
+             CONTINUE_OR_FAIL;
+           }
+
+         /* Job spec used.  Kill the process group. If the job was started
+            without job control, then its pgrp == shell_pgrp, so we have
+            to be careful.  We take the pid of the first job in the pipeline
+            in that case. */
+         pid = IS_JOBCONTROL (job) ? jobs[job]->pgrp : jobs[job]->pipe->pid;
+
+         UNBLOCK_CHILD (oset);
+
+         if (kill_pid (pid, sig, 1) < 0)
+           {
+             if (errno == EINVAL)
+               sh_invalidsig (sigspec);
+             else
+               kill_error (pid, errno);
+             CONTINUE_OR_FAIL;
+           }
+         else
+           any_succeeded++;
+       }
+#endif /* !JOB_CONTROL */
+      else
+       {
+         sh_badpid (list->word->word);
+         CONTINUE_OR_FAIL;
+       }
+    continue_killing:
+      list = list->next;
+    }
+
+  return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+}
+
+static void
+kill_error (pid, e)
+     pid_t pid;
+     int e;
+{
+  char *x;
+
+  x = strerror (e);
+  if (x == 0)
+    x = _("Unknown error");
+  builtin_error ("(%ld) - %s", (long)pid, x);
+}
index 23c8b19..9eb66f6 100644 (file)
@@ -1,7 +1,7 @@
 This file is wait.def, from which is created wait.c.
 It implements the builtin "wait" in Bash.
 
-Copyright (C) 1987-2002 Free Software Foundation, Inc.
+Copyright (C) 1987-2004 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -141,7 +141,7 @@ wait_builtin (list)
            }
        }
 #if defined (JOB_CONTROL)
-      else if (job_control && *w)
+      else if (*w && *w == '%')
        /* Must be a job spec.  Check it out. */
        {
          int job;
@@ -164,12 +164,6 @@ wait_builtin (list)
          UNBLOCK_CHILD (oset);
          status = wait_for_job (job);
        }
-      else if (job_control == 0 && *w == '%')
-       {
-         /* can't use jobspecs as arguments if job control is not active. */
-         sh_nojobs ((char *)NULL);
-         status = EXECUTION_FAILURE;
-       }
 #endif /* JOB_CONTROL */
       else
        {
diff --git a/builtins/wait.def.save1 b/builtins/wait.def.save1
new file mode 100644 (file)
index 0000000..23c8b19
--- /dev/null
@@ -0,0 +1,183 @@
+This file is wait.def, from which is created wait.c.
+It implements the builtin "wait" in Bash.
+
+Copyright (C) 1987-2002 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 2, 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; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+$BUILTIN wait
+$FUNCTION wait_builtin
+$DEPENDS_ON JOB_CONTROL
+$PRODUCES wait.c
+$SHORT_DOC wait [n]
+Wait for the specified process and report its termination status.  If
+N is not given, all currently active child processes are waited for,
+and the return code is zero.  N may be a process ID or a job
+specification; if a job spec is given, all processes in the job's
+pipeline are waited for.
+$END
+
+$BUILTIN wait
+$FUNCTION wait_builtin
+$DEPENDS_ON !JOB_CONTROL
+$SHORT_DOC wait [n]
+Wait for the specified process and report its termination status.  If
+N is not given, all currently active child processes are waited for,
+and the return code is zero.  N is a process ID; if it is not given,
+all child processes of the shell are waited for.
+$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 interrupt_immediately;
+extern int wait_signal_received;
+
+procenv_t wait_intr_buf;
+
+/* 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;\
+      return (s);\
+    } \
+  while (0)
+
+int
+wait_builtin (list)
+     WORD_LIST *list;
+{
+  int status, code;
+  volatile int old_interrupt_immediately;
+
+  USE_VAR(list);
+
+  if (no_options (list))
+    return (EX_USAGE);
+  list = loptend;
+
+  old_interrupt_immediately = interrupt_immediately;
+  interrupt_immediately++;
+
+  /* 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. */
+  code = setjmp (wait_intr_buf);
+  if (code)
+    {
+      status = 128 + wait_signal_received;
+      WAIT_RETURN (status);
+    }
+
+  /* We support jobs or pids.
+     wait <pid-or-job> [pid-or-job ...] */
+
+  /* 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);
+           }
+         else
+           {
+             sh_badpid (w);
+             WAIT_RETURN (EXECUTION_FAILURE);
+           }
+       }
+#if defined (JOB_CONTROL)
+      else if (job_control && *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 (job < 0 || job >= job_slots || !jobs[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);
+       }
+      else if (job_control == 0 && *w == '%')
+       {
+         /* can't use jobspecs as arguments if job control is not active. */
+         sh_nojobs ((char *)NULL);
+         status = EXECUTION_FAILURE;
+       }
+#endif /* JOB_CONTROL */
+      else
+       {
+         sh_badpid (w);
+         status = EXECUTION_FAILURE;
+       }
+      list = list->next;
+    }
+
+  WAIT_RETURN (status);
+}
diff --git a/builtins/wait.def~ b/builtins/wait.def~
new file mode 100644 (file)
index 0000000..53533ba
--- /dev/null
@@ -0,0 +1,177 @@
+This file is wait.def, from which is created wait.c.
+It implements the builtin "wait" in Bash.
+
+Copyright (C) 1987-2004 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 2, 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; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+$BUILTIN wait
+$FUNCTION wait_builtin
+$DEPENDS_ON JOB_CONTROL
+$PRODUCES wait.c
+$SHORT_DOC wait [n]
+Wait for the specified process and report its termination status.  If
+N is not given, all currently active child processes are waited for,
+and the return code is zero.  N may be a process ID or a job
+specification; if a job spec is given, all processes in the job's
+pipeline are waited for.
+$END
+
+$BUILTIN wait
+$FUNCTION wait_builtin
+$DEPENDS_ON !JOB_CONTROL
+$SHORT_DOC wait [n]
+Wait for the specified process and report its termination status.  If
+N is not given, all currently active child processes are waited for,
+and the return code is zero.  N is a process ID; if it is not given,
+all child processes of the shell are waited for.
+$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 interrupt_immediately;
+extern int wait_signal_received;
+
+procenv_t wait_intr_buf;
+
+/* 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;\
+      return (s);\
+    } \
+  while (0)
+
+int
+wait_builtin (list)
+     WORD_LIST *list;
+{
+  int status, code;
+  volatile int old_interrupt_immediately;
+
+  USE_VAR(list);
+
+  if (no_options (list))
+    return (EX_USAGE);
+  list = loptend;
+
+  old_interrupt_immediately = interrupt_immediately;
+  interrupt_immediately++;
+
+  /* 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. */
+  code = setjmp (wait_intr_buf);
+  if (code)
+    {
+      status = 128 + wait_signal_received;
+      WAIT_RETURN (status);
+    }
+
+  /* We support jobs or pids.
+     wait <pid-or-job> [pid-or-job ...] */
+
+  /* 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);
+           }
+         else
+           {
+             sh_badpid (w);
+             WAIT_RETURN (EXECUTION_FAILURE);
+           }
+       }
+#if defined (JOB_CONTROL)
+      else if (*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 (job < 0 || job >= job_slots || !jobs[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);
+}
index 53ef150..ba83423 100644 (file)
@@ -1729,17 +1729,17 @@ A\bAL\bLI\bIA\bAS\bSE\bES\bS
        the first word of a simple command.  The  shell  maintains  a  list  of
        aliases  that  may  be set and unset with the a\bal\bli\bia\bas\bs and u\bun\bna\bal\bli\bia\bas\bs builtin
        commands (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below).  The first  word  of  each
-       command,  if  unquoted,  is  checked to see if it has an alias.  If so,
-       that word is replaced by the text of the alias.  The alias name and the
-       replacement  text  may  contain  any  valid  shell input, including the
-       _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br_\bs listed above, with the exception that the alias name may
-       not  contain  _\b=.   The first word of the replacement text is tested for
-       aliases, but a word that is identical to an alias being expanded is not
-       expanded a second time.  This means that one may alias l\bls\bs to l\bls\bs -\b-F\bF, for
-       instance, and b\bba\bas\bsh\bh does not try to recursively expand  the  replacement
-       text.   If  the  last character of the alias value is a _\bb_\bl_\ba_\bn_\bk, then the
-       next command word following the alias is also checked for alias  expan-
-       sion.
+       simple  command, if unquoted, is checked to see if it has an alias.  If
+       so, that word is replaced by the text of the alias.  The characters  /\b/,
+       $\b$,  `\b`,  and =\b= and any of the shell _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br_\bs or quoting characters
+       listed above may not appear in an alias name.  The replacement text may
+       contain  any  valid  shell  input, including shell metacharacters.  The
+       first word of the replacement text is tested for aliases,  but  a  word
+       that  is  identical to an alias being expanded is not expanded a second
+       time.  This means that one may alias l\bls\bs to l\bls\bs  -\b-F\bF,  for  instance,  and
+       b\bba\bas\bsh\bh  does  not try to recursively expand the replacement text.  If the
+       last character of the alias value is a _\bb_\bl_\ba_\bn_\bk,  then  the  next  command
+       word following the alias is also checked for alias expansion.
 
        Aliases are created and listed with the a\bal\bli\bia\bas\bs command, and removed with
        the u\bun\bna\bal\bli\bia\bas\bs command.
@@ -1778,16 +1778,16 @@ F\bFU\bUN\bNC\bCT\bTI\bIO\bON\bNS\bS
        interpret them (contrast this with the execution of  a  shell  script).
        When  a  function is executed, the arguments to the function become the
        positional parameters during its execution.  The special parameter #\b# is
-       updated  to  reflect  the change.  Positional parameter 0 is unchanged.
-       The first element of the F\bFU\bUN\bNC\bCN\bNA\bAM\bME\bE variable is set to the  name  of  the
-       function  while  the  function  is executing.  All other aspects of the
-       shell execution environment are identical between a  function  and  its
-       caller  with  the exception that the D\bDE\bEB\bBU\bUG\bG trap (see the description of
-       the t\btr\bra\bap\bp builtin under S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below) is  not  inherited
-       unless  the  function  has  been  given  the  t\btr\bra\bac\bce\be  attribute (see the
-       description of the d\bde\bec\bcl\bla\bar\bre\be builtin below) or  the  -\b-o\bo  f\bfu\bun\bnc\bct\btr\bra\bac\bce\be  shell
-       option  has  been enabled with the s\bse\bet\bt builtin (in which case all func-
-       tions inherit the D\bDE\bEB\bBU\bUG\bG trap).
+       updated  to reflect the change.  Special parameter 0 is unchanged.  The
+       first element of the F\bFU\bUN\bNC\bCN\bNA\bAM\bME\bE variable is set to the name of the  func-
+       tion  while  the function is executing.  All other aspects of the shell
+       execution environment are identical between a function and  its  caller
+       with the exception that the D\bDE\bEB\bBU\bUG\bG trap (see the description of the t\btr\bra\bap\bp
+       builtin under S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below) is not inherited unless the
+       function has been given the t\btr\bra\bac\bce\be attribute (see the description of the
+       d\bde\bec\bcl\bla\bar\bre\be builtin below) or  the  -\b-o\bo  f\bfu\bun\bnc\bct\btr\bra\bac\bce\be  shell  option  has  been
+       enabled  with  the s\bse\bet\bt builtin (in which case all functions inherit the
+       D\bDE\bEB\bBU\bUG\bG trap).
 
        Variables local to the function may be declared with the l\blo\boc\bca\bal\bl  builtin
        command.  Ordinarily, variables and their values are shared between the
@@ -4775,4 +4775,4 @@ B\bBU\bUG\bGS\bS
 
 
 
-GNU Bash-3.0                      2004 Jan 28                          BASH(1)
+GNU Bash-3.0                      2004 Apr 20                          BASH(1)
index 8cab77f..4d1cc25 100644 (file)
@@ -6,12 +6,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.CWRU.Edu
 .\"
-.\"    Last Change: Wed Jan 28 15:49:29 EST 2004
+.\"    Last Change: Tue Apr 20 13:39:08 EDT 2004
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2004 Jan 28" "GNU Bash-3.0"
+.TH BASH 1 "2004 Apr 20" "GNU Bash-3.0"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -3189,16 +3189,18 @@ builtin commands (see
 .SM
 .B SHELL BUILTIN COMMANDS
 below).
-The first word of each command, if unquoted,
+The first word of each simple command, if unquoted,
 is checked to see if it has an
 alias.  If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including the
-.I metacharacters
-listed above, with the exception that the alias name may not
-contain \fI=\fP.  The first word of the replacement text is tested
+The characters \fB/\fP, \fB$\fP, \fB`\fP, and \fB=\fP and
+any of the shell \fImetacharacters\fP or quoting characters
+listed above may not appear in an alias name.
+The replacement text may contain any valid shell input,
+including shell metacharacters.
+The first word of the replacement text is tested
 for aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.  This means that one may alias
+is not expanded a second time.
+This means that one may alias
 .B ls
 to
 .BR "ls \-F" ,
@@ -3272,7 +3274,7 @@ function become the positional parameters
 during its execution.
 The special parameter
 .B #
-is updated to reflect the change.  Positional parameter 0
+is updated to reflect the change.  Special parameter 0
 is unchanged.
 The first element of the
 .SM
index 5953d06..77b63f8 100644 (file)
@@ -2,7 +2,7 @@
 <TITLE>BASH(1) Manual Page</TITLE>
 </HEAD>
 <BODY><TABLE WIDTH=100%>
-<TH ALIGN=LEFT>BASH(1)<TH ALIGN=CENTER>2004 Jan 28<TH ALIGN=RIGHT>BASH(1)
+<TH ALIGN=LEFT>BASH(1)<TH ALIGN=CENTER>2004 Apr 20<TH ALIGN=RIGHT>BASH(1)
 </TABLE>
 <BR><A HREF="#index">Index</A>
 <HR>
@@ -4156,17 +4156,18 @@ builtin commands (see
 
 </FONT>
 below).
-The first word of each command, if unquoted,
+The first word of each simple command, if unquoted,
 is checked to see if it has an
 alias.  If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including the
-<I>metacharacters</I>
-
-listed above, with the exception that the alias name may not
-contain <I>=</I>.  The first word of the replacement text is tested
+The characters <B>/</B>, <B>$</B>, <B>`</B>, and <B>=</B> and
+any of the shell <I>metacharacters</I> or quoting characters
+listed above may not appear in an alias name.
+The replacement text may contain any valid shell input,
+including shell metacharacters.
+The first word of the replacement text is tested
 for aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.  This means that one may alias
+is not expanded a second time.
+This means that one may alias
 <B>ls</B>
 
 to
@@ -4260,7 +4261,7 @@ during its execution.
 The special parameter
 <B>#</B>
 
-is updated to reflect the change.  Positional parameter 0
+is updated to reflect the change.  Special parameter 0
 is unchanged.
 The first element of the
 <FONT SIZE=-1><B>FUNCNAME</B>
@@ -11343,6 +11344,6 @@ Array variables may not (yet) be exported.
 </DL>
 <HR>
 This document was created by man2html from bash.1.<BR>
-Time: 29 January 2004 16:59:30 EST
+Time: 20 April 2004 15:26:54 EDT
 </BODY>
 </HTML>
index 35be556..a8c6955 100644 (file)
@@ -1,6 +1,6 @@
 %!PS-Adobe-3.0
-%%Creator: groff version 1.18.1
-%%CreationDate: Thu Jan 29 16:59:28 2004
+%%Creator: groff version 1.19
+%%CreationDate: Tue Apr 20 15:26:44 2004
 %%DocumentNeededResources: font Times-Roman
 %%+ font Times-Bold
 %%+ font Times-Italic
@@ -9,13 +9,17 @@
 %%+ font Palatino-Roman
 %%+ font Palatino-Italic
 %%+ font Palatino-Bold
-%%DocumentSuppliedResources: procset grops 1.18 1
+%%DocumentSuppliedResources: procset grops 1.19 0
 %%Pages: 63
 %%PageOrder: Ascend
+%%DocumentMedia: Default 612 792 0 () ()
 %%Orientation: Portrait
 %%EndComments
+%%BeginDefaults
+%%PageMedia: Default
+%%EndDefaults
 %%BeginProlog
-%%BeginResource: procset grops 1.18 1
+%%BeginResource: procset grops 1.19 0
 /setpacking where{
 pop
 currentpacking
@@ -116,16 +120,22 @@ TM setmatrix
 /Fr{
 setrgbcolor fill
 }bind def
+/setcmykcolor where{
+pop
 /Fk{
 setcmykcolor fill
 }bind def
+}if
 /Fg{
 setgray fill
 }bind def
 /FL/fill load def
 /LW/setlinewidth load def
 /Cr/setrgbcolor load def
+/setcmykcolor where{
+pop
 /Ck/setcmykcolor load def
+}if
 /Cg/setgray load def
 /RE{
 findfont
@@ -168,6 +178,7 @@ newpath
 /CNT countdictstack def
 userdict begin
 /showpage{}def
+/setpagedevice{}def
 }bind def
 /PEND{
 clear
@@ -180,6 +191,9 @@ pop
 setpacking
 }if
 %%EndResource
+%%BeginFeature: *PageSize Default
+<< /PageSize [ 612 792 ] /ImagingBBox null >> setpagedevice
+%%EndFeature
 %%IncludeResource: font Times-Roman
 %%IncludeResource: font Times-Bold
 %%IncludeResource: font Times-Italic
@@ -321,7 +335,7 @@ E F2(po)2.5 E F0(\(portable object\) \214le format.)2.5 E F2
 144 686.4 Q .3 -.15(ve \()-.25 H(see).15 E F4(INV)2.5 E(OCA)-.405 E
 (TION)-.855 E F0(belo)2.25 E(w\).)-.25 E F2(\255\255login)108 703.2 Q F0
 (Equi)144 715.2 Q -.25(va)-.25 G(lent to).25 E F2<ad6c>2.5 E F0(.)A
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(1)204.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(1)203.725 E 0 Cg EP
 %%Page: 2 2
 %%BeginPageSetup
 BP
@@ -444,7 +458,7 @@ F(ariable)-.25 E F3 -.27(BA)108 679.2 S(SH_ENV).27 E F0 1.01(in the en)
 108 727.2 S 2.5(tt).2 G(he v)-2.5 E(alue of the)-.25 E F3 -.666(PA)2.5 G
 (TH)-.189 E F0 -.25(va)2.25 G
 (riable is not used to search for the \214le name.).25 E(GNU Bash-3.0)72
-768 Q(2004 Jan 28)149.845 E(2)204.835 E 0 Cg EP
+768 Q(2004 Apr 20)148.735 E(2)203.725 E 0 Cg EP
 %%Page: 3 3
 %%BeginPageSetup
 BP
@@ -569,7 +583,7 @@ F1(Pipelines)87 679.2 Q F0(A)108 691.2 Q F2(pipeline)2.919 E F0 .419
 F F1(|)2.92 E F0 5.42(.T)C .42(he format for a pipeline)-5.42 F(is:)108
 703.2 Q([)144 720 Q F1(time)A F0([)2.5 E F1<ad70>A F0(]] [ ! ])A F2
 (command)2.5 E F0([)2.5 E F1(|)2.5 E F2(command2)2.5 E F0(... ])2.5 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(3)204.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(3)203.725 E 0 Cg EP
 %%Page: 4 4
 %%BeginPageSetup
 BP
@@ -689,7 +703,7 @@ A({)108 573.6 Q F1(list)2.5 E F0 2.5(;})C F1(list)3.89 E F0 .402
 F(SIONS)144 727.2 Q F5(.)A F0 -.8(Wo)5.633 G 1.133
 (rd splitting and pathname e).8 F 1.133
 (xpansion are not performed on the w)-.15 F 1.133(ords between the)-.1 F
-F3([[)3.632 E F0(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(4)204.835 E
+F3([[)3.632 E F0(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(4)203.725 E
 0 Cg EP
 %%Page: 5 5
 %%BeginPageSetup
@@ -829,7 +843,7 @@ F F2(name)144 727.2 Q F0 .759(to be set to null.)3.439 F .759
 (The line read is sa)5.759 F -.15(ve)-.2 G 3.26(di).15 G 3.26(nt)-3.26 G
 .76(he v)-3.26 F(ariable)-.25 E F1(REPL)3.26 E(Y)-.92 E F0 5.76(.T)C(he)
 -5.76 E F2(list)3.35 E F0 .76(is e)3.94 F -.15(xe)-.15 G .76
-(cuted after).15 F(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(5)204.835
+(cuted after).15 F(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(5)203.725
 E 0 Cg EP
 %%Page: 6 6
 %%BeginPageSetup
@@ -965,7 +979,7 @@ E(xpansion.)-.15 E(There are three quoting mechanisms: the)108 708 Q F2
 G(he)-2.974 E F2 .474(escape c)2.974 F(har)-.15 E(acter)-.15 E F0 5.474
 (.I).73 G 2.974(tp)-5.474 G(reserv)-2.974 E .474(es the literal v)-.15 F
 .474(alue of the ne)-.25 F .474(xt character that)-.15 F(GNU Bash-3.0)72
-768 Q(2004 Jan 28)149.845 E(6)204.835 E 0 Cg EP
+768 Q(2004 Apr 20)148.735 E(6)203.725 E 0 Cg EP
 %%Page: 7 7
 %%BeginPageSetup
 BP
@@ -1082,7 +1096,7 @@ d by one or more digits, other than the single digit 0.)3.935 F(Posi-)
 5.706 E .445(tional parameters are assigned from the shell')108 729.6 R
 2.944(sa)-.55 G -.18(rg)-2.944 G .444(uments when it is in).18 F -.2(vo)
 -.4 G -.1(ke).2 G .444(d, and may be reassigned using).1 F(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(7)204.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(7)203.725 E 0 Cg EP
 %%Page: 8 8
 %%BeginPageSetup
 BP
@@ -1200,7 +1214,7 @@ F F1 -.3(BA)144 619.2 S(SH_ARGV).3 E F0(.)A F1 -.3(BA)108 631.2 S
 F F1(${FUNCN)144 727.2 Q(AME[)-.2 E F3 8.951($i + 1)B F1(]})A F0 -.1(wa)
 11.451 G 11.451(sc).1 G 11.451(alled. The)-11.451 F 8.951
 (corresponding source \214le name is)11.451 F(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(8)204.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(8)203.725 E 0 Cg EP
 %%Page: 9 9
 %%BeginPageSetup
 BP
@@ -1301,7 +1315,7 @@ F(ariable)-.25 E .351(will not change the current directory)144 711.6 R
 5.35(.I)-.65 G(f)-5.35 E F3(DIRST)2.85 E -.495(AC)-.81 G(K).495 E F0 .35
 (is unset, it loses its special properties, e)2.6 F -.15(ve)-.25 G 2.85
 (ni).15 G(f)-2.85 E(it is subsequently reset.)144 723.6 Q(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(9)204.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(9)203.725 E 0 Cg EP
 %%Page: 10 10
 %%BeginPageSetup
 BP
@@ -1390,7 +1404,7 @@ R .01(alue to)-.25 F F2(RANDOM)2.51 E/F4 9/Times-Roman@0 SF(.)A F0(If)
 4.51 E F2(RANDOM)2.51 E F0(is)2.26 E
 (unset, it loses its special properties, e)144 720 Q -.15(ve)-.25 G 2.5
 (ni).15 G 2.5(fi)-2.5 G 2.5(ti)-2.5 G 2.5(ss)-2.5 G(ubsequently reset.)
--2.5 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(10)199.835 E 0 Cg EP
+-2.5 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(10)198.725 E 0 Cg EP
 %%Page: 11 11
 %%BeginPageSetup
 BP
@@ -1499,7 +1513,7 @@ me e)-3.118 F(xpan-)-.15 E 3.131(sion. If)144 640.8 R 3.132<618c>3.131 G
 (all pre)144 724.8 R .698
 (vious lines matching the current line to be remo)-.25 F -.15(ve)-.15 G
 3.198(df).15 G .698(rom the history list before that line is)-3.198 F
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(11)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(11)198.725 E 0 Cg EP
 %%Page: 12 12
 %%BeginPageSetup
 BP
@@ -1612,7 +1626,7 @@ E F1(LANG)108 648 Q F0 1.24(Used to determine the locale cate)7.11 F
 (rrides the v).15 F .764(alue of)-.25 F F1(LANG)3.264 E F0 .764(and an)
 3.264 F 3.264(yo)-.15 G(ther)-3.264 E F1(LC_)3.264 E F0 -.25(va)3.264 G
 .764(riable specifying a locale cate-).25 F(gory)144 696 Q(.)-.65 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(12)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(12)198.725 E 0 Cg EP
 %%Page: 13 13
 %%BeginPageSetup
 BP
@@ -1716,8 +1730,8 @@ F0 1.225(displays during an e)3.725 F -.15(xe)-.15 G 1.225
 E F0 1.226(is replicated multiple)3.476 F(times, as necessary)144 696 Q
 2.5(,t)-.65 G 2.5(oi)-2.5 G(ndicate multiple le)-2.5 E -.15(ve)-.25 G
 (ls of indirection.).15 E(The def)5 E(ault is `)-.1 E(`)-.74 E F1(+)A F0
--.74('')2.5 G(.).74 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(13)
-199.835 E 0 Cg EP
+-.74('')2.5 G(.).74 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(13)
+198.725 E 0 Cg EP
 %%Page: 14 14
 %%BeginPageSetup
 BP
@@ -1835,7 +1849,7 @@ G .961(or an)-3.461 F 3.461(yr)-.15 G(equirement)-3.461 E
 1.302(An array is created automatically if an)108 728.4 R 3.801(yv)-.15
 G 1.301(ariable is assigned to using the syntax)-4.051 F F2(name)3.801 E
 F0([)A F2(subscript)A F0(]=)A F2(value)A F0(.)A(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(14)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(14)198.725 E 0 Cg EP
 %%Page: 15 15
 %%BeginPageSetup
 BP
@@ -1987,7 +2001,7 @@ F0(must be of the same type.)2.5 E .582(Brace e)108 705.6 R .582
 (does not apply an)2.516 F 2.516(ys)-.15 G .016
 (yntactic interpretation to the con-)-2.516 F(te)108 729.6 Q
 (xt of the e)-.15 E(xpansion or the te)-.15 E(xt between the braces.)
--.15 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(15)199.835 E 0 Cg EP
+-.15 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(15)198.725 E 0 Cg EP
 %%Page: 16 16
 %%BeginPageSetup
 BP
@@ -2115,7 +2129,7 @@ E .351(able is then e)108 700.8 R .351(xpanded and that v)-.15 F .352
 F2(@)A F0 .762(]} described belo)B 4.563 -.65(w. T)-.25 H .763(he e).65
 F .763(xclamation point must immediately follo)-.15 F 3.263(wt)-.25 G
 .763(he left brace in order to)-3.263 F(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(16)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(16)198.725 E 0 Cg EP
 %%Page: 17 17
 %%BeginPageSetup
 BP
@@ -2238,7 +2252,7 @@ F1(par)145.25 664.8 Q(ameter)-.15 E F0 .607
 3.151(,t)C .651(he pattern remo)-3.151 F -.25(va)-.15 G 3.151(lo).25 G
 .65(peration is applied to each member of the array in)-3.151 F
 (turn, and the e)144 712.8 Q(xpansion is the resultant list.)-.15 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(17)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(17)198.725 E 0 Cg EP
 %%Page: 18 18
 %%BeginPageSetup
 BP
@@ -2351,7 +2365,7 @@ F1 -.2(ex)2.666 G(pr).2 E(ession)-.37 E F0 .165
 A F0(If)5.878 E F1 -.2(ex)108 705.6 S(pr).2 E(ession)-.37 E F0(is in)
 2.74 E -.25(va)-.4 G(lid,).25 E F2(bash)2.5 E F0
 (prints a message indicating f)2.5 E(ailure and no substitution occurs.)
--.1 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(18)199.835 E 0 Cg EP
+-.1 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(18)198.725 E 0 Cg EP
 %%Page: 19 19
 %%BeginPageSetup
 BP
@@ -2488,8 +2502,8 @@ R 1.12(NUL character may not occur in a pattern.)3.62 F 3.62(Ab)6.12 G
 (The special pattern characters must be quoted if the)5.576 F 3.076(ya)
 -.15 G(re)-3.076 E(to be matched literally)108 691.2 Q(.)-.65 E
 (The special pattern characters ha)108 708 Q .3 -.15(ve t)-.2 H
-(he follo).15 E(wing meanings:)-.25 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)
-149.845 E(19)199.835 E 0 Cg EP
+(he follo).15 E(wing meanings:)-.25 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)
+148.735 E(19)198.725 E 0 Cg EP
 %%Page: 20 20
 %%BeginPageSetup
 BP
@@ -2576,12 +2590,12 @@ F2 -.37(re)3.045 G(dir).37 E(ected)-.37 E F0 .545
 (ywhere within a)-.15 F F2 .775(simple command)3.615 F F0(or)4.045 E
 (may follo)108 584.4 Q 2.5(wa)-.25 G F2(command)A F0 5(.R).77 G
 (edirections are processed in the order the)-5 E 2.5(ya)-.15 G(ppear)
--2.5 E 2.5(,f)-.4 G(rom left to right.)-2.5 E .448(In the follo)108
-601.2 R .447(wing descriptions, if the \214le descriptor number is omit\
-ted, and the \214rst character of the redirec-)-.25 F .365
-(tion operator is)108 613.2 R F1(<)2.865 E F0 2.865(,t)C .366
+-2.5 E 2.5(,f)-.4 G(rom left to right.)-2.5 E .284(In the follo)108
+601.2 R .283(wing descriptions, if the \214le descriptor number is omit\
+ted, and the \214rst character of the redirect-)-.25 F .512
+(ion operator is)108 613.2 R F1(<)3.012 E F0 3.012(,t)C .512
 (he redirection refers to the standard input \(\214le descriptor 0\).)
--2.865 F .366(If the \214rst character of the)5.366 F
+-3.012 F .512(If the \214rst character of the)5.512 F
 (redirection operator is)108 625.2 Q F1(>)2.5 E F0 2.5(,t)C
 (he redirection refers to the standard output \(\214le descriptor 1\).)
 -2.5 E .825(The w)108 642 R .825(ord follo)-.1 F .824
@@ -2599,7 +2613,7 @@ ted, and the \214rst character of the redirec-)-.25 F .365
 E F0(dirlist 2)2.5 E F1(>&)A F0(1)A
 (directs both standard output and standard error to the \214le)108 728.4
 Q F2(dirlist)2.5 E F0 2.5(,w).68 G(hile the command)-2.5 E(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(20)199.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(20)198.725 E 0 Cg EP
 %%Page: 21 21
 %%BeginPageSetup
 BP
@@ -2658,15 +2672,15 @@ F2(n)A F0(])A F1(>)A F2(wor)A(d)-.37 E F0 .155
 (If the redirection operator is)108 508.8 R F1(>)2.655 E F0 2.655(,a)C
 .155(nd the)-2.655 F F1(noclob)2.655 E(ber)-.1 E F0 .154(option to the)
 2.654 F F1(set)2.654 E F0 -.2(bu)2.654 G .154
-(iltin has been enabled, the redirection).2 F .076(will f)108 520.8 R
-.076(ail if the \214le whose name results from the e)-.1 F .076
-(xpansion of)-.15 F F2(wor)2.576 E(d)-.37 E F0 -.15(ex)2.576 G .076
-(ists and is a re).15 F .077(gular \214le.)-.15 F .077(If the redirec-)
-5.077 F .548(tion operator is)108 532.8 R F1(>|)3.048 E F0 3.048(,o)C
-3.048(rt)-3.048 G .548(he redirection operator is)-3.048 F F1(>)3.047 E
-F0 .547(and the)3.047 F F1(noclob)3.047 E(ber)-.1 E F0 .547
-(option to the)3.047 F F1(set)3.047 E F0 -.2(bu)3.047 G .547
-(iltin command is).2 F(not enabled, the redirection is attempted e)108
+(iltin has been enabled, the redirection).2 F .657(will f)108 520.8 R
+.657(ail if the \214le whose name results from the e)-.1 F .658
+(xpansion of)-.15 F F2(wor)3.158 E(d)-.37 E F0 -.15(ex)3.158 G .658
+(ists and is a re).15 F .658(gular \214le.)-.15 F .658(If the redi-)
+5.658 F .409(rection operator is)108 532.8 R F1(>|)2.909 E F0 2.909(,o)C
+2.909(rt)-2.909 G .409(he redirection operator is)-2.909 F F1(>)2.909 E
+F0 .409(and the)2.909 F F1(noclob)2.909 E(ber)-.1 E F0 .409
+(option to the)2.909 F F1(set)2.909 E F0 -.2(bu)2.908 G .408
+(iltin command).2 F(is not enabled, the redirection is attempted e)108
 544.8 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)-2.5 G(he \214le named by)
 -2.5 E F2(wor)2.5 E(d)-.37 E F0 -.15(ex)2.5 G(ists.).15 E F1 -.25(Ap)87
 561.6 S(pending Redir).25 E(ected Output)-.18 E F0 .641
@@ -2688,7 +2702,7 @@ Q F0(allo)3.141 E .642(ws both the standard output \(\214le descriptor \
 E(There are tw)108 693.6 Q 2.5(of)-.1 G
 (ormats for redirecting standard output and standard error:)-2.5 E F1
 (&>)144 710.4 Q F2(wor)A(d)-.37 E F0(and)108 722.4 Q(GNU Bash-3.0)72 768
-Q(2004 Jan 28)149.845 E(21)199.835 E 0 Cg EP
+Q(2004 Apr 20)148.735 E(21)198.725 E 0 Cg EP
 %%Page: 22 22
 %%BeginPageSetup
 BP
@@ -2775,7 +2789,7 @@ E F0(is closed after being duplicated to)2.5 E F2(n)2.5 E F0(.)A
 .24 G 2.786(rt)-2.786 G .285
 (he standard output \(\214le descriptor 1\) if)-2.786 F F2(n)2.785 E F0
 .285(is not speci-)2.785 F(\214ed.)108 705.6 Q(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(22)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(22)198.725 E 0 Cg EP
 %%Page: 23 23
 %%BeginPageSetup
 BP
@@ -2796,32 +2810,34 @@ E 3.174(was)-.25 G .674(tring to be substituted for a w)-3.174 F .674
 (ord of a simple command.)-.1 F .394(The shell maintains a list of alia\
 ses that may be set and unset with the)108 182.4 R F1(alias)2.894 E F0
 (and)2.894 E F1(unalias)2.894 E F0 -.2(bu)2.894 G .394(iltin commands).2
-F(\(see)108 194.4 Q/F4 9/Times-Bold@0 SF .763(SHELL B)3.264 F(UIL)-.09 E
-.763(TIN COMMANDS)-.828 F F0(belo)3.013 E 3.263(w\). The)-.25 F .763
-(\214rst w)3.263 F .763(ord of each command, if unquoted, is check)-.1 F
-.763(ed to)-.1 F .633(see if it has an alias.)108 206.4 R .633
-(If so, that w)5.633 F .633(ord is replaced by the te)-.1 F .634
-(xt of the alias.)-.15 F .634(The alias name and the replace-)5.634 F
-.538(ment te)108 218.4 R .538(xt may contain an)-.15 F 3.038(yv)-.15 G
-.537(alid shell input, including the)-3.288 F F2(metac)3.417 E(har)-.15
-E(acter)-.15 E(s)-.1 E F0 .537(listed abo)3.307 F -.15(ve)-.15 G 3.037
-(,w).15 G .537(ith the e)-3.037 F(xception)-.15 E .996
-(that the alias name may not contain)108 230.4 R F2(=)3.496 E F0 5.996
-(.T)C .996(he \214rst w)-5.996 F .997(ord of the replacement te)-.1 F
-.997(xt is tested for aliases, b)-.15 F .997(ut a)-.2 F -.1(wo)108 242.4
-S .495(rd that is identical to an alias being e).1 F .495
-(xpanded is not e)-.15 F .495(xpanded a second time.)-.15 F .494
-(This means that one may)5.494 F(alias)108 254.4 Q F1(ls)3.019 E F0(to)
-3.019 E F1 .519(ls \255F)3.019 F F0 3.019(,f)C .519(or instance, and)
--3.019 F F1(bash)3.019 E F0 .52(does not try to recursi)3.019 F -.15(ve)
--.25 G .52(ly e).15 F .52(xpand the replacement te)-.15 F 3.02(xt. If)
--.15 F .52(the last)3.02 F .441(character of the alias v)108 266.4 R
-.441(alue is a)-.25 F F2(blank)2.941 E F0 2.941(,t).67 G .441
-(hen the ne)-2.941 F .441(xt command w)-.15 F .441(ord follo)-.1 F .441
-(wing the alias is also check)-.25 F .441(ed for)-.1 F(alias e)108 278.4
-Q(xpansion.)-.15 E(Aliases are created and listed with the)108 295.2 Q
-F1(alias)2.5 E F0(command, and remo)2.5 E -.15(ve)-.15 G 2.5(dw).15 G
-(ith the)-2.5 E F1(unalias)2.5 E F0(command.)2.5 E .284
+F(\(see)108 194.4 Q/F4 9/Times-Bold@0 SF 1.98(SHELL B)4.48 F(UIL)-.09 E
+1.98(TIN COMMANDS)-.828 F F0(belo)4.23 E 4.48(w\). The)-.25 F 1.98
+(\214rst w)4.48 F 1.979(ord of each simple command, if unquoted, is)-.1
+F(check)108 206.4 Q .472(ed to see if it has an alias.)-.1 F .472
+(If so, that w)5.472 F .473(ord is replaced by the te)-.1 F .473
+(xt of the alias.)-.15 F .473(The characters)5.473 F F1(/)2.973 E F0(,)A
+F1($)2.973 E F0(,)A F1(`)2.973 E F0(,)A(and)108 218.4 Q F1(=)3.612 E F0
+1.112(and an)3.612 F 3.612(yo)-.15 G 3.612(ft)-3.612 G 1.112(he shell)
+-3.612 F F2(metac)3.612 E(har)-.15 E(acter)-.15 E(s)-.1 E F0 1.112
+(or quoting characters listed abo)3.612 F 1.411 -.15(ve m)-.15 H 1.111
+(ay not appear in an alias).15 F 3.619(name. The)108 230.4 R 1.119
+(replacement te)3.619 F 1.119(xt may contain an)-.15 F 3.619(yv)-.15 G
+1.119(alid shell input, including shell metacharacters.)-3.869 F 1.12
+(The \214rst)6.12 F -.1(wo)108 242.4 S .514(rd of the replacement te).1
+F .514(xt is tested for aliases, b)-.15 F .514(ut a w)-.2 F .513
+(ord that is identical to an alias being e)-.1 F .513(xpanded is)-.15 F
+.295(not e)108 254.4 R .295(xpanded a second time.)-.15 F .296
+(This means that one may alias)5.295 F F1(ls)2.796 E F0(to)2.796 E F1
+.296(ls \255F)2.796 F F0 2.796(,f)C .296(or instance, and)-2.796 F F1
+(bash)2.796 E F0 .296(does not try)2.796 F .543(to recursi)108 266.4 R
+-.15(ve)-.25 G .543(ly e).15 F .543(xpand the replacement te)-.15 F
+3.043(xt. If)-.15 F .543(the last character of the alias v)3.043 F .542
+(alue is a)-.25 F F2(blank)3.042 E F0 3.042(,t).67 G .542(hen the ne)
+-3.042 F(xt)-.15 E(command w)108 278.4 Q(ord follo)-.1 E
+(wing the alias is also check)-.25 E(ed for alias e)-.1 E(xpansion.)-.15
+E(Aliases are created and listed with the)108 295.2 Q F1(alias)2.5 E F0
+(command, and remo)2.5 E -.15(ve)-.15 G 2.5(dw).15 G(ith the)-2.5 E F1
+(unalias)2.5 E F0(command.)2.5 E .284
 (There is no mechanism for using ar)108 312 R .284
 (guments in the replacement te)-.18 F 2.784(xt. If)-.15 F(ar)2.784 E
 .284(guments are needed, a shell func-)-.18 F(tion should be used \(see)
@@ -2877,13 +2893,13 @@ G 2.816(cuted. Functions).15 F .316(are e)2.816 F -.15(xe)-.15 G .316
 F .639(function is e)108 559.2 R -.15(xe)-.15 G .639(cuted, the ar).15 F
 .639
 (guments to the function become the positional parameters during its e)
--.18 F -.15(xe)-.15 G(cution.).15 E .999(The special parameter)108 571.2
-R F1(#)3.498 E F0 .998(is updated to re\215ect the change.)3.498 F .998
-(Positional parameter 0 is unchanged.)5.998 F .998(The \214rst)5.998 F
-.369(element of the)108 583.2 R F4(FUNCN)2.869 E(AME)-.18 E F0 -.25(va)
-2.619 G .37
+-.18 F -.15(xe)-.15 G(cution.).15 E .533(The special parameter)108 571.2
+R F1(#)3.033 E F0 .532(is updated to re\215ect the change.)3.033 F .532
+(Special parameter 0 is unchanged.)5.532 F .532(The \214rst ele-)5.532 F
+1.017(ment of the)108 583.2 R F4(FUNCN)3.517 E(AME)-.18 E F0 -.25(va)
+3.267 G 1.017
 (riable is set to the name of the function while the function is e).25 F
--.15(xe)-.15 G 2.87(cuting. All).15 F 1.285
+-.15(xe)-.15 G 3.518(cuting. All).15 F 1.285
 (other aspects of the shell e)108 595.2 R -.15(xe)-.15 G 1.285
 (cution en).15 F 1.285
 (vironment are identical between a function and its caller with the)-.4
@@ -2915,8 +2931,8 @@ F F1 .616(\255o functrace)3.115 F F0 .616
 (alues of the positional parameters and the spe-)-.25 F(cial parameter)
 108 724.8 Q F1(#)2.5 E F0(are restored to the v)2.5 E(alues the)-.25 E
 2.5(yh)-.15 G(ad prior to the function')-2.5 E 2.5(se)-.55 G -.15(xe)
--2.65 G(cution.).15 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(23)
-199.835 E 0 Cg EP
+-2.65 G(cution.).15 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(23)
+198.725 E 0 Cg EP
 %%Page: 24 24
 %%BeginPageSetup
 BP
@@ -3018,7 +3034,7 @@ H .343(ts inte).15 F .343(ger attrib)-.15 F .343(ute turned on)-.2 F
 (xpressions in parentheses are e)-.15 F -.25(va)-.25 G .234
 (luated \214rst and may).25 F -.15(ove)108 724.8 S
 (rride the precedence rules abo).15 E -.15(ve)-.15 G(.).15 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(24)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(24)198.725 E 0 Cg EP
 %%Page: 25 25
 %%BeginPageSetup
 BP
@@ -3128,7 +3144,7 @@ qual to, greater than, or greater than or equal to)144 696 R F3(ar)144
 -.65 E F3(Ar)6.01 E(g1)-.37 E F0(and)2.5 E F3(ar)2.83 E(g2)-.37 E F0
 (may be positi)2.52 E .3 -.15(ve o)-.25 H 2.5(rn).15 G -2.25 -.15(eg a)
 -2.5 H(ti).15 E .3 -.15(ve i)-.25 H(nte).15 E(gers.)-.15 E(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(25)199.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(25)198.725 E 0 Cg EP
 %%Page: 26 26
 %%BeginPageSetup
 BP
@@ -3244,7 +3260,7 @@ e remainder of the \214rst line speci\214es an interpreter for the pro-)
 (COMMAND EXECUTION ENVIR)72 703.2 Q(ONMENT)-.329 E F0(The shell has an)
 108 715.2 Q F5 -.2(ex)2.5 G(ecution en).2 E(vir)-.4 E(onment)-.45 E F0
 2.5(,w)C(hich consists of the follo)-2.5 E(wing:)-.25 E(GNU Bash-3.0)72
-768 Q(2004 Jan 28)149.845 E(26)199.835 E 0 Cg EP
+768 Q(2004 Apr 20)148.735 E(26)198.725 E 0 Cg EP
 %%Page: 27 27
 %%BeginPageSetup
 BP
@@ -3354,8 +3370,8 @@ t for)-.4 F F2 -.2(ex)2.643 G(port).2 E F0 .143(to child pro-)3.323 F
 .202(parameter assignments, as described abo)108 724.8 R .502 -.15(ve i)
 -.15 H(n).15 E/F4 9/Times-Bold@0 SF -.666(PA)2.702 G(RAMETERS).666 E/F5
 9/Times-Roman@0 SF(.)A F0 .202(These assignment statements af)4.702 F
-.203(fect only the)-.25 F(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E
-(27)199.835 E 0 Cg EP
+.203(fect only the)-.25 F(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E
+(27)198.725 E 0 Cg EP
 %%Page: 28 28
 %%BeginPageSetup
 BP
@@ -3440,14 +3456,14 @@ E F1(diso)2.5 E(wn \255h)-.1 E F0(.)A .166(If the)108 484.8 R F1
 (huponexit)2.666 E F0 .166(shell option has been set with)2.666 F F1
 (shopt)2.666 E F0(,)A F1(bash)2.666 E F0 .166(sends a)2.666 F F4(SIGHUP)
 2.666 E F0 .166(to all jobs when an interacti)2.416 F -.15(ve)-.25 G
-(login shell e)108 496.8 Q(xits.)-.15 E .076
-(If 0for which a trap has been set, the trap will not be e)108 513.6 R
--.15(xe)-.15 G .077(cuted until the command completes.).15 F(When)5.077
-E F1(bash)2.577 E F0(is)2.577 E -.1(wa)108 525.6 S .826
-(iting for an asynchronous command via the).1 F F1(wait)3.326 E F0 -.2
-(bu)3.326 G .826(iltin, the reception of a signal for which a trap has)
-.2 F .369(been set will cause the)108 537.6 R F1(wait)2.869 E F0 -.2(bu)
-2.869 G .369(iltin to return immediately with an e).2 F .37
+(login shell e)108 496.8 Q(xits.)-.15 E .41
+(If 0 for which a trap has been set, the trap will not be e)108 513.6 R
+-.15(xe)-.15 G .41(cuted until the command completes.).15 F(When)5.41 E
+F1(bash)2.91 E F0 .3(is w)108 525.6 R .3
+(aiting for an asynchronous command via the)-.1 F F1(wait)2.8 E F0 -.2
+(bu)2.8 G .3(iltin, the reception of a signal for which a trap has).2 F
+.369(been set will cause the)108 537.6 R F1(wait)2.869 E F0 -.2(bu)2.869
+G .369(iltin to return immediately with an e).2 F .37
 (xit status greater than 128, immediately)-.15 F
 (after which the trap is e)108 549.6 Q -.15(xe)-.15 G(cuted.).15 E F3
 (JOB CONTR)72 566.4 Q(OL)-.329 E F2 -.25(Jo)108 578.4 S 4.568(bc).25 G
@@ -3479,7 +3495,7 @@ iated)108 676.8 R .732(with this job is 25647.)108 688.8 R .733
 .87(notion of a)108 729.6 R F2(curr)3.37 E .87(ent terminal pr)-.37 F
 .871(ocess gr)-.45 F .871(oup ID)-.45 F F0 5.871(.M)C .871
 (embers of this process group \(processes whose process)-5.871 F
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(28)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(28)198.725 E 0 Cg EP
 %%Page: 29 29
 %%BeginPageSetup
 BP
@@ -3606,7 +3622,7 @@ ized by inserting a number of backslash-escaped special characters that\
 (\\r)144 700.8 Q F0(carriage return)28.78 E F4(\\s)144 712.8 Q F0
 (the name of the shell, the basename of)29.33 E F4($0)2.5 E F0
 (\(the portion follo)2.5 E(wing the \214nal slash\))-.25 E(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(29)199.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(29)198.725 E 0 Cg EP
 %%Page: 30 30
 %%BeginPageSetup
 BP
@@ -3727,8 +3743,8 @@ nd the k)108 652.8 R 1.334 -.15(ey b)-.1 H 1.034(indings and).15 F -.25
 -.15(ey)-.1 G .987(-bindings may be changed with an).15 F F2(inputr)
 3.497 E(c)-.37 E F0 3.487(\214le. Other)3.797 F .987
 (programs that use this library may)3.487 F(add their o)108 717.6 Q
-(wn commands and bindings.)-.25 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)
-149.845 E(30)199.835 E 0 Cg EP
+(wn commands and bindings.)-.25 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)
+148.735 E(30)198.725 E 0 Cg EP
 %%Page: 31 31
 %%BeginPageSetup
 BP
@@ -3810,8 +3826,8 @@ pes is a)108 612 Q -.25(va)-.2 G(ilable:).25 E F2(\\a)144 624 Q F0
 648 Q F0(delete)27.66 E F2(\\f)144 660 Q F0(form feed)29.89 E F2(\\n)144
 672 Q F0(ne)27.66 E(wline)-.25 E F2(\\r)144 684 Q F0(carriage return)
 28.78 E F2(\\t)144 696 Q F0(horizontal tab)29.89 E F2(\\v)144 708 Q F0
--.15(ve)28.22 G(rtical tab).15 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)
-149.845 E(31)199.835 E 0 Cg EP
+-.15(ve)28.22 G(rtical tab).15 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)
+148.735 E(31)198.725 E 0 Cg EP
 %%Page: 32 32
 %%BeginPageSetup
 BP
@@ -3910,7 +3926,7 @@ F0 .448(When set to)144 688.8 R F1(On)2.948 E F0 2.948(,m)C(ak)-2.948 E
 .449(crolling the input horizontally on a)-2.948 F 1.194(single screen \
 line when it becomes longer than the screen width rather than wrapping \
 to a ne)144 700.8 R(w)-.25 E(line.)144 712.8 Q(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(32)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(32)198.725 E 0 Cg EP
 %%Page: 33 33
 %%BeginPageSetup
 BP
@@ -4009,7 +4025,7 @@ F0 .463(construct allo)2.963 F .462(ws bindings to be made based on the\
 (xt of the test e)-.15 F .477
 (xtends to the end of the line; no characters)-.15 F
 (are required to isolate it.)144 705.6 Q(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(33)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(33)198.725 E 0 Cg EP
 %%Page: 34 34
 %%BeginPageSetup
 BP
@@ -4117,8 +4133,8 @@ E F0 .911(refers to the current cursor position, and)3.411 F F2(mark)
 (db).15 G 3.41(yt)-3.41 G(he)-3.41 E F1(set\255mark)108 724.8 Q F0 2.5
 (command. The)2.5 F(te)2.5 E
 (xt between the point and mark is referred to as the)-.15 E F2 -.37(re)
-2.5 G(gion)-.03 E F0(.)A(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(34)
-199.835 E 0 Cg EP
+2.5 G(gion)-.03 E F0(.)A(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(34)
+198.725 E 0 Cg EP
 %%Page: 35 35
 %%BeginPageSetup
 BP
@@ -4197,8 +4213,8 @@ etween the start of the current)-.1 F(line and the point.)144 688.8 Q
 (th an ar).4 F(gument)-.18 E/F3 10/Times-Italic@0 SF(n)3.294 E F0 3.294
 (,i).24 G .794(nsert the)-3.294 F F3(n)3.294 E F0 .794(th w)B .794
 (ord from the pre)-.1 F .794(vious command \(the w)-.25 F .795
-(ords in the)-.1 F(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(35)
-199.835 E 0 Cg EP
+(ords in the)-.1 F(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(35)
+198.725 E 0 Cg EP
 %%Page: 36 36
 %%BeginPageSetup
 BP
@@ -4294,8 +4310,8 @@ G .779(nsert characters lik)-3.279 F(e)-.1 E F2(C\255q)3.278 E F0 3.278
 -.1 F .023(ving point o)-.15 F -.15(ve)-.15 G 2.524(rt).15 G .024(hat w)
 -2.524 F .024(ord as well.)-.1 F .024(If point)5.024 F
 (is at the end of the line, this transposes the last tw)144 700.8 Q 2.5
-(ow)-.1 G(ords on the line.)-2.6 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)
-149.845 E(36)199.835 E 0 Cg EP
+(ow)-.1 G(ords on the line.)-2.6 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)
+148.735 E(36)198.725 E 0 Cg EP
 %%Page: 37 37
 %%BeginPageSetup
 BP
@@ -4384,7 +4400,7 @@ F0 -1(Ya)144 676.8 S(nk the top of the kill ring into the b)1 E(uf)-.2 E
 (Rotate the kill ring, and yank the ne)144 700.8 Q 2.5(wt)-.25 G 2.5
 (op. Only)-2.5 F -.1(wo)2.5 G(rks follo).1 E(wing)-.25 E F1(yank)2.5 E
 F0(or)2.5 E F1(yank\255pop)2.5 E F0(.)A(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(37)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(37)198.725 E 0 Cg EP
 %%Page: 38 38
 %%BeginPageSetup
 BP
@@ -4486,7 +4502,7 @@ F0(List the possible completions of the te)144 628.8 Q
 .715(ords, shell functions, shell b)-.1 F .715(uiltins, and)-.2 F
 (\214nally e)144 724.8 Q -.15(xe)-.15 G
 (cutable \214lenames, in that order).15 E(.)-.55 E(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(38)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(38)198.725 E 0 Cg EP
 %%Page: 39 39
 %%BeginPageSetup
 BP
@@ -4582,8 +4598,8 @@ F0 1.095(command enough times to)3.595 F
 (he current line a shell comment.)-3.339 F .839(If a numeric ar)5.839 F
 (gu-)-.18 E(ment causes the comment character to be remo)144 729.6 Q
 -.15(ve)-.15 G(d, the line will be e).15 E -.15(xe)-.15 G
-(cuted by the shell.).15 E(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E
-(39)199.835 E 0 Cg EP
+(cuted by the shell.).15 E(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E
+(39)198.725 E 0 Cg EP
 %%Page: 40 40
 %%BeginPageSetup
 BP
@@ -4703,7 +4719,7 @@ F .404(gument is the name of the command whose ar)-.18 F .403
 (guments are being completed, the second)-.18 F(ar)108 729.6 Q 1.993
 (gument is the w)-.18 F 1.993(ord being completed, and the third ar)-.1
 F 1.993(gument is the w)-.18 F 1.993(ord preceding the w)-.1 F 1.994
-(ord being)-.1 F(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(40)199.835
+(ord being)-.1 F(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(40)198.725
 E 0 Cg EP
 %%Page: 41 41
 %%BeginPageSetup
@@ -4849,7 +4865,7 @@ R 1.485(ws control o)-.25 F -.15(ve)-.15 G 3.986(rw).15 G 1.486
 E(OL)-.27 E F0(and)3.736 E F2(HISTIGNORE)108 729.6 Q F0 -.25(va)2.708 G
 .458(riables may be set to cause the shell to sa).25 F .757 -.15(ve o)
 -.2 H .457(nly a subset of the commands entered.).15 F(The)5.457 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(41)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(41)198.725 E 0 Cg EP
 %%Page: 42 42
 %%BeginPageSetup
 BP
@@ -4972,7 +4988,7 @@ SF(^)108 667.4 Q F4(string1)-5 I F5(^)5 I F4(string2)-5 I F5(^)5 I F0
 F4(string2)A F0(/')A 2.5('\()-.74 G(see)-2.5 E F1(Modi\214ers)2.5 E F0
 (belo)2.5 E(w\).)-.25 E F1(!#)108 698.4 Q F0
 (The entire command line typed so f)27.67 E(ar)-.1 E(.)-.55 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(42)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(42)198.725 E 0 Cg EP
 %%Page: 43 43
 %%BeginPageSetup
 BP
@@ -5088,7 +5104,7 @@ R -.15(xe)-.15 G 3.332(cutable. When).15 F F1(bash)3.332 E F0 .832
 /Times-Roman@0 SF(.)A F0 .981(If the)5.481 F F1(sour)3.481 E(cepath)-.18
 E F0 .981(option to the)3.481 F F1(shopt)3.481 E F0 -.2(bu)3.481 G .981
 (iltin command is turned of).2 F .981(f, the)-.25 F(GNU Bash-3.0)72 768
-Q(2004 Jan 28)149.845 E(43)199.835 E 0 Cg EP
+Q(2004 Apr 20)148.735 E(43)198.725 E 0 Cg EP
 %%Page: 44 44
 %%BeginPageSetup
 BP
@@ -5200,7 +5216,7 @@ F2 -.1(ke)2.5 G(yseq)-.2 E F0(Remo)180 650.4 Q .3 -.15(ve a)-.15 H .3
 F2 -.1(ke)2.5 G(yseq)-.2 E F0(is entered.)2.5 E(The return v)144 691.2 Q
 (alue is 0 unless an unrecognized option is gi)-.25 E -.15(ve)-.25 G 2.5
 (no).15 G 2.5(ra)-2.5 G 2.5(ne)-2.5 G(rror occurred.)-2.5 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(44)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(44)198.725 E 0 Cg EP
 %%Page: 45 45
 %%BeginPageSetup
 BP
@@ -5336,8 +5352,8 @@ F2(action)2.786 E F0 2.786(][)C F1<ad47>-2.786 E F2(globpat)2.786 E F0
 E F2(suf-)2.786 E<8c78>108 712.8 Q F0(])A([)144 724.8 Q F1<ad58>A F2
 (\214lterpat)2.5 E F0 2.5(][)C F1<ad46>-2.5 E F2(function)2.5 E F0 2.5
 (][)C F1<ad43>-2.5 E F2(command)2.5 E F0(])A F2(name)2.5 E F0([)2.5 E F2
-(name ...)A F0(])A(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(45)
-199.835 E 0 Cg EP
+(name ...)A F0(])A(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(45)
+198.725 E 0 Cg EP
 %%Page: 46 46
 %%BeginPageSetup
 BP
@@ -5412,7 +5428,7 @@ Q(en from the \214le speci\214ed by the)-.1 E/F3 9/Times-Bold@0 SF
 (HOSTFILE)2.5 E F0(shell v)2.25 E(ariable.)-.25 E F1(job)184 696 Q F0
 (Job names, if job control is acti)26.11 E -.15(ve)-.25 G 5(.M).15 G
 (ay also be speci\214ed as)-5 E F1<ad6a>2.5 E F0(.)A(GNU Bash-3.0)72 768
-Q(2004 Jan 28)149.845 E(46)199.835 E 0 Cg EP
+Q(2004 Apr 20)148.735 E(46)198.725 E 0 Cg EP
 %%Page: 47 47
 %%BeginPageSetup
 BP
@@ -5519,7 +5535,7 @@ n is de\214ned are displayed as well.)144 662.4 R(The)6.309 E F1<ad46>
 698.4 Q F0(Each)25.3 E F2(name)2.5 E F0(is an array v)2.5 E
 (ariable \(see)-.25 E F1(Arrays)2.5 E F0(abo)2.5 E -.15(ve)-.15 G(\).)
 .15 E F1<ad66>144 710.4 Q F0(Use function names only)26.97 E(.)-.65 E
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(47)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(47)198.725 E 0 Cg EP
 %%Page: 48 48
 %%BeginPageSetup
 BP
@@ -5639,7 +5655,7 @@ F .659(by def)144 648 R(ault.)-.1 E F1(echo)5.659 E F0 .659
 (\\a)144 672 Q F0(alert \(bell\))28.22 E F1(\\b)144 684 Q F0(backspace)
 27.66 E F1(\\c)144 696 Q F0(suppress trailing ne)28.78 E(wline)-.25 E F1
 (\\e)144 708 Q F0(an escape character)28.78 E(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(48)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(48)198.725 E 0 Cg EP
 %%Page: 49 49
 %%BeginPageSetup
 BP
@@ -5773,8 +5789,8 @@ Q F0(that is not a function.)2.68 E F1(fc)108 688.8 Q F0([)2.5 E F1
 (is selected from the his-)3.658 F .882(tory list.)144 724.8 R F2 -.45
 (Fi)5.882 G -.1(rs).45 G(t).1 E F0(and)4.062 E F2(last)3.472 E F0 .882
 (may be speci\214ed as a string \(to locate the last command be)4.062 F
-.881(ginning with)-.15 F(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(49)
-199.835 E 0 Cg EP
+.881(ginning with)-.15 F(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(49)
+198.725 E 0 Cg EP
 %%Page: 50 50
 %%BeginPageSetup
 BP
@@ -5904,7 +5920,7 @@ F0 .399(is silent, the option character found is placed in)2.899 F F4
 729.6 R 1.241(gument is not found, and)-.18 F F3(getopts)3.741 E F0
 1.241(is not silent, a question mark \()3.741 F F3(?).833 E F0 3.742
 (\)i).833 G 3.742(sp)-3.742 G 1.242(laced in)-3.742 F(GNU Bash-3.0)72
-768 Q(2004 Jan 28)149.845 E(50)199.835 E 0 Cg EP
+768 Q(2004 Apr 20)148.735 E(50)198.725 E 0 Cg EP
 %%Page: 51 51
 %%BeginPageSetup
 BP
@@ -6019,7 +6035,7 @@ E F0 .28
 (is supplied as an ar)2.922 F .421(gument to)-.18 F F3<ad64>2.921 E F0
 (,)A(or the history e)144 703.2 Q(xpansion supplied as an ar)-.15 E
 (gument to)-.18 E F3<ad70>2.5 E F0 -.1(fa)2.5 G(ils.).1 E(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(51)199.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(51)198.725 E 0 Cg EP
 %%Page: 52 52
 %%BeginPageSetup
 BP
@@ -6146,7 +6162,7 @@ tring which contains three types of objects: plain characters, which ar\
 e simply)144 715.2 R 1.859
 (copied to standard output, character escape sequences, which are con)
 144 727.2 R -.15(ve)-.4 G 1.858(rted and copied to the).15 F
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(52)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(52)198.725 E 0 Cg EP
 %%Page: 53 53
 %%BeginPageSetup
 BP
@@ -6264,8 +6280,8 @@ F2<ad65>144 655.2 Q F0 .373
 -.15 E(s)-.1 E F2 -.18(re)180 691.2 S(ad).18 E F0 1.394
 (returns after reading)3.894 F F1(nc)3.894 E(har)-.15 E(s)-.1 E F0 1.395
 (characters rather than w)3.894 F 1.395(aiting for a complete line of)
--.1 F(input.)180 703.2 Q(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(53)
-199.835 E 0 Cg EP
+-.1 F(input.)180 703.2 Q(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(53)
+198.725 E 0 Cg EP
 %%Page: 54 54
 %%BeginPageSetup
 BP
@@ -6389,7 +6405,7 @@ SF<efef>3.481 E F3 .98(list, or if the command's r)3.481 F .98
 .711(This option is on by default for interac-)5.711 F 1.165
 (tive shells on systems that support it \(see)184 727.2 R F5 1.164
 (JOB CONTROL)3.664 F F3 3.664(above\). Backgr)3.414 F(ound)-.18 E F0
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(54)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(54)198.725 E 0 Cg EP
 %%Page: 55 55
 %%BeginPageSetup
 BP
@@ -6451,7 +6467,7 @@ F2<ad6f>4.631 E F1 2.131(is supplied with no)4.631 F F3(option\255name)
 (ent options ar)-.18 F(e)-.18 E 4.411(printed. If)184 726 R F2(+o)4.411
 E F1 1.911(is supplied with no)4.411 F F3(option\255name)4.412 E F1
 4.412(,as)C 1.912(eries of)-4.412 F F2(set)4.412 E F1 1.912(commands to)
-4.412 F F0(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(55)199.835 E 0 Cg
+4.412 F F0(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(55)198.725 E 0 Cg
 EP
 %%Page: 56 56
 %%BeginPageSetup
@@ -6573,8 +6589,8 @@ G(f)-2.5 E F3(n)2.76 E F1(is gr)2.58 E(eater than)-.18 E F2($#)2.5 E F1
 (olling optional shell behavior)-.18 F 6.523(.W)-.74 G 1.523
 (ith no options, or)-7.073 F 2.532(with the)144 722.4 R F2<ad70>5.032 E
 F1 2.531(option, a list of all settable options is displayed, with an i\
-ndication of)5.032 F F0(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(56)
-199.835 E 0 Cg EP
+ndication of)5.032 F F0(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(56)
+198.725 E 0 Cg EP
 %%Page: 57 57
 %%BeginPageSetup
 BP
@@ -6668,7 +6684,7 @@ F1 1.106(trap r)3.606 F 1.107(eturns a value of 2, and the)-.18 F .871
 (outine \(a shell function or a shell script exe-)-.18 F(cuted by the)
 220 728.4 Q F2(.)2.5 E F1(or)2.5 E F2(source)2.5 E F1
 (builtins\), a call to)2.5 E F2(return)2.5 E F1(is simulated.)2.5 E F0
-(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(57)199.835 E 0 Cg EP
+(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(57)198.725 E 0 Cg EP
 %%Page: 58 58
 %%BeginPageSetup
 BP
@@ -6748,8 +6764,8 @@ F3(mail\214le)4.147 E F2 1.647(has been r)4.147 F(ead')-.18 E 4.147('i)
 F2 1.548
 (matches \214lenames in a case\255insensitive fashion when performing)
 4.048 F(pathname expansion \(see)184 696 Q F1(Pathname Expansion)2.5 E
-F2(above\).)2.5 E F0(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(58)
-199.835 E 0 Cg EP
+F2(above\).)2.5 E F0(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(58)
+198.725 E 0 Cg EP
 %%Page: 59 59
 %%BeginPageSetup
 BP
@@ -6835,7 +6851,7 @@ F2 1.401(the expr)3.651 F 1.401(ession is tr)-.18 F 1.401
 1.356(the \214rst ar)3.856 F 1.356
 (gument is not a valid unary conditional operator)-.18 F 3.855(,t)-.74 G
 (he)-3.855 E(expr)180 712.8 Q(ession is false.)-.18 E F0(GNU Bash-3.0)72
-768 Q(2004 Jan 28)149.845 E(59)199.835 E 0 Cg EP
+768 Q(2004 Apr 20)148.735 E(59)198.725 E 0 Cg EP
 %%Page: 60 60
 %%BeginPageSetup
 BP
@@ -6976,7 +6992,7 @@ E F1 2.515(,e)C .015(ven if)-2.515 F F7 .015(type -t)2.515 F(name)144
 .411(option is used,)2.911 F F4(type)2.91 E F1 .41(prints all)2.91 F
 .164(of the places that contain an executable named)144 722.4 R F5(name)
 2.664 E F1 5.164(.T).35 G .164(his includes aliases and functions,)
--5.164 F F0(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(60)199.835 E 0
+-5.164 F F0(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(60)198.725 E 0
 Cg EP
 %%Page: 61 61
 %%BeginPageSetup
@@ -7098,7 +7114,7 @@ E F5(,)A F4(HISTCMD)3.724 E F5(,)A F4(FUNCNAME)144 708 Q F5(,)A F4
 .553(operties, even if)-.18 F(they ar)144 720 Q 2.5(es)-.18 G
 (ubsequently r)-2.5 E 2.5(eset. The)-.18 F(exit status is tr)2.5 E
 (ue unless a)-.08 E F3(name)2.76 E F1(is r)2.85 E(eadonly)-.18 E(.)-1.11
-E F0(GNU Bash-3.0)72 768 Q(2004 Jan 28)149.845 E(61)199.835 E 0 Cg EP
+E F0(GNU Bash-3.0)72 768 Q(2004 Apr 20)148.735 E(61)198.725 E 0 Cg EP
 %%Page: 62 62
 %%BeginPageSetup
 BP
@@ -7182,7 +7198,7 @@ F2 2.5(,B)C(rian Fox and Chet Ramey)-2.5 E F3(Portable Operating System\
 (The personal initialization \214le, executed for login shells)144 686.4
 Q F3(~/.bashr)109.666 698.4 Q(c)-.18 E F2(The individual per)144 710.4 Q
 (-interactive-shell startup \214le)-.18 E F0(GNU Bash-3.0)72 768 Q
-(2004 Jan 28)149.845 E(62)199.835 E 0 Cg EP
+(2004 Apr 20)148.735 E(62)198.725 E 0 Cg EP
 %%Page: 63 63
 %%BeginPageSetup
 BP
@@ -7249,7 +7265,7 @@ F1(bashbug)108.13 393.6 Q F2 1.316(inserts the \214rst thr)4.296 F 1.316
 -.18 F .431(or messages while the con-)-.18 F(str)108 631.2 Q
 (uct is being r)-.08 E(ead.)-.18 E
 (Array variables may not \(yet\) be exported.)108 648 Q F0(GNU Bash-3.0)
-72 768 Q(2004 Jan 28)149.845 E(63)199.835 E 0 Cg EP
+72 768 Q(2004 Apr 20)148.735 E(63)198.725 E 0 Cg EP
 %%Trailer
 end
 %%EOF
index 081341a..32fbaac 100644 (file)
Binary files a/doc/bashref.dvi and b/doc/bashref.dvi differ
index 8c12747..42fce5d 100644 (file)
@@ -1,6 +1,6 @@
 <HTML>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!-- Created on January, 28  2004 by texi2html 1.64 -->
+<!-- Created on April, 20  2004 by texi2html 1.64 -->
 <!-- 
 Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
             Karl Berry  <karl@freefriends.org>
@@ -33,10 +33,10 @@ Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
 <H1>Bash Reference Manual</H1></P><P>
 
 This text is a brief description of the features that are present in
-the Bash shell (version 3.0-beta1, 28 January 2004)..
+the Bash shell (version 3.0-beta1, 20 April 2004)..
 </P><P>
 
-This is Edition 3.0, last updated 28 January 2004,
+This is Edition 3.0, last updated 20 April 2004,
 of <CITE>The GNU Bash Reference Manual</CITE>,
 for <CODE>Bash</CODE>, Version 3.0-beta1.
 </P><P>
@@ -1554,7 +1554,7 @@ function become the positional parameters
 during its execution (see section <A HREF="bashref.html#SEC25">3.4.1 Positional Parameters</A>).
 The special parameter <SAMP>`#'</SAMP> that expands to the number of
 positional parameters is updated to reflect the change.
-Positional parameter <CODE>0</CODE> is unchanged.
+Special parameter <CODE>0</CODE> is unchanged.
 The first element of the <CODE>FUNCNAME</CODE> variable is set to the
 name of the function while the function is executing.
 All other aspects of the shell execution
@@ -2142,9 +2142,9 @@ if the colon is omitted, the operator tests only for existence.
 <DD>If <VAR>parameter</VAR>
 is unset or null, the expansion of <VAR>word</VAR>
 is assigned to <VAR>parameter</VAR>.
-The value of <VAR>parameter</VAR>
-is then substituted.  Positional parameters and special parameters may
-not be assigned to in this way.
+The value of <VAR>parameter</VAR> is then substituted. 
+Positional parameters and special parameters may not be assigned to
+in this way.
 <P>
 
 <DT><CODE>${<VAR>parameter</VAR>:?<VAR>word</VAR>}</CODE>
@@ -7281,13 +7281,15 @@ the <CODE>alias</CODE> and <CODE>unalias</CODE> builtin commands.
 The first word of each simple command, if unquoted, is checked to see
 if it has an alias.
 If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including shell metacharacters, with the exception
-that the alias name may not contain <SAMP>`='</SAMP>.
+The characters <SAMP>`/'</SAMP>, <SAMP>`$'</SAMP>, <SAMP>``'</SAMP>, <SAMP>`='</SAMP> and any of the
+shell metacharacters or quoting characters listed above may not appear
+in an alias name.
+The replacement text may contain any valid
+shell input, including shell metacharacters.
 The first word of the replacement text is tested for
 aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.  This means that one may alias
-<CODE>ls</CODE> to <CODE>"ls -F"</CODE>,
+is not expanded a second time.
+This means that one may alias <CODE>ls</CODE> to <CODE>"ls -F"</CODE>,
 for instance, and Bash does not try to recursively expand the
 replacement text. If the last character of the alias value is a
 space or tab character, then the next command word following the
@@ -8138,7 +8140,7 @@ Any trap on <CODE>SIGCHLD</CODE> is executed for each child process
 that exits.
 </P><P>
 
-If an attempt to exit Bash is while jobs are stopped, the
+If an attempt to exit Bash is made while jobs are stopped, the
 shell prints a message warning that there are stopped jobs.
 The <CODE>jobs</CODE> command may then be used to inspect their status.
 If a second attempt to exit is made without an intervening command,
@@ -14996,7 +14998,7 @@ to permit their use in free software.
 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="bashref.html#SEC_About"> ? </A>]</TD>
 </TR></TABLE>
 <H1>About this document</H1>
-This document was generated by <I>Chet Ramey</I> on <I>January, 28  2004</I>
+This document was generated by <I>Chet Ramey</I> on <I>April, 20  2004</I>
 using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
 "><I>texi2html</I></A>
 <P></P>  
@@ -15158,7 +15160,7 @@ the following structure:
 <BR>  
 <FONT SIZE="-1">
 This document was generated
-by <I>Chet Ramey</I> on <I>January, 28  2004</I>
+by <I>Chet Ramey</I> on <I>April, 20  2004</I>
 using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
 "><I>texi2html</I></A>
 
index b0b5d01..6d71088 100644 (file)
@@ -2,9 +2,9 @@ This is bashref.info, produced by makeinfo version 4.5 from
 /usr/homes/chet/src/bash/src/doc/bashref.texi.
 
 This text is a brief description of the features that are present in
-the Bash shell (version 3.0-beta1, 28 January 2004).
+the Bash shell (version 3.0-beta1, 20 April 2004).
 
-   This is Edition 3.0, last updated 28 January 2004, of `The GNU Bash
+   This is Edition 3.0, last updated 20 April 2004, of `The GNU Bash
 Reference Manual', for `Bash', Version 3.0-beta1.
 
    Copyright (C) 1988-2003 Free Software Foundation, Inc.
@@ -37,9 +37,9 @@ Bash Features
 *************
 
    This text is a brief description of the features that are present in
-the Bash shell (version 3.0-beta1, 28 January 2004)..
+the Bash shell (version 3.0-beta1, 20 April 2004)..
 
-   This is Edition 3.0, last updated 28 January 2004, of `The GNU Bash
+   This is Edition 3.0, last updated 20 April 2004, of `The GNU Bash
 Reference Manual', for `Bash', Version 3.0-beta1.
 
    Bash contains features that appear in other popular shells, and some
@@ -975,7 +975,7 @@ terminated by a semicolon, a `&', or a newline.
    When a function is executed, the arguments to the function become
 the positional parameters during its execution (*note Positional
 Parameters::).  The special parameter `#' that expands to the number of
-positional parameters is updated to reflect the change.  Positional
+positional parameters is updated to reflect the change.  Special
 parameter `0' is unchanged.  The first element of the `FUNCNAME'
 variable is set to the name of the function while the function is
 executing.  All other aspects of the shell execution environment are
@@ -1351,8 +1351,8 @@ if the colon is omitted, the operator tests only for existence.
 `${PARAMETER:=WORD}'
      If PARAMETER is unset or null, the expansion of WORD is assigned
      to PARAMETER.  The value of PARAMETER is then substituted.
-     Positional parameters and special parameters may not be assigned
-     to in this way.
+     Positional parameters and special parameters may not be assigned to
+     in this way.
 
 `${PARAMETER:?WORD}'
      If PARAMETER is null or unset, the expansion of WORD (or a message
@@ -4809,15 +4809,16 @@ builtin commands.
 
    The first word of each simple command, if unquoted, is checked to see
 if it has an alias.  If so, that word is replaced by the text of the
-alias.  The alias name and the replacement text may contain any valid
-shell input, including shell metacharacters, with the exception that
-the alias name may not contain `='.  The first word of the replacement
-text is tested for aliases, but a word that is identical to an alias
-being expanded is not expanded a second time.  This means that one may
-alias `ls' to `"ls -F"', for instance, and Bash does not try to
-recursively expand the replacement text. If the last character of the
-alias value is a space or tab character, then the next command word
-following the alias is also checked for alias expansion.
+alias.  The characters `/', `$', ``', `=' and any of the shell
+metacharacters or quoting characters listed above may not appear in an
+alias name.  The replacement text may contain any valid shell input,
+including shell metacharacters.  The first word of the replacement text
+is tested for aliases, but a word that is identical to an alias being
+expanded is not expanded a second time.  This means that one may alias
+`ls' to `"ls -F"', for instance, and Bash does not try to recursively
+expand the replacement text. If the last character of the alias value
+is a space or tab character, then the next command word following the
+alias is also checked for alias expansion.
 
    Aliases are created and listed with the `alias' command, and removed
 with the `unalias' command.
@@ -5428,7 +5429,7 @@ output.  If the `-b' option to the `set' builtin is enabled, Bash
 reports such changes immediately (*note The Set Builtin::).  Any trap
 on `SIGCHLD' is executed for each child process that exits.
 
-   If an attempt to exit Bash is while jobs are stopped, the shell
+   If an attempt to exit Bash is made while jobs are stopped, the shell
 prints a message warning that there are stopped jobs.  The `jobs'
 command may then be used to inspect their status.  If a second attempt
 to exit is made without an intervening command, Bash does not print
@@ -9256,129 +9257,129 @@ Concept Index
 
 \1f
 Tag Table:
-Node: Top\7f1371
-Node: Introduction\7f3528
-Node: What is Bash?\7f3753
-Node: What is a shell?\7f4841
-Node: Definitions\7f7377
-Node: Basic Shell Features\7f10117
-Node: Shell Syntax\7f11335
-Node: Shell Operation\7f12359
-Node: Quoting\7f13644
-Node: Escape Character\7f14906
-Node: Single Quotes\7f15378
-Node: Double Quotes\7f15713
-Node: ANSI-C Quoting\7f16726
-Node: Locale Translation\7f17669
-Node: Comments\7f18552
-Node: Shell Commands\7f19157
-Node: Simple Commands\7f19918
-Node: Pipelines\7f20539
-Node: Lists\7f22405
-Node: Compound Commands\7f24027
-Node: Looping Constructs\7f24799
-Node: Conditional Constructs\7f27233
-Node: Command Grouping\7f34286
-Node: Shell Functions\7f35722
-Node: Shell Parameters\7f39987
-Node: Positional Parameters\7f41558
-Node: Special Parameters\7f42449
-Node: Shell Expansions\7f45107
-Node: Brace Expansion\7f47027
-Node: Tilde Expansion\7f49343
-Node: Shell Parameter Expansion\7f51675
-Node: Command Substitution\7f58929
-Node: Arithmetic Expansion\7f60251
-Node: Process Substitution\7f61092
-Node: Word Splitting\7f62129
-Node: Filename Expansion\7f63581
-Node: Pattern Matching\7f65705
-Node: Quote Removal\7f69026
-Node: Redirections\7f69312
-Node: Executing Commands\7f76787
-Node: Simple Command Expansion\7f77454
-Node: Command Search and Execution\7f79375
-Node: Command Execution Environment\7f81372
-Node: Environment\7f84134
-Node: Exit Status\7f85785
-Node: Signals\7f86980
-Node: Shell Scripts\7f88935
-Node: Shell Builtin Commands\7f91446
-Node: Bourne Shell Builtins\7f92876
-Node: Bash Builtins\7f109759
-Node: The Set Builtin\7f137881
-Node: Special Builtins\7f146099
-Node: Shell Variables\7f147071
-Node: Bourne Shell Variables\7f147507
-Node: Bash Variables\7f149484
-Node: Bash Features\7f168989
-Node: Invoking Bash\7f169871
-Node: Bash Startup Files\7f175682
-Node: Interactive Shells\7f180552
-Node: What is an Interactive Shell?\7f180954
-Node: Is this Shell Interactive?\7f181589
-Node: Interactive Shell Behavior\7f182395
-Node: Bash Conditional Expressions\7f185662
-Node: Shell Arithmetic\7f189082
-Node: Aliases\7f191822
-Node: Arrays\7f194325
-Node: The Directory Stack\7f197345
-Node: Directory Stack Builtins\7f198051
-Node: Printing a Prompt\7f200930
-Node: The Restricted Shell\7f203639
-Node: Bash POSIX Mode\7f205464
-Node: Job Control\7f212110
-Node: Job Control Basics\7f212576
-Node: Job Control Builtins\7f216856
-Node: Job Control Variables\7f221152
-Node: Command Line Editing\7f222302
-Node: Introduction and Notation\7f223300
-Node: Readline Interaction\7f224917
-Node: Readline Bare Essentials\7f226103
-Node: Readline Movement Commands\7f227883
-Node: Readline Killing Commands\7f228839
-Node: Readline Arguments\7f230748
-Node: Searching\7f231783
-Node: Readline Init File\7f233960
-Node: Readline Init File Syntax\7f235014
-Node: Conditional Init Constructs\7f246658
-Node: Sample Init File\7f249182
-Node: Bindable Readline Commands\7f252365
-Node: Commands For Moving\7f253564
-Node: Commands For History\7f254413
-Node: Commands For Text\7f257302
-Node: Commands For Killing\7f259963
-Node: Numeric Arguments\7f262093
-Node: Commands For Completion\7f263220
-Node: Keyboard Macros\7f266801
-Node: Miscellaneous Commands\7f267360
-Node: Readline vi Mode\7f272659
-Node: Programmable Completion\7f273568
-Node: Programmable Completion Builtins\7f279375
-Node: Using History Interactively\7f286737
-Node: Bash History Facilities\7f287416
-Node: Bash History Builtins\7f290106
-Node: History Interaction\7f293958
-Node: Event Designators\7f296509
-Node: Word Designators\7f297513
-Node: Modifiers\7f299143
-Node: Installing Bash\7f300540
-Node: Basic Installation\7f301674
-Node: Compilers and Options\7f304359
-Node: Compiling For Multiple Architectures\7f305093
-Node: Installation Names\7f306750
-Node: Specifying the System Type\7f307561
-Node: Sharing Defaults\7f308270
-Node: Operation Controls\7f308935
-Node: Optional Features\7f309886
-Node: Reporting Bugs\7f318158
-Node: Major Differences From The Bourne Shell\7f319333
-Node: Copying This Manual\7f335081
-Node: GNU Free Documentation License\7f335335
-Node: Builtin Index\7f357728
-Node: Reserved Word Index\7f361355
-Node: Variable Index\7f362831
-Node: Function Index\7f369824
-Node: Concept Index\7f374437
+Node: Top\7f1367
+Node: Introduction\7f3520
+Node: What is Bash?\7f3745
+Node: What is a shell?\7f4833
+Node: Definitions\7f7369
+Node: Basic Shell Features\7f10109
+Node: Shell Syntax\7f11327
+Node: Shell Operation\7f12351
+Node: Quoting\7f13636
+Node: Escape Character\7f14898
+Node: Single Quotes\7f15370
+Node: Double Quotes\7f15705
+Node: ANSI-C Quoting\7f16718
+Node: Locale Translation\7f17661
+Node: Comments\7f18544
+Node: Shell Commands\7f19149
+Node: Simple Commands\7f19910
+Node: Pipelines\7f20531
+Node: Lists\7f22397
+Node: Compound Commands\7f24019
+Node: Looping Constructs\7f24791
+Node: Conditional Constructs\7f27225
+Node: Command Grouping\7f34278
+Node: Shell Functions\7f35714
+Node: Shell Parameters\7f39976
+Node: Positional Parameters\7f41547
+Node: Special Parameters\7f42438
+Node: Shell Expansions\7f45096
+Node: Brace Expansion\7f47016
+Node: Tilde Expansion\7f49332
+Node: Shell Parameter Expansion\7f51664
+Node: Command Substitution\7f58918
+Node: Arithmetic Expansion\7f60240
+Node: Process Substitution\7f61081
+Node: Word Splitting\7f62118
+Node: Filename Expansion\7f63570
+Node: Pattern Matching\7f65694
+Node: Quote Removal\7f69015
+Node: Redirections\7f69301
+Node: Executing Commands\7f76776
+Node: Simple Command Expansion\7f77443
+Node: Command Search and Execution\7f79364
+Node: Command Execution Environment\7f81361
+Node: Environment\7f84123
+Node: Exit Status\7f85774
+Node: Signals\7f86969
+Node: Shell Scripts\7f88924
+Node: Shell Builtin Commands\7f91435
+Node: Bourne Shell Builtins\7f92865
+Node: Bash Builtins\7f109748
+Node: The Set Builtin\7f137870
+Node: Special Builtins\7f146088
+Node: Shell Variables\7f147060
+Node: Bourne Shell Variables\7f147496
+Node: Bash Variables\7f149473
+Node: Bash Features\7f168978
+Node: Invoking Bash\7f169860
+Node: Bash Startup Files\7f175671
+Node: Interactive Shells\7f180541
+Node: What is an Interactive Shell?\7f180943
+Node: Is this Shell Interactive?\7f181578
+Node: Interactive Shell Behavior\7f182384
+Node: Bash Conditional Expressions\7f185651
+Node: Shell Arithmetic\7f189071
+Node: Aliases\7f191811
+Node: Arrays\7f194374
+Node: The Directory Stack\7f197394
+Node: Directory Stack Builtins\7f198100
+Node: Printing a Prompt\7f200979
+Node: The Restricted Shell\7f203688
+Node: Bash POSIX Mode\7f205513
+Node: Job Control\7f212159
+Node: Job Control Basics\7f212625
+Node: Job Control Builtins\7f216910
+Node: Job Control Variables\7f221206
+Node: Command Line Editing\7f222356
+Node: Introduction and Notation\7f223354
+Node: Readline Interaction\7f224971
+Node: Readline Bare Essentials\7f226157
+Node: Readline Movement Commands\7f227937
+Node: Readline Killing Commands\7f228893
+Node: Readline Arguments\7f230802
+Node: Searching\7f231837
+Node: Readline Init File\7f234014
+Node: Readline Init File Syntax\7f235068
+Node: Conditional Init Constructs\7f246712
+Node: Sample Init File\7f249236
+Node: Bindable Readline Commands\7f252419
+Node: Commands For Moving\7f253618
+Node: Commands For History\7f254467
+Node: Commands For Text\7f257356
+Node: Commands For Killing\7f260017
+Node: Numeric Arguments\7f262147
+Node: Commands For Completion\7f263274
+Node: Keyboard Macros\7f266855
+Node: Miscellaneous Commands\7f267414
+Node: Readline vi Mode\7f272713
+Node: Programmable Completion\7f273622
+Node: Programmable Completion Builtins\7f279429
+Node: Using History Interactively\7f286791
+Node: Bash History Facilities\7f287470
+Node: Bash History Builtins\7f290160
+Node: History Interaction\7f294012
+Node: Event Designators\7f296563
+Node: Word Designators\7f297567
+Node: Modifiers\7f299197
+Node: Installing Bash\7f300594
+Node: Basic Installation\7f301728
+Node: Compilers and Options\7f304413
+Node: Compiling For Multiple Architectures\7f305147
+Node: Installation Names\7f306804
+Node: Specifying the System Type\7f307615
+Node: Sharing Defaults\7f308324
+Node: Operation Controls\7f308989
+Node: Optional Features\7f309940
+Node: Reporting Bugs\7f318212
+Node: Major Differences From The Bourne Shell\7f319387
+Node: Copying This Manual\7f335135
+Node: GNU Free Documentation License\7f335389
+Node: Builtin Index\7f357782
+Node: Reserved Word Index\7f361409
+Node: Variable Index\7f362885
+Node: Function Index\7f369878
+Node: Concept Index\7f374491
 \1f
 End Tag Table
index 812f40e..6d23554 100644 (file)
@@ -1,4 +1,4 @@
-This is TeX, Version 3.14159 (Web2C 7.3.1) (format=tex 2001.2.12)  28 JAN 2004 15:50
+This is TeX, Version 3.14159 (Web2C 7.3.1) (format=tex 2001.2.12)  20 APR 2004 15:26
 **/usr/homes/chet/src/bash/src/doc/bashref.texi
 (/usr/homes/chet/src/bash/src/doc/bashref.texi (texinfo.tex
 Loading texinfo [version 2003-02-03.16]: Basics,
@@ -318,7 +318,7 @@ Underfull \hbox (badness 2753) in paragraph at lines 1742--1745
 
 [107]) (/usr/homes/chet/src/bash/src/lib/readline/doc/hsuser.texi Chapter 9
 [108] [109] [110] [111] [112]) Chapter 10 [113] [114] [115] [116] [117]
-Underfull \hbox (badness 2772) in paragraph at lines 6598--6602
+Underfull \hbox (badness 2772) in paragraph at lines 6600--6604
  []@textrm Enable sup-port for large files (@texttt http://www.sas.com/standard
 s/large_
 
@@ -357,10 +357,10 @@ Overfull \vbox (42.26959pt too high) has occurred while \output is active
 Here is how much of TeX's memory you used:
  1713 strings out of 13013
  23227 string characters out of 97233
- 52393 words of memory out of 263001
+ 52389 words of memory out of 263001
  2577 multiletter control sequences out of 10000+0
  31953 words of font info for 111 fonts, out of 400000 for 1000
  19 hyphenation exceptions out of 1000
  15i,8n,11p,273b,465s stack positions out of 300i,100n,500p,50000b,4000s
 
-Output written on bashref.dvi (154 pages, 579212 bytes).
+Output written on bashref.dvi (154 pages, 579284 bytes).
index f89fe30..01dd02b 100644 (file)
@@ -8,7 +8,7 @@
 %DVIPSWebPage: (www.radicaleye.com)
 %DVIPSCommandLine: dvips -D 600 -t letter -o bashref.ps bashref.dvi
 %DVIPSParameters: dpi=600, compressed
-%DVIPSSource:  TeX output 2004.01.28:1550
+%DVIPSSource:  TeX output 2004.04.20:1526
 %%BeginProcSet: texc.pro
 %!
 /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S
@@ -2540,7 +2540,7 @@ letter
 1 0 bop 150 1318 a Fu(Bash)64 b(Reference)j(Man)-5 b(ual)p
 150 1385 3600 34 v 2361 1481 a Ft(Reference)31 b(Do)s(cumen)m(tation)h
 (for)e(Bash)2178 1589 y(Edition)f(3.0,)i(for)f Fs(Bash)g
-Ft(V)-8 b(ersion)30 b(3.0-b)s(eta1.)3218 1697 y(Jan)m(uary)g(2004)150
+Ft(V)-8 b(ersion)30 b(3.0-b)s(eta1.)3333 1697 y(April)e(2004)150
 4935 y Fr(Chet)45 b(Ramey)-11 b(,)46 b(Case)g(W)-11 b(estern)46
 b(Reserv)l(e)g(Univ)l(ersit)l(y)150 5068 y(Brian)f(F)-11
 b(o)l(x,)45 b(F)-11 b(ree)45 b(Soft)l(w)l(are)h(F)-11
@@ -2548,10 +2548,10 @@ b(oundation)p 150 5141 3600 17 v eop
 %%Page: 2 2
 2 1 bop 150 2889 a Ft(This)34 b(text)i(is)f(a)h(brief)e(description)g
 (of)h(the)h(features)g(that)g(are)g(presen)m(t)g(in)e(the)i(Bash)f
-(shell)f(\(v)m(ersion)150 2999 y(3.0-b)s(eta1,)f(28)e(Jan)m(uary)f
-(2004\).)150 3133 y(This)i(is)g(Edition)f(3.0,)36 b(last)d(up)s(dated)f
-(28)i(Jan)m(uary)f(2004,)j(of)d Fq(The)g(GNU)h(Bash)g(Reference)g(Man)m
-(ual)p Ft(,)150 3243 y(for)c Fs(Bash)p Ft(,)g(V)-8 b(ersion)30
+(shell)f(\(v)m(ersion)150 2999 y(3.0-b)s(eta1,)f(20)e(April)d(2004\).)
+150 3133 y(This)k(is)h(Edition)e(3.0,)36 b(last)e(up)s(dated)e(20)j
+(April)c(2004,)37 b(of)d Fq(The)f(GNU)h(Bash)g(Reference)g(Man)m(ual)p
+Ft(,)h(for)150 3243 y Fs(Bash)p Ft(,)29 b(V)-8 b(ersion)30
 b(3.0-b)s(eta1.)150 3377 y(Cop)m(yrigh)m(t)602 3374 y(c)577
 3377 y Fp(\015)g Ft(1988-2003)k(F)-8 b(ree)32 b(Soft)m(w)m(are)f(F)-8
 b(oundation,)31 b(Inc.)150 3512 y(P)m(ermission)f(is)i(gran)m(ted)h(to)
@@ -3828,21 +3828,21 @@ Fq(list)h Ft(m)m(ust)e(b)s(e)g(terminated)h(b)m(y)g(a)150
 b(The)150 2436 y(sp)s(ecial)35 b(parameter)h(`)p Fs(#)p
 Ft(')g(that)h(expands)e(to)i(the)f(n)m(um)m(b)s(er)f(of)h(p)s
 (ositional)e(parameters)i(is)f(up)s(dated)g(to)150 2545
-y(re\015ect)28 b(the)g(c)m(hange.)41 b(P)m(ositional)27
-b(parameter)h Fs(0)f Ft(is)f(unc)m(hanged.)40 b(The)27
-b(\014rst)g(elemen)m(t)h(of)f(the)h Fs(FUNCNAME)150 2655
-y Ft(v)-5 b(ariable)25 b(is)h(set)h(to)h(the)f(name)f(of)h(the)g
-(function)e(while)g(the)i(function)e(is)h(executing.)39
-b(All)26 b(other)h(asp)s(ects)150 2765 y(of)32 b(the)g(shell)e
-(execution)j(en)m(vironmen)m(t)e(are)i(iden)m(tical)d(b)s(et)m(w)m(een)
-j(a)f(function)f(and)g(its)h(caller)f(with)g(the)150
-2874 y(exception)25 b(that)h(the)f Fs(DEBUG)f Ft(trap)h(b)s(elo)m(w\))g
-(is)f(not)i(inherited)c(unless)i(the)h(function)f(has)h(b)s(een)g(giv)m
-(en)g(the)150 2984 y Fs(trace)36 b Ft(attribute)g(using)g(the)h
-Fs(declare)e Ft(builtin)e(or)k(the)g Fs(-o)30 b(functrace)35
-b Ft(option)h(has)h(b)s(een)f(enabled)150 3093 y(with)c(the)h
-Fs(set)g Ft(builtin,)e(\(in)h(whic)m(h)g(case)i(all)e(functions)g
-(inherit)f(the)j Fs(DEBUG)e Ft(trap\).)49 b(See)34 b(Section)f(4.1)150
+y(re\015ect)h(the)f(c)m(hange.)56 b(Sp)s(ecial)33 b(parameter)j
+Fs(0)f Ft(is)f(unc)m(hanged.)54 b(The)35 b(\014rst)f(elemen)m(t)i(of)f
+(the)g Fs(FUNCNAME)150 2655 y Ft(v)-5 b(ariable)25 b(is)h(set)h(to)h
+(the)f(name)f(of)h(the)g(function)e(while)g(the)i(function)e(is)h
+(executing.)39 b(All)26 b(other)h(asp)s(ects)150 2765
+y(of)32 b(the)g(shell)e(execution)j(en)m(vironmen)m(t)e(are)i(iden)m
+(tical)d(b)s(et)m(w)m(een)j(a)f(function)f(and)g(its)h(caller)f(with)g
+(the)150 2874 y(exception)25 b(that)h(the)f Fs(DEBUG)f
+Ft(trap)h(b)s(elo)m(w\))g(is)f(not)i(inherited)c(unless)i(the)h
+(function)f(has)h(b)s(een)g(giv)m(en)g(the)150 2984 y
+Fs(trace)36 b Ft(attribute)g(using)g(the)h Fs(declare)e
+Ft(builtin)e(or)k(the)g Fs(-o)30 b(functrace)35 b Ft(option)h(has)h(b)s
+(een)f(enabled)150 3093 y(with)c(the)h Fs(set)g Ft(builtin,)e(\(in)h
+(whic)m(h)g(case)i(all)e(functions)g(inherit)f(the)j
+Fs(DEBUG)e Ft(trap\).)49 b(See)34 b(Section)f(4.1)150
 3203 y([Bourne)d(Shell)f(Builtins],)f(page)j(33,)g(for)g(the)f
 (description)f(of)h(the)h Fs(trap)e Ft(builtin.)275 3354
 y(If)37 b(the)g(builtin)d(command)k Fs(return)d Ft(is)i(executed)h(in)f
@@ -7874,24 +7874,26 @@ Ft(and)h Fs(unalias)e Ft(builtin)f(commands.)p eop
 72 77 bop 150 -116 a Ft(72)2572 b(Bash)31 b(Reference)g(Man)m(ual)275
 299 y(The)e(\014rst)f(w)m(ord)i(of)f(eac)m(h)i(simple)d(command,)i(if)e
 (unquoted,)h(is)g(c)m(hec)m(k)m(ed)i(to)g(see)f(if)f(it)g(has)g(an)g
-(alias.)150 408 y(If)34 b(so,)i(that)f(w)m(ord)f(is)f(replaced)h(b)m(y)
-g(the)h(text)g(of)g(the)f(alias.)52 b(The)34 b(alias)g(name)g(and)g
-(the)g(replacemen)m(t)150 518 y(text)g(ma)m(y)f(con)m(tain)g(an)m(y)g
-(v)-5 b(alid)31 b(shell)g(input,)h(including)d(shell)i(metac)m
-(haracters,)36 b(with)c(the)h(exception)150 628 y(that)i(the)f(alias)f
-(name)h(ma)m(y)h(not)g(con)m(tain)f(`)p Fs(=)p Ft('.)52
-b(The)34 b(\014rst)f(w)m(ord)h(of)g(the)g(replacemen)m(t)h(text)g(is)e
-(tested)150 737 y(for)26 b(aliases,)h(but)f(a)h(w)m(ord)f(that)h(is)f
-(iden)m(tical)f(to)i(an)g(alias)e(b)s(eing)g(expanded)h(is)g(not)g
-(expanded)g(a)h(second)150 847 y(time.)40 b(This)27 b(means)i(that)g
-(one)g(ma)m(y)h(alias)e Fs(ls)g Ft(to)i Fs("ls)f(-F")p
-Ft(,)g(for)f(instance,)i(and)e(Bash)h(do)s(es)f(not)h(try)g(to)150
-956 y(recursiv)m(ely)j(expand)g(the)h(replacemen)m(t)g(text.)50
-b(If)32 b(the)h(last)g(c)m(haracter)h(of)g(the)f(alias)f(v)-5
-b(alue)32 b(is)g(a)h(space)150 1066 y(or)f(tab)g(c)m(haracter,)j(then)d
-(the)g(next)g(command)g(w)m(ord)g(follo)m(wing)e(the)i(alias)g(is)f
-(also)h(c)m(hec)m(k)m(ed)i(for)e(alias)150 1176 y(expansion.)275
-1325 y(Aliases)27 b(are)h(created)i(and)d(listed)g(with)g(the)h
+(alias.)150 408 y(If)24 b(so,)i(that)g(w)m(ord)e(is)g(replaced)g(b)m(y)
+g(the)h(text)h(of)e(the)h(alias.)38 b(The)24 b(c)m(haracters)i(`)p
+Fs(/)p Ft(',)h(`)p Fs($)p Ft(',)f(`)p Fs(`)p Ft(',)g(`)p
+Fs(=)p Ft(')f(and)f(an)m(y)h(of)150 518 y(the)e(shell)e(metac)m
+(haracters)k(or)e(quoting)f(c)m(haracters)i(listed)e(ab)s(o)m(v)m(e)i
+(ma)m(y)f(not)g(app)s(ear)f(in)g(an)h(alias)f(name.)150
+628 y(The)g(replacemen)m(t)g(text)h(ma)m(y)g(con)m(tain)g(an)m(y)f(v)-5
+b(alid)21 b(shell)f(input,)i(including)d(shell)h(metac)m(haracters.)40
+b(The)150 737 y(\014rst)35 b(w)m(ord)g(of)h(the)g(replacemen)m(t)h
+(text)f(is)f(tested)i(for)e(aliases,)i(but)e(a)h(w)m(ord)g(that)g(is)f
+(iden)m(tical)g(to)h(an)150 847 y(alias)30 b(b)s(eing)g(expanded)g(is)g
+(not)h(expanded)f(a)h(second)g(time.)42 b(This)29 b(means)i(that)g(one)
+g(ma)m(y)h(alias)e Fs(ls)g Ft(to)150 956 y Fs("ls)f(-F")p
+Ft(,)36 b(for)f(instance,)h(and)e(Bash)h(do)s(es)g(not)g(try)g(to)g
+(recursiv)m(ely)f(expand)g(the)h(replacemen)m(t)h(text.)150
+1066 y(If)31 b(the)h(last)g(c)m(haracter)h(of)f(the)g(alias)f(v)-5
+b(alue)31 b(is)g(a)h(space)g(or)g(tab)g(c)m(haracter,)i(then)d(the)h
+(next)g(command)150 1176 y(w)m(ord)e(follo)m(wing)f(the)h(alias)g(is)f
+(also)i(c)m(hec)m(k)m(ed)h(for)e(alias)g(expansion.)275
+1325 y(Aliases)d(are)h(created)i(and)d(listed)g(with)g(the)h
 Fs(alias)f Ft(command,)h(and)g(remo)m(v)m(ed)h(with)e(the)h
 Fs(unalias)150 1434 y Ft(command.)275 1583 y(There)44
 b(is)g(no)h(mec)m(hanism)f(for)g(using)g(argumen)m(ts)h(in)e(the)i
@@ -8512,28 +8514,28 @@ Fs(set)f Ft(builtin)e(is)i(enabled,)h(Bash)g(rep)s(orts)f(suc)m(h)h(c)m
 (hanges)150 1228 y(immediately)j(\(see)i(Section)f(4.3)h([The)f(Set)h
 (Builtin],)d(page)j(50\).)42 b(An)m(y)29 b(trap)g(on)g
 Fs(SIGCHLD)f Ft(is)g(executed)150 1338 y(for)i(eac)m(h)i(c)m(hild)c
-(pro)s(cess)i(that)h(exits.)275 1474 y(If)e(an)g(attempt)i(to)g(exit)e
-(Bash)h(is)f(while)f(jobs)h(are)h(stopp)s(ed,)f(the)h(shell)e(prin)m
-(ts)g(a)i(message)h(w)m(arning)150 1583 y(that)f(there)g(are)g(stopp)s
-(ed)f(jobs.)40 b(The)30 b Fs(jobs)e Ft(command)i(ma)m(y)g(then)f(b)s(e)
-h(used)f(to)h(insp)s(ect)f(their)f(status.)150 1693 y(If)i(a)h(second)g
-(attempt)g(to)h(exit)e(is)g(made)g(without)g(an)g(in)m(terv)m(ening)g
-(command,)h(Bash)f(do)s(es)h(not)f(prin)m(t)150 1802
-y(another)h(w)m(arning,)e(and)h(the)g(stopp)s(ed)g(jobs)g(are)g
-(terminated.)150 2063 y Fr(7.2)68 b(Job)45 b(Con)l(trol)h(Builtins)150
-2308 y Fs(bg)870 2443 y(bg)h([)p Fj(jobspec)11 b Fs(])630
-2578 y Ft(Resume)28 b(the)g(susp)s(ended)d(job)j Fq(jobsp)s(ec)k
-Ft(in)27 b(the)h(bac)m(kground,)h(as)f(if)f(it)g(had)g(b)s(een)g
-(started)630 2688 y(with)k(`)p Fs(&)p Ft('.)45 b(If)31
-b Fq(jobsp)s(ec)37 b Ft(is)31 b(not)h(supplied,)d(the)j(curren)m(t)g
-(job)f(is)g(used.)45 b(The)31 b(return)g(status)630 2797
-y(is)h(zero)h(unless)e(it)h(is)g(run)f(when)h(job)g(con)m(trol)h(is)f
-(not)h(enabled,)g(or,)g(when)f(run)f(with)g(job)630 2907
-y(con)m(trol)37 b(enabled,)h(if)e Fq(jobsp)s(ec)42 b
-Ft(w)m(as)37 b(not)h(found)d(or)i Fq(jobsp)s(ec)42 b
-Ft(sp)s(eci\014es)36 b(a)h(job)g(that)h(w)m(as)630 3017
-y(started)31 b(without)e(job)h(con)m(trol.)150 3177 y
-Fs(fg)870 3312 y(fg)47 b([)p Fj(jobspec)11 b Fs(])630
+(pro)s(cess)i(that)h(exits.)275 1474 y(If)k(an)h(attempt)h(to)g(exit)f
+(Bash)h(is)e(made)h(while)e(jobs)i(are)g(stopp)s(ed,)h(the)f(shell)f
+(prin)m(ts)f(a)j(message)150 1583 y(w)m(arning)25 b(that)i(there)f(are)
+g(stopp)s(ed)g(jobs.)38 b(The)26 b Fs(jobs)f Ft(command)h(ma)m(y)h
+(then)e(b)s(e)h(used)f(to)i(insp)s(ect)e(their)150 1693
+y(status.)57 b(If)35 b(a)h(second)g(attempt)g(to)h(exit)e(is)g(made)h
+(without)e(an)i(in)m(terv)m(ening)f(command,)h(Bash)g(do)s(es)150
+1802 y(not)31 b(prin)m(t)e(another)h(w)m(arning,)g(and)f(the)i(stopp)s
+(ed)e(jobs)h(are)h(terminated.)150 2063 y Fr(7.2)68 b(Job)45
+b(Con)l(trol)h(Builtins)150 2308 y Fs(bg)870 2443 y(bg)h([)p
+Fj(jobspec)11 b Fs(])630 2578 y Ft(Resume)28 b(the)g(susp)s(ended)d
+(job)j Fq(jobsp)s(ec)k Ft(in)27 b(the)h(bac)m(kground,)h(as)f(if)f(it)g
+(had)g(b)s(een)g(started)630 2688 y(with)k(`)p Fs(&)p
+Ft('.)45 b(If)31 b Fq(jobsp)s(ec)37 b Ft(is)31 b(not)h(supplied,)d(the)
+j(curren)m(t)g(job)f(is)g(used.)45 b(The)31 b(return)g(status)630
+2797 y(is)h(zero)h(unless)e(it)h(is)g(run)f(when)h(job)g(con)m(trol)h
+(is)f(not)h(enabled,)g(or,)g(when)f(run)f(with)g(job)630
+2907 y(con)m(trol)37 b(enabled,)h(if)e Fq(jobsp)s(ec)42
+b Ft(w)m(as)37 b(not)h(found)d(or)i Fq(jobsp)s(ec)42
+b Ft(sp)s(eci\014es)36 b(a)h(job)g(that)h(w)m(as)630
+3017 y(started)31 b(without)e(job)h(con)m(trol.)150 3177
+Fs(fg)870 3312 y(fg)47 b([)p Fj(jobspec)11 b Fs(])630
 3448 y Ft(Resume)43 b(the)g(job)g Fq(jobsp)s(ec)48 b
 Ft(in)42 b(the)h(foreground)g(and)f(mak)m(e)j(it)d(the)i(curren)m(t)f
 (job.)78 b(If)630 3557 y Fq(jobsp)s(ec)41 b Ft(is)36
index c1cdcf3..653e5c5 100644 (file)
@@ -1113,7 +1113,7 @@ function become the positional parameters
 during its execution (@pxref{Positional Parameters}).
 The special parameter @samp{#} that expands to the number of
 positional parameters is updated to reflect the change.
-Positional parameter @code{0} is unchanged.
+Special parameter @code{0} is unchanged.
 The first element of the @env{FUNCNAME} variable is set to the
 name of the function while the function is executing.
 All other aspects of the shell execution
@@ -1545,9 +1545,9 @@ If @var{parameter} is unset or null, the expansion of
 If @var{parameter}
 is unset or null, the expansion of @var{word}
 is assigned to @var{parameter}.
-The value of @var{parameter}
-is then substituted.  Positional parameters and special parameters may
-not be assigned to in this way.
+The value of @var{parameter} is then substituted. 
+Positional parameters and special parameters may not be assigned to
+in this way.
 
 @item $@{@var{parameter}:?@var{word}@}
 If @var{parameter}
@@ -2600,6 +2600,10 @@ facilities (@pxref{Programmable Completion Builtins}).
 
 Many of the builtins have been extended by @sc{posix} or Bash.
 
+Unless otherwise noted, each builtin command documented as accepting
+options preceded by @samp{-} accepts @samp{--}
+to signify the end of the options.
+
 @node Bourne Shell Builtins
 @section Bourne Shell Builtins
 
@@ -5424,13 +5428,15 @@ the @code{alias} and @code{unalias} builtin commands.
 The first word of each simple command, if unquoted, is checked to see
 if it has an alias.
 If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including shell metacharacters, with the exception
-that the alias name may not contain @samp{=}.
+The characters @samp{/}, @samp{$}, @samp{`}, @samp{=} and any of the
+shell metacharacters or quoting characters listed above may not appear
+in an alias name.
+The replacement text may contain any valid
+shell input, including shell metacharacters.
 The first word of the replacement text is tested for
 aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.  This means that one may alias
-@code{ls} to @code{"ls -F"},
+is not expanded a second time.
+This means that one may alias @code{ls} to @code{"ls -F"},
 for instance, and Bash does not try to recursively expand the
 replacement text. If the last character of the alias value is a
 space or tab character, then the next command word following the
index 511887a..445ef81 100644 (file)
@@ -1113,7 +1113,7 @@ function become the positional parameters
 during its execution (@pxref{Positional Parameters}).
 The special parameter @samp{#} that expands to the number of
 positional parameters is updated to reflect the change.
-Positional parameter @code{0} is unchanged.
+Special parameter @code{0} is unchanged.
 The first element of the @env{FUNCNAME} variable is set to the
 name of the function while the function is executing.
 All other aspects of the shell execution
@@ -1545,9 +1545,9 @@ If @var{parameter} is unset or null, the expansion of
 If @var{parameter}
 is unset or null, the expansion of @var{word}
 is assigned to @var{parameter}.
-The value of @var{parameter}
-is then substituted.  Positional parameters and special parameters may
-not be assigned to in this way.
+The value of @var{parameter} is then substituted. 
+Positional parameters and special parameters may not be assigned to
+in this way.
 
 @item $@{@var{parameter}:?@var{word}@}
 If @var{parameter}
@@ -5424,13 +5424,15 @@ the @code{alias} and @code{unalias} builtin commands.
 The first word of each simple command, if unquoted, is checked to see
 if it has an alias.
 If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including shell metacharacters, with the exception
-that the alias name may not contain @samp{=}.
+The characters @samp{/}, @samp{$}, @samp{`}, @samp{=} and any of the
+shell metacharacters or quoting characters listed above may not appear
+in an alias name.
+The replacement text may contain any valid
+shell input, including shell metacharacters.
 The first word of the replacement text is tested for
 aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.  This means that one may alias
-@code{ls} to @code{"ls -F"},
+is not expanded a second time.
+This means that one may alias @code{ls} to @code{"ls -F"},
 for instance, and Bash does not try to recursively expand the
 replacement text. If the last character of the alias value is a
 space or tab character, then the next command word following the
@@ -5718,7 +5720,7 @@ The release of Bash, version + patchlevel (e.g., 2.00.0)
 @item \w
 The current working directory, with @env{$HOME} abbreviated with a tilde.
 @item \W
-The basename of @env{$PWD}.
+The basename of @env{$PWD}, with @env{$HOME} abbreviated with a tilde.
 @item \!
 The history number of this command.
 @item \#
@@ -6106,7 +6108,7 @@ Bash reports such changes immediately (@pxref{The Set Builtin}).
 Any trap on @code{SIGCHLD} is executed for each child process
 that exits.
 
-If an attempt to exit Bash is while jobs are stopped, the
+If an attempt to exit Bash is made while jobs are stopped, the
 shell prints a message warning that there are stopped jobs.
 The @code{jobs} command may then be used to inspect their status.
 If a second attempt to exit is made without an intervening command,
index cd928cb..0165b6f 100644 (file)
@@ -474,12 +474,12 @@ B\bBA\bAS\bSH\bH B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
               to _\bl_\ba_\bs_\bt is selected from the history list.  _\bF_\bi_\br_\bs_\bt and  _\bl_\ba_\bs_\bt  may
               be  specified  as a string (to locate the last command beginning
               with that string) or as a number  (an  index  into  the  history
-              list,  where  a  negative  number  is used as an offset from the
-              current command number).  If _\bl_\ba_\bs_\bt is not specified it is set  to
-              the  current  command  for listing (so that ``fc -l -10'' prints
-              the last 10 commands) and to _\bf_\bi_\br_\bs_\bt otherwise.  If _\bf_\bi_\br_\bs_\bt  is  not
-              specified  it is set to the previous command for editing and -16
-              for listing.
+              list, where a negative number is used as an offset from the cur-
+              rent command number).  If _\bl_\ba_\bs_\bt is not specified it is set to the
+              current  command  for  listing (so that ``fc -l -10'' prints the
+              last 10 commands) and to _\bf_\bi_\br_\bs_\bt otherwise.  If _\bf_\bi_\br_\bs_\bt is not spec-
+              ified  it is set to the previous command for editing and -16 for
+              listing.
 
               The -\b-n\bn option suppresses the command numbers when listing.   The
               -\b-r\br  option reverses the order of the commands.  If the -\b-l\bl option
@@ -766,14 +766,14 @@ B\bBA\bAS\bSH\bH B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
               One  line  is  read  from  the  standard input, or from the file
               descriptor _\bf_\bd supplied as an argument to the -\b-u\bu option, and  the
               first word is assigned to the first _\bn_\ba_\bm_\be, the second word to the
-              second  _\bn_\ba_\bm_\be,  and  so  on,  with  leftover  words   and   their
-              intervening  separators assigned to the last _\bn_\ba_\bm_\be.  If there are
-              fewer words read from the input stream than names, the remaining
-              names are assigned empty values.  The characters in I\bIF\bFS\bS are used
-              to split the line into words.  The backslash character  (\\b\)  may
-              be  used  to  remove  any special meaning for the next character
-              read and for line continuation.  Options, if supplied, have  the
-              following meanings:
+              second _\bn_\ba_\bm_\be, and so on, with leftover words and their  interven-
+              ing  separators  assigned  to the last _\bn_\ba_\bm_\be.  If there are fewer
+              words read from the input stream than names, the remaining names
+              are  assigned  empty  values.  The characters in I\bIF\bFS\bS are used to
+              split the line into words.  The backslash character (\\b\)  may  be
+              used  to  remove any special meaning for the next character read
+              and for line continuation.  Options, if supplied, have the  fol-
+              lowing meanings:
               -\b-a\ba _\ba_\bn_\ba_\bm_\be
                      The words are assigned to sequential indices of the array
                      variable _\ba_\bn_\ba_\bm_\be, starting at 0.  _\ba_\bn_\ba_\bm_\be is unset before any
@@ -985,8 +985,8 @@ B\bBA\bAS\bSH\bH B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
               rather  than  -  causes  these  options  to  be turned off.  The
               options can also be specified as arguments to an  invocation  of
               the  shell.  The current set of options may be found in $\b$-\b-.  The
-              return status  is  always  true  unless  an  invalid  option  is
-              encountered.
+              return status is always true unless an invalid option is encoun-
+              tered.
 
        s\bsh\bhi\bif\bft\bt [_\bn]
               The  positional  parameters  from _\bn+1 ... are renamed to $\b$1\b1 .\b..\b..\b..\b.
@@ -1044,8 +1044,8 @@ B\bBA\bAS\bSH\bH B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                       formed.
               c\bch\bhe\bec\bck\bkw\bwi\bin\bns\bsi\biz\bze\be
                       If set, b\bba\bas\bsh\bh checks the window size after  each  command
-                      and,  if  necessary,  updates  the  values  of L\bLI\bIN\bNE\bES\bS and
-                      C\bCO\bOL\bLU\bUM\bMN\bNS\bS.
+                      and,  if necessary, updates the values of L\bLI\bIN\bNE\bES\bS and C\bCO\bOL\bL-\b-
+                      U\bUM\bMN\bNS\bS.
               c\bcm\bmd\bdh\bhi\bis\bst\bt If set, b\bba\bas\bsh\bh attempts to save all lines of  a  multiple-
                       line  command  in  the  same history entry.  This allows
                       easy re-editing of multi-line commands.
@@ -1058,8 +1058,8 @@ B\bBA\bAS\bSH\bH B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                       exit if e\bex\bxe\bec\bc fails.
               e\bex\bxp\bpa\ban\bnd\bd_\b_a\bal\bli\bia\bas\bse\bes\bs
                       If set, aliases are expanded as  described  above  under
-                      A\bAL\bLI\bIA\bAS\bSE\bES\bS.    This   option  is  enabled  by  default  for
-                      interactive shells.
+                      A\bAL\bLI\bIA\bAS\bSE\bES\bS.  This option is enabled by default for interac-
+                      tive shells.
               e\bex\bxt\btd\bde\beb\bbu\bug\bg
                       If set,  behavior  intended  for  use  by  debuggers  is
                       enabled:
index 8998085..2e5cf29 100644 (file)
@@ -1,6 +1,6 @@
 %!PS-Adobe-3.0
-%%Creator: groff version 1.18.1
-%%CreationDate: Thu Jan 29 16:59:29 2004
+%%Creator: groff version 1.19
+%%CreationDate: Tue Apr 20 15:26:45 2004
 %%DocumentNeededResources: font Times-Roman
 %%+ font Times-Bold
 %%+ font Times-Italic
@@ -9,13 +9,17 @@
 %%+ font Palatino-Roman
 %%+ font Palatino-Italic
 %%+ font Palatino-Bold
-%%DocumentSuppliedResources: procset grops 1.18 1
+%%DocumentSuppliedResources: procset grops 1.19 0
 %%Pages: 19
 %%PageOrder: Ascend
+%%DocumentMedia: Default 612 792 0 () ()
 %%Orientation: Portrait
 %%EndComments
+%%BeginDefaults
+%%PageMedia: Default
+%%EndDefaults
 %%BeginProlog
-%%BeginResource: procset grops 1.18 1
+%%BeginResource: procset grops 1.19 0
 /setpacking where{
 pop
 currentpacking
@@ -116,16 +120,22 @@ TM setmatrix
 /Fr{
 setrgbcolor fill
 }bind def
+/setcmykcolor where{
+pop
 /Fk{
 setcmykcolor fill
 }bind def
+}if
 /Fg{
 setgray fill
 }bind def
 /FL/fill load def
 /LW/setlinewidth load def
 /Cr/setrgbcolor load def
+/setcmykcolor where{
+pop
 /Ck/setcmykcolor load def
+}if
 /Cg/setgray load def
 /RE{
 findfont
@@ -168,6 +178,7 @@ newpath
 /CNT countdictstack def
 userdict begin
 /showpage{}def
+/setpagedevice{}def
 }bind def
 /PEND{
 clear
@@ -180,6 +191,9 @@ pop
 setpacking
 }if
 %%EndResource
+%%BeginFeature: *PageSize Default
+<< /PageSize [ 612 792 ] /ImagingBBox null >> setpagedevice
+%%EndFeature
 %%IncludeResource: font Times-Roman
 %%IncludeResource: font Times-Bold
 %%IncludeResource: font Times-Italic
index f53687c..af022ad 100644 (file)
@@ -30,8 +30,8 @@ R\bRE\bES\bST\bTR\bRI\bIC\bCT\bTE\bED\bD S\bSH\bHE\bEL\bLL\bL
        +\bo      parsing  the  value  of  S\bSH\bHE\bEL\bLL\bLO\bOP\bPT\bTS\bS from the shell environment at
               startup
 
-       +\bo      redirecting output using the >, >|, <>, >&, &>, and >>  redirec-
-              tion operators
+       +\bo      redirecting output using the >, >|, <>, >&, &>, and >> redirect-
+              ion operators
 
        +\bo      using the e\bex\bxe\bec\bc builtin command to replace the shell with another
               command
index 5a4eee4..567ea95 100644 (file)
@@ -1,15 +1,19 @@
 %!PS-Adobe-3.0
-%%Creator: groff version 1.18.1
-%%CreationDate: Thu Jan 29 16:59:29 2004
+%%Creator: groff version 1.19
+%%CreationDate: Tue Apr 20 15:26:45 2004
 %%DocumentNeededResources: font Times-Roman
 %%+ font Times-Bold
-%%DocumentSuppliedResources: procset grops 1.18 1
+%%DocumentSuppliedResources: procset grops 1.19 0
 %%Pages: 1
 %%PageOrder: Ascend
+%%DocumentMedia: Default 612 792 0 () ()
 %%Orientation: Portrait
 %%EndComments
+%%BeginDefaults
+%%PageMedia: Default
+%%EndDefaults
 %%BeginProlog
-%%BeginResource: procset grops 1.18 1
+%%BeginResource: procset grops 1.19 0
 /setpacking where{
 pop
 currentpacking
@@ -110,16 +114,22 @@ TM setmatrix
 /Fr{
 setrgbcolor fill
 }bind def
+/setcmykcolor where{
+pop
 /Fk{
 setcmykcolor fill
 }bind def
+}if
 /Fg{
 setgray fill
 }bind def
 /FL/fill load def
 /LW/setlinewidth load def
 /Cr/setrgbcolor load def
+/setcmykcolor where{
+pop
 /Ck/setcmykcolor load def
+}if
 /Cg/setgray load def
 /RE{
 findfont
@@ -162,6 +172,7 @@ newpath
 /CNT countdictstack def
 userdict begin
 /showpage{}def
+/setpagedevice{}def
 }bind def
 /PEND{
 clear
@@ -174,6 +185,9 @@ pop
 setpacking
 }if
 %%EndResource
+%%BeginFeature: *PageSize Default
+<< /PageSize [ 612 792 ] /ImagingBBox null >> setpagedevice
+%%EndFeature
 %%IncludeResource: font Times-Roman
 %%IncludeResource: font Times-Bold
 grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
index 278de3d..937dae0 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc.
 
 @set EDITION 3.0
 @set VERSION 3.0-beta1
-@set UPDATED 28 January 2004
-@set UPDATED-MONTH January 2004
+@set UPDATED 20 April 2004
+@set UPDATED-MONTH April 2004
 
-@set LASTCHANGE Wed Jan 28 15:50:08 EST 2004
+@set LASTCHANGE Tue Apr 20 13:54:25 EDT 2004
diff --git a/jobs.c b/jobs.c
index 3950b93..8418267 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -476,6 +476,7 @@ stop_pipeline (async, deferred)
     }
 
   /* Scan from the last slot backward, looking for the next free one. */
+  /* XXX - revisit this interactive assumption */
   if (interactive)
     {
       for (i = job_slots; i; i--)
diff --git a/jobs.c~ b/jobs.c~
index b4e06c7..4fcd07c 100644 (file)
--- a/jobs.c~
+++ b/jobs.c~
@@ -476,6 +476,7 @@ stop_pipeline (async, deferred)
     }
 
   /* Scan from the last slot backward, looking for the next free one. */
+  /* XXX - revisit this interactive assumption */
   if (interactive)
     {
       for (i = job_slots; i; i--)
@@ -554,6 +555,7 @@ stop_pipeline (async, deferred)
       newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
       newjob->cleanarg = (PTR_T) NULL;
 
+itrace("stop_pipeline: adding new job %d", i + 1);
       jobs[i] = newjob;
       if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
        setjstatus (i);
@@ -704,6 +706,7 @@ delete_job (job_index, warn_stopped)
   if (temp->deferred)
     dispose_command (temp->deferred);
 
+itrace("delete_job: deleting job %d", job_index + 1);
   free (temp);
 }
 
@@ -1359,7 +1362,6 @@ make_child (command, async_p)
          if (setpgid (mypid, pipeline_pgrp) < 0)
            sys_error ("child setpgid (%ld to %ld)", (long)mypid, (long)pipeline_pgrp);
 
-itrace("make_child: setpgid (pid = %d, pgrp = %d)", mypid, pipeline_pgrp);
          /* By convention (and assumption above), if
             pipeline_pgrp == shell_pgrp, we are making a child for
             command substitution.
index ad2866f..6fa9350 100644 (file)
@@ -1441,7 +1441,7 @@ argument is ignored.
 Invoke an editor on the current command line, and execute the result as shell
 commands.
 Bash attempts to invoke
-@code{$FCEDIT}, @code{$EDITOR}, and @code{emacs}
+@code{$VISUAL}, @code{$EDITOR}, and @code{emacs}
 as the editor, in that order.
 
 @end ifset
diff --git a/lib/readline/doc/rluser.texi~ b/lib/readline/doc/rluser.texi~
new file mode 100644 (file)
index 0000000..ad2866f
--- /dev/null
@@ -0,0 +1,1824 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rluser.info
+@comment %**end of header (This is for running Texinfo on a region.)
+@setchapternewpage odd
+
+@ignore
+This file documents the end user interface to the GNU command line
+editing features.  It is to be an appendix to manuals for programs which
+use these features.  There is a document entitled "readline.texinfo"
+which contains both end-user and programmer documentation for the
+GNU Readline Library.
+
+Copyright (C) 1988-2004 Free Software Foundation, Inc.
+
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@comment If you are including this manual as an appendix, then set the
+@comment variable readline-appendix.
+
+@ifclear BashFeatures
+@defcodeindex bt
+@end ifclear
+
+@node Command Line Editing
+@chapter Command Line Editing
+
+This chapter describes the basic features of the @sc{gnu}
+command line editing interface.
+@ifset BashFeatures
+Command line editing is provided by the Readline library, which is
+used by several different programs, including Bash.
+@end ifset
+
+@menu
+* Introduction and Notation::  Notation used in this text.
+* Readline Interaction::       The minimum set of commands for editing a line.
+* Readline Init File::         Customizing Readline from a user's view.
+* Bindable Readline Commands:: A description of most of the Readline commands
+                               available for binding
+* Readline vi Mode::           A short description of how to make Readline
+                               behave like the vi editor.
+@ifset BashFeatures
+* Programmable Completion::    How to specify the possible completions for
+                               a specific command.
+* Programmable Completion Builtins::   Builtin commands to specify how to
+                               complete arguments for a particular command.
+@end ifset
+@end menu
+
+@node Introduction and Notation
+@section Introduction to Line Editing
+
+The following paragraphs describe the notation used to represent
+keystrokes.
+
+The text @kbd{C-k} is read as `Control-K' and describes the character
+produced when the @key{k} key is pressed while the Control key
+is depressed.
+
+The text @kbd{M-k} is read as `Meta-K' and describes the character
+produced when the Meta key (if you have one) is depressed, and the @key{k}
+key is pressed.
+The Meta key is labeled @key{ALT} on many keyboards.
+On keyboards with two keys labeled @key{ALT} (usually to either side of
+the space bar), the @key{ALT} on the left side is generally set to
+work as a Meta key.
+The @key{ALT} key on the right may also be configured to work as a
+Meta key or may be configured as some other modifier, such as a
+Compose key for typing accented characters.
+
+If you do not have a Meta or @key{ALT} key, or another key working as
+a Meta key, the identical keystroke can be generated by typing @key{ESC}
+@emph{first}, and then typing @key{k}.
+Either process is known as @dfn{metafying} the @key{k} key.
+
+The text @kbd{M-C-k} is read as `Meta-Control-k' and describes the
+character produced by @dfn{metafying} @kbd{C-k}.
+
+In addition, several keys have their own names.  Specifically,
+@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
+stand for themselves when seen in this text, or in an init file
+(@pxref{Readline Init File}).
+If your keyboard lacks a @key{LFD} key, typing @key{C-j} will
+produce the desired character.
+The @key{RET} key may be labeled @key{Return} or @key{Enter} on
+some keyboards.
+
+@node Readline Interaction
+@section Readline Interaction
+@cindex interaction, readline
+
+Often during an interactive session you type in a long line of text,
+only to notice that the first word on the line is misspelled.  The
+Readline library gives you a set of commands for manipulating the text
+as you type it in, allowing you to just fix your typo, and not forcing
+you to retype the majority of the line.  Using these editing commands,
+you move the cursor to the place that needs correction, and delete or
+insert the text of the corrections.  Then, when you are satisfied with
+the line, you simply press @key{RET}.  You do not have to be at the
+end of the line to press @key{RET}; the entire line is accepted
+regardless of the location of the cursor within the line.
+
+@menu
+* Readline Bare Essentials::   The least you need to know about Readline.
+* Readline Movement Commands:: Moving about the input line.
+* Readline Killing Commands::  How to delete text, and how to get it back!
+* Readline Arguments::         Giving numeric arguments to commands.
+* Searching::                  Searching through previous lines.
+@end menu
+
+@node Readline Bare Essentials
+@subsection Readline Bare Essentials
+@cindex notation, readline
+@cindex command editing
+@cindex editing command lines
+
+In order to enter characters into the line, simply type them.  The typed
+character appears where the cursor was, and then the cursor moves one
+space to the right.  If you mistype a character, you can use your
+erase character to back up and delete the mistyped character.
+
+Sometimes you may mistype a character, and
+not notice the error until you have typed several other characters.  In
+that case, you can type @kbd{C-b} to move the cursor to the left, and then
+correct your mistake.  Afterwards, you can move the cursor to the right
+with @kbd{C-f}.
+
+When you add text in the middle of a line, you will notice that characters
+to the right of the cursor are `pushed over' to make room for the text
+that you have inserted.  Likewise, when you delete text behind the cursor,
+characters to the right of the cursor are `pulled back' to fill in the
+blank space created by the removal of the text.  A list of the bare
+essentials for editing the text of an input line follows.
+
+@table @asis
+@item @kbd{C-b}
+Move back one character.
+@item @kbd{C-f}
+Move forward one character.
+@item @key{DEL} or @key{Backspace}
+Delete the character to the left of the cursor.
+@item @kbd{C-d}
+Delete the character underneath the cursor.
+@item @w{Printing characters}
+Insert the character into the line at the cursor.
+@item @kbd{C-_} or @kbd{C-x C-u}
+Undo the last editing command.  You can undo all the way back to an
+empty line.
+@end table
+
+@noindent
+(Depending on your configuration, the @key{Backspace} key be set to
+delete the character to the left of the cursor and the @key{DEL} key set
+to delete the character underneath the cursor, like @kbd{C-d}, rather
+than the character to the left of the cursor.)
+
+@node Readline Movement Commands
+@subsection Readline Movement Commands
+
+
+The above table describes the most basic keystrokes that you need
+in order to do editing of the input line.  For your convenience, many
+other commands have been added in addition to @kbd{C-b}, @kbd{C-f},
+@kbd{C-d}, and @key{DEL}.  Here are some commands for moving more rapidly
+about the line.
+
+@table @kbd
+@item C-a
+Move to the start of the line.
+@item C-e
+Move to the end of the line.
+@item M-f
+Move forward a word, where a word is composed of letters and digits.
+@item M-b
+Move backward a word.
+@item C-l
+Clear the screen, reprinting the current line at the top.
+@end table
+
+Notice how @kbd{C-f} moves forward a character, while @kbd{M-f} moves
+forward a word.  It is a loose convention that control keystrokes
+operate on characters while meta keystrokes operate on words.
+
+@node Readline Killing Commands
+@subsection Readline Killing Commands
+
+@cindex killing text
+@cindex yanking text
+
+@dfn{Killing} text means to delete the text from the line, but to save
+it away for later use, usually by @dfn{yanking} (re-inserting)
+it back into the line.
+(`Cut' and `paste' are more recent jargon for `kill' and `yank'.)
+
+If the description for a command says that it `kills' text, then you can
+be sure that you can get the text back in a different (or the same)
+place later.
+
+When you use a kill command, the text is saved in a @dfn{kill-ring}.
+Any number of consecutive kills save all of the killed text together, so
+that when you yank it back, you get it all.  The kill
+ring is not line specific; the text that you killed on a previously
+typed line is available to be yanked back later, when you are typing
+another line.
+@cindex kill ring
+
+Here is the list of commands for killing text.
+
+@table @kbd
+@item C-k
+Kill the text from the current cursor position to the end of the line.
+
+@item M-d
+Kill from the cursor to the end of the current word, or, if between
+words, to the end of the next word.
+Word boundaries are the same as those used by @kbd{M-f}.
+
+@item M-@key{DEL}
+Kill from the cursor the start of the current word, or, if between
+words, to the start of the previous word.
+Word boundaries are the same as those used by @kbd{M-b}.
+
+@item C-w
+Kill from the cursor to the previous whitespace.  This is different than
+@kbd{M-@key{DEL}} because the word boundaries differ.
+
+@end table
+
+Here is how to @dfn{yank} the text back into the line.  Yanking
+means to copy the most-recently-killed text from the kill buffer.
+
+@table @kbd
+@item C-y
+Yank the most recently killed text back into the buffer at the cursor.
+
+@item M-y
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is @kbd{C-y} or @kbd{M-y}.
+@end table
+
+@node Readline Arguments
+@subsection Readline Arguments
+
+You can pass numeric arguments to Readline commands.  Sometimes the
+argument acts as a repeat count, other times it is the @i{sign} of the
+argument that is significant.  If you pass a negative argument to a
+command which normally acts in a forward direction, that command will
+act in a backward direction.  For example, to kill text back to the
+start of the line, you might type @samp{M-- C-k}.
+
+The general way to pass numeric arguments to a command is to type meta
+digits before the command.  If the first `digit' typed is a minus
+sign (@samp{-}), then the sign of the argument will be negative.  Once
+you have typed one meta digit to get the argument started, you can type
+the remainder of the digits, and then the command.  For example, to give
+the @kbd{C-d} command an argument of 10, you could type @samp{M-1 0 C-d},
+which will delete the next ten characters on the input line.
+
+@node Searching
+@subsection Searching for Commands in the History
+
+Readline provides commands for searching through the command history
+@ifset BashFeatures
+(@pxref{Bash History Facilities})
+@end ifset
+for lines containing a specified string.
+There are two search modes:  @dfn{incremental} and @dfn{non-incremental}.
+
+Incremental searches begin before the user has finished typing the
+search string.
+As each character of the search string is typed, Readline displays
+the next entry from the history matching the string typed so far.
+An incremental search requires only as many characters as needed to
+find the desired history entry.
+To search backward in the history for a particular string, type
+@kbd{C-r}.  Typing @kbd{C-s} searches forward through the history.
+The characters present in the value of the @code{isearch-terminators} variable
+are used to terminate an incremental search.
+If that variable has not been assigned a value, the @key{ESC} and
+@kbd{C-J} characters will terminate an incremental search.
+@kbd{C-g} will abort an incremental search and restore the original line.
+When the search is terminated, the history entry containing the
+search string becomes the current line.
+
+To find other matching entries in the history list, type @kbd{C-r} or
+@kbd{C-s} as appropriate.
+This will search backward or forward in the history for the next
+entry matching the search string typed so far.
+Any other key sequence bound to a Readline command will terminate
+the search and execute that command.
+For instance, a @key{RET} will terminate the search and accept
+the line, thereby executing the command from the history list.
+A movement command will terminate the search, make the last line found
+the current line, and begin editing.
+
+Readline remembers the last incremental search string.  If two
+@kbd{C-r}s are typed without any intervening characters defining a new
+search string, any remembered search string is used.
+
+Non-incremental searches read the entire search string before starting
+to search for matching history lines.  The search string may be
+typed by the user or be part of the contents of the current line.
+
+@node Readline Init File
+@section Readline Init File
+@cindex initialization file, readline
+
+Although the Readline library comes with a set of Emacs-like
+keybindings installed by default, it is possible to use a different set
+of keybindings.
+Any user can customize programs that use Readline by putting
+commands in an @dfn{inputrc} file, conventionally in his home directory.
+The name of this
+@ifset BashFeatures
+file is taken from the value of the shell variable @env{INPUTRC}.  If
+@end ifset
+@ifclear BashFeatures
+file is taken from the value of the environment variable @env{INPUTRC}.  If
+@end ifclear
+that variable is unset, the default is @file{~/.inputrc}.
+
+When a program which uses the Readline library starts up, the
+init file is read, and the key bindings are set.
+
+In addition, the @code{C-x C-r} command re-reads this init file, thus
+incorporating any changes that you might have made to it.
+
+@menu
+* Readline Init File Syntax::  Syntax for the commands in the inputrc file.
+
+* Conditional Init Constructs::        Conditional key bindings in the inputrc file.
+
+* Sample Init File::           An example inputrc file.
+@end menu
+
+@node Readline Init File Syntax
+@subsection Readline Init File Syntax
+
+There are only a few basic constructs allowed in the
+Readline init file.  Blank lines are ignored.
+Lines beginning with a @samp{#} are comments.
+Lines beginning with a @samp{$} indicate conditional
+constructs (@pxref{Conditional Init Constructs}).  Other lines
+denote variable settings and key bindings.
+
+@table @asis
+@item Variable Settings
+You can modify the run-time behavior of Readline by
+altering the values of variables in Readline
+using the @code{set} command within the init file.
+The syntax is simple:
+
+@example
+set @var{variable} @var{value}
+@end example
+
+@noindent
+Here, for example, is how to
+change from the default Emacs-like key binding to use
+@code{vi} line editing commands:
+
+@example
+set editing-mode vi
+@end example
+
+Variable names and values, where appropriate, are recognized without regard
+to case. 
+
+@ifset BashFeatures
+The @w{@code{bind -V}} command lists the current Readline variable names
+and values.  @xref{Bash Builtins}.
+@end ifset
+
+A great deal of run-time behavior is changeable with the following
+variables.
+
+@cindex variables, readline
+@table @code
+
+@item bell-style
+@vindex bell-style
+Controls what happens when Readline wants to ring the terminal bell.
+If set to @samp{none}, Readline never rings the bell.  If set to
+@samp{visible}, Readline uses a visible bell if one is available.
+If set to @samp{audible} (the default), Readline attempts to ring
+the terminal's bell.
+
+@item comment-begin
+@vindex comment-begin
+The string to insert at the beginning of the line when the
+@code{insert-comment} command is executed.  The default value
+is @code{"#"}.
+
+@item completion-ignore-case
+If set to @samp{on}, Readline performs filename matching and completion
+in a case-insensitive fashion.
+The default value is @samp{off}.
+
+@item completion-query-items
+@vindex completion-query-items
+The number of possible completions that determines when the user is
+asked whether the list of possibilities should be displayed.
+If the number of possible completions is greater than this value,
+Readline will ask the user whether or not he wishes to view
+them; otherwise, they are simply listed.
+This variable must be set to an integer value greater than or equal to 0.
+The default limit is @code{100}.
+
+@item convert-meta
+@vindex convert-meta
+If set to @samp{on}, Readline will convert characters with the
+eighth bit set to an @sc{ascii} key sequence by stripping the eighth
+bit and prefixing an @key{ESC} character, converting them to a
+meta-prefixed key sequence.  The default value is @samp{on}.
+
+@item disable-completion
+@vindex disable-completion
+If set to @samp{On}, Readline will inhibit word completion.
+Completion  characters will be inserted into the line as if they had
+been mapped to @code{self-insert}.  The default is @samp{off}.
+
+@item editing-mode
+@vindex editing-mode
+The @code{editing-mode} variable controls which default set of
+key bindings is used.  By default, Readline starts up in Emacs editing
+mode, where the keystrokes are most similar to Emacs.  This variable can be
+set to either @samp{emacs} or @samp{vi}.
+
+@item enable-keypad
+@vindex enable-keypad
+When set to @samp{on}, Readline will try to enable the application
+keypad when it is called.  Some systems need this to enable the
+arrow keys.  The default is @samp{off}.
+
+@item expand-tilde
+@vindex expand-tilde
+If set to @samp{on}, tilde expansion is performed when Readline
+attempts word completion.  The default is @samp{off}.
+
+@vindex history-preserve-point
+If set to @samp{on}, the history code attempts to place point at the
+same location on each history line retrieved with @code{previous-history}
+or @code{next-history}.
+
+@item horizontal-scroll-mode
+@vindex horizontal-scroll-mode
+This variable can be set to either @samp{on} or @samp{off}.  Setting it
+to @samp{on} means that the text of the lines being edited will scroll
+horizontally on a single screen line when they are longer than the width
+of the screen, instead of wrapping onto a new screen line.  By default,
+this variable is set to @samp{off}.
+
+@item input-meta
+@vindex input-meta
+@vindex meta-flag
+If set to @samp{on}, Readline will enable eight-bit input (it
+will not clear the eighth bit in the characters it reads),
+regardless of what the terminal claims it can support.  The
+default value is @samp{off}.  The name @code{meta-flag} is a
+synonym for this variable.
+
+@item isearch-terminators
+@vindex isearch-terminators
+The string of characters that should terminate an incremental search without
+subsequently executing the character as a command (@pxref{Searching}).
+If this variable has not been given a value, the characters @key{ESC} and
+@kbd{C-J} will terminate an incremental search.
+
+@item keymap
+@vindex keymap
+Sets Readline's idea of the current keymap for key binding commands.
+Acceptable @code{keymap} names are
+@code{emacs},
+@code{emacs-standard},
+@code{emacs-meta},
+@code{emacs-ctlx},
+@code{vi},
+@code{vi-move},
+@code{vi-command}, and
+@code{vi-insert}.
+@code{vi} is equivalent to @code{vi-command}; @code{emacs} is
+equivalent to @code{emacs-standard}.  The default value is @code{emacs}.
+The value of the @code{editing-mode} variable also affects the
+default keymap.
+
+@item mark-directories
+If set to @samp{on}, completed directory names have a slash
+appended.  The default is @samp{on}.
+
+@item mark-modified-lines
+@vindex mark-modified-lines
+This variable, when set to @samp{on}, causes Readline to display an
+asterisk (@samp{*}) at the start of history lines which have been modified.
+This variable is @samp{off} by default.
+
+@item mark-symlinked-directories
+@vindex mark-symlinked-directories
+If set to @samp{on}, completed names which are symbolic links
+to directories have a slash appended (subject to the value of
+@code{mark-directories}).
+The default is @samp{off}.
+
+@item match-hidden-files
+@vindex match-hidden-files
+This variable, when set to @samp{on}, causes Readline to match files whose
+names begin with a @samp{.} (hidden files) when performing filename
+completion, unless the leading @samp{.} is
+supplied by the user in the filename to be completed.
+This variable is @samp{on} by default.
+
+@item output-meta
+@vindex output-meta
+If set to @samp{on}, Readline will display characters with the
+eighth bit set directly rather than as a meta-prefixed escape
+sequence.  The default is @samp{off}.
+
+@item page-completions
+@vindex page-completions
+If set to @samp{on}, Readline uses an internal @code{more}-like pager
+to display a screenful of possible completions at a time.
+This variable is @samp{on} by default.
+
+@item print-completions-horizontally
+If set to @samp{on}, Readline will display completions with matches
+sorted horizontally in alphabetical order, rather than down the screen.
+The default is @samp{off}.
+
+@item show-all-if-ambiguous
+@vindex show-all-if-ambiguous
+This alters the default behavior of the completion functions.  If
+set to @samp{on}, 
+words which have more than one possible completion cause the
+matches to be listed immediately instead of ringing the bell.
+The default value is @samp{off}.
+
+@item show-all-if-unmodified
+@vindex show-all-if-unmodified
+This alters the default behavior of the completion functions in
+a fashion similar to @var{show-all-if-ambiguous}.
+If set to @samp{on}, 
+words which have more than one possible completion without any
+possible partial completion (the possible completions don't share
+a common prefix) cause the matches to be listed immediately instead
+of ringing the bell.
+The default value is @samp{off}.
+
+@item visible-stats
+@vindex visible-stats
+If set to @samp{on}, a character denoting a file's type
+is appended to the filename when listing possible
+completions.  The default is @samp{off}.
+
+@end table
+
+@item Key Bindings
+The syntax for controlling key bindings in the init file is
+simple.  First you need to find the name of the command that you
+want to change.  The following sections contain tables of the command
+name, the default keybinding, if any, and a short description of what
+the command does.
+
+Once you know the name of the command, simply place on a line
+in the init file the name of the key
+you wish to bind the command to, a colon, and then the name of the
+command.  The name of the key
+can be expressed in different ways, depending on what you find most
+comfortable.
+
+In addition to command names, readline allows keys to be bound
+to a string that is inserted when the key is pressed (a @var{macro}).
+
+@ifset BashFeatures
+The @w{@code{bind -p}} command displays Readline function names and
+bindings in a format that can put directly into an initialization file.
+@xref{Bash Builtins}.
+@end ifset
+
+@table @asis
+@item @w{@var{keyname}: @var{function-name} or @var{macro}}
+@var{keyname} is the name of a key spelled out in English.  For example:
+@example
+Control-u: universal-argument
+Meta-Rubout: backward-kill-word
+Control-o: "> output"
+@end example
+
+In the above example, @kbd{C-u} is bound to the function
+@code{universal-argument},
+@kbd{M-DEL} is bound to the function @code{backward-kill-word}, and
+@kbd{C-o} is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+@samp{> output} into the line).
+
+A number of symbolic character names are recognized while
+processing this key binding syntax:
+@var{DEL},
+@var{ESC},
+@var{ESCAPE},
+@var{LFD},
+@var{NEWLINE},
+@var{RET},
+@var{RETURN},
+@var{RUBOUT},
+@var{SPACE},
+@var{SPC},
+and
+@var{TAB}.
+
+@item @w{"@var{keyseq}": @var{function-name} or @var{macro}}
+@var{keyseq} differs from @var{keyname} above in that strings
+denoting an entire key sequence can be specified, by placing
+the key sequence in double quotes.  Some @sc{gnu} Emacs style key
+escapes can be used, as in the following example, but the
+special character names are not recognized.
+
+@example
+"\C-u": universal-argument
+"\C-x\C-r": re-read-init-file
+"\e[11~": "Function Key 1"
+@end example
+
+In the above example, @kbd{C-u} is again bound to the function
+@code{universal-argument} (just as it was in the first example),
+@samp{@kbd{C-x} @kbd{C-r}} is bound to the function @code{re-read-init-file},
+and @samp{@key{ESC} @key{[} @key{1} @key{1} @key{~}} is bound to insert
+the text @samp{Function Key 1}.
+
+@end table
+
+The following @sc{gnu} Emacs style escape sequences are available when
+specifying key sequences:
+
+@table @code
+@item @kbd{\C-}
+control prefix
+@item @kbd{\M-}
+meta prefix
+@item @kbd{\e}
+an escape character
+@item @kbd{\\}
+backslash
+@item @kbd{\"}
+@key{"}, a double quotation mark
+@item @kbd{\'}
+@key{'}, a single quote or apostrophe
+@end table
+
+In addition to the @sc{gnu} Emacs style escape sequences, a second
+set of backslash escapes is available:
+
+@table @code
+@item \a
+alert (bell)
+@item \b
+backspace
+@item \d
+delete
+@item \f
+form feed
+@item \n
+newline
+@item \r
+carriage return
+@item \t
+horizontal tab
+@item \v
+vertical tab
+@item \@var{nnn}
+the eight-bit character whose value is the octal value @var{nnn}
+(one to three digits)
+@item \x@var{HH}
+the eight-bit character whose value is the hexadecimal value @var{HH}
+(one or two hex digits)
+@end table
+
+When entering the text of a macro, single or double quotes must
+be used to indicate a macro definition.
+Unquoted text is assumed to be a function name.
+In the macro body, the backslash escapes described above are expanded.
+Backslash will quote any other character in the macro text,
+including @samp{"} and @samp{'}.
+For example, the following binding will make @samp{@kbd{C-x} \}
+insert a single @samp{\} into the line:
+@example
+"\C-x\\": "\\"
+@end example
+
+@end table
+
+@node Conditional Init Constructs
+@subsection Conditional Init Constructs
+
+Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key
+bindings and variable settings to be performed as the result
+of tests.  There are four parser directives used.
+
+@table @code
+@item $if
+The @code{$if} construct allows bindings to be made based on the
+editing mode, the terminal being used, or the application using
+Readline.  The text of the test extends to the end of the line;
+no characters are required to isolate it.
+
+@table @code
+@item mode
+The @code{mode=} form of the @code{$if} directive is used to test
+whether Readline is in @code{emacs} or @code{vi} mode.
+This may be used in conjunction
+with the @samp{set keymap} command, for instance, to set bindings in
+the @code{emacs-standard} and @code{emacs-ctlx} keymaps only if
+Readline is starting out in @code{emacs} mode.
+
+@item term
+The @code{term=} form may be used to include terminal-specific
+key bindings, perhaps to bind the key sequences output by the
+terminal's function keys.  The word on the right side of the
+@samp{=} is tested against both the full name of the terminal and
+the portion of the terminal name before the first @samp{-}.  This
+allows @code{sun} to match both @code{sun} and @code{sun-cmd},
+for instance.
+
+@item application
+The @var{application} construct is used to include
+application-specific settings.  Each program using the Readline
+library sets the @var{application name}, and you can test for
+a particular value. 
+This could be used to bind key sequences to functions useful for
+a specific program.  For instance, the following command adds a
+key sequence that quotes the current or previous word in Bash:
+@example
+$if Bash
+# Quote the current or previous word
+"\C-xq": "\eb\"\ef\""
+$endif
+@end example
+@end table
+
+@item $endif
+This command, as seen in the previous example, terminates an
+@code{$if} command.
+
+@item $else
+Commands in this branch of the @code{$if} directive are executed if
+the test fails.
+
+@item $include
+This directive takes a single filename as an argument and reads commands
+and bindings from that file.
+For example, the following directive reads from @file{/etc/inputrc}:
+@example
+$include /etc/inputrc
+@end example
+@end table
+
+@node Sample Init File
+@subsection Sample Init File
+
+Here is an example of an @var{inputrc} file.  This illustrates key
+binding, variable assignment, and conditional syntax.
+
+@example
+@page
+# This file controls the behaviour of line input editing for
+# programs that use the GNU Readline library.  Existing
+# programs include FTP, Bash, and GDB.
+#
+# You can re-read the inputrc file with C-x C-r.
+# Lines beginning with '#' are comments.
+#
+# First, include any systemwide bindings and variable
+# assignments from /etc/Inputrc
+$include /etc/Inputrc
+
+#
+# Set various bindings for emacs mode.
+
+set editing-mode emacs 
+
+$if mode=emacs
+
+Meta-Control-h:        backward-kill-word      Text after the function name is ignored
+
+#
+# Arrow keys in keypad mode
+#
+#"\M-OD":        backward-char
+#"\M-OC":        forward-char
+#"\M-OA":        previous-history
+#"\M-OB":        next-history
+#
+# Arrow keys in ANSI mode
+#
+"\M-[D":        backward-char
+"\M-[C":        forward-char
+"\M-[A":        previous-history
+"\M-[B":        next-history
+#
+# Arrow keys in 8 bit keypad mode
+#
+#"\M-\C-OD":       backward-char
+#"\M-\C-OC":       forward-char
+#"\M-\C-OA":       previous-history
+#"\M-\C-OB":       next-history
+#
+# Arrow keys in 8 bit ANSI mode
+#
+#"\M-\C-[D":       backward-char
+#"\M-\C-[C":       forward-char
+#"\M-\C-[A":       previous-history
+#"\M-\C-[B":       next-history
+
+C-q: quoted-insert
+
+$endif
+
+# An old-style binding.  This happens to be the default.
+TAB: complete
+
+# Macros that are convenient for shell interaction
+$if Bash
+# edit the path
+"\C-xp": "PATH=$@{PATH@}\e\C-e\C-a\ef\C-f"
+# prepare to type a quoted word --
+# insert open and close double quotes
+# and move to just after the open quote
+"\C-x\"": "\"\"\C-b"
+# insert a backslash (testing backslash escapes
+# in sequences and macros)
+"\C-x\\": "\\"
+# Quote the current or previous word
+"\C-xq": "\eb\"\ef\""
+# Add a binding to refresh the line, which is unbound
+"\C-xr": redraw-current-line
+# Edit variable on current line.
+"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="
+$endif
+
+# use a visible bell if one is available
+set bell-style visible
+
+# don't strip characters to 7 bits when reading
+set input-meta on
+
+# allow iso-latin1 characters to be inserted rather
+# than converted to prefix-meta sequences
+set convert-meta off
+
+# display characters with the eighth bit set directly
+# rather than as meta-prefixed characters
+set output-meta on
+
+# if there are more than 150 possible completions for
+# a word, ask the user if he wants to see all of them
+set completion-query-items 150
+
+# For FTP
+$if Ftp
+"\C-xg": "get \M-?"
+"\C-xt": "put \M-?"
+"\M-.": yank-last-arg
+$endif
+@end example
+
+@node Bindable Readline Commands
+@section Bindable Readline Commands
+
+@menu
+* Commands For Moving::                Moving about the line.
+* Commands For History::       Getting at previous lines.
+* Commands For Text::          Commands for changing text.
+* Commands For Killing::       Commands for killing and yanking.
+* Numeric Arguments::          Specifying numeric arguments, repeat counts.
+* Commands For Completion::    Getting Readline to do the typing for you.
+* Keyboard Macros::            Saving and re-executing typed characters
+* Miscellaneous Commands::     Other miscellaneous commands.
+@end menu
+
+This section describes Readline commands that may be bound to key
+sequences.
+@ifset BashFeatures
+You can list your key bindings by executing
+@w{@code{bind -P}} or, for a more terse format, suitable for an
+@var{inputrc} file, @w{@code{bind -p}}.  (@xref{Bash Builtins}.)
+@end ifset
+Command names without an accompanying key sequence are unbound by default.
+
+In the following descriptions, @dfn{point} refers to the current cursor
+position, and @dfn{mark} refers to a cursor position saved by the
+@code{set-mark} command.
+The text between the point and mark is referred to as the @dfn{region}.
+
+@node Commands For Moving
+@subsection Commands For Moving
+@ftable @code
+@item beginning-of-line (C-a)
+Move to the start of the current line.
+
+@item end-of-line (C-e)
+Move to the end of the line.
+
+@item forward-char (C-f)
+Move forward a character.
+
+@item backward-char (C-b)
+Move back a character.
+
+@item forward-word (M-f)
+Move forward to the end of the next word.  Words are composed of
+letters and digits.
+
+@item backward-word (M-b)
+Move back to the start of the current or previous word.  Words are
+composed of letters and digits.
+
+@item clear-screen (C-l)
+Clear the screen and redraw the current line,
+leaving the current line at the top of the screen.
+
+@item redraw-current-line ()
+Refresh the current line.  By default, this is unbound.
+
+@end ftable
+
+@node Commands For History
+@subsection Commands For Manipulating The History
+
+@ftable @code
+@item accept-line (Newline or Return)
+@ifset BashFeatures
+Accept the line regardless of where the cursor is.
+If this line is
+non-empty, add it to the history list according to the setting of
+the @env{HISTCONTROL} and @env{HISTIGNORE} variables.
+If this line is a modified history line, then restore the history line
+to its original state.
+@end ifset
+@ifclear BashFeatures
+Accept the line regardless of where the cursor is.
+If this line is
+non-empty, it may be added to the history list for future recall with
+@code{add_history()}.
+If this line is a modified history line, the history line is restored
+to its original state.
+@end ifclear
+
+@item previous-history (C-p)
+Move `back' through the history list, fetching the previous command.
+
+@item next-history (C-n)
+Move `forward' through the history list, fetching the next command.
+
+@item beginning-of-history (M-<)
+Move to the first line in the history.
+
+@item end-of-history (M->)
+Move to the end of the input history, i.e., the line currently
+being entered.
+
+@item reverse-search-history (C-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+
+@item forward-search-history (C-s)
+Search forward starting at the current line and moving `down' through
+the the history as necessary.  This is an incremental search.
+
+@item non-incremental-reverse-search-history (M-p)
+Search backward starting at the current line and moving `up'
+through the history as necessary using a non-incremental search
+for a string supplied by the user.
+
+@item non-incremental-forward-search-history (M-n)
+Search forward starting at the current line and moving `down'
+through the the history as necessary using a non-incremental search
+for a string supplied by the user.
+
+@item history-search-forward ()
+Search forward through the history for the string of characters
+between the start of the current line and the point.
+This is a non-incremental search.
+By default, this command is unbound.
+
+@item history-search-backward ()
+Search backward through the history for the string of characters
+between the start of the current line and the point.  This
+is a non-incremental search.  By default, this command is unbound.
+
+@item yank-nth-arg (M-C-y)
+Insert the first argument to the previous command (usually
+the second word on the previous line) at point.
+With an argument @var{n},
+insert the @var{n}th word from the previous command (the words
+in the previous command begin with word 0).  A negative argument
+inserts the @var{n}th word from the end of the previous command.
+
+@item yank-last-arg (M-. or M-_)
+Insert last argument to the previous command (the last word of the
+previous history entry).  With an
+argument, behave exactly like @code{yank-nth-arg}.
+Successive calls to @code{yank-last-arg} move back through the history
+list, inserting the last argument of each line in turn.
+
+@end ftable
+
+@node Commands For Text
+@subsection Commands For Changing Text
+
+@ftable @code
+@item delete-char (C-d)
+Delete the character at point.  If point is at the
+beginning of the line, there are no characters in the line, and
+the last character typed was not bound to @code{delete-char}, then
+return @sc{eof}.
+
+@item backward-delete-char (Rubout)
+Delete the character behind the cursor.  A numeric argument means
+to kill the characters instead of deleting them.
+
+@item forward-backward-delete-char ()
+Delete the character under the cursor, unless the cursor is at the
+end of the line, in which case the character behind the cursor is
+deleted.  By default, this is not bound to a key.
+
+@item quoted-insert (C-q or C-v)
+Add the next character typed to the line verbatim.  This is
+how to insert key sequences like @kbd{C-q}, for example.
+
+@ifclear BashFeatures
+@item tab-insert (M-@key{TAB})
+Insert a tab character.
+@end ifclear
+
+@item self-insert (a, b, A, 1, !, @dots{})
+Insert yourself.
+
+@item transpose-chars (C-t)
+Drag the character before the cursor forward over
+the character at the cursor, moving the
+cursor forward as well.  If the insertion point
+is at the end of the line, then this
+transposes the last two characters of the line.
+Negative arguments have no effect.
+
+@item transpose-words (M-t)
+Drag the word before point past the word after point,
+moving point past that word as well.
+If the insertion point is at the end of the line, this transposes
+the last two words on the line.
+
+@item upcase-word (M-u)
+Uppercase the current (or following) word.  With a negative argument,
+uppercase the previous word, but do not move the cursor.
+
+@item downcase-word (M-l)
+Lowercase the current (or following) word.  With a negative argument,
+lowercase the previous word, but do not move the cursor.
+
+@item capitalize-word (M-c)
+Capitalize the current (or following) word.  With a negative argument,
+capitalize the previous word, but do not move the cursor.
+
+@item overwrite-mode ()
+Toggle overwrite mode.  With an explicit positive numeric argument,
+switches to overwrite mode.  With an explicit non-positive numeric
+argument, switches to insert mode.  This command affects only
+@code{emacs} mode; @code{vi} mode does overwrite differently.
+Each call to @code{readline()} starts in insert mode.
+
+In overwrite mode, characters bound to @code{self-insert} replace
+the text at point rather than pushing the text to the right.
+Characters bound to @code{backward-delete-char} replace the character
+before point with a space.
+
+By default, this command is unbound.
+
+@end ftable
+
+@node Commands For Killing
+@subsection Killing And Yanking
+
+@ftable @code
+
+@item kill-line (C-k)
+Kill the text from point to the end of the line.
+
+@item backward-kill-line (C-x Rubout)
+Kill backward to the beginning of the line.
+
+@item unix-line-discard (C-u)
+Kill backward from the cursor to the beginning of the current line.
+
+@item kill-whole-line ()
+Kill all characters on the current line, no matter where point is.
+By default, this is unbound.
+
+@item kill-word (M-d)
+Kill from point to the end of the current word, or if between
+words, to the end of the next word.
+Word boundaries are the same as @code{forward-word}.
+
+@item backward-kill-word (M-@key{DEL})
+Kill the word behind point.
+Word boundaries are the same as @code{backward-word}.
+
+@item unix-word-rubout (C-w)
+Kill the word behind point, using white space as a word boundary.
+The killed text is saved on the kill-ring.
+
+@item unix-filename-rubout ()
+Kill the word behind point, using white space and the slash character
+as the word boundaries.
+The killed text is saved on the kill-ring.
+
+@item delete-horizontal-space ()
+Delete all spaces and tabs around point.  By default, this is unbound.
+
+@item kill-region ()
+Kill the text in the current region.
+By default, this command is unbound.
+
+@item copy-region-as-kill ()
+Copy the text in the region to the kill buffer, so it can be yanked
+right away.  By default, this command is unbound.
+
+@item copy-backward-word ()
+Copy the word before point to the kill buffer.
+The word boundaries are the same as @code{backward-word}.
+By default, this command is unbound.
+
+@item copy-forward-word ()
+Copy the word following point to the kill buffer.
+The word boundaries are the same as @code{forward-word}.
+By default, this command is unbound.
+
+@item yank (C-y)
+Yank the top of the kill ring into the buffer at point.
+
+@item yank-pop (M-y)
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is @code{yank} or @code{yank-pop}.
+@end ftable
+
+@node Numeric Arguments
+@subsection Specifying Numeric Arguments
+@ftable @code
+
+@item digit-argument (@kbd{M-0}, @kbd{M-1}, @dots{} @kbd{M--})
+Add this digit to the argument already accumulating, or start a new
+argument.  @kbd{M--} starts a negative argument.
+
+@item universal-argument ()
+This is another way to specify an argument.
+If this command is followed by one or more digits, optionally with a
+leading minus sign, those digits define the argument.
+If the command is followed by digits, executing @code{universal-argument}
+again ends the numeric argument, but is otherwise ignored.
+As a special case, if this command is immediately followed by a
+character that is neither a digit or minus sign, the argument count
+for the next command is multiplied by four.
+The argument count is initially one, so executing this function the
+first time makes the argument count four, a second time makes the
+argument count sixteen, and so on.
+By default, this is not bound to a key.
+@end ftable
+
+@node Commands For Completion
+@subsection Letting Readline Type For You
+
+@ftable @code
+@item complete (@key{TAB})
+Attempt to perform completion on the text before point.
+The actual completion performed is application-specific.
+@ifset BashFeatures
+Bash attempts completion treating the text as a variable (if the
+text begins with @samp{$}), username (if the text begins with
+@samp{~}), hostname (if the text begins with @samp{@@}), or
+command (including aliases and functions) in turn.  If none 
+of these produces a match, filename completion is attempted.
+@end ifset
+@ifclear BashFeatures
+The default is filename completion.
+@end ifclear
+
+@item possible-completions (M-?)
+List the possible completions of the text before point.
+
+@item insert-completions (M-*)
+Insert all completions of the text before point that would have
+been generated by @code{possible-completions}.
+
+@item menu-complete ()
+Similar to @code{complete}, but replaces the word to be completed
+with a single match from the list of possible completions.
+Repeated execution of @code{menu-complete} steps through the list
+of possible completions, inserting each match in turn.
+At the end of the list of completions, the bell is rung
+(subject to the setting of @code{bell-style})
+and the original text is restored.
+An argument of @var{n} moves @var{n} positions forward in the list
+of matches; a negative argument may be used to move backward
+through the list.
+This command is intended to be bound to @key{TAB}, but is unbound
+by default.
+
+@item delete-char-or-list ()
+Deletes the character under the cursor if not at the beginning or
+end of the line (like @code{delete-char}).
+If at the end of the line, behaves identically to
+@code{possible-completions}.
+This command is unbound by default.
+
+@ifset BashFeatures
+@item complete-filename (M-/)
+Attempt filename completion on the text before point.
+
+@item possible-filename-completions (C-x /)
+List the possible completions of the text before point,
+treating it as a filename.
+
+@item complete-username (M-~)
+Attempt completion on the text before point, treating
+it as a username.
+
+@item possible-username-completions (C-x ~)
+List the possible completions of the text before point,
+treating it as a username.
+
+@item complete-variable (M-$)
+Attempt completion on the text before point, treating
+it as a shell variable.
+
+@item possible-variable-completions (C-x $)
+List the possible completions of the text before point,
+treating it as a shell variable.
+
+@item complete-hostname (M-@@)
+Attempt completion on the text before point, treating
+it as a hostname.
+
+@item possible-hostname-completions (C-x @@)
+List the possible completions of the text before point,
+treating it as a hostname.
+
+@item complete-command (M-!)
+Attempt completion on the text before point, treating
+it as a command name.  Command completion attempts to
+match the text against aliases, reserved words, shell
+functions, shell builtins, and finally executable filenames,
+in that order.
+
+@item possible-command-completions (C-x !)
+List the possible completions of the text before point,
+treating it as a command name.
+
+@item dynamic-complete-history (M-@key{TAB})
+Attempt completion on the text before point, comparing
+the text against lines from the history list for possible
+completion matches.
+
+@item complete-into-braces (M-@{)
+Perform filename completion and insert the list of possible completions
+enclosed within braces so the list is available to the shell
+(@pxref{Brace Expansion}).
+
+@end ifset
+@end ftable
+
+@node Keyboard Macros
+@subsection Keyboard Macros
+@ftable @code
+
+@item start-kbd-macro (C-x ()
+Begin saving the characters typed into the current keyboard macro.
+
+@item end-kbd-macro (C-x ))
+Stop saving the characters typed into the current keyboard macro
+and save the definition.
+
+@item call-last-kbd-macro (C-x e)
+Re-execute the last keyboard macro defined, by making the characters
+in the macro appear as if typed at the keyboard.
+
+@end ftable
+
+@node Miscellaneous Commands
+@subsection Some Miscellaneous Commands
+@ftable @code
+
+@item re-read-init-file (C-x C-r)
+Read in the contents of the @var{inputrc} file, and incorporate
+any bindings or variable assignments found there.
+
+@item abort (C-g)
+Abort the current editing command and
+ring the terminal's bell (subject to the setting of
+@code{bell-style}).
+
+@item do-uppercase-version (M-a, M-b, M-@var{x}, @dots{})
+If the metafied character @var{x} is lowercase, run the command
+that is bound to the corresponding uppercase character.
+
+@item prefix-meta (@key{ESC})
+Metafy the next character typed.  This is for keyboards
+without a meta key.  Typing @samp{@key{ESC} f} is equivalent to typing
+@kbd{M-f}.
+
+@item undo (C-_ or C-x C-u)
+Incremental undo, separately remembered for each line.
+
+@item revert-line (M-r)
+Undo all changes made to this line.  This is like executing the @code{undo}
+command enough times to get back to the beginning.
+
+@ifset BashFeatures
+@item tilde-expand (M-&)
+@end ifset
+@ifclear BashFeatures
+@item tilde-expand (M-~)
+@end ifclear
+Perform tilde expansion on the current word.
+
+@item set-mark (C-@@)
+Set the mark to the point.  If a
+numeric argument is supplied, the mark is set to that position.
+
+@item exchange-point-and-mark (C-x C-x)
+Swap the point with the mark.  The current cursor position is set to
+the saved position, and the old cursor position is saved as the mark.
+
+@item character-search (C-])
+A character is read and point is moved to the next occurrence of that
+character.  A negative count searches for previous occurrences.
+
+@item character-search-backward (M-C-])
+A character is read and point is moved to the previous occurrence
+of that character.  A negative count searches for subsequent
+occurrences.
+
+@item insert-comment (M-#)
+Without a numeric argument, the value of the @code{comment-begin}
+variable is inserted at the beginning of the current line.
+If a numeric argument is supplied, this command acts as a toggle:  if
+the characters at the beginning of the line do not match the value
+of @code{comment-begin}, the value is inserted, otherwise
+the characters in @code{comment-begin} are deleted from the beginning of
+the line.
+In either case, the line is accepted as if a newline had been typed.
+@ifset BashFeatures
+The default value of @code{comment-begin} causes this command
+to make the current line a shell comment.
+If a numeric argument causes the comment character to be removed, the line
+will be executed by the shell.
+@end ifset
+
+@item dump-functions ()
+Print all of the functions and their key bindings to the
+Readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an @var{inputrc} file.  This command is unbound by default.
+
+@item dump-variables ()
+Print all of the settable variables and their values to the
+Readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an @var{inputrc} file.  This command is unbound by default.
+
+@item dump-macros ()
+Print all of the Readline key sequences bound to macros and the
+strings they output.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an @var{inputrc} file.  This command is unbound by default.
+
+@ifset BashFeatures
+@item glob-complete-word (M-g)
+The word before point is treated as a pattern for pathname expansion,
+with an asterisk implicitly appended.  This pattern is used to
+generate a list of matching file names for possible completions.
+
+@item glob-expand-word (C-x *)
+The word before point is treated as a pattern for pathname expansion,
+and the list of matching file names is inserted, replacing the word.
+If a numeric argument is supplied, a @samp{*} is appended before
+pathname expansion.
+
+@item glob-list-expansions (C-x g)
+The list of expansions that would have been generated by
+@code{glob-expand-word} is displayed, and the line is redrawn.
+If a numeric argument is supplied, a @samp{*} is appended before
+pathname expansion.
+
+@item display-shell-version (C-x C-v)
+Display version information about the current instance of Bash.
+
+@item shell-expand-line (M-C-e)
+Expand the line as the shell does.
+This performs alias and history expansion as well as all of the shell
+word expansions (@pxref{Shell Expansions}).
+
+@item history-expand-line (M-^)
+Perform history expansion on the current line.
+
+@item magic-space ()
+Perform history expansion on the current line and insert a space
+(@pxref{History Interaction}).
+
+@item alias-expand-line ()
+Perform alias expansion on the current line (@pxref{Aliases}).
+
+@item history-and-alias-expand-line ()
+Perform history and alias expansion on the current line.
+
+@item insert-last-argument (M-. or M-_)
+A synonym for @code{yank-last-arg}.
+
+@item operate-and-get-next (C-o)
+Accept the current line for execution and fetch the next line
+relative to the current line from the history for editing.  Any
+argument is ignored.
+
+@item edit-and-execute-command (C-xC-e)
+Invoke an editor on the current command line, and execute the result as shell
+commands.
+Bash attempts to invoke
+@code{$FCEDIT}, @code{$EDITOR}, and @code{emacs}
+as the editor, in that order.
+
+@end ifset
+
+@ifclear BashFeatures
+@item emacs-editing-mode (C-e)
+When in @code{vi} command mode, this causes a switch to @code{emacs}
+editing mode.
+
+@item vi-editing-mode (M-C-j)
+When in @code{emacs} editing mode, this causes a switch to @code{vi}
+editing mode.
+
+@end ifclear
+
+@end ftable
+
+@node Readline vi Mode
+@section Readline vi Mode
+
+While the Readline library does not have a full set of @code{vi}
+editing functions, it does contain enough to allow simple editing
+of the line.  The Readline @code{vi} mode behaves as specified in
+the @sc{posix} 1003.2 standard.
+
+@ifset BashFeatures
+In order to switch interactively between @code{emacs} and @code{vi}
+editing modes, use the @samp{set -o emacs} and @samp{set -o vi}
+commands (@pxref{The Set Builtin}).
+@end ifset
+@ifclear BashFeatures
+In order to switch interactively between @code{emacs} and @code{vi}
+editing modes, use the command @kbd{M-C-j} (bound to emacs-editing-mode
+when in @code{vi} mode and to vi-editing-mode in @code{emacs} mode).
+@end ifclear
+The Readline default is @code{emacs} mode.
+
+When you enter a line in @code{vi} mode, you are already placed in
+`insertion' mode, as if you had typed an @samp{i}.  Pressing @key{ESC}
+switches you into `command' mode, where you can edit the text of the
+line with the standard @code{vi} movement keys, move to previous
+history lines with @samp{k} and subsequent lines with @samp{j}, and
+so forth.
+
+@ifset BashFeatures
+@node Programmable Completion
+@section Programmable Completion
+@cindex programmable completion
+
+When word completion is attempted for an argument to a command for
+which a completion specification (a @var{compspec}) has been defined
+using the @code{complete} builtin (@pxref{Programmable Completion Builtins}),
+the programmable completion facilities are invoked. 
+
+First, the command name is identified.
+If a compspec has been defined for that command, the
+compspec is used to generate the list of possible completions for the word.
+If the command word is a full pathname, a compspec for the full
+pathname is searched for first.
+If no compspec is found for the full pathname, an attempt is made to
+find a compspec for the portion following the final slash.
+
+Once a compspec has been found, it is used to generate the list of
+matching words.
+If a compspec is not found, the default Bash completion
+described above (@pxref{Commands For Completion}) is performed.
+
+First, the actions specified by the compspec are used.
+Only matches which are prefixed by the word being completed are
+returned.
+When the @option{-f} or @option{-d} option is used for filename or
+directory name completion, the shell variable @env{FIGNORE} is
+used to filter the matches.
+@xref{Bash Variables}, for a description of @env{FIGNORE}.
+
+Any completions specified by a filename expansion pattern to the
+@option{-G} option are generated next.
+The words generated by the pattern need not match the word being completed.
+The @env{GLOBIGNORE} shell variable is not used to filter the matches,
+but the @env{FIGNORE} shell variable is used.
+
+Next, the string specified as the argument to the @option{-W} option
+is considered.
+The string is first split using the characters in the @env{IFS}
+special variable as delimiters.
+Shell quoting is honored.
+Each word is then expanded using
+brace expansion, tilde expansion, parameter and variable expansion,
+command substitution, arithmetic expansion, and pathname expansion,
+as described above (@pxref{Shell Expansions}).
+The results are split using the rules described above
+(@pxref{Word Splitting}).
+The results of the expansion are prefix-matched against the word being
+completed, and the matching words become the possible completions.
+
+After these matches have been generated, any shell function or command
+specified with the @option{-F} and @option{-C} options is invoked.
+When the command or function is invoked, the @env{COMP_LINE} and
+@env{COMP_POINT} variables are assigned values as described above
+(@pxref{Bash Variables}).
+If a shell function is being invoked, the @env{COMP_WORDS} and
+@env{COMP_CWORD} variables are also set.
+When the function or command is invoked, the first argument is the
+name of the command whose arguments are being completed, the
+second argument is the word being completed, and the third argument
+is the word preceding the word being completed on the current command line.
+No filtering of the generated completions against the word being completed
+is performed; the function or command has complete freedom in generating
+the matches.
+
+Any function specified with @option{-F} is invoked first.
+The function may use any of the shell facilities, including the
+@code{compgen} builtin described below
+(@pxref{Programmable Completion Builtins}), to generate the matches.
+It must put the possible completions in the @env{COMPREPLY} array
+variable.
+
+Next, any command specified with the @option{-C} option is invoked
+in an environment equivalent to command substitution.
+It should print a list of completions, one per line, to
+the standard output.
+Backslash may be used to escape a newline, if necessary.
+
+After all of the possible completions are generated, any filter
+specified with the @option{-X} option is applied to the list.
+The filter is a pattern as used for pathname expansion; a @samp{&}
+in the pattern is replaced with the text of the word being completed.
+A literal @samp{&} may be escaped with a backslash; the backslash
+is removed before attempting a match.
+Any completion that matches the pattern will be removed from the list.
+A leading @samp{!} negates the pattern; in this case any completion
+not matching the pattern will be removed.
+
+Finally, any prefix and suffix specified with the @option{-P} and @option{-S}
+options are added to each member of the completion list, and the result is
+returned to the Readline completion code as the list of possible
+completions.
+
+If the previously-applied actions do not generate any matches, and the
+@option{-o dirnames} option was supplied to @code{complete} when the
+compspec was defined, directory name completion is attempted. 
+
+If the @option{-o plusdirs} option was supplied to @code{complete} when
+the compspec was defined, directory name completion is attempted and any
+matches are added to the results of the other actions.
+
+By default, if a compspec is found, whatever it generates is returned to
+the completion code as the full set of possible completions.
+The default Bash completions are not attempted, and the Readline default
+of filename completion is disabled.
+If the @option{-o bashdefault} option was supplied to @code{complete} when
+the compspec was defined, the default Bash completions are attempted
+if the compspec generates no matches.
+If the @option{-o default} option was supplied to @code{complete} when the
+compspec was defined, Readline's default completion will be performed
+if the compspec (and, if attempted, the default Bash completions)
+generate no matches.
+
+When a compspec indicates that directory name completion is desired,
+the programmable completion functions force Readline to append a slash
+to completed names which are symbolic links to directories, subject to
+the value of the @var{mark-directories} Readline variable, regardless
+of the setting of the @var{mark-symlinked-directories} Readline variable.
+
+@node Programmable Completion Builtins
+@section Programmable Completion Builtins
+@cindex completion builtins
+
+Two builtin commands are available to manipulate the programmable completion
+facilities.
+
+@table @code
+@item compgen
+@btindex compgen
+@example
+@code{compgen [@var{option}] [@var{word}]}
+@end example
+
+Generate possible completion matches for @var{word} according to
+the @var{option}s, which may be any option accepted by the
+@code{complete}
+builtin with the exception of @option{-p} and @option{-r}, and write
+the matches to the standard output.
+When using the @option{-F} or @option{-C} options, the various shell variables
+set by the programmable completion facilities, while available, will not
+have useful values.
+
+The matches will be generated in the same way as if the programmable
+completion code had generated them directly from a completion specification
+with the same flags.
+If @var{word} is specified, only those completions matching @var{word}
+will be displayed.
+
+The return value is true unless an invalid option is supplied, or no
+matches were generated.
+
+@item complete
+@btindex complete
+@example
+@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-A @var{action}] [-G @var{globpat}] [-W @var{wordlist}]
+[-P @var{prefix}] [-S @var{suffix}] [-X @var{filterpat}] [-F @var{function}]
+[-C @var{command}] @var{name} [@var{name} @dots{}]}
+@code{complete -pr [@var{name} @dots{}]}
+@end example
+
+Specify how arguments to each @var{name} should be completed.
+If the @option{-p} option is supplied, or if no options are supplied, existing
+completion specifications are printed in a way that allows them to be
+reused as input.
+The @option{-r} option removes a completion specification for
+each @var{name}, or, if no @var{name}s are supplied, all
+completion specifications.
+
+The process of applying these completion specifications when word completion
+is attempted is described above (@pxref{Programmable Completion}).
+
+Other options, if specified, have the following meanings.
+The arguments to the @option{-G}, @option{-W}, and @option{-X} options
+(and, if necessary, the @option{-P} and @option{-S} options)
+should be quoted to protect them from expansion before the
+@code{complete} builtin is invoked.
+
+
+@table @code
+@item -o @var{comp-option}
+The @var{comp-option} controls several aspects of the compspec's behavior
+beyond the simple generation of completions.
+@var{comp-option} may be one of: 
+
+@table @code
+
+@item bashdefault
+Perform the rest of the default Bash completions if the compspec
+generates no matches.
+
+@item default
+Use Readline's default filename completion if the compspec generates
+no matches.
+
+@item dirnames
+Perform directory name completion if the compspec generates no matches.
+
+@item filenames
+Tell Readline that the compspec generates filenames, so it can perform any
+filename-specific processing (like adding a slash to directory names or
+suppressing trailing spaces).  This option is intended to be used with
+shell functions specified with @option{-F}.
+
+@item nospace
+Tell Readline not to append a space (the default) to words completed at
+the end of the line.
+@end table
+
+@item -A @var{action}
+The @var{action} may be one of the following to generate a list of possible
+completions:
+
+@table @code
+@item alias
+Alias names.  May also be specified as @option{-a}.
+
+@item arrayvar
+Array variable names.
+
+@item binding
+Readline key binding names (@pxref{Bindable Readline Commands}).
+
+@item builtin
+Names of shell builtin commands.  May also be specified as @option{-b}.
+
+@item command
+Command names.  May also be specified as @option{-c}.
+
+@item directory
+Directory names.  May also be specified as @option{-d}.
+
+@item disabled
+Names of disabled shell builtins.
+
+@item enabled
+Names of enabled shell builtins.
+
+@item export
+Names of exported shell variables.  May also be specified as @option{-e}.
+
+@item file
+File names.  May also be specified as @option{-f}.
+
+@item function
+Names of shell functions.
+
+@item group
+Group names.  May also be specified as @option{-g}.
+
+@item helptopic
+Help topics as accepted by the @code{help} builtin (@pxref{Bash Builtins}).
+
+@item hostname
+Hostnames, as taken from the file specified by the
+@env{HOSTFILE} shell variable (@pxref{Bash Variables}).
+
+@item job
+Job names, if job control is active.  May also be specified as @option{-j}.
+
+@item keyword
+Shell reserved words.  May also be specified as @option{-k}.
+
+@item running
+Names of running jobs, if job control is active.
+
+@item service
+Service names.  May also be specified as @option{-s}.
+
+@item setopt
+Valid arguments for the @option{-o} option to the @code{set} builtin
+(@pxref{The Set Builtin}).
+
+@item shopt
+Shell option names as accepted by the @code{shopt} builtin
+(@pxref{Bash Builtins}).
+
+@item signal
+Signal names.
+
+@item stopped
+Names of stopped jobs, if job control is active.
+
+@item user
+User names.  May also be specified as @option{-u}.
+
+@item variable
+Names of all shell variables.  May also be specified as @option{-v}.
+@end table
+
+@item -G @var{globpat}
+The filename expansion pattern @var{globpat} is expanded to generate
+the possible completions.
+
+@item -W @var{wordlist}
+The @var{wordlist} is split using the characters in the
+@env{IFS} special variable as delimiters, and each resultant word
+is expanded.
+The possible completions are the members of the resultant list which
+match the word being completed.
+
+@item -C @var{command}
+@var{command} is executed in a subshell environment, and its output is
+used as the possible completions.
+
+@item -F @var{function}
+The shell function @var{function} is executed in the current shell
+environment.
+When it finishes, the possible completions are retrieved from the value
+of the @env{COMPREPLY} array variable.
+
+@item -X @var{filterpat}
+@var{filterpat} is a pattern as used for filename expansion.
+It is applied to the list of possible completions generated by the
+preceding options and arguments, and each completion matching
+@var{filterpat} is removed from the list.
+A leading @samp{!} in @var{filterpat} negates the pattern; in this
+case, any completion not matching @var{filterpat} is removed.
+
+@item -P @var{prefix}
+@var{prefix} is added at the beginning of each possible completion
+after all other options have been applied.
+
+@item -S @var{suffix}
+@var{suffix} is appended to each possible completion
+after all other options have been applied.
+@end table
+
+The return value is true unless an invalid option is supplied, an option
+other than @option{-p} or @option{-r} is supplied without a @var{name}
+argument, an attempt is made to remove a completion specification for
+a @var{name} for which no specification exists, or
+an error occurs adding a completion specification.
+
+@end table
+@end ifset
diff --git a/njobs.c b/njobs.c
new file mode 100644 (file)
index 0000000..8418267
--- /dev/null
+++ b/njobs.c
@@ -0,0 +1,3535 @@
+/* The thing that makes children, remembers them, and contains wait loops. */
+
+/* This file works with both POSIX and BSD systems.  It implements job
+   control. */
+
+/* Copyright (C) 1989-2003 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 2, 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; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include "config.h"
+
+#include "bashtypes.h"
+#include "trap.h"
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "posixtime.h"
+
+#if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) && !defined (RLIMTYPE)
+#  include <sys/resource.h>
+#endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */
+
+#if defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+
+#include "filecntl.h"
+#include <sys/ioctl.h>
+#include <sys/param.h>
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+/* Need to include this up here for *_TTY_DRIVER definitions. */
+#include "shtty.h"
+
+/* Define this if your output is getting swallowed.  It's a no-op on
+   machines with the termio or termios tty drivers. */
+/* #define DRAIN_OUTPUT */
+
+/* For the TIOCGPGRP and TIOCSPGRP ioctl parameters on HP-UX */
+#if defined (hpux) && !defined (TERMIOS_TTY_DRIVER)
+#  include <bsdtty.h>
+#endif /* hpux && !TERMIOS_TTY_DRIVER */
+
+#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
+/* For struct winsize on SCO */
+/*   sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
+#  if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+#    if defined (HAVE_SYS_STREAM_H)
+#      include <sys/stream.h>
+#    endif
+#    include <sys/ptem.h>
+#  endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
+#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
+
+#include "bashansi.h"
+#include "bashintl.h"
+#include "shell.h"
+#include "jobs.h"
+#include "flags.h"
+
+#include "builtins/builtext.h"
+#include "builtins/common.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#define DEFAULT_CHILD_MAX 32
+#define MAX_JOBS_IN_ARRAY 4096         /* testing */
+
+/* Take care of system dependencies that must be handled when waiting for
+   children.  The arguments to the WAITPID macro match those to the Posix.1
+   waitpid() function. */
+
+#if defined (ultrix) && defined (mips) && defined (_POSIX_VERSION)
+#  define WAITPID(pid, statusp, options) \
+       wait3 ((union wait *)statusp, options, (struct rusage *)0)
+#else
+#  if defined (_POSIX_VERSION) || defined (HAVE_WAITPID)
+#    define WAITPID(pid, statusp, options) \
+       waitpid ((pid_t)pid, statusp, options)
+#  else
+#    if defined (HAVE_WAIT3)
+#      define WAITPID(pid, statusp, options) \
+       wait3 (statusp, options, (struct rusage *)0)
+#    else
+#      define WAITPID(pid, statusp, options) \
+       wait3 (statusp, options, (int *)0)
+#    endif /* HAVE_WAIT3 */
+#  endif /* !_POSIX_VERSION && !HAVE_WAITPID*/
+#endif /* !(Ultrix && mips && _POSIX_VERSION) */
+
+/* getpgrp () varies between systems.  Even systems that claim to be
+   Posix.1 compatible lie sometimes (Ultrix, SunOS4, apollo). */
+#if defined (GETPGRP_VOID)
+#  define getpgid(p) getpgrp ()
+#else
+#  define getpgid(p) getpgrp (p)
+#endif /* !GETPGRP_VOID */
+
+/* If the system needs it, REINSTALL_SIGCHLD_HANDLER will reinstall the
+   handler for SIGCHLD. */
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+#  define REINSTALL_SIGCHLD_HANDLER signal (SIGCHLD, sigchld_handler)
+#else
+#  define REINSTALL_SIGCHLD_HANDLER
+#endif /* !MUST_REINSTALL_SIGHANDLERS */
+
+/* Some systems let waitpid(2) tell callers about stopped children. */
+#if !defined (WCONTINUED)
+#  define WCONTINUED 0
+#endif
+#if !defined (WIFCONTINUED)
+#  define WIFCONTINUED(s)      (0)
+#endif
+
+/* The number of additional slots to allocate when we run out. */
+#define JOB_SLOTS 8
+
+typedef int sh_job_map_func_t __P((JOB *, int, int, int));
+
+#if defined (READLINE)
+extern void rl_set_screen_size __P((int, int));
+#endif
+
+/* Variables used here but defined in other files. */
+extern int subshell_environment, line_number;
+extern int posixly_correct, shell_level;
+extern int interrupt_immediately;
+extern int last_command_exit_value, last_command_exit_signal;
+extern int loop_level, breaking;
+extern int sourcelevel;
+extern sh_builtin_func_t *this_shell_builtin;
+extern char *shell_name, *this_command_name;
+extern sigset_t top_level_mask;
+extern procenv_t wait_intr_buf;
+extern int wait_signal_received;
+extern WORD_LIST *subst_assign_varlist;
+
+/* The array of known jobs. */
+JOB **jobs = (JOB **)NULL;
+
+/* The number of slots currently allocated to JOBS. */
+int job_slots = 0;
+
+/* The controlling tty for this shell. */
+int shell_tty = -1;
+
+/* The shell's process group. */
+pid_t shell_pgrp = NO_PID;
+
+/* The terminal's process group. */
+pid_t terminal_pgrp = NO_PID;
+
+/* The process group of the shell's parent. */
+pid_t original_pgrp = NO_PID;
+
+/* The process group of the pipeline currently being made. */
+pid_t pipeline_pgrp = (pid_t)0;
+
+#if defined (PGRP_PIPE)
+/* Pipes which each shell uses to communicate with the process group leader
+   until all of the processes in a pipeline have been started.  Then the
+   process leader is allowed to continue. */
+int pgrp_pipe[2] = { -1, -1 };
+#endif
+
+/* The job which is current; i.e. the one that `%+' stands for. */
+int current_job = NO_JOB;
+
+/* The previous job; i.e. the one that `%-' stands for. */
+int previous_job = NO_JOB;
+
+/* Last child made by the shell.  */
+pid_t last_made_pid = NO_PID;
+
+/* Pid of the last asynchronous child. */
+pid_t last_asynchronous_pid = NO_PID;
+
+/* The pipeline currently being built. */
+PROCESS *the_pipeline = (PROCESS *)NULL;
+
+/* If this is non-zero, do job control. */
+int job_control = 1;
+
+/* Call this when you start making children. */
+int already_making_children = 0;
+
+/* If this is non-zero, $LINES and $COLUMNS are reset after every process
+   exits from get_tty_state(). */
+int check_window_size;
+
+/* Functions local to this file. */
+
+static void get_new_window_size __P((int));
+
+static void run_sigchld_trap __P((int));
+
+static sighandler wait_sigint_handler __P((int));
+static sighandler sigchld_handler __P((int));
+static sighandler sigwinch_sighandler __P((int));
+static sighandler sigcont_sighandler __P((int));
+static sighandler sigstop_sighandler __P((int));
+
+static int waitchld __P((pid_t, int));
+
+static PROCESS *find_pipeline __P((pid_t, int, int *));
+
+static char *current_working_directory __P((void));
+static char *job_working_directory __P((void));
+static char *j_strsignal __P((int));
+static char *printable_job_status __P((int, PROCESS *, int));
+
+static pid_t find_last_pid __P((int, int));
+
+static int set_new_line_discipline __P((int));
+static int map_over_jobs __P((sh_job_map_func_t *, int, int));
+static int job_last_stopped __P((int));
+static int job_last_running __P((int));
+static int most_recent_job_in_state __P((int, JOB_STATE));
+static int find_job __P((pid_t, int));
+static int print_job __P((JOB *, int, int, int));
+static int process_exit_status __P((WAIT));
+static int process_exit_signal __P((WAIT));
+static int job_exit_status __P((int));
+static int job_exit_signal __P((int));
+static int set_job_status_and_cleanup __P((int));
+
+static WAIT raw_job_exit_status __P((int));
+
+static void notify_of_job_status __P((void));
+static void cleanup_dead_jobs __P((void));
+static int compact_jobs_list __P((int));
+static void discard_pipeline __P((PROCESS *));
+static void add_process __P((char *, pid_t));
+static void print_pipeline __P((PROCESS *, int, int, FILE *));
+static void pretty_print_job __P((int, int, FILE *));
+static void set_current_job __P((int));
+static void reset_current __P((void));
+static void set_job_running __P((int));
+static void setjstatus __P((int));
+static void mark_all_jobs_as_dead __P((void));
+static void mark_dead_jobs_as_notified __P((int));
+static void restore_sigint_handler __P((void));
+#if defined (PGRP_PIPE)
+static void pipe_read __P((int *));
+static void pipe_close __P((int *));
+#endif
+
+#if defined (ARRAY_VARS)
+static int *pstatuses;         /* list of pipeline statuses */
+static int statsize;
+#endif
+
+/* Used to synchronize between wait_for and other functions and the SIGCHLD
+   signal handler. */
+static int sigchld;
+static int queue_sigchld;
+
+#define QUEUE_SIGCHLD(os)      (os) = sigchld, queue_sigchld++
+
+#define UNQUEUE_SIGCHLD(os) \
+       do { \
+         queue_sigchld--; \
+         if (queue_sigchld == 0 && os != sigchld) \
+           waitchld (-1, 0); \
+       } while (0)
+
+static SigHandler *old_tstp, *old_ttou, *old_ttin;
+static SigHandler *old_cont = (SigHandler *)SIG_DFL;
+
+#if defined (TIOCGWINSZ) && defined (SIGWINCH)
+static SigHandler *old_winch = (SigHandler *)SIG_DFL;
+#endif
+
+/* A place to temporarily save the current pipeline. */
+static PROCESS *saved_pipeline;
+static int saved_already_making_children;
+
+/* Set this to non-zero whenever you don't want the jobs list to change at
+   all: no jobs deleted and no status change notifications.  This is used,
+   for example, when executing SIGCHLD traps, which may run arbitrary
+   commands. */
+static int jobs_list_frozen;
+
+static char retcode_name_buffer[64];
+
+static long child_max = -1L;
+
+#if !defined (_POSIX_VERSION)
+
+/* These are definitions to map POSIX 1003.1 functions onto existing BSD
+   library functions and system calls. */
+#define setpgid(pid, pgrp)     setpgrp (pid, pgrp)
+#define tcsetpgrp(fd, pgrp)    ioctl ((fd), TIOCSPGRP, &(pgrp))
+
+pid_t
+tcgetpgrp (fd)
+     int fd;
+{
+  pid_t pgrp;
+
+  /* ioctl will handle setting errno correctly. */
+  if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
+    return (-1);
+  return (pgrp);
+}
+
+#endif /* !_POSIX_VERSION */
+
+/* Return the working directory for the current process.  Unlike
+   job_working_directory, this does not call malloc (), nor do any
+   of the functions it calls.  This is so that it can safely be called
+   from a signal handler. */
+static char *
+current_working_directory ()
+{
+  char *dir;
+  static char d[PATH_MAX];
+
+  dir = get_string_value ("PWD");
+
+  if (dir == 0 && the_current_working_directory && no_symbolic_links)
+    dir = the_current_working_directory;
+
+  if (dir == 0)
+    {
+      dir = getcwd (d, sizeof(d));
+      if (dir)
+       dir = d;
+    }
+
+  return (dir == 0) ? "<unknown>" : dir;
+}
+
+/* Return the working directory for the current process. */
+static char *
+job_working_directory ()
+{
+  char *dir;
+
+  dir = get_string_value ("PWD");
+  if (dir)
+    return (savestring (dir));
+
+  dir = get_working_directory ("job-working-directory");
+  if (dir)
+    return (dir);
+
+  return (savestring ("<unknown>"));
+}
+
+void
+making_children ()
+{
+  if (already_making_children)
+    return;
+
+  already_making_children = 1;
+  start_pipeline ();
+}
+
+void
+stop_making_children ()
+{
+  already_making_children = 0;
+}
+
+void
+cleanup_the_pipeline ()
+{
+  if (the_pipeline)
+    {
+      discard_pipeline (the_pipeline);
+      the_pipeline = (PROCESS *)NULL;
+    }
+}
+
+void
+save_pipeline (clear)
+     int clear;
+{
+  saved_pipeline = the_pipeline;
+  saved_already_making_children = already_making_children;
+  if (clear)
+    the_pipeline = (PROCESS *)NULL;
+}
+
+void
+restore_pipeline (discard)
+     int discard;
+{
+  PROCESS *old_pipeline;
+
+  old_pipeline = the_pipeline;
+  the_pipeline = saved_pipeline;
+  already_making_children = saved_already_making_children;
+  if (discard)
+    discard_pipeline (old_pipeline);
+}
+
+/* Start building a pipeline.  */
+void
+start_pipeline ()
+{
+  if (the_pipeline)
+    {
+      cleanup_the_pipeline ();
+      pipeline_pgrp = 0;
+#if defined (PGRP_PIPE)
+      pipe_close (pgrp_pipe);
+#endif
+    }
+
+#if defined (PGRP_PIPE)
+  if (job_control)
+    {
+      if (pipe (pgrp_pipe) == -1)
+       sys_error ("start_pipeline: pgrp pipe");
+    }
+#endif
+}
+
+/* Stop building a pipeline.  Install the process list in the job array.
+   This returns the index of the newly installed job.
+   DEFERRED is a command structure to be executed upon satisfactory
+   execution exit of this pipeline. */
+int
+stop_pipeline (async, deferred)
+     int async;
+     COMMAND *deferred;
+{
+  register int i, j;
+  JOB *newjob;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+#if defined (PGRP_PIPE)
+  /* The parent closes the process group synchronization pipe. */
+  pipe_close (pgrp_pipe);
+#endif
+
+  cleanup_dead_jobs ();
+
+  if (job_slots == 0)
+    {
+      job_slots = JOB_SLOTS;
+      jobs = (JOB **)xmalloc (job_slots * sizeof (JOB *));
+
+      /* Now blank out these new entries. */
+      for (i = 0; i < job_slots; i++)
+       jobs[i] = (JOB *)NULL;
+    }
+
+  /* Scan from the last slot backward, looking for the next free one. */
+  /* XXX - revisit this interactive assumption */
+  if (interactive)
+    {
+      for (i = job_slots; i; i--)
+       if (jobs[i - 1])
+         break;
+    }
+  else
+    {
+      /* If we're not interactive, we don't need to monotonically increase
+        the job number (in fact, we don't care about the job number at all),
+        so we can simply scan for the first free slot.  This helps to keep
+        us from continuously reallocating the jobs array when running
+        certain kinds of shell loops, and saves time spent searching. */
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] == 0)
+         break;
+    }
+
+  /* Do we need more room? */
+
+  /* First try compaction */
+  if (subshell_environment && interactive_shell && i == job_slots && job_slots >= MAX_JOBS_IN_ARRAY)
+    i = compact_jobs_list (0);
+
+  /* If we can't compact, reallocate */
+  if (i == job_slots)
+    {
+      job_slots += JOB_SLOTS;
+      jobs = (JOB **)xrealloc (jobs, ((1 + job_slots) * sizeof (JOB *)));
+
+      for (j = i; j < job_slots; j++)
+       jobs[j] = (JOB *)NULL;
+    }
+
+  /* Add the current pipeline to the job list. */
+  if (the_pipeline)
+    {
+      register PROCESS *p;
+      int any_alive, any_stopped;
+
+      newjob = (JOB *)xmalloc (sizeof (JOB));
+
+      for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+       ;
+      p->next = (PROCESS *)NULL;
+      newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);
+      for (p = newjob->pipe; p->next; p = p->next)
+       ;
+      p->next = newjob->pipe;
+
+      the_pipeline = (PROCESS *)NULL;
+      newjob->pgrp = pipeline_pgrp;
+      pipeline_pgrp = 0;
+
+      newjob->flags = 0;
+
+      /* Flag to see if in another pgrp. */
+      if (job_control)
+       newjob->flags |= J_JOBCONTROL;
+
+      /* Set the state of this pipeline. */
+      p = newjob->pipe;
+      any_alive = any_stopped = 0;
+      do
+       {
+         any_alive |= p->running;
+         any_stopped |= WIFSTOPPED (p->status);
+         p = p->next;
+       }
+      while (p != newjob->pipe);
+
+      newjob->state = any_alive ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
+      newjob->wd = job_working_directory ();
+      newjob->deferred = deferred;
+
+      newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
+      newjob->cleanarg = (PTR_T) NULL;
+
+      jobs[i] = newjob;
+      if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
+       setjstatus (i);
+    }
+  else
+    newjob = (JOB *)NULL;
+
+  if (async)
+    {
+      if (newjob)
+       newjob->flags &= ~J_FOREGROUND;
+      reset_current ();
+    }
+  else
+    {
+      if (newjob)
+       {
+         newjob->flags |= J_FOREGROUND;
+         /*
+          *            !!!!! NOTE !!!!!  (chet@ins.cwru.edu)
+          *
+          * The currently-accepted job control wisdom says to set the
+          * terminal's process group n+1 times in an n-step pipeline:
+          * once in the parent and once in each child.  This is where
+          * the parent gives it away.
+          *
+          */
+         if (job_control && newjob->pgrp)
+           give_terminal_to (newjob->pgrp, 0);
+       }
+    }
+
+  stop_making_children ();
+  UNBLOCK_CHILD (oset);
+  return (current_job);
+}
+
+/* Delete all DEAD jobs that the user had received notification about. */
+static void
+cleanup_dead_jobs ()
+{
+  register int i;
+  int os;
+
+  if (job_slots == 0 || jobs_list_frozen)
+    return;
+
+  QUEUE_SIGCHLD(os);
+
+  for (i = 0; i < job_slots; i++)
+    if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))
+      delete_job (i, 0);
+
+  UNQUEUE_SIGCHLD(os);
+}
+
+/* Compact the jobs list by removing dead jobs.  Assumed that we have filled
+   the jobs array to some predefined maximum.  Called when the shell is not
+   the foreground process (subshell_environment != 0).  Returns the first
+   available slot in the compacted list.  If that value is job_slots, then
+   the list needs to be reallocated.  The jobs array is in new memory if
+   this returns > 0 and < job_slots.  FLAGS is reserved for future use. */
+static int
+compact_jobs_list (flags)
+     int flags;
+{
+  sigset_t set, oset;
+  register int i, j;
+  int nremove, ndel;
+  JOB **newlist;
+
+  if (job_slots == 0 || jobs_list_frozen)
+    return job_slots;
+
+  if (child_max < 0)
+    child_max = getmaxchild ();
+
+  /* Take out at most a quarter of the jobs in the jobs array, but leave at
+     least child_max */
+  nremove = job_slots >> 2;
+  if ((job_slots - nremove) < child_max)
+    nremove = job_slots - child_max;
+
+  /* need to increase jobs list to at least CHILD_MAX entries */
+  if (nremove < 0)
+    return job_slots;
+
+  BLOCK_CHILD (set, oset);  
+
+  for (ndel = i = 0; i < job_slots; i++)
+    if (jobs[i])
+      {
+       if (DEADJOB (i) && (find_last_pid (i, 0) != last_asynchronous_pid))
+         {
+           delete_job (i, 0);
+           ndel++;
+           if (ndel == nremove)
+             break;
+         }
+      }
+
+  if (ndel == 0)
+    {
+      UNBLOCK_CHILD (oset);
+      return job_slots;
+    }
+
+  newlist = (JOB **)xmalloc ((1 + job_slots) * sizeof (JOB *));
+  for (i = j = 0; i < job_slots; i++)
+    if (jobs[i])
+      newlist[j++] = jobs[i];
+
+  ndel = j;
+  for ( ; j < job_slots; j++)
+    newlist[j] = (JOB *)NULL;
+
+  free (jobs);
+  jobs = newlist;
+
+  UNBLOCK_CHILD (oset);
+
+  return ndel;
+}
+
+/* Delete the job at INDEX from the job list.  Must be called
+   with SIGCHLD blocked. */
+void
+delete_job (job_index, warn_stopped)
+     int job_index, warn_stopped;
+{
+  register JOB *temp;
+
+  if (job_slots == 0 || jobs_list_frozen)
+    return;
+
+  if (warn_stopped && subshell_environment == 0 && STOPPED (job_index))
+    internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
+
+  temp = jobs[job_index];
+  if (job_index == current_job || job_index == previous_job)
+    reset_current ();
+
+  jobs[job_index] = (JOB *)NULL;
+
+  free (temp->wd);
+  discard_pipeline (temp->pipe);
+
+  if (temp->deferred)
+    dispose_command (temp->deferred);
+
+  free (temp);
+}
+
+/* Must be called with SIGCHLD blocked. */
+void
+nohup_job (job_index)
+     int job_index;
+{
+  register JOB *temp;
+
+  if (job_slots == 0)
+    return;
+
+  if (temp = jobs[job_index])
+    temp->flags |= J_NOHUP;
+}
+
+/* Get rid of the data structure associated with a process chain. */
+static void
+discard_pipeline (chain)
+     register PROCESS *chain;
+{
+  register PROCESS *this, *next;
+
+  this = chain;
+  do
+    {
+      next = this->next;
+      FREE (this->command);
+      free (this);
+      this = next;
+    }
+  while (this != chain);
+}
+
+/* Add this process to the chain being built in the_pipeline.
+   NAME is the command string that will be exec'ed later.
+   PID is the process id of the child. */
+static void
+add_process (name, pid)
+     char *name;
+     pid_t pid;
+{
+  PROCESS *t, *p;
+
+  t = (PROCESS *)xmalloc (sizeof (PROCESS));
+  t->next = the_pipeline;
+  t->pid = pid;
+  WSTATUS (t->status) = 0;
+  t->running = PS_RUNNING;
+  t->command = name;
+  the_pipeline = t;
+
+  if (t->next == 0)
+    t->next = t;
+  else
+    {
+      p = t->next;
+      while (p->next != t->next)
+       p = p->next;
+      p->next = t;
+    }
+}
+
+#if 0
+/* Take the last job and make it the first job.  Must be called with
+   SIGCHLD blocked. */
+int
+rotate_the_pipeline ()
+{
+  PROCESS *p;
+
+  if (the_pipeline->next == the_pipeline)
+    return;
+  for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+    ;
+  the_pipeline = p;
+}
+
+/* Reverse the order of the processes in the_pipeline.  Must be called with
+   SIGCHLD blocked. */
+int
+reverse_the_pipeline ()
+{
+  PROCESS *p, *n;
+
+  if (the_pipeline->next == the_pipeline)
+    return;
+
+  for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+    ;
+  p->next = (PROCESS *)NULL;
+
+  n = REVERSE_LIST (the_pipeline, PROCESS *);
+
+  the_pipeline = n;
+  for (p = the_pipeline; p->next; p = p->next)
+    ;
+  p->next = the_pipeline;
+}
+#endif
+
+/* Map FUNC over the list of jobs.  If FUNC returns non-zero,
+   then it is time to stop mapping, and that is the return value
+   for map_over_jobs.  FUNC is called with a JOB, arg1, arg2,
+   and INDEX. */
+static int
+map_over_jobs (func, arg1, arg2)
+     sh_job_map_func_t *func;
+     int arg1, arg2;
+{
+  register int i;
+  int result;
+  sigset_t set, oset;
+
+  if (job_slots == 0)
+    return 0;
+
+  BLOCK_CHILD (set, oset);
+
+  for (i = result = 0; i < job_slots; i++)
+    {
+      if (jobs[i])
+       {
+         result = (*func)(jobs[i], arg1, arg2, i);
+         if (result)
+           break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+
+  return (result);
+}
+
+/* Cause all the jobs in the current pipeline to exit. */
+void
+terminate_current_pipeline ()
+{
+  if (pipeline_pgrp && pipeline_pgrp != shell_pgrp)
+    {
+      killpg (pipeline_pgrp, SIGTERM);
+      killpg (pipeline_pgrp, SIGCONT);
+    }
+}
+
+/* Cause all stopped jobs to exit. */
+void
+terminate_stopped_jobs ()
+{
+  register int i;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i] && STOPPED (i))
+       {
+         killpg (jobs[i]->pgrp, SIGTERM);
+         killpg (jobs[i]->pgrp, SIGCONT);
+       }
+    }
+}
+
+/* Cause all jobs, running or stopped, to receive a hangup signal.  If
+   a job is marked J_NOHUP, don't send the SIGHUP. */
+void
+hangup_all_jobs ()
+{
+  register int i;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i])
+       {
+         if  ((jobs[i]->flags & J_NOHUP) == 0)
+           killpg (jobs[i]->pgrp, SIGHUP);
+         if (STOPPED (i))
+           killpg (jobs[i]->pgrp, SIGCONT);
+       }
+    }
+}
+
+void
+kill_current_pipeline ()
+{
+  stop_making_children ();
+  start_pipeline ();
+}
+
+/* Return the pipeline that PID belongs to.  Note that the pipeline
+   doesn't have to belong to a job.  Must be called with SIGCHLD blocked. */
+static PROCESS *
+find_pipeline (pid, running_only, jobp)
+     pid_t pid;
+     int running_only;
+     int *jobp;                /* index into jobs list or NO_JOB */
+{
+  int job;
+  register PROCESS *p;
+
+  /* See if this process is in the pipeline that we are building. */
+  if (jobp)
+    *jobp = NO_JOB;
+  if (the_pipeline)
+    {
+      p = the_pipeline;
+      do
+       {
+         /* Return it if we found it. */
+         if (p->pid == pid)
+           {
+             if ((running_only && PRUNNING(p)) || (running_only == 0))
+               return (p);
+           }
+
+         p = p->next;
+       }
+      while (p != the_pipeline);
+    }
+
+  job = find_job (pid, running_only);
+  if (jobp)
+    *jobp = job;
+  return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
+}
+
+/* Return the job index that PID belongs to, or NO_JOB if it doesn't
+   belong to any job.  Must be called with SIGCHLD blocked. */
+static int
+find_job (pid, running_only)
+     pid_t pid;
+     int running_only;
+{
+  register int i;
+  register PROCESS *p;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i])
+       {
+         p = jobs[i]->pipe;
+
+         do
+           {
+             if (p->pid == pid)
+               {
+                 if ((running_only && PRUNNING(p)) || (running_only == 0))
+                   return (i);
+               }
+
+             p = p->next;
+           }
+         while (p != jobs[i]->pipe);
+       }
+    }
+
+  return (NO_JOB);
+}
+
+/* Find a job given a PID.  If BLOCK is non-zero, block SIGCHLD as
+   required by find_job. */
+int
+get_job_by_pid (pid, block)
+     pid_t pid;
+     int block;
+{
+  int job;
+  sigset_t set, oset;
+
+  if (block)
+    BLOCK_CHILD (set, oset);
+
+  job = find_job (pid, 0);
+
+  if (block)
+    UNBLOCK_CHILD (oset);
+
+  return job;
+}
+
+/* Print descriptive information about the job with leader pid PID. */
+void
+describe_pid (pid)
+     pid_t pid;
+{
+  int job;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  job = find_job (pid, 0);
+
+  if (job != NO_JOB)
+    printf ("[%d] %ld\n", job + 1, (long)pid);
+  else
+    programming_error (_("describe_pid: %ld: no such pid"), (long)pid);
+
+  UNBLOCK_CHILD (oset);
+}
+
+static char *
+j_strsignal (s)
+     int s;
+{
+  char *x;
+
+  x = strsignal (s);
+  if (x == 0)
+    {
+      x = retcode_name_buffer;
+      sprintf (x, "Signal %d", s);
+    }
+  return x;
+}
+
+static char *
+printable_job_status (j, p, format)
+     int j;
+     PROCESS *p;
+     int format;
+{
+  static char *temp;
+  int es;
+
+  temp = "Done";
+
+  if (STOPPED (j) && format == 0)
+    {
+      if (posixly_correct == 0 || p == 0 || (WIFSTOPPED (p->status) == 0))
+       temp = "Stopped";
+      else
+       {
+         temp = retcode_name_buffer;
+         sprintf (temp, "Stopped(%s)", signal_name (WSTOPSIG (p->status)));
+       }
+    }
+  else if (RUNNING (j))
+    temp = "Running";
+  else
+    {
+      if (WIFSTOPPED (p->status))
+       temp = j_strsignal (WSTOPSIG (p->status));
+      else if (WIFSIGNALED (p->status))
+       temp = j_strsignal (WTERMSIG (p->status));
+      else if (WIFEXITED (p->status))
+       {
+         temp = retcode_name_buffer;
+         es = WEXITSTATUS (p->status);
+         if (es == 0)
+           strcpy (temp, "Done");
+         else if (posixly_correct)
+           sprintf (temp, "Done(%d)", es);
+         else
+           sprintf (temp, "Exit %d", es);
+       }
+      else
+       temp = "Unknown status";
+    }
+
+  return temp;
+}
+
+/* This is the way to print out information on a job if you
+   know the index.  FORMAT is:
+
+    JLIST_NORMAL)   [1]+ Running          emacs
+    JLIST_LONG  )   [1]+ 2378 Running      emacs
+    -1   )   [1]+ 2378       emacs
+
+    JLIST_NORMAL)   [1]+ Stopped          ls | more
+    JLIST_LONG  )   [1]+ 2369 Stopped      ls
+                        2367       | more
+    JLIST_PID_ONLY)
+       Just list the pid of the process group leader (really
+       the process group).
+    JLIST_CHANGED_ONLY)
+       Use format JLIST_NORMAL, but list only jobs about which
+       the user has not been notified. */
+
+/* Print status for pipeline P.  If JOB_INDEX is >= 0, it is the index into
+   the JOBS array corresponding to this pipeline.  FORMAT is as described
+   above.  Must be called with SIGCHLD blocked.
+
+   If you're printing a pipeline that's not in the jobs array, like the
+   current pipeline as it's being created, pass -1 for JOB_INDEX */
+static void
+print_pipeline (p, job_index, format, stream)
+     PROCESS *p;
+     int job_index, format;
+     FILE *stream;
+{
+  PROCESS *first, *last, *show;
+  int es, name_padding;
+  char *temp;
+
+  if (p == 0)
+    return;
+
+  first = last = p;
+  while (last->next != first)
+    last = last->next;
+
+  for (;;)
+    {
+      if (p != first)
+       fprintf (stream, format ? "     " : " |");
+
+      if (format != JLIST_STANDARD)
+       fprintf (stream, "%5ld", (long)p->pid);
+
+      fprintf (stream, " ");
+
+      if (format > -1 && job_index >= 0)
+       {
+         show = format ? p : last;
+         temp = printable_job_status (job_index, show, format);
+
+         if (p != first)
+           {
+             if (format)
+               {
+                 if (show->running == first->running &&
+                     WSTATUS (show->status) == WSTATUS (first->status))
+                   temp = "";
+               }
+             else
+               temp = (char *)NULL;
+           }
+
+         if (temp)
+           {
+             fprintf (stream, "%s", temp);
+
+             es = STRLEN (temp);
+             if (es == 0)
+               es = 2; /* strlen ("| ") */
+             name_padding = LONGEST_SIGNAL_DESC - es;
+
+             fprintf (stream, "%*s", name_padding, "");
+
+             if ((WIFSTOPPED (show->status) == 0) &&
+                 (WIFCONTINUED (show->status) == 0) &&
+                 WIFCORED (show->status))
+               fprintf (stream, "(core dumped) ");
+           }
+       }
+
+      if (p != first && format)
+       fprintf (stream, "| ");
+
+      if (p->command)
+       fprintf (stream, "%s", p->command);
+
+      if (p == last && job_index >= 0)
+       {
+         temp = current_working_directory ();
+
+         if (RUNNING (job_index) && (IS_FOREGROUND (job_index) == 0))
+           fprintf (stream, " &");
+
+         if (strcmp (temp, jobs[job_index]->wd) != 0)
+           fprintf (stream,
+             "  (wd: %s)", polite_directory_format (jobs[job_index]->wd));
+       }
+
+      if (format || (p == last))
+       {
+         /* We need to add a CR only if this is an interactive shell, and
+            we're reporting the status of a completed job asynchronously.
+            We can't really check whether this particular job is being
+            reported asynchronously, so just add the CR if the shell is
+            currently interactive and asynchronous notification is enabled. */
+         if (asynchronous_notification && interactive)
+           fprintf (stream, "\r\n");
+         else
+           fprintf (stream, "\n");
+       }
+
+      if (p == last)
+       break;
+      p = p->next;
+    }
+  fflush (stream);
+}
+
+/* Print information to STREAM about jobs[JOB_INDEX] according to FORMAT.
+   Must be called with SIGCHLD blocked or queued with queue_sigchld */
+static void
+pretty_print_job (job_index, format, stream)
+     int job_index, format;
+     FILE *stream;
+{
+  register PROCESS *p;
+
+  /* Format only pid information about the process group leader? */
+  if (format == JLIST_PID_ONLY)
+    {
+      fprintf (stream, "%ld\n", (long)jobs[job_index]->pipe->pid);
+      return;
+    }
+
+  if (format == JLIST_CHANGED_ONLY)
+    {
+      if (IS_NOTIFIED (job_index))
+       return;
+      format = JLIST_STANDARD;
+    }
+
+  if (format != JLIST_NONINTERACTIVE)
+    fprintf (stream, "[%d]%c ", job_index + 1,
+             (job_index == current_job) ? '+':
+               (job_index == previous_job) ? '-' : ' ');
+
+  if (format == JLIST_NONINTERACTIVE)
+    format = JLIST_LONG;
+
+  p = jobs[job_index]->pipe;
+
+  print_pipeline (p, job_index, format, stream);
+
+  /* We have printed information about this job.  When the job's
+     status changes, waitchld () sets the notification flag to 0. */
+  jobs[job_index]->flags |= J_NOTIFIED;
+}
+
+static int
+print_job (job, format, state, job_index)
+     JOB *job;
+     int format, state, job_index;
+{
+  if (state == -1 || (JOB_STATE)state == job->state)
+    pretty_print_job (job_index, format, stdout);
+  return (0);
+}
+
+void
+list_one_job (job, format, ignore, job_index)
+     JOB *job;
+     int format, ignore, job_index;
+{
+  pretty_print_job (job_index, format, stdout);
+}
+
+void
+list_stopped_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (print_job, format, (int)JSTOPPED);
+}
+
+void
+list_running_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (print_job, format, (int)JRUNNING);
+}
+
+/* List jobs.  If FORMAT is non-zero, then the long form of the information
+   is printed, else just a short version. */
+void
+list_all_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (print_job, format, -1);
+}
+
+/* Fork, handling errors.  Returns the pid of the newly made child, or 0.
+   COMMAND is just for remembering the name of the command; we don't do
+   anything else with it.  ASYNC_P says what to do with the tty.  If
+   non-zero, then don't give it away. */
+pid_t
+make_child (command, async_p)
+     char *command;
+     int async_p;
+{
+  sigset_t set, oset;
+  pid_t pid;
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGCHLD);
+  sigaddset (&set, SIGINT);
+  sigemptyset (&oset);
+  sigprocmask (SIG_BLOCK, &set, &oset);
+
+  making_children ();
+
+#if defined (BUFFERED_INPUT)
+  /* If default_buffered_input is active, we are reading a script.  If
+     the command is asynchronous, we have already duplicated /dev/null
+     as fd 0, but have not changed the buffered stream corresponding to
+     the old fd 0.  We don't want to sync the stream in this case. */
+  if (default_buffered_input != -1 &&
+      (!async_p || default_buffered_input > 0))
+    sync_buffered_stream (default_buffered_input);
+#endif /* BUFFERED_INPUT */
+
+  /* Create the child, handle severe errors. */
+  if ((pid = fork ()) < 0)
+    {
+      sys_error ("fork");
+
+      /* Kill all of the processes in the current pipeline. */
+      terminate_current_pipeline ();
+
+      /* Discard the current pipeline, if any. */
+      if (the_pipeline)
+       kill_current_pipeline ();
+
+      throw_to_top_level ();   /* Reset signals, etc. */
+    }
+
+  if (pid == 0)
+    {
+      /* In the child.  Give this child the right process group, set the
+        signals to the default state for a new process. */
+      pid_t mypid;
+
+      mypid = getpid ();
+#if defined (BUFFERED_INPUT)
+      /* Close default_buffered_input if it's > 0.  We don't close it if it's
+        0 because that's the file descriptor used when redirecting input,
+        and it's wrong to close the file in that case. */
+      unset_bash_input (0);
+#endif /* BUFFERED_INPUT */
+
+      /* Restore top-level signal mask. */
+      sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+
+      if (job_control)
+       {
+         /* All processes in this pipeline belong in the same
+            process group. */
+
+         if (pipeline_pgrp == 0)       /* This is the first child. */
+           pipeline_pgrp = mypid;
+
+         /* Check for running command in backquotes. */
+         if (pipeline_pgrp == shell_pgrp)
+           ignore_tty_job_signals ();
+         else
+           default_tty_job_signals ();
+
+         /* Set the process group before trying to mess with the terminal's
+            process group.  This is mandated by POSIX. */
+         /* This is in accordance with the Posix 1003.1 standard,
+            section B.7.2.4, which says that trying to set the terminal
+            process group with tcsetpgrp() to an unused pgrp value (like
+            this would have for the first child) is an error.  Section
+            B.4.3.3, p. 237 also covers this, in the context of job control
+            shells. */
+         if (setpgid (mypid, pipeline_pgrp) < 0)
+           sys_error ("child setpgid (%ld to %ld)", (long)mypid, (long)pipeline_pgrp);
+
+         /* By convention (and assumption above), if
+            pipeline_pgrp == shell_pgrp, we are making a child for
+            command substitution.
+            In this case, we don't want to give the terminal to the
+            shell's process group (we could be in the middle of a
+            pipeline, for example). */
+         if (async_p == 0 && pipeline_pgrp != shell_pgrp)
+           give_terminal_to (pipeline_pgrp, 0);
+
+#if defined (PGRP_PIPE)
+         if (pipeline_pgrp == mypid)
+           pipe_read (pgrp_pipe);
+#endif
+       }
+      else                     /* Without job control... */
+       {
+         if (pipeline_pgrp == 0)
+           pipeline_pgrp = shell_pgrp;
+
+         /* If these signals are set to SIG_DFL, we encounter the curious
+            situation of an interactive ^Z to a running process *working*
+            and stopping the process, but being unable to do anything with
+            that process to change its state.  On the other hand, if they
+            are set to SIG_IGN, jobs started from scripts do not stop when
+            the shell running the script gets a SIGTSTP and stops. */
+
+         default_tty_job_signals ();
+       }
+
+#if defined (PGRP_PIPE)
+      /* Release the process group pipe, since our call to setpgid ()
+        is done.  The last call to pipe_close is done in stop_pipeline. */
+      pipe_close (pgrp_pipe);
+#endif /* PGRP_PIPE */
+
+      if (async_p)
+       last_asynchronous_pid = getpid ();
+    }
+  else
+    {
+      /* In the parent.  Remember the pid of the child just created
+        as the proper pgrp if this is the first child. */
+
+      if (job_control)
+       {
+         if (pipeline_pgrp == 0)
+           {
+             pipeline_pgrp = pid;
+             /* Don't twiddle terminal pgrps in the parent!  This is the bug,
+                not the good thing of twiddling them in the child! */
+             /* give_terminal_to (pipeline_pgrp, 0); */
+           }
+         /* This is done on the recommendation of the Rationale section of
+            the POSIX 1003.1 standard, where it discusses job control and
+            shells.  It is done to avoid possible race conditions. (Ref.
+            1003.1 Rationale, section B.4.3.3, page 236). */
+         setpgid (pid, pipeline_pgrp);
+       }
+      else
+       {
+         if (pipeline_pgrp == 0)
+           pipeline_pgrp = shell_pgrp;
+       }
+
+      /* Place all processes into the jobs array regardless of the
+        state of job_control. */
+      add_process (command, pid);
+
+      if (async_p)
+       last_asynchronous_pid = pid;
+
+      last_made_pid = pid;
+
+      /* Unblock SIGINT and SIGCHLD. */
+      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+    }
+
+  return (pid);
+}
+
+/* These two functions are called only in child processes. */
+void
+ignore_tty_job_signals ()
+{
+  set_signal_handler (SIGTSTP, SIG_IGN);
+  set_signal_handler (SIGTTIN, SIG_IGN);
+  set_signal_handler (SIGTTOU, SIG_IGN);
+}
+
+void
+default_tty_job_signals ()
+{
+  set_signal_handler (SIGTSTP, SIG_DFL);
+  set_signal_handler (SIGTTIN, SIG_DFL);
+  set_signal_handler (SIGTTOU, SIG_DFL);
+}
+
+/* When we end a job abnormally, or if we stop a job, we set the tty to the
+   state kept in here.  When a job ends normally, we set the state in here
+   to the state of the tty. */
+
+static TTYSTRUCT shell_tty_info;
+
+#if defined (NEW_TTY_DRIVER)
+static struct tchars shell_tchars;
+static struct ltchars shell_ltchars;
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (NEW_TTY_DRIVER) && defined (DRAIN_OUTPUT)
+/* Since the BSD tty driver does not allow us to change the tty modes
+   while simultaneously waiting for output to drain and preserving
+   typeahead, we have to drain the output ourselves before calling
+   ioctl.  We cheat by finding the length of the output queue, and
+   using select to wait for an appropriate length of time.  This is
+   a hack, and should be labeled as such (it's a hastily-adapted
+   mutation of a `usleep' implementation).  It's only reason for
+   existing is the flaw in the BSD tty driver. */
+
+static int ttspeeds[] =
+{
+  0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+  1800, 2400, 4800, 9600, 19200, 38400
+};
+
+static void
+draino (fd, ospeed)
+     int fd, ospeed;
+{
+  register int delay = ttspeeds[ospeed];
+  int n;
+
+  if (!delay)
+    return;
+
+  while ((ioctl (fd, TIOCOUTQ, &n) == 0) && n)
+    {
+      if (n > (delay / 100))
+       {
+         struct timeval tv;
+
+         n *= 10;              /* 2 bits more for conservativeness. */
+         tv.tv_sec = n / delay;
+         tv.tv_usec = ((n % delay) * 1000000) / delay;
+         select (fd, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
+       }
+      else
+       break;
+    }
+}
+#endif /* NEW_TTY_DRIVER && DRAIN_OUTPUT */
+
+/* Return the fd from which we are actually getting input. */
+#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
+
+/* Fill the contents of shell_tty_info with the current tty info. */
+int
+get_tty_state ()
+{
+  int tty;
+
+  tty = input_tty ();
+  if (tty != -1)
+    {
+#if defined (NEW_TTY_DRIVER)
+      ioctl (tty, TIOCGETP, &shell_tty_info);
+      ioctl (tty, TIOCGETC, &shell_tchars);
+      ioctl (tty, TIOCGLTC, &shell_ltchars);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+      ioctl (tty, TCGETA, &shell_tty_info);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+      if (tcgetattr (tty, &shell_tty_info) < 0)
+       {
+#if 0
+         /* Only print an error message if we're really interactive at
+            this time. */
+         if (interactive)
+           sys_error ("[%ld: %d] tcgetattr", (long)getpid (), shell_level);
+#endif
+         return -1;
+       }
+#endif /* TERMIOS_TTY_DRIVER */
+      if (check_window_size)
+       get_new_window_size (0);
+    }
+  return 0;
+}
+
+/* Make the current tty use the state in shell_tty_info. */
+int
+set_tty_state ()
+{
+  int tty;
+
+  tty = input_tty ();
+  if (tty != -1)
+    {
+#if defined (NEW_TTY_DRIVER)
+#  if defined (DRAIN_OUTPUT)
+      draino (tty, shell_tty_info.sg_ospeed);
+#  endif /* DRAIN_OUTPUT */
+      ioctl (tty, TIOCSETN, &shell_tty_info);
+      ioctl (tty, TIOCSETC, &shell_tchars);
+      ioctl (tty, TIOCSLTC, &shell_ltchars);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+      ioctl (tty, TCSETAW, &shell_tty_info);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+      if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
+       {
+         /* Only print an error message if we're really interactive at
+            this time. */
+         if (interactive)
+           sys_error ("[%ld: %d] tcsetattr", (long)getpid (), shell_level);
+         return -1;
+       }
+#endif /* TERMIOS_TTY_DRIVER */
+    }
+  return 0;
+}
+
+/* Given an index into the jobs array JOB, return the pid of the last
+   process in that job's pipeline.  This is the one whose exit status
+   counts.  Must be called with SIGCHLD blocked or queued. */
+static pid_t
+find_last_pid (job, block)
+     int job;
+     int block;
+{
+  register PROCESS *p;
+  sigset_t set, oset;
+
+  if (block)
+    BLOCK_CHILD (set, oset);
+
+  p = jobs[job]->pipe;
+  while (p->next != jobs[job]->pipe)
+    p = p->next;
+
+  if (block)
+    UNBLOCK_CHILD (oset);
+
+  return (p->pid);
+}
+
+/* Wait for a particular child of the shell to finish executing.
+   This low-level function prints an error message if PID is not
+   a child of this shell.  It returns -1 if it fails, or whatever
+   wait_for returns otherwise.  If the child is not found in the
+   jobs table, it returns 127. */
+int
+wait_for_single_pid (pid)
+     pid_t pid;
+{
+  register PROCESS *child;
+  sigset_t set, oset;
+  int r, job;
+
+  BLOCK_CHILD (set, oset);
+  child = find_pipeline (pid, 0, (int *)NULL);
+  UNBLOCK_CHILD (oset);
+
+  if (child == 0)
+    {
+      internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
+      return (127);
+    }
+
+  r = wait_for (pid);
+
+  /* POSIX.2: if we just waited for a job, we can remove it from the jobs
+     table. */
+  BLOCK_CHILD (set, oset);
+  job = find_job (pid, 0);
+  if (job != NO_JOB && jobs[job] && DEADJOB (job))
+    jobs[job]->flags |= J_NOTIFIED;
+  UNBLOCK_CHILD (oset);
+
+  return r;
+}
+
+/* Wait for all of the backgrounds of this shell to finish. */
+void
+wait_for_background_pids ()
+{
+  register int i, r, waited_for;
+  sigset_t set, oset;
+  pid_t pid;
+
+  for (waited_for = 0;;)
+    {
+      BLOCK_CHILD (set, oset);
+
+      /* find first running job; if none running in foreground, break */
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
+         break;
+
+      if (i == job_slots)
+       {
+         UNBLOCK_CHILD (oset);
+         break;
+       }
+
+      /* now wait for the last pid in that job. */
+      pid = find_last_pid (i, 0);
+      UNBLOCK_CHILD (oset);
+      QUIT;
+      errno = 0;               /* XXX */
+      r = wait_for_single_pid (pid);
+      if (r == -1)
+       {
+         /* If we're mistaken about job state, compensate. */
+         if (errno == ECHILD)
+           mark_all_jobs_as_dead ();
+       }
+      else
+       waited_for++;
+    }
+
+  /* POSIX.2 says the shell can discard the statuses of all completed jobs if
+     `wait' is called with no arguments. */
+  mark_dead_jobs_as_notified (1);
+  cleanup_dead_jobs ();
+}
+
+/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
+#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
+static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
+
+static void
+restore_sigint_handler ()
+{
+  if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
+    {
+      set_signal_handler (SIGINT, old_sigint_handler);
+      old_sigint_handler = INVALID_SIGNAL_HANDLER;
+    }
+}
+
+static int wait_sigint_received;
+
+/* Handle SIGINT while we are waiting for children in a script to exit.
+   The `wait' builtin should be interruptible, but all others should be
+   effectively ignored (i.e. not cause the shell to exit). */
+static sighandler
+wait_sigint_handler (sig)
+     int sig;
+{
+  SigHandler *sigint_handler;
+
+  if (interrupt_immediately ||
+      (this_shell_builtin && this_shell_builtin == wait_builtin))
+    {
+      last_command_exit_value = EXECUTION_FAILURE;
+      restore_sigint_handler ();
+      /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
+        what POSIX.2 says (see builtins/wait.def for more info). */
+      if (this_shell_builtin && this_shell_builtin == wait_builtin &&
+         signal_is_trapped (SIGINT) &&
+         ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
+       {
+         interrupt_immediately = 0;
+         trap_handler (SIGINT);        /* set pending_traps[SIGINT] */
+         wait_signal_received = SIGINT;
+         longjmp (wait_intr_buf, 1);
+       }
+      
+      ADDINTERRUPT;
+      QUIT;
+    }
+
+  /* XXX - should this be interrupt_state?  If it is, the shell will act
+     as if it got the SIGINT interrupt. */
+  wait_sigint_received = 1;
+
+  /* Otherwise effectively ignore the SIGINT and allow the running job to
+     be killed. */
+  SIGRETURN (0);
+}
+
+static int
+process_exit_signal (status)
+     WAIT status;
+{
+  return (WIFSIGNALED (status) ? WTERMSIG (status) : 0);
+}
+
+static int
+process_exit_status (status)
+     WAIT status;
+{
+  if (WIFSIGNALED (status))
+    return (128 + WTERMSIG (status));
+  else if (WIFSTOPPED (status) == 0)
+    return (WEXITSTATUS (status));
+  else
+    return (EXECUTION_SUCCESS);
+}
+
+/* Return the exit status of the last process in the pipeline for job JOB.
+   This is the exit status of the entire job. */
+static WAIT
+raw_job_exit_status (job)
+     int job;
+{
+  register PROCESS *p;
+  int fail;
+
+  if (pipefail_opt)
+    {
+      fail = 0;
+      for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
+        if (p->status != EXECUTION_SUCCESS) fail = p->status;
+      return fail;
+    }
+
+  for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
+    ;
+  return (p->status);
+}
+
+/* Return the exit status of job JOB.  This is the exit status of the last
+   (rightmost) process in the job's pipeline, modified if the job was killed
+   by a signal or stopped. */
+static int
+job_exit_status (job)
+     int job;
+{
+  return (process_exit_status (raw_job_exit_status (job)));
+}
+
+static int
+job_exit_signal (job)
+     int job;
+{
+  return (process_exit_signal (raw_job_exit_status (job)));
+}
+
+#define FIND_CHILD(pid, child) \
+  do \
+    { \
+      child = find_pipeline (pid, 0, (int *)NULL); \
+      if (child == 0) \
+       { \
+         give_terminal_to (shell_pgrp, 0); \
+         UNBLOCK_CHILD (oset); \
+         internal_error (_("wait_for: No record of process %ld"), (long)pid); \
+         restore_sigint_handler (); \
+         return (termination_state = 127); \
+       } \
+    } \
+  while (0)
+
+/* Wait for pid (one of our children) to terminate, then
+   return the termination state.  Returns 127 if PID is not found in
+   the jobs table.  Returns -1 if waitchld() returns -1, indicating
+   that there are no unwaited-for child processes. */
+int
+wait_for (pid)
+     pid_t pid;
+{
+  int job, termination_state, r;
+  WAIT s;
+  register PROCESS *child;
+  sigset_t set, oset;
+  register PROCESS *p;
+
+  /* In the case that this code is interrupted, and we longjmp () out of it,
+     we are relying on the code in throw_to_top_level () to restore the
+     top-level signal mask. */
+  BLOCK_CHILD (set, oset);
+
+  /* Ignore interrupts while waiting for a job run without job control
+     to finish.  We don't want the shell to exit if an interrupt is
+     received, only if one of the jobs run is killed via SIGINT.  If
+     job control is not set, the job will be run in the same pgrp as
+     the shell, and the shell will see any signals the job gets. */
+
+  /* This is possibly a race condition -- should it go in stop_pipeline? */
+  wait_sigint_received = 0;
+  if (job_control == 0)
+    old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+
+  termination_state = last_command_exit_value;
+
+  if (interactive && job_control == 0)
+    QUIT;
+
+  /* If we say wait_for (), then we have a record of this child somewhere.
+     If it and none of its peers are running, don't call waitchld(). */
+
+  job = NO_JOB;
+  do
+    {
+      FIND_CHILD (pid, child);
+
+      /* If this child is part of a job, then we are really waiting for the
+        job to finish.  Otherwise, we are waiting for the child to finish.
+        We check for JDEAD in case the job state has been set by waitchld
+        after receipt of a SIGCHLD. */
+      if (job == NO_JOB)
+       job = find_job (pid, 0);
+
+      /* waitchld() takes care of setting the state of the job.  If the job
+        has already exited before this is called, sigchld_handler will have
+        called waitchld and the state will be set to JDEAD. */
+
+      if (child->running || (job != NO_JOB && RUNNING (job)))
+       {
+#if defined (WAITPID_BROKEN)    /* SCOv4 */
+         sigset_t suspend_set;
+         sigemptyset (&suspend_set);
+         sigsuspend (&suspend_set);
+#else /* !WAITPID_BROKEN */
+#  if defined (MUST_UNBLOCK_CHLD)
+         struct sigaction act, oact;
+         sigset_t nullset, chldset;
+
+         sigemptyset (&nullset);
+         sigemptyset (&chldset);
+         sigprocmask (SIG_SETMASK, &nullset, &chldset);
+         act.sa_handler = SIG_DFL;
+         sigemptyset (&act.sa_mask);
+         sigemptyset (&oact.sa_mask);
+         act.sa_flags = 0;
+         sigaction (SIGCHLD, &act, &oact);
+#  endif
+         queue_sigchld = 1;
+         r = waitchld (pid, 1);
+#  if defined (MUST_UNBLOCK_CHLD)
+         sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
+         sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
+#  endif
+         queue_sigchld = 0;
+         if (r == -1 && errno == ECHILD && this_shell_builtin == wait_builtin)
+           {
+             termination_state = -1;
+             goto wait_for_return;
+           }
+
+         /* If child is marked as running, but waitpid() returns -1/ECHILD,
+            there is something wrong.  Somewhere, wait should have returned
+            that child's pid.  Mark the child as not running and the job,
+            if it exists, as JDEAD. */
+         if (r == -1 && errno == ECHILD)
+           {
+             child->running = PS_DONE;
+             child->status = 0;        /* XXX -- can't find true status */
+             if (job != NO_JOB)
+               jobs[job]->state = JDEAD;
+           }
+#endif /* WAITPID_BROKEN */
+       }
+
+      /* If the shell is interactive, and job control is disabled, see
+        if the foreground process has died due to SIGINT and jump out
+        of the wait loop if it has.  waitchld has already restored the
+        old SIGINT signal handler. */
+      if (interactive && job_control == 0)
+       QUIT;
+    }
+  while (child->running || (job != NO_JOB && RUNNING (job)));
+
+  /* The exit state of the command is either the termination state of the
+     child, or the termination state of the job.  If a job, the status
+     of the last child in the pipeline is the significant one.  If the command
+     or job was terminated by a signal, note that value also. */
+  termination_state = (job != NO_JOB) ? job_exit_status (job)
+                                     : process_exit_status (child->status);
+  last_command_exit_signal = (job != NO_JOB) ? job_exit_signal (job)
+                                            : process_exit_signal (child->status);
+
+  if (job == NO_JOB || IS_JOBCONTROL (job))
+    {
+      /* XXX - under what circumstances is a job not present in the jobs
+        table (job == NO_JOB)?
+               1.  command substitution
+
+        In the case of command substitution, at least, it's probably not
+        the right thing to give the terminal to the shell's process group,
+        even though there is code in subst.c:command_substitute to work
+        around it.
+
+        Things that don't:
+               $PROMPT_COMMAND execution
+               process substitution
+       */
+#if 0
+if (job == NO_JOB)
+  itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
+#endif
+
+      give_terminal_to (shell_pgrp, 0);
+    }
+
+  /* If the command did not exit cleanly, or the job is just
+     being stopped, then reset the tty state back to what it
+     was before this command.  Reset the tty state and notify
+     the user of the job termination only if the shell is
+     interactive.  Clean up any dead jobs in either case. */
+  if (job != NO_JOB)
+    {
+      if (interactive_shell && subshell_environment == 0)
+       {
+         /* This used to use `child->status'.  That's wrong, however, for
+            pipelines.  `child' is the first process in the pipeline.  It's
+            likely that the process we want to check for abnormal termination
+            or stopping is the last process in the pipeline, especially if
+            it's long-lived and the first process is short-lived.  Since we
+            know we have a job here, we can check all the processes in this
+            job's pipeline and see if one of them stopped or terminated due
+            to a signal.  We might want to change this later to just check
+            the last process in the pipeline.  If no process exits due to a
+            signal, S is left as the status of the last job in the pipeline. */
+         p = jobs[job]->pipe;
+         do
+           {
+             s = p->status;
+             if (WIFSIGNALED(s) || WIFSTOPPED(s))
+               break;
+             p = p->next;
+           }
+         while (p != jobs[job]->pipe);
+
+         if (WIFSIGNALED (s) || WIFSTOPPED (s))
+           {
+             set_tty_state ();
+
+             /* If the current job was stopped or killed by a signal, and
+                the user has requested it, get a possibly new window size */
+             if (check_window_size && (job == current_job || IS_FOREGROUND (job)))
+               get_new_window_size (0);
+           }
+         else
+           get_tty_state ();
+
+         /* If job control is enabled, the job was started with job
+            control, the job was the foreground job, and it was killed
+            by SIGINT, then print a newline to compensate for the kernel
+            printing the ^C without a trailing newline. */
+         if (job_control && IS_JOBCONTROL (job) && IS_FOREGROUND (job) &&
+               WIFSIGNALED (s) && WTERMSIG (s) == SIGINT)
+           {
+             /* If SIGINT is not trapped and the shell is in a for, while,
+                or until loop, act as if the shell received SIGINT as
+                well, so the loop can be broken.  This doesn't call the
+                SIGINT signal handler; maybe it should. */
+             if (signal_is_trapped (SIGINT) == 0 && loop_level)
+               ADDINTERRUPT;
+             else
+               {
+                 putchar ('\n');
+                 fflush (stdout);
+               }
+           }
+       }
+
+      /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
+         signal handler path */
+      if (DEADJOB (job) && IS_FOREGROUND (job) /*&& subshell_environment == 0*/)
+       setjstatus (job);
+
+      /* If this job is dead, notify the user of the status.  If the shell
+        is interactive, this will display a message on the terminal.  If
+        the shell is not interactive, make sure we turn on the notify bit
+        so we don't get an unwanted message about the job's termination,
+        and so delete_job really clears the slot in the jobs table. */
+      notify_and_cleanup ();
+    }
+
+wait_for_return:
+
+  UNBLOCK_CHILD (oset);
+
+  /* Restore the original SIGINT signal handler before we return. */
+  restore_sigint_handler ();
+
+  return (termination_state);
+}
+
+/* Wait for the last process in the pipeline for JOB.  Returns whatever
+   wait_for returns: the last process's termination state or -1 if there
+   are no unwaited-for child processes or an error occurs. */
+int
+wait_for_job (job)
+     int job;
+{
+  pid_t pid;
+  int r;
+  sigset_t set, oset;
+
+  BLOCK_CHILD(set, oset);
+  if (JOBSTATE (job) == JSTOPPED)
+    internal_warning (_("wait_for_job: job %d is stopped"), job+1);
+
+  pid = find_last_pid (job, 0);
+  UNBLOCK_CHILD(oset);
+  r = wait_for (pid);
+
+  /* POSIX.2: we can remove the job from the jobs table if we just waited
+     for it. */
+  BLOCK_CHILD (set, oset);
+  if (job != NO_JOB && jobs[job] && DEADJOB (job))
+    jobs[job]->flags |= J_NOTIFIED;
+  UNBLOCK_CHILD (oset);
+
+  return r;
+}
+
+/* Print info about dead jobs, and then delete them from the list
+   of known jobs.  This does not actually delete jobs when the
+   shell is not interactive, because the dead jobs are not marked
+   as notified. */
+void
+notify_and_cleanup ()
+{
+  if (jobs_list_frozen)
+    return;
+
+  if (interactive || interactive_shell == 0 || sourcelevel)
+    notify_of_job_status ();
+
+  cleanup_dead_jobs ();
+}
+
+/* Make dead jobs disappear from the jobs array without notification.
+   This is used when the shell is not interactive. */
+void
+reap_dead_jobs ()
+{
+  mark_dead_jobs_as_notified (0);
+  cleanup_dead_jobs ();
+}
+
+/* Return the next closest (chronologically) job to JOB which is in
+   STATE.  STATE can be JSTOPPED, JRUNNING.  NO_JOB is returned if
+   there is no next recent job. */
+static int
+most_recent_job_in_state (job, state)
+     int job;
+     JOB_STATE state;
+{
+  register int i, result;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  for (result = NO_JOB, i = job - 1; i >= 0; i--)
+    {
+      if (jobs[i] && (JOBSTATE (i) == state))
+       {
+         result = i;
+         break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+
+  return (result);
+}
+
+/* Return the newest *stopped* job older than JOB, or NO_JOB if not
+   found. */
+static int
+job_last_stopped (job)
+     int job;
+{
+  return (most_recent_job_in_state (job, JSTOPPED));
+}
+
+/* Return the newest *running* job older than JOB, or NO_JOB if not
+   found. */
+static int
+job_last_running (job)
+     int job;
+{
+  return (most_recent_job_in_state (job, JRUNNING));
+}
+
+/* Make JOB be the current job, and make previous be useful.  Must be
+   called with SIGCHLD blocked. */
+static void
+set_current_job (job)
+     int job;
+{
+  int candidate;
+
+  if (current_job != job)
+    {
+      previous_job = current_job;
+      current_job = job;
+    }
+
+  /* First choice for previous_job is the old current_job. */
+  if (previous_job != current_job &&
+      previous_job != NO_JOB &&
+      jobs[previous_job] &&
+      STOPPED (previous_job))
+    return;
+
+  /* Second choice:  Newest stopped job that is older than
+     the current job. */
+  candidate = NO_JOB;
+  if (STOPPED (current_job))
+    {
+      candidate = job_last_stopped (current_job);
+
+      if (candidate != NO_JOB)
+       {
+         previous_job = candidate;
+         return;
+       }
+    }
+
+  /* If we get here, there is either only one stopped job, in which case it is
+     the current job and the previous job should be set to the newest running
+     job, or there are only running jobs and the previous job should be set to
+     the newest running job older than the current job.  We decide on which
+     alternative to use based on whether or not JOBSTATE(current_job) is
+     JSTOPPED. */
+
+  candidate = RUNNING (current_job) ? job_last_running (current_job)
+                                   : job_last_running (job_slots);
+
+  if (candidate != NO_JOB)
+    {
+      previous_job = candidate;
+      return;
+    }
+
+  /* There is only a single job, and it is both `+' and `-'. */
+  previous_job = current_job;
+}
+
+/* Make current_job be something useful, if it isn't already. */
+
+/* Here's the deal:  The newest non-running job should be `+', and the
+   next-newest non-running job should be `-'.  If there is only a single
+   stopped job, the previous_job is the newest non-running job.  If there
+   are only running jobs, the newest running job is `+' and the
+   next-newest running job is `-'.  Must be called with SIGCHLD blocked. */
+
+static void
+reset_current ()
+{
+  int candidate;
+
+  if (job_slots && current_job != NO_JOB && jobs[current_job] && STOPPED (current_job))
+    candidate = current_job;
+  else
+    {
+      candidate = NO_JOB;
+
+      /* First choice: the previous job. */
+      if (previous_job != NO_JOB && jobs[previous_job] && STOPPED (previous_job))
+       candidate = previous_job;
+
+      /* Second choice: the most recently stopped job. */
+      if (candidate == NO_JOB)
+       candidate = job_last_stopped (job_slots);
+
+      /* Third choice: the newest running job. */
+      if (candidate == NO_JOB)
+       candidate = job_last_running (job_slots);
+    }
+
+  /* If we found a job to use, then use it.  Otherwise, there
+     are no jobs period. */
+  if (candidate != NO_JOB)
+    set_current_job (candidate);
+  else
+    current_job = previous_job = NO_JOB;
+}
+
+/* Set up the job structures so we know the job and its processes are
+   all running. */
+static void
+set_job_running (job)
+     int job;
+{
+  register PROCESS *p;
+
+  /* Each member of the pipeline is now running. */
+  p = jobs[job]->pipe;
+
+  do
+    {
+      if (WIFSTOPPED (p->status))
+       p->running = PS_RUNNING;        /* XXX - could be PS_STOPPED */
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  /* This means that the job is running. */
+  JOBSTATE (job) = JRUNNING;
+}
+
+/* Start a job.  FOREGROUND if non-zero says to do that.  Otherwise,
+   start the job in the background.  JOB is a zero-based index into
+   JOBS.  Returns -1 if it is unable to start a job, and the return
+   status of the job otherwise. */
+int
+start_job (job, foreground)
+     int job, foreground;
+{
+  register PROCESS *p;
+  int already_running;
+  sigset_t set, oset;
+  char *wd;
+  static TTYSTRUCT save_stty;
+
+  BLOCK_CHILD (set, oset);
+
+  if (DEADJOB (job))
+    {
+      internal_error (_("%s: job has terminated"), this_command_name);
+      UNBLOCK_CHILD (oset);
+      return (-1);
+    }
+
+  already_running = RUNNING (job);
+
+  if (foreground == 0 && already_running)
+    {
+      internal_error (_("%s: job %d already in background"), this_command_name, job + 1);
+      UNBLOCK_CHILD (oset);
+      return (-1);
+    }
+
+  wd = current_working_directory ();
+
+  /* You don't know about the state of this job.  Do you? */
+  jobs[job]->flags &= ~J_NOTIFIED;
+
+  if (foreground)
+    {
+      set_current_job (job);
+      jobs[job]->flags |= J_FOREGROUND;
+    }
+
+  /* Tell the outside world what we're doing. */
+  p = jobs[job]->pipe;
+
+  if (foreground == 0)
+    fprintf (stderr, "[%d]%c ", job + 1,
+          (job == current_job) ? '+': ((job == previous_job) ? '-' : ' '));
+
+  do
+    {
+      fprintf (stderr, "%s%s",
+              p->command ? p->command : "",
+              p->next != jobs[job]->pipe? " | " : "");
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  if (foreground == 0)
+    fprintf (stderr, " &");
+
+  if (strcmp (wd, jobs[job]->wd) != 0)
+    fprintf (stderr, " (wd: %s)", polite_directory_format (jobs[job]->wd));
+
+  fprintf (stderr, "\n");
+
+  /* Run the job. */
+  if (already_running == 0)
+    set_job_running (job);
+
+  /* Save the tty settings before we start the job in the foreground. */
+  if (foreground)
+    {
+      get_tty_state ();
+      save_stty = shell_tty_info;
+      /* Give the terminal to this job. */
+      if (IS_JOBCONTROL (job))
+       give_terminal_to (jobs[job]->pgrp, 0);
+    }
+  else
+    jobs[job]->flags &= ~J_FOREGROUND;
+
+  /* If the job is already running, then don't bother jump-starting it. */
+  if (already_running == 0)
+    {
+      jobs[job]->flags |= J_NOTIFIED;
+      killpg (jobs[job]->pgrp, SIGCONT);
+    }
+
+  if (foreground)
+    {
+      pid_t pid;
+      int s;
+
+      pid = find_last_pid (job, 0);
+      UNBLOCK_CHILD (oset);
+      s = wait_for (pid);
+      shell_tty_info = save_stty;
+      set_tty_state ();
+      return (s);
+    }
+  else
+    {
+      reset_current ();
+      UNBLOCK_CHILD (oset);
+      return (0);
+    }
+}
+
+/* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
+   If PID does belong to a job, and the job is stopped, then CONTinue the
+   job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
+   then kill the process group associated with PID. */
+int
+kill_pid (pid, sig, group)
+     pid_t pid;
+     int sig, group;
+{
+  register PROCESS *p;
+  int job, result;
+  sigset_t set, oset;
+
+  result = EXECUTION_SUCCESS;
+  if (group)
+    {
+      BLOCK_CHILD (set, oset);
+      p = find_pipeline (pid, 0, &job);
+
+      if (job != NO_JOB)
+       {
+         jobs[job]->flags &= ~J_NOTIFIED;
+
+         /* Kill process in backquotes or one started without job control? */
+         if (jobs[job]->pgrp == shell_pgrp)
+           {
+             p = jobs[job]->pipe;
+
+             do
+               {
+                 kill (p->pid, sig);
+                 if (p->running == PS_DONE && (sig == SIGTERM || sig == SIGHUP))
+                   kill (p->pid, SIGCONT);
+                 p = p->next;
+               }
+             while (p != jobs[job]->pipe);
+           }
+         else
+           {
+             result = killpg (jobs[job]->pgrp, sig);
+             if (p && STOPPED (job) && (sig == SIGTERM || sig == SIGHUP))
+               killpg (jobs[job]->pgrp, SIGCONT);
+             /* If we're continuing a stopped job via kill rather than bg or
+                fg, emulate the `bg' behavior. */
+             if (p && STOPPED (job) && (sig == SIGCONT))
+               {
+                 set_job_running (job);
+                 jobs[job]->flags &= ~J_FOREGROUND;
+                 jobs[job]->flags |= J_NOTIFIED;
+               }
+           }
+       }
+      else
+       result = killpg (pid, sig);
+
+      UNBLOCK_CHILD (oset);
+    }
+  else
+    result = kill (pid, sig);
+
+  return (result);
+}
+
+/* sigchld_handler () flushes at least one of the children that we are
+   waiting for.  It gets run when we have gotten a SIGCHLD signal. */
+static sighandler
+sigchld_handler (sig)
+     int sig;
+{
+  int n, oerrno;
+
+  oerrno = errno;
+  REINSTALL_SIGCHLD_HANDLER;
+  sigchld++;
+  n = 0;
+  if (queue_sigchld == 0)
+    n = waitchld (-1, 0);
+  errno = oerrno;
+  SIGRETURN (n);
+}
+
+/* waitchld() reaps dead or stopped children.  It's called by wait_for and
+   sigchld_handler, and runs until there aren't any children terminating any
+   more.
+   If BLOCK is 1, this is to be a blocking wait for a single child, although
+   an arriving SIGCHLD could cause the wait to be non-blocking.  It returns
+   the number of children reaped, or -1 if there are no unwaited-for child
+   processes. */
+static int
+waitchld (wpid, block)
+     pid_t wpid;
+     int block;
+{
+  WAIT status;
+  PROCESS *child;
+  pid_t pid;
+  int call_set_current, last_stopped_job, job, children_exited, waitpid_flags;
+
+  call_set_current = children_exited = 0;
+  last_stopped_job = NO_JOB;
+
+  do
+    {
+      /* We don't want to be notified about jobs stopping if job control
+        is not active.  XXX - was interactive_shell instead of job_control */
+      waitpid_flags = (job_control && subshell_environment == 0)
+                       ? (WUNTRACED|WCONTINUED)
+                       : 0;
+      if (sigchld || block == 0)
+       waitpid_flags |= WNOHANG;
+      pid = WAITPID (-1, &status, waitpid_flags);
+
+      /* The check for WNOHANG is to make sure we decrement sigchld only
+        if it was non-zero before we called waitpid. */
+      if (sigchld > 0 && (waitpid_flags & WNOHANG))
+       sigchld--;
+  
+      /* If waitpid returns -1 with errno == ECHILD, there are no more
+        unwaited-for child processes of this shell. */
+      if (pid < 0 && errno == ECHILD)
+       {
+         if (children_exited == 0)
+           return -1;
+         else
+           break;
+       }
+
+      /* If waitpid returns 0, there are running children.  If it returns -1,
+        the only other error POSIX says it can return is EINTR. */
+      if (pid <= 0)
+       continue;       /* jumps right to the test */
+
+      /* children_exited is used to run traps on SIGCHLD.  We don't want to
+         run the trap if a process is just being continued. */
+      if (WIFCONTINUED(status) == 0)
+       children_exited++;
+
+      /* Locate our PROCESS for this pid. */
+      child = find_pipeline (pid, 1, &job);    /* want running procs only */
+
+      /* It is not an error to have a child terminate that we did
+        not have a record of.  This child could have been part of
+        a pipeline in backquote substitution.  Even so, I'm not
+        sure child is ever non-zero. */
+      if (child == 0)
+       continue;
+
+      while (child->pid != pid)
+       child = child->next;
+
+      /* Remember status, and whether or not the process is running. */
+      child->status = status;
+      child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
+
+      if (job == NO_JOB)
+       continue;
+
+      call_set_current += set_job_status_and_cleanup (job);
+
+      if (STOPPED (job))
+       last_stopped_job = job;
+      else if (DEADJOB (job) && last_stopped_job == job)
+       last_stopped_job = NO_JOB;
+    }
+  while ((sigchld || block == 0) && pid > (pid_t)0);
+
+  /* If a job was running and became stopped, then set the current
+     job.  Otherwise, don't change a thing. */
+  if (call_set_current)
+    {
+      if (last_stopped_job != NO_JOB)
+       set_current_job (last_stopped_job);
+      else
+       reset_current ();
+    }
+
+  /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
+  if (job_control && signal_is_trapped (SIGCHLD) && children_exited &&
+      trap_list[SIGCHLD] != (char *)IGNORE_SIG)
+    run_sigchld_trap (children_exited);
+
+  /* We have successfully recorded the useful information about this process
+     that has just changed state.  If we notify asynchronously, and the job
+     that this process belongs to is no longer running, then notify the user
+     of that fact now. */
+  if (asynchronous_notification && interactive)
+    notify_of_job_status ();
+
+  return (children_exited);
+}
+
+/* Set the status of JOB and perform any necessary cleanup if the job is
+   marked as JDEAD.
+
+   Currently, the cleanup activity is restricted to handling any SIGINT
+   received while waiting for a foreground job to finish. */
+static int
+set_job_status_and_cleanup (job)
+     int job;
+{
+  PROCESS *child;
+  int tstatus, job_state, any_stopped, any_tstped, call_set_current;
+  SigHandler *temp_handler;
+
+  child = jobs[job]->pipe;
+  jobs[job]->flags &= ~J_NOTIFIED;
+
+  call_set_current = 0;
+
+  /*
+   * COMPUTE JOB STATUS
+   */
+
+  /* If all children are not running, but any of them is  stopped, then
+     the job is stopped, not dead. */
+  job_state = any_stopped = any_tstped = 0;
+  do
+    {
+      job_state |= child->running;
+      if (child->running == PS_DONE && (WIFSTOPPED (child->status)))
+       {
+         any_stopped = 1;
+         any_tstped |= interactive && job_control &&
+                           (WSTOPSIG (child->status) == SIGTSTP);
+       }
+      child = child->next;
+    }
+  while (child != jobs[job]->pipe);
+
+  /* If job_state != 0, the job is still running, so don't bother with
+     setting the process exit status and job state unless we're
+     transitioning from stopped to running. */
+  if (job_state != 0 && JOBSTATE(job) != JSTOPPED)
+    return 0;
+
+  /*
+   * SET JOB STATUS
+   */
+
+  /* The job is either stopped or dead.  Set the state of the job accordingly. */
+  if (any_stopped)
+    {
+      jobs[job]->state = JSTOPPED;
+      jobs[job]->flags &= ~J_FOREGROUND;
+      call_set_current++;
+      /* Suspending a job with SIGTSTP breaks all active loops. */
+      if (any_tstped && loop_level)
+       breaking = loop_level;
+    }
+  else if (job_state != 0)     /* was stopped, now running */
+    {
+      jobs[job]->state = JRUNNING;
+      call_set_current++;
+    }
+  else
+    {
+      jobs[job]->state = JDEAD;
+
+#if 0
+      if (IS_FOREGROUND (job))
+       setjstatus (job);
+#endif
+
+      /* If this job has a cleanup function associated with it, call it
+        with `cleanarg' as the single argument, then set the function
+        pointer to NULL so it is not inadvertently called twice.  The
+        cleanup function is responsible for deallocating cleanarg. */
+      if (jobs[job]->j_cleanup)
+       {
+         (*jobs[job]->j_cleanup) (jobs[job]->cleanarg);
+         jobs[job]->j_cleanup = (sh_vptrfunc_t *)NULL;
+       }
+    }
+
+  /*
+   * CLEANUP
+   *
+   * Currently, we just do special things if we got a SIGINT while waiting
+   * for a foreground job to complete
+   */
+
+  if (jobs[job]->state == JDEAD)
+    {
+      /* If we're running a shell script and we get a SIGINT with a
+        SIGINT trap handler, but the foreground job handles it and
+        does not exit due to SIGINT, run the trap handler but do not
+        otherwise act as if we got the interrupt. */
+      if (wait_sigint_received && interactive_shell == 0 &&
+         WIFSIGNALED (child->status) == 0 && IS_FOREGROUND (job) &&
+         signal_is_trapped (SIGINT))
+       {
+         int old_frozen;
+         wait_sigint_received = 0;
+         last_command_exit_value = process_exit_status (child->status);
+
+         old_frozen = jobs_list_frozen;
+         jobs_list_frozen = 1;
+         tstatus = maybe_call_trap_handler (SIGINT);
+         jobs_list_frozen = old_frozen;
+       }
+
+      /* If the foreground job is killed by SIGINT when job control is not
+        active, we need to perform some special handling.
+
+        The check of wait_sigint_received is a way to determine if the
+        SIGINT came from the keyboard (in which case the shell has already
+        seen it, and wait_sigint_received is non-zero, because keyboard
+        signals are sent to process groups) or via kill(2) to the foreground
+        process by another process (or itself).  If the shell did receive the
+        SIGINT, it needs to perform normal SIGINT processing. */
+      else if (wait_sigint_received && (WTERMSIG (child->status) == SIGINT) &&
+             IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
+       {
+         int old_frozen;
+
+         wait_sigint_received = 0;
+
+         /* If SIGINT is trapped, set the exit status so that the trap
+            handler can see it. */
+         if (signal_is_trapped (SIGINT))
+           last_command_exit_value = process_exit_status (child->status);
+
+         /* If the signal is trapped, let the trap handler get it no matter
+            what and simply return if the trap handler returns.
+           maybe_call_trap_handler() may cause dead jobs to be removed from
+           the job table because of a call to execute_command.  We work
+           around this by setting JOBS_LIST_FROZEN. */
+         old_frozen = jobs_list_frozen;
+         jobs_list_frozen = 1;
+         tstatus = maybe_call_trap_handler (SIGINT);
+         jobs_list_frozen = old_frozen;
+         if (tstatus == 0 && old_sigint_handler != INVALID_SIGNAL_HANDLER)
+           {
+             /* wait_sigint_handler () has already seen SIGINT and
+                allowed the wait builtin to jump out.  We need to
+                call the original SIGINT handler, if necessary.  If
+                the original handler is SIG_DFL, we need to resend
+                the signal to ourselves. */
+
+             temp_handler = old_sigint_handler;
+
+             /* Bogus.  If we've reset the signal handler as the result
+                of a trap caught on SIGINT, then old_sigint_handler
+                will point to trap_handler, which now knows nothing about
+                SIGINT (if we reset the sighandler to the default).
+                In this case, we have to fix things up.  What a crock. */
+             if (temp_handler == trap_handler && signal_is_trapped (SIGINT) == 0)
+                 temp_handler = trap_to_sighandler (SIGINT);
+               restore_sigint_handler ();
+               if (temp_handler == SIG_DFL)
+                 termination_unwind_protect (SIGINT);
+               else if (temp_handler != SIG_IGN)
+                 (*temp_handler) (SIGINT);
+           }
+       }
+    }
+
+  return call_set_current;
+}
+
+/* Build the array of values for the $PIPESTATUS variable from the set of
+   exit statuses of all processes in the job J. */
+static void
+setjstatus (j)
+     int j;
+{
+#if defined (ARRAY_VARS)
+  register int i;
+  register PROCESS *p;
+
+  for (i = 1, p = jobs[j]->pipe; p->next != jobs[j]->pipe; p = p->next, i++)
+    ;
+  i++;
+  if (statsize < i)
+    {
+      pstatuses = (int *)xrealloc (pstatuses, i * sizeof (int));
+      statsize = i;
+    }
+  i = 0;
+  p = jobs[j]->pipe;
+  do
+    {
+      pstatuses[i++] = process_exit_status (p->status);
+      p = p->next;
+    }
+  while (p != jobs[j]->pipe);
+
+  pstatuses[i] = -1;   /* sentinel */
+  set_pipestatus_array (pstatuses, i);
+#endif
+}
+
+static void
+run_sigchld_trap (nchild)
+     int nchild;
+{
+  char *trap_command;
+  int i;
+
+  /* Turn off the trap list during the call to parse_and_execute ()
+     to avoid potentially infinite recursive calls.  Preserve the
+     values of last_command_exit_value, last_made_pid, and the_pipeline
+     around the execution of the trap commands. */
+  trap_command = savestring (trap_list[SIGCHLD]);
+
+  begin_unwind_frame ("SIGCHLD trap");
+  unwind_protect_int (last_command_exit_value);
+  unwind_protect_int (last_command_exit_signal);
+  unwind_protect_var (last_made_pid);
+  unwind_protect_int (interrupt_immediately);
+  unwind_protect_int (jobs_list_frozen);
+  unwind_protect_pointer (the_pipeline);
+  unwind_protect_pointer (subst_assign_varlist);
+
+  /* We have to add the commands this way because they will be run
+     in reverse order of adding.  We don't want maybe_set_sigchld_trap ()
+     to reference freed memory. */
+  add_unwind_protect (xfree, trap_command);
+  add_unwind_protect (maybe_set_sigchld_trap, trap_command);
+
+  subst_assign_varlist = (WORD_LIST *)NULL;
+  the_pipeline = (PROCESS *)NULL;
+
+  restore_default_signal (SIGCHLD);
+  jobs_list_frozen = 1;
+  for (i = 0; i < nchild; i++)
+    {
+      interrupt_immediately = 1;
+      parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE);
+    }
+
+  run_unwind_frame ("SIGCHLD trap");
+}
+
+/* Function to call when you want to notify people of changes
+   in job status.  This prints out all jobs which are pending
+   notification to stderr, and marks those printed as already
+   notified, thus making them candidates for cleanup. */
+static void
+notify_of_job_status ()
+{
+  register int job, termsig;
+  char *dir;
+  sigset_t set, oset;
+  WAIT s;
+
+  if (jobs == 0 || job_slots == 0)
+    return;
+
+  if (old_ttou != 0)
+    {
+      sigemptyset (&set);
+      sigaddset (&set, SIGCHLD);
+      sigaddset (&set, SIGTTOU);
+      sigemptyset (&oset);
+      sigprocmask (SIG_BLOCK, &set, &oset);
+    }
+  else
+    queue_sigchld++;
+
+  for (job = 0, dir = (char *)NULL; job < job_slots; job++)
+    {
+      if (jobs[job] && IS_NOTIFIED (job) == 0)
+       {
+         s = raw_job_exit_status (job);
+         termsig = WTERMSIG (s);
+
+         /* POSIX.2 says we have to hang onto the statuses of at most the
+            last CHILD_MAX background processes if the shell is running a
+            script.  If the shell is not interactive, don't print anything
+            unless the job was killed by a signal. */
+         if (startup_state == 0 && WIFSIGNALED (s) == 0 &&
+               ((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
+           continue;
+         
+#if 0
+         /* If job control is disabled, don't print the status messages.
+            Mark dead jobs as notified so that they get cleaned up.  If
+            startup_state == 2, we were started to run `-c command', so
+            don't print anything. */
+         if ((job_control == 0 && interactive_shell) || startup_state == 2)
+#else
+         /* If job control is disabled, don't print the status messages.
+            Mark dead jobs as notified so that they get cleaned up.  If
+            startup_state == 2 and subshell_environment has the
+            SUBSHELL_COMSUB bit turned on, we were started to run a command
+            substitution, so don't print anything. */
+         if ((job_control == 0 && interactive_shell) ||
+             (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)))
+#endif
+           {
+             /* POSIX.2 compatibility:  if the shell is not interactive,
+                hang onto the job corresponding to the last asynchronous
+                pid until the user has been notified of its status or does
+                a `wait'. */
+             if (DEADJOB (job) && (interactive_shell || (find_last_pid (job, 0) != last_asynchronous_pid)))
+               jobs[job]->flags |= J_NOTIFIED;
+             continue;
+           }
+
+         /* Print info on jobs that are running in the background,
+            and on foreground jobs that were killed by anything
+            except SIGINT (and possibly SIGPIPE). */
+         switch (JOBSTATE (job))
+           {
+           case JDEAD:
+             if (interactive_shell == 0 && termsig && WIFSIGNALED (s) &&
+                 termsig != SIGINT &&
+#if defined (DONT_REPORT_SIGPIPE)
+                 termsig != SIGPIPE &&
+#endif
+                 signal_is_trapped (termsig) == 0)
+               {
+                 /* Don't print `0' for a line number. */
+                 fprintf (stderr, "%s: line %d: ", get_name_for_error (), (line_number == 0) ? 1 : line_number);
+                 pretty_print_job (job, JLIST_NONINTERACTIVE, stderr);
+               }
+             else if (IS_FOREGROUND (job))
+               {
+#if !defined (DONT_REPORT_SIGPIPE)
+                 if (termsig && WIFSIGNALED (s) && termsig != SIGINT)
+#else
+                 if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE)
+#endif
+                   {
+                     fprintf (stderr, "%s", j_strsignal (termsig));
+
+                     if (WIFCORED (s))
+                       fprintf (stderr, " (core dumped)");
+
+                     fprintf (stderr, "\n");
+                   }
+               }
+             else
+               {
+                 if (dir == 0)
+                   dir = current_working_directory ();
+                 pretty_print_job (job, JLIST_STANDARD, stderr);
+                 if (dir && strcmp (dir, jobs[job]->wd) != 0)
+                   fprintf (stderr,
+                            "(wd now: %s)\n", polite_directory_format (dir));
+               }
+
+             jobs[job]->flags |= J_NOTIFIED;
+             break;
+
+           case JSTOPPED:
+             fprintf (stderr, "\n");
+             if (dir == 0)
+               dir = current_working_directory ();
+             pretty_print_job (job, JLIST_STANDARD, stderr);
+             if (dir && (strcmp (dir, jobs[job]->wd) != 0))
+               fprintf (stderr,
+                        "(wd now: %s)\n", polite_directory_format (dir));
+             jobs[job]->flags |= J_NOTIFIED;
+             break;
+
+           case JRUNNING:
+           case JMIXED:
+             break;
+
+           default:
+             programming_error ("notify_of_job_status");
+           }
+       }
+    }
+  if (old_ttou != 0)
+    sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+  else
+    queue_sigchld--;
+}
+
+/* Initialize the job control mechanism, and set up the tty stuff. */
+int
+initialize_job_control (force)
+     int force;
+{
+  shell_pgrp = getpgid (0);
+
+  if (shell_pgrp == -1)
+    {
+      sys_error ("initialize_job_control: getpgrp failed");
+      exit (1);
+    }
+
+  /* We can only have job control if we are interactive. */
+  if (interactive == 0)
+    {
+      job_control = 0;
+      original_pgrp = NO_PID;
+      shell_tty = fileno (stderr);
+    }
+  else
+    {
+      /* Get our controlling terminal.  If job_control is set, or
+        interactive is set, then this is an interactive shell no
+        matter where fd 2 is directed. */
+      shell_tty = dup (fileno (stderr));       /* fd 2 */
+
+      shell_tty = move_to_high_fd (shell_tty, 1, -1);
+
+      /* Compensate for a bug in systems that compiled the BSD
+        rlogind with DEBUG defined, like NeXT and Alliant. */
+      if (shell_pgrp == 0)
+       {
+         shell_pgrp = getpid ();
+         setpgid (0, shell_pgrp);
+         tcsetpgrp (shell_tty, shell_pgrp);
+       }
+
+      while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
+       {
+         if (shell_pgrp != terminal_pgrp)
+           {
+             SigHandler *ottin;
+
+             ottin = set_signal_handler(SIGTTIN, SIG_DFL);
+             kill (0, SIGTTIN);
+             set_signal_handler (SIGTTIN, ottin);
+             continue;
+           }
+         break;
+       }
+
+      /* Make sure that we are using the new line discipline. */
+      if (set_new_line_discipline (shell_tty) < 0)
+       {
+         sys_error ("initialize_job_control: line discipline");
+         job_control = 0;
+       }
+      else
+       {
+         original_pgrp = shell_pgrp;
+         shell_pgrp = getpid ();
+
+         if ((original_pgrp != shell_pgrp) && (setpgid (0, shell_pgrp) < 0))
+           {
+             sys_error ("initialize_job_control: setpgid");
+             shell_pgrp = original_pgrp;
+           }
+
+         job_control = 1;
+
+         /* If (and only if) we just set our process group to our pid,
+            thereby becoming a process group leader, and the terminal
+            is not in the same process group as our (new) process group,
+            then set the terminal's process group to our (new) process
+            group.  If that fails, set our process group back to what it
+            was originally (so we can still read from the terminal) and
+            turn off job control.  */
+         if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
+           {
+             if (give_terminal_to (shell_pgrp, 0) < 0)
+               {
+                 setpgid (0, original_pgrp);
+                 shell_pgrp = original_pgrp;
+                 job_control = 0;
+               }
+           }
+       }
+      if (job_control == 0)
+       internal_error (_("no job control in this shell"));
+    }
+
+  if (shell_tty != fileno (stderr))
+    SET_CLOSE_ON_EXEC (shell_tty);
+
+  set_signal_handler (SIGCHLD, sigchld_handler);
+
+  change_flag ('m', job_control ? '-' : '+');
+
+  if (interactive)
+    get_tty_state ();
+
+  return job_control;
+}
+
+#ifdef DEBUG
+void
+debug_print_pgrps ()
+{
+  itrace("original_pgrp = %ld shell_pgrp = %ld terminal_pgrp = %ld",
+        (long)original_pgrp, (long)shell_pgrp, (long)terminal_pgrp);
+  itrace("tcgetpgrp(%d) -> %ld, getpgid(0) -> %ld",
+        shell_tty, (long)tcgetpgrp (shell_tty), (long)getpgid(0));
+}
+#endif
+
+/* Set the line discipline to the best this system has to offer.
+   Return -1 if this is not possible. */
+static int
+set_new_line_discipline (tty)
+     int tty;
+{
+#if defined (NEW_TTY_DRIVER)
+  int ldisc;
+
+  if (ioctl (tty, TIOCGETD, &ldisc) < 0)
+    return (-1);
+
+  if (ldisc != NTTYDISC)
+    {
+      ldisc = NTTYDISC;
+
+      if (ioctl (tty, TIOCSETD, &ldisc) < 0)
+       return (-1);
+    }
+  return (0);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+#  if defined (TERMIO_LDISC) && (NTTYDISC)
+  if (ioctl (tty, TCGETA, &shell_tty_info) < 0)
+    return (-1);
+
+  if (shell_tty_info.c_line != NTTYDISC)
+    {
+      shell_tty_info.c_line = NTTYDISC;
+      if (ioctl (tty, TCSETAW, &shell_tty_info) < 0)
+       return (-1);
+    }
+#  endif /* TERMIO_LDISC && NTTYDISC */
+  return (0);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  if defined (TERMIOS_LDISC) && defined (NTTYDISC)
+  if (tcgetattr (tty, &shell_tty_info) < 0)
+    return (-1);
+
+  if (shell_tty_info.c_line != NTTYDISC)
+    {
+      shell_tty_info.c_line = NTTYDISC;
+      if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
+       return (-1);
+    }
+#  endif /* TERMIOS_LDISC && NTTYDISC */
+  return (0);
+#endif /* TERMIOS_TTY_DRIVER */
+
+#if !defined (NEW_TTY_DRIVER) && !defined (TERMIO_TTY_DRIVER) && !defined (TERMIOS_TTY_DRIVER)
+  return (-1);
+#endif
+}
+
+#if defined (TIOCGWINSZ) && defined (SIGWINCH)
+static void
+get_new_window_size (from_sig)
+     int from_sig;
+{
+  struct winsize win;
+
+  if ((ioctl (shell_tty, TIOCGWINSZ, &win) == 0) &&
+      win.ws_row > 0 && win.ws_col > 0)
+    {
+#if defined (aixpc)
+      shell_tty_info.c_winsize = win;  /* structure copying */
+#endif
+      sh_set_lines_and_columns (win.ws_row, win.ws_col);
+#if defined (READLINE)
+      rl_set_screen_size (win.ws_row, win.ws_col);
+#endif
+    }
+}
+
+static sighandler
+sigwinch_sighandler (sig)
+     int sig;
+{
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+  set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif /* MUST_REINSTALL_SIGHANDLERS */
+  get_new_window_size (1);
+  SIGRETURN (0);
+}
+#else
+static void
+get_new_window_size (from_sig)
+     int from_sig;
+{
+}
+#endif /* TIOCGWINSZ && SIGWINCH */
+
+void
+set_sigwinch_handler ()
+{
+#if defined (TIOCGWINSZ) && defined (SIGWINCH)
+ old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif
+}
+
+void
+unset_sigwinch_handler ()
+{
+#if defined (TIOCGWINSZ) && defined (SIGWINCH)
+  set_signal_handler (SIGWINCH, old_winch);
+#endif
+}
+
+/* Setup this shell to handle C-C, etc. */
+void
+initialize_job_signals ()
+{
+  if (interactive)
+    {
+      set_signal_handler (SIGINT, sigint_sighandler);
+      set_signal_handler (SIGTSTP, SIG_IGN);
+      set_signal_handler (SIGTTOU, SIG_IGN);
+      set_signal_handler (SIGTTIN, SIG_IGN);
+      set_sigwinch_handler ();
+    }
+  else if (job_control)
+    {
+      old_tstp = set_signal_handler (SIGTSTP, sigstop_sighandler);
+      old_ttin = set_signal_handler (SIGTTIN, sigstop_sighandler);
+      old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
+    }
+  /* Leave these things alone for non-interactive shells without job
+     control. */
+}
+
+/* Here we handle CONT signals. */
+static sighandler
+sigcont_sighandler (sig)
+     int sig;
+{
+  initialize_job_signals ();
+  set_signal_handler (SIGCONT, old_cont);
+  kill (getpid (), SIGCONT);
+
+  SIGRETURN (0);
+}
+
+/* Here we handle stop signals while we are running not as a login shell. */
+static sighandler
+sigstop_sighandler (sig)
+     int sig;
+{
+  set_signal_handler (SIGTSTP, old_tstp);
+  set_signal_handler (SIGTTOU, old_ttou);
+  set_signal_handler (SIGTTIN, old_ttin);
+
+  old_cont = set_signal_handler (SIGCONT, sigcont_sighandler);
+
+  give_terminal_to (shell_pgrp, 0);
+
+  kill (getpid (), sig);
+
+  SIGRETURN (0);
+}
+
+/* Give the terminal to PGRP.  */
+int
+give_terminal_to (pgrp, force)
+     pid_t pgrp;
+     int force;
+{
+  sigset_t set, oset;
+  int r;
+
+  r = 0;
+  if (job_control || force)
+    {
+      sigemptyset (&set);
+      sigaddset (&set, SIGTTOU);
+      sigaddset (&set, SIGTTIN);
+      sigaddset (&set, SIGTSTP);
+      sigaddset (&set, SIGCHLD);
+      sigemptyset (&oset);
+      sigprocmask (SIG_BLOCK, &set, &oset);
+
+      if (tcsetpgrp (shell_tty, pgrp) < 0)
+       {
+         /* Maybe we should print an error message? */
+#if 0
+         sys_error ("tcsetpgrp(%d) failed: pid %ld to pgrp %ld",
+           shell_tty, (long)getpid(), (long)pgrp);
+#endif
+         r = -1;
+       }
+      else
+       terminal_pgrp = pgrp;
+      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+    }
+
+  return r;
+}
+
+/* Clear out any jobs in the job array.  This is intended to be used by
+   children of the shell, who should not have any job structures as baggage
+   when they start executing (forking subshells for parenthesized execution
+   and functions with pipes are the two that spring to mind).  If RUNNING_ONLY
+   is nonzero, only running jobs are removed from the table. */
+void
+delete_all_jobs (running_only)
+     int running_only;
+{
+  register int i;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  if (job_slots)
+    {
+      current_job = previous_job = NO_JOB;
+
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
+         delete_job (i, 1);
+
+      if (running_only == 0)
+       {
+         free ((char *)jobs);
+         job_slots = 0;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Mark all jobs in the job array so that they don't get a SIGHUP when the
+   shell gets one.  If RUNNING_ONLY is nonzero, mark only running jobs. */
+void
+nohup_all_jobs (running_only)
+     int running_only;
+{
+  register int i;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  if (job_slots)
+    {
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
+         nohup_job (i);
+    }
+
+  UNBLOCK_CHILD (oset);
+}
+
+int
+count_all_jobs ()
+{
+  int i, n;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+  for (i = n = 0; i < job_slots; i++)
+    if (jobs[i] && DEADJOB(i) == 0)
+      n++;
+  UNBLOCK_CHILD (oset);
+  return n;
+}
+
+static void
+mark_all_jobs_as_dead ()
+{
+  register int i;
+  sigset_t set, oset;
+
+  if (job_slots == 0)
+    return;
+
+  BLOCK_CHILD (set, oset);
+
+  for (i = 0; i < job_slots; i++)
+    if (jobs[i])
+      jobs[i]->state = JDEAD;
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Mark all dead jobs as notified, so delete_job () cleans them out
+   of the job table properly.  POSIX.2 says we need to save the
+   status of the last CHILD_MAX jobs, so we count the number of dead
+   jobs and mark only enough as notified to save CHILD_MAX statuses. */
+static void
+mark_dead_jobs_as_notified (force)
+     int force;
+{
+  register int i, ndead;
+  sigset_t set, oset;
+
+  if (job_slots == 0)
+    return;
+
+  BLOCK_CHILD (set, oset);
+
+  /* If FORCE is non-zero, we don't have to keep CHILD_MAX statuses
+     around; just run through the array. */
+  if (force)
+    {
+      for (i = 0; i < job_slots; i++)
+       {
+         if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
+           jobs[i]->flags |= J_NOTIFIED;
+       }
+      UNBLOCK_CHILD (oset);
+      return;
+    }
+
+  /* Mark enough dead jobs as notified to keep CHILD_MAX jobs left in the
+     array not marked as notified. */
+          
+  /* Count the number of dead jobs */
+  for (i = ndead = 0; i < job_slots; i++)
+    {
+      if (jobs[i] && DEADJOB (i))
+       ndead++;
+    }
+
+  if (child_max < 0)
+    child_max = getmaxchild ();
+  if (child_max < 0)
+    child_max = DEFAULT_CHILD_MAX;
+
+  /* Don't do anything if the number of dead jobs is less than CHILD_MAX and
+     we're not forcing a cleanup. */
+  if (ndead <= child_max)
+    {
+      UNBLOCK_CHILD (oset);
+      return;
+    }
+
+  /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
+     the list.  This isn't exactly right yet; changes need to be made
+     to stop_pipeline so we don't mark the newer jobs after we've
+     created CHILD_MAX slots in the jobs array. */
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
+       {
+         jobs[i]->flags |= J_NOTIFIED;
+         if (--ndead <= child_max)
+           break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Here to allow other parts of the shell (like the trap stuff) to
+   unfreeze the jobs list. */
+void
+unfreeze_jobs_list ()
+{
+  jobs_list_frozen = 0;
+}
+
+/* Allow or disallow job control to take place.  Returns the old value
+   of job_control. */
+int
+set_job_control (arg)
+     int arg;
+{
+  int old;
+
+  old = job_control;
+  job_control = arg;
+
+  /* If we're turning on job control, reset pipeline_pgrp so make_child will
+     put new child processes into the right pgrp */
+  if (job_control != old && job_control)
+    pipeline_pgrp = 0;
+
+  return (old);
+}
+
+/* Turn off all traces of job control.  This is run by children of the shell
+   which are going to do shellsy things, like wait (), etc. */
+void
+without_job_control ()
+{
+  stop_making_children ();
+  start_pipeline ();
+  delete_all_jobs (0);
+  set_job_control (0);
+}
+
+/* If this shell is interactive, terminate all stopped jobs and
+   restore the original terminal process group.  This is done
+   before the `exec' builtin calls shell_execve. */
+void
+end_job_control ()
+{
+  if (interactive_shell)               /* XXX - should it be interactive? */
+    {
+      terminate_stopped_jobs ();
+
+      if (original_pgrp >= 0)
+       give_terminal_to (original_pgrp, 1);
+    }
+
+  if (original_pgrp >= 0)
+    setpgid (0, original_pgrp);
+}
+
+/* Restart job control by closing shell tty and reinitializing.  This is
+   called after an exec fails in an interactive shell and we do not exit. */
+void
+restart_job_control ()
+{
+  if (shell_tty != -1)
+    close (shell_tty);
+  initialize_job_control (0);
+}
+
+/* Set the handler to run when the shell receives a SIGCHLD signal. */
+void
+set_sigchld_handler ()
+{
+  set_signal_handler (SIGCHLD, sigchld_handler);
+}
+
+#if defined (PGRP_PIPE)
+/* Read from the read end of a pipe.  This is how the process group leader
+   blocks until all of the processes in a pipeline have been made. */
+static void
+pipe_read (pp)
+     int *pp;
+{
+  char ch;
+
+  if (pp[1] >= 0)
+    {
+      close (pp[1]);
+      pp[1] = -1;
+    }
+
+  if (pp[0] >= 0)
+    {
+      while (read (pp[0], &ch, 1) == -1 && errno == EINTR)
+       ;
+    }
+}
+
+/* Close the read and write ends of PP, an array of file descriptors. */
+static void
+pipe_close (pp)
+     int *pp;
+{
+  if (pp[0] >= 0)
+    close (pp[0]);
+
+  if (pp[1] >= 0)
+    close (pp[1]);
+
+  pp[0] = pp[1] = -1;
+}
+
+/* Functional interface closes our local-to-job-control pipes. */
+void
+close_pgrp_pipe ()
+{
+  pipe_close (pgrp_pipe);
+}
+
+#endif /* PGRP_PIPE */
index ef7efe4..7e373f1 100644 (file)
@@ -67,6 +67,11 @@ msgstr ""
 msgid "%s: missing colon separator"
 msgstr ""
 
+#: builtins/alias.def:123
+#, c-format
+msgid "`%s': invalid alias name"
+msgstr ""
+
 #: builtins/bind.def:194
 #, c-format
 msgid "`%s': invalid keymap name"
@@ -412,7 +417,7 @@ msgstr ""
 msgid "%s: history expansion failed"
 msgstr ""
 
-#: builtins/jobs.def:102
+#: builtins/jobs.def:99
 msgid "no other options allowed with `-x'"
 msgstr ""
 
diff --git a/po/bash.pot~ b/po/bash.pot~
new file mode 100644 (file)
index 0000000..e3bbd28
--- /dev/null
@@ -0,0 +1,4174 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#: builtins/caller.def:128 builtins/caller.def:132 builtins/pushd.def:655
+#: builtins/pushd.def:663 builtins/pushd.def:666 builtins/pushd.def:676
+#: builtins/pushd.def:680 builtins/pushd.def:684 builtins/pushd.def:687
+#: builtins/pushd.def:690 builtins/pushd.def:699 builtins/pushd.def:703
+#: builtins/pushd.def:707 builtins/pushd.def:710 builtins.c:321 builtins.c:325
+#: builtins.c:390 builtins.c:392 builtins.c:401 builtins.c:404 builtins.c:408
+#: builtins.c:445 builtins.c:487 builtins.c:491 builtins.c:498 builtins.c:509
+#: builtins.c:513 builtins.c:552 builtins.c:555 builtins.c:559 builtins.c:562
+#: builtins.c:630 builtins.c:637 builtins.c:692 builtins.c:713 builtins.c:718
+#: builtins.c:722 builtins.c:745 builtins.c:835 builtins.c:919 builtins.c:921
+#: builtins.c:943 builtins.c:946 builtins.c:948 builtins.c:950 builtins.c:952
+#: builtins.c:954 builtins.c:957 builtins.c:966 builtins.c:968 builtins.c:973
+#: builtins.c:976 builtins.c:1019 builtins.c:1024 builtins.c:1028
+#: builtins.c:1032 builtins.c:1034 builtins.c:1047 builtins.c:1062
+#: builtins.c:1226 builtins.c:1231 builtins.c:1305 builtins.c:1309
+#: builtins.c:1313 builtins.c:1316 builtins.c:1319 builtins.c:1331
+#: builtins.c:1335 builtins.c:1339 builtins.c:1342 builtins.c:1354
+#: builtins.c:1362 builtins.c:1365
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: bug-bash@gnu.org\n"
+"POT-Creation-Date: 2003-12-22 15:34-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: arrayfunc.c:45
+msgid "bad array subscript"
+msgstr ""
+
+#: arrayfunc.c:306
+#, c-format
+msgid "%s: cannot assign to non-numeric index"
+msgstr ""
+
+#: bashhist.c:321
+#, c-format
+msgid "%s: cannot create: %s"
+msgstr ""
+
+#: bashline.c:2791
+msgid "bash_execute_unix_command: cannot find keymap for command"
+msgstr ""
+
+#: bashline.c:2840
+#, c-format
+msgid "%s: first non-whitespace character is not `\"'"
+msgstr ""
+
+#: bashline.c:2869
+#, c-format
+msgid "no closing `%c' in %s"
+msgstr ""
+
+#: bashline.c:2903
+#, c-format
+msgid "%s: missing colon separator"
+msgstr ""
+
+#: builtins/alias.def:123
+#, c-format
+msgid "`%s': invalid alias name"
+msgstr ""
+
+#: builtins/bind.def:194
+#, c-format
+msgid "`%s': invalid keymap name"
+msgstr ""
+
+#: builtins/bind.def:233
+#, c-format
+msgid "%s: cannot read: %s"
+msgstr ""
+
+#: builtins/bind.def:248
+#, c-format
+msgid "`%s': cannot unbind"
+msgstr ""
+
+#: builtins/bind.def:283
+#, c-format
+msgid "`%s': unknown function name"
+msgstr ""
+
+#: builtins/bind.def:291
+#, c-format
+msgid "%s is not bound to any keys.\n"
+msgstr ""
+
+#: builtins/bind.def:295
+#, c-format
+msgid "%s can be invoked via "
+msgstr ""
+
+#: builtins/break.def:128
+msgid "only meaningful in a `for', `while', or `until' loop"
+msgstr ""
+
+#: builtins/caller.def:127 builtins.c:320
+msgid "Returns the context of the current subroutine call."
+msgstr ""
+
+#: builtins/caller.def:129 builtins.c:322
+msgid "Without EXPR, returns returns \"$line $filename\".  With EXPR,"
+msgstr ""
+
+#: builtins/caller.def:130 builtins.c:323
+msgid "returns \"$line $subroutine $filename\"; this extra information"
+msgstr ""
+
+#: builtins/caller.def:131 builtins.c:324
+msgid "can be used used to provide a stack trace."
+msgstr ""
+
+#: builtins/caller.def:133 builtins.c:326
+msgid "The value of EXPR indicates how many call frames to go back before the"
+msgstr ""
+
+#: builtins/caller.def:134 builtins.c:327
+msgid "current one; the top frame is frame 0."
+msgstr ""
+
+#: builtins/cd.def:188
+msgid "HOME not set"
+msgstr ""
+
+#: builtins/cd.def:200
+msgid "OLDPWD not set"
+msgstr ""
+
+#: builtins/cd.def:350
+#, c-format
+msgid "write error: %s"
+msgstr ""
+
+#: builtins/common.c:133 test.c:921
+msgid "too many arguments"
+msgstr ""
+
+#: builtins/common.c:157 shell.c:465 shell.c:737
+#, c-format
+msgid "%s: option requires an argument"
+msgstr ""
+
+#: builtins/common.c:164
+#, c-format
+msgid "%s: numeric argument required"
+msgstr ""
+
+#: builtins/common.c:171
+#, c-format
+msgid "%s: not found"
+msgstr ""
+
+#: builtins/common.c:180 shell.c:750
+#, c-format
+msgid "%s: invalid option"
+msgstr ""
+
+#: builtins/common.c:187
+#, c-format
+msgid "%s: invalid option name"
+msgstr ""
+
+#: builtins/common.c:194 general.c:229 general.c:234
+#, c-format
+msgid "`%s': not a valid identifier"
+msgstr ""
+
+#: builtins/common.c:201
+#, c-format
+msgid "%s: invalid number"
+msgstr ""
+
+#: builtins/common.c:208
+#, c-format
+msgid "%s: invalid signal specification"
+msgstr ""
+
+#: builtins/common.c:215
+#, c-format
+msgid "`%s': not a pid or valid job spec"
+msgstr ""
+
+#: builtins/common.c:222 error.c:453
+#, c-format
+msgid "%s: readonly variable"
+msgstr ""
+
+#: builtins/common.c:230
+#, c-format
+msgid "%s: %s out of range"
+msgstr ""
+
+#: builtins/common.c:230 builtins/common.c:232
+msgid "argument"
+msgstr ""
+
+#: builtins/common.c:232
+#, c-format
+msgid "%s out of range"
+msgstr ""
+
+#: builtins/common.c:240
+#, c-format
+msgid "%s: no such job"
+msgstr ""
+
+#: builtins/common.c:248
+#, c-format
+msgid "%s: no job control"
+msgstr ""
+
+#: builtins/common.c:250
+msgid "no job control"
+msgstr ""
+
+#: builtins/common.c:260
+#, c-format
+msgid "%s: restricted"
+msgstr ""
+
+#: builtins/common.c:262
+msgid "restricted"
+msgstr ""
+
+#: builtins/common.c:270
+#, c-format
+msgid "%s: not a shell builtin"
+msgstr ""
+
+#: builtins/common.c:481
+#, c-format
+msgid "%s: could not get current directory: %s: %s\n"
+msgstr ""
+
+#: builtins/common.c:548 builtins/common.c:550
+#, c-format
+msgid "%s: ambiguous job spec"
+msgstr ""
+
+#: builtins/complete.def:251
+#, c-format
+msgid "%s: invalid action name"
+msgstr ""
+
+#: builtins/complete.def:381 builtins/complete.def:524
+#, c-format
+msgid "%s: no completion specification"
+msgstr ""
+
+#: builtins/complete.def:571
+msgid "warning: -F option may not work as you expect"
+msgstr ""
+
+#: builtins/complete.def:573
+msgid "warning: -C option may not work as you expect"
+msgstr ""
+
+#: builtins/declare.def:105
+msgid "can only be used in a function"
+msgstr ""
+
+#: builtins/declare.def:295
+msgid "cannot use `-f' to make functions"
+msgstr ""
+
+#: builtins/declare.def:307 execute_cmd.c:3949
+#, c-format
+msgid "%s: readonly function"
+msgstr ""
+
+#: builtins/declare.def:389
+#, c-format
+msgid "%s: cannot destroy array variables in this way"
+msgstr ""
+
+#: builtins/enable.def:128 builtins/enable.def:136
+msgid "dynamic loading not available"
+msgstr ""
+
+#: builtins/enable.def:303
+#, c-format
+msgid "cannot open shared object %s: %s"
+msgstr ""
+
+#: builtins/enable.def:326
+#, c-format
+msgid "cannot find %s in shared object %s: %s"
+msgstr ""
+
+#: builtins/enable.def:450
+#, c-format
+msgid "%s: not dynamically loaded"
+msgstr ""
+
+#: builtins/enable.def:465
+#, c-format
+msgid "%s: cannot delete: %s"
+msgstr ""
+
+#: builtins/evalfile.c:128 execute_cmd.c:3821 shell.c:1395
+#, c-format
+msgid "%s: is a directory"
+msgstr ""
+
+#: builtins/evalfile.c:133
+#, c-format
+msgid "%s: not a regular file"
+msgstr ""
+
+#: builtins/evalfile.c:141
+#, c-format
+msgid "%s: file is too large"
+msgstr ""
+
+#: builtins/exec.def:205
+#, c-format
+msgid "%s: cannot execute: %s"
+msgstr ""
+
+#: builtins/exit.def:83
+msgid "not login shell: use `exit'"
+msgstr ""
+
+#: builtins/exit.def:111
+msgid "There are stopped jobs.\n"
+msgstr ""
+
+#: builtins/fc.def:252
+msgid "no command found"
+msgstr ""
+
+#: builtins/fc.def:317
+msgid "history specification"
+msgstr ""
+
+#: builtins/fc.def:338
+#, c-format
+msgid "%s: cannot open temp file: %s"
+msgstr ""
+
+#: builtins/fg_bg.def:133
+#, c-format
+msgid "job %d started without job control"
+msgstr ""
+
+#: builtins/getopt.c:109
+#, c-format
+msgid "%s: illegal option -- %c\n"
+msgstr ""
+
+#: builtins/getopt.c:110
+#, c-format
+msgid "%s: option requires an argument -- %c\n"
+msgstr ""
+
+#: builtins/hash.def:83
+msgid "hashing disabled"
+msgstr ""
+
+#: builtins/hash.def:128
+#, c-format
+msgid "%s: hash table empty\n"
+msgstr ""
+
+#: builtins/help.def:108
+msgid "Shell commands matching keywords `"
+msgstr ""
+
+#: builtins/help.def:110
+msgid "Shell commands matching keyword `"
+msgstr ""
+
+#: builtins/help.def:138
+#, c-format
+msgid ""
+"no help topics match `%s'.  Try `help help' or `man -k %s' or `info %s'."
+msgstr ""
+
+#: builtins/help.def:164
+#, c-format
+msgid "%s: cannot open: %s"
+msgstr ""
+
+#: builtins/help.def:182
+msgid ""
+"These shell commands are defined internally.  Type `help' to see this list.\n"
+"Type `help name' to find out more about the function `name'.\n"
+"Use `info bash' to find out more about the shell in general.\n"
+"Use `man -k' or `info' to find out more about commands not in this list.\n"
+"\n"
+"A star (*) next to a name means that the command is disabled.\n"
+"\n"
+msgstr ""
+
+#: builtins/history.def:148
+msgid "cannot use more than one of -anrw"
+msgstr ""
+
+#: builtins/history.def:180
+msgid "history position"
+msgstr ""
+
+#: builtins/history.def:390
+#, c-format
+msgid "%s: history expansion failed"
+msgstr ""
+
+#: builtins/jobs.def:102
+msgid "no other options allowed with `-x'"
+msgstr ""
+
+#: builtins/kill.def:187
+#, c-format
+msgid "%s: arguments must be process or job IDs"
+msgstr ""
+
+#: builtins/kill.def:248
+msgid "Unknown error"
+msgstr ""
+
+#: builtins/let.def:94 builtins/let.def:119 expr.c:496 expr.c:511
+msgid "expression expected"
+msgstr ""
+
+#: builtins/printf.def:249
+#, c-format
+msgid "`%s': missing format character"
+msgstr ""
+
+#: builtins/printf.def:408
+#, c-format
+msgid "`%c': invalid format character"
+msgstr ""
+
+#: builtins/printf.def:601
+msgid "missing hex digit for \\x"
+msgstr ""
+
+#: builtins/pushd.def:168
+msgid "no other directory"
+msgstr ""
+
+#: builtins/pushd.def:435
+msgid "<no current directory>"
+msgstr ""
+
+#: builtins/pushd.def:652 builtins.c:1351
+msgid "Display the list of currently remembered directories.  Directories"
+msgstr ""
+
+#: builtins/pushd.def:653 builtins.c:1352
+msgid "find their way onto the list with the `pushd' command; you can get"
+msgstr ""
+
+#: builtins/pushd.def:654 builtins.c:1353
+msgid "back up through the list with the `popd' command."
+msgstr ""
+
+#: builtins/pushd.def:656 builtins.c:1355
+msgid "The -l flag specifies that `dirs' should not print shorthand versions"
+msgstr ""
+
+#: builtins/pushd.def:657 builtins.c:1356
+msgid "of directories which are relative to your home directory.  This means"
+msgstr ""
+
+#: builtins/pushd.def:658 builtins.c:1357
+msgid "that `~/bin' might be displayed as `/homes/bfox/bin'.  The -v flag"
+msgstr ""
+
+#: builtins/pushd.def:659 builtins.c:1358
+msgid "causes `dirs' to print the directory stack with one entry per line,"
+msgstr ""
+
+#: builtins/pushd.def:660 builtins.c:1359
+msgid "prepending the directory name with its position in the stack.  The -p"
+msgstr ""
+
+#: builtins/pushd.def:661 builtins.c:1360
+msgid "flag does the same thing, but the stack position is not prepended."
+msgstr ""
+
+#: builtins/pushd.def:662 builtins.c:1361
+msgid "The -c flag clears the directory stack by deleting all of the elements."
+msgstr ""
+
+#: builtins/pushd.def:664
+msgid "+N   displays the Nth entry counting from the left of the list shown by"
+msgstr ""
+
+#: builtins/pushd.def:665 builtins/pushd.def:668
+msgid "     dirs when invoked without options, starting with zero."
+msgstr ""
+
+#: builtins/pushd.def:667
+msgid ""
+"-N   displays the Nth entry counting from the right of the list shown by"
+msgstr ""
+
+#: builtins/pushd.def:673 builtins.c:1302
+msgid "Adds a directory to the top of the directory stack, or rotates"
+msgstr ""
+
+#: builtins/pushd.def:674 builtins.c:1303
+msgid "the stack, making the new top of the stack the current working"
+msgstr ""
+
+#: builtins/pushd.def:675 builtins.c:1304
+msgid "directory.  With no arguments, exchanges the top two directories."
+msgstr ""
+
+#: builtins/pushd.def:677
+msgid "+N   Rotates the stack so that the Nth directory (counting"
+msgstr ""
+
+#: builtins/pushd.def:678
+msgid "     from the left of the list shown by `dirs', starting with"
+msgstr ""
+
+#: builtins/pushd.def:679 builtins/pushd.def:683
+msgid "     zero) is at the top."
+msgstr ""
+
+#: builtins/pushd.def:681
+msgid "-N   Rotates the stack so that the Nth directory (counting"
+msgstr ""
+
+#: builtins/pushd.def:682
+msgid "     from the right of the list shown by `dirs', starting with"
+msgstr ""
+
+#: builtins/pushd.def:685
+msgid "-n   suppress the normal change of directory when adding directories"
+msgstr ""
+
+#: builtins/pushd.def:686
+msgid "     to the stack, so only the stack is manipulated."
+msgstr ""
+
+#: builtins/pushd.def:688
+msgid "dir  adds DIR to the directory stack at the top, making it the"
+msgstr ""
+
+#: builtins/pushd.def:689
+msgid "     new current working directory."
+msgstr ""
+
+#: builtins/pushd.def:691 builtins/pushd.def:711 builtins.c:1320
+#: builtins.c:1343
+msgid "You can see the directory stack with the `dirs' command."
+msgstr ""
+
+#: builtins/pushd.def:696 builtins.c:1328
+msgid "Removes entries from the directory stack.  With no arguments,"
+msgstr ""
+
+#: builtins/pushd.def:697 builtins.c:1329
+msgid "removes the top directory from the stack, and cd's to the new"
+msgstr ""
+
+#: builtins/pushd.def:698 builtins.c:1330
+msgid "top directory."
+msgstr ""
+
+#: builtins/pushd.def:700
+msgid "+N   removes the Nth entry counting from the left of the list"
+msgstr ""
+
+#: builtins/pushd.def:701
+msgid "     shown by `dirs', starting with zero.  For example: `popd +0'"
+msgstr ""
+
+#: builtins/pushd.def:702
+msgid "     removes the first directory, `popd +1' the second."
+msgstr ""
+
+#: builtins/pushd.def:704
+msgid "-N   removes the Nth entry counting from the right of the list"
+msgstr ""
+
+#: builtins/pushd.def:705
+msgid "     shown by `dirs', starting with zero.  For example: `popd -0'"
+msgstr ""
+
+#: builtins/pushd.def:706
+msgid "     removes the last directory, `popd -1' the next to last."
+msgstr ""
+
+#: builtins/pushd.def:708
+msgid "-n   suppress the normal change of directory when removing directories"
+msgstr ""
+
+#: builtins/pushd.def:709
+msgid "     from the stack, so only the stack is manipulated."
+msgstr ""
+
+#: builtins/read.def:207
+#, c-format
+msgid "%s: invalid timeout specification"
+msgstr ""
+
+#: builtins/read.def:230
+#, c-format
+msgid "%s: invalid file descriptor specification"
+msgstr ""
+
+#: builtins/read.def:237
+#, c-format
+msgid "%d: invalid file descriptor: %s"
+msgstr ""
+
+#: builtins/read.def:463
+#, c-format
+msgid "read error: %d: %s"
+msgstr ""
+
+#: builtins/return.def:63
+msgid "can only `return' from a function or sourced script"
+msgstr ""
+
+#: builtins/set.def:743
+msgid "cannot simultaneously unset a function and a variable"
+msgstr ""
+
+#: builtins/set.def:780
+#, c-format
+msgid "%s: cannot unset"
+msgstr ""
+
+#: builtins/set.def:787
+#, c-format
+msgid "%s: cannot unset: readonly %s"
+msgstr ""
+
+#: builtins/set.def:798
+#, c-format
+msgid "%s: not an array variable"
+msgstr ""
+
+#: builtins/setattr.def:165
+#, c-format
+msgid "%s: not a function"
+msgstr ""
+
+#: builtins/shift.def:66 builtins/shift.def:72
+msgid "shift count"
+msgstr ""
+
+#: builtins/shopt.def:226
+msgid "cannot set and unset shell options simultaneously"
+msgstr ""
+
+#: builtins/shopt.def:291
+#, c-format
+msgid "%s: invalid shell option name"
+msgstr ""
+
+#: builtins/source.def:117
+msgid "filename argument required"
+msgstr ""
+
+#: builtins/source.def:137
+#, c-format
+msgid "%s: file not found"
+msgstr ""
+
+#: builtins/suspend.def:93
+msgid "cannot suspend"
+msgstr ""
+
+#: builtins/suspend.def:103
+msgid "cannot suspend a login shell"
+msgstr ""
+
+#: builtins/type.def:231
+#, c-format
+msgid "%s is aliased to `%s'\n"
+msgstr ""
+
+#: builtins/type.def:252
+#, c-format
+msgid "%s is a shell keyword\n"
+msgstr ""
+
+#: builtins/type.def:272
+#, c-format
+msgid "%s is a function\n"
+msgstr ""
+
+#: builtins/type.def:297
+#, c-format
+msgid "%s is a shell builtin\n"
+msgstr ""
+
+#: builtins/type.def:318
+#, c-format
+msgid "%s is %s\n"
+msgstr ""
+
+#: builtins/type.def:338
+#, c-format
+msgid "%s is hashed (%s)\n"
+msgstr ""
+
+#: builtins/ulimit.def:332
+#, c-format
+msgid "%s: invalid limit argument"
+msgstr ""
+
+#: builtins/ulimit.def:358
+#, c-format
+msgid "`%c': bad command"
+msgstr ""
+
+#: builtins/ulimit.def:387
+#, c-format
+msgid "%s: cannot get limit: %s"
+msgstr ""
+
+#: builtins/ulimit.def:425
+#, c-format
+msgid "%s: cannot modify limit: %s"
+msgstr ""
+
+#: builtins/umask.def:112
+msgid "octal number"
+msgstr ""
+
+#: builtins/umask.def:226
+#, c-format
+msgid "`%c': invalid symbolic mode operator"
+msgstr ""
+
+#: builtins/umask.def:279
+#, c-format
+msgid "`%c': invalid symbolic mode character"
+msgstr ""
+
+#: error.c:165
+#, c-format
+msgid "last command: %s\n"
+msgstr ""
+
+#: error.c:173
+msgid "Aborting..."
+msgstr ""
+
+#: error.c:260
+#, c-format
+msgid "%s: warning: "
+msgstr ""
+
+#: error.c:405
+msgid "unknown command error"
+msgstr ""
+
+#: error.c:406
+msgid "bad command type"
+msgstr ""
+
+#: error.c:407
+msgid "bad connector"
+msgstr ""
+
+#: error.c:408
+msgid "bad jump"
+msgstr ""
+
+#: error.c:446
+#, c-format
+msgid "%s: unbound variable"
+msgstr ""
+
+#: eval.c:175
+msgid "\atimed out waiting for input: auto-logout\n"
+msgstr ""
+
+#: execute_cmd.c:466
+#, c-format
+msgid "cannot redirect standard input from /dev/null: %s"
+msgstr ""
+
+#: execute_cmd.c:1036
+#, c-format
+msgid "TIMEFORMAT: `%c': invalid format character"
+msgstr ""
+
+#: execute_cmd.c:3521
+#, c-format
+msgid "%s: restricted: cannot specify `/' in command names"
+msgstr ""
+
+#: execute_cmd.c:3609
+#, c-format
+msgid "%s: command not found"
+msgstr ""
+
+#: execute_cmd.c:3839
+#, c-format
+msgid "%s: %s: bad interpreter"
+msgstr ""
+
+#: execute_cmd.c:3876
+#, c-format
+msgid "%s: cannot execute binary file"
+msgstr ""
+
+#: execute_cmd.c:3988
+#, c-format
+msgid "cannot duplicate fd %d to fd %d"
+msgstr ""
+
+#: expr.c:239
+msgid "expression recursion level exceeded"
+msgstr ""
+
+#: expr.c:263
+msgid "recursion stack underflow"
+msgstr ""
+
+#: expr.c:374
+msgid "syntax error in expression"
+msgstr ""
+
+#: expr.c:414
+msgid "attempted assignment to non-variable"
+msgstr ""
+
+#: expr.c:435 expr.c:440 expr.c:750
+msgid "division by 0"
+msgstr ""
+
+#: expr.c:466
+msgid "bug: bad expassign token"
+msgstr ""
+
+#: expr.c:508
+msgid "`:' expected for conditional expression"
+msgstr ""
+
+#: expr.c:775
+msgid "exponent less than 0"
+msgstr ""
+
+#: expr.c:819
+msgid "identifier expected after pre-increment or pre-decrement"
+msgstr ""
+
+#: expr.c:847
+msgid "missing `)'"
+msgstr ""
+
+#: expr.c:871
+msgid "syntax error: operand expected"
+msgstr ""
+
+#: expr.c:1146
+msgid "invalid number"
+msgstr ""
+
+#: expr.c:1150
+msgid "invalid arithmetic base"
+msgstr ""
+
+#: expr.c:1170
+msgid "value too great for base"
+msgstr ""
+
+#: general.c:60
+msgid "getcwd: cannot access parent directories"
+msgstr ""
+
+#: input.c:231
+#, c-format
+msgid "cannot allocate new file descriptor for bash input from fd %d"
+msgstr ""
+
+#: input.c:239
+#, c-format
+msgid "save_bash_input: buffer already exists for new fd %d"
+msgstr ""
+
+#: jobs.c:693
+#, c-format
+msgid "deleting stopped job %d with process group %ld"
+msgstr ""
+
+#: jobs.c:1001
+#, c-format
+msgid "describe_pid: %ld: no such pid"
+msgstr ""
+
+#: jobs.c:1632 nojobs.c:648
+#, c-format
+msgid "wait: pid %ld is not a child of this shell"
+msgstr ""
+
+#: jobs.c:1815
+#, c-format
+msgid "wait_for: No record of process %ld"
+msgstr ""
+
+#: jobs.c:2062
+#, c-format
+msgid "wait_for_job: job %d is stopped"
+msgstr ""
+
+#: jobs.c:2284
+#, c-format
+msgid "%s: job has terminated"
+msgstr ""
+
+#: jobs.c:2293
+#, c-format
+msgid "%s: job %d already in background"
+msgstr ""
+
+#: jobs.c:3037
+msgid "no job control in this shell"
+msgstr ""
+
+#: lib/malloc/malloc.c:298
+#, c-format
+msgid "malloc: failed assertion: %s\n"
+msgstr ""
+
+#: lib/malloc/malloc.c:314
+#, c-format
+msgid ""
+"\r\n"
+"malloc: %s:%d: assertion botched\r\n"
+msgstr ""
+
+#: lib/malloc/malloc.c:740
+msgid "malloc: block on free list clobbered"
+msgstr ""
+
+#: lib/malloc/malloc.c:817
+msgid "free: called with already freed block argument"
+msgstr ""
+
+#: lib/malloc/malloc.c:820
+msgid "free: called with unallocated block argument"
+msgstr ""
+
+#: lib/malloc/malloc.c:839
+msgid "free: underflow detected; mh_nbytes out of range"
+msgstr ""
+
+#: lib/malloc/malloc.c:845
+msgid "free: start and end chunk sizes differ"
+msgstr ""
+
+#: lib/malloc/malloc.c:942
+msgid "realloc: called with unallocated block argument"
+msgstr ""
+
+#: lib/malloc/malloc.c:957
+msgid "realloc: underflow detected; mh_nbytes out of range"
+msgstr ""
+
+#: lib/malloc/malloc.c:963
+msgid "realloc: start and end chunk sizes differ"
+msgstr ""
+
+#: lib/malloc/table.c:175
+msgid "register_alloc: alloc table is full with FIND_ALLOC?\n"
+msgstr ""
+
+#: lib/malloc/table.c:182
+#, c-format
+msgid "register_alloc: %p already in table as allocated?\n"
+msgstr ""
+
+#: lib/malloc/table.c:218
+#, c-format
+msgid "register_free: %p already in table as free?\n"
+msgstr ""
+
+#: lib/malloc/watch.c:46
+msgid "allocated"
+msgstr ""
+
+#: lib/malloc/watch.c:48
+msgid "freed"
+msgstr ""
+
+#: lib/malloc/watch.c:50
+msgid "requesting resize"
+msgstr ""
+
+#: lib/malloc/watch.c:52
+msgid "just resized"
+msgstr ""
+
+#: lib/malloc/watch.c:54
+msgid "bug: unknown operation"
+msgstr ""
+
+#: lib/malloc/watch.c:56
+#, c-format
+msgid "malloc: watch alert: %p %s "
+msgstr ""
+
+#: lib/sh/fmtulong.c:101
+msgid "invalid base"
+msgstr ""
+
+#: lib/sh/netopen.c:158
+#, c-format
+msgid "%s: host unknown"
+msgstr ""
+
+#: lib/sh/netopen.c:165
+#, c-format
+msgid "%s: invalid service"
+msgstr ""
+
+#: lib/sh/netopen.c:296
+#, c-format
+msgid "%s: bad network path specification"
+msgstr ""
+
+#: lib/sh/netopen.c:336
+msgid "network operations not supported"
+msgstr ""
+
+#: mailcheck.c:382
+msgid "You have mail in $_"
+msgstr ""
+
+#: mailcheck.c:407
+msgid "You have new mail in $_"
+msgstr ""
+
+#: mailcheck.c:423
+#, c-format
+msgid "The mail in %s has been read\n"
+msgstr ""
+
+#: make_cmd.c:318
+msgid "syntax error: arithmetic expression required"
+msgstr ""
+
+#: make_cmd.c:320
+msgid "syntax error: `;' unexpected"
+msgstr ""
+
+#: make_cmd.c:321
+#, c-format
+msgid "syntax error: `((%s))'"
+msgstr ""
+
+#: make_cmd.c:560
+#, c-format
+msgid "make_here_document: bad instruction type %d"
+msgstr ""
+
+#: make_cmd.c:730
+#, c-format
+msgid "make_redirection: redirection instruction `%d' out of range"
+msgstr ""
+
+#: parse.y:2726
+#, c-format
+msgid "unexpected EOF while looking for matching `%c'"
+msgstr ""
+
+#: parse.y:3011
+msgid "unexpected EOF while looking for `]]'"
+msgstr ""
+
+#: parse.y:3016
+#, c-format
+msgid "syntax error in conditional expression: unexpected token `%s'"
+msgstr ""
+
+#: parse.y:3020
+msgid "syntax error in conditional expression"
+msgstr ""
+
+#: parse.y:3098
+#, c-format
+msgid "unexpected token `%s', expected `)'"
+msgstr ""
+
+#: parse.y:3102
+msgid "expected `)'"
+msgstr ""
+
+#: parse.y:3130
+#, c-format
+msgid "unexpected argument `%s' to conditional unary operator"
+msgstr ""
+
+#: parse.y:3134
+msgid "unexpected argument to conditional unary operator"
+msgstr ""
+
+#: parse.y:3171
+#, c-format
+msgid "unexpected token `%s', conditional binary operator expected"
+msgstr ""
+
+#: parse.y:3175
+msgid "conditional binary operator expected"
+msgstr ""
+
+#: parse.y:3191
+#, c-format
+msgid "unexpected argument `%s' to conditional binary operator"
+msgstr ""
+
+#: parse.y:3195
+msgid "unexpected argument to conditional binary operator"
+msgstr ""
+
+#: parse.y:3206
+#, c-format
+msgid "unexpected token `%c' in conditional command"
+msgstr ""
+
+#: parse.y:3209
+#, c-format
+msgid "unexpected token `%s' in conditional command"
+msgstr ""
+
+#: parse.y:3213
+#, c-format
+msgid "unexpected token %d in conditional command"
+msgstr ""
+
+#: parse.y:4400
+#, c-format
+msgid "syntax error near unexpected token `%s'"
+msgstr ""
+
+#: parse.y:4418
+#, c-format
+msgid "syntax error near `%s'"
+msgstr ""
+
+#: parse.y:4428
+msgid "syntax error: unexpected end of file"
+msgstr ""
+
+#: parse.y:4428
+msgid "syntax error"
+msgstr ""
+
+#: parse.y:4490
+#, c-format
+msgid "Use \"%s\" to leave the shell.\n"
+msgstr ""
+
+#: parse.y:4649
+msgid "unexpected EOF while looking for matching `)'"
+msgstr ""
+
+#: pcomplete.c:988
+#, c-format
+msgid "completion: function `%s' not found"
+msgstr ""
+
+#: pcomplib.c:179
+#, c-format
+msgid "progcomp_insert: %s: NULL COMPSPEC"
+msgstr ""
+
+#: print_cmd.c:260
+#, c-format
+msgid "print_command: bad connector `%d'"
+msgstr ""
+
+#: print_cmd.c:1172
+#, c-format
+msgid "cprintf: `%c': invalid format character"
+msgstr ""
+
+#: redir.c:99
+msgid "file descriptor out of range"
+msgstr ""
+
+#: redir.c:141
+#, c-format
+msgid "%s: ambiguous redirect"
+msgstr ""
+
+#: redir.c:145
+#, c-format
+msgid "%s: cannot overwrite existing file"
+msgstr ""
+
+#: redir.c:150
+#, c-format
+msgid "%s: restricted: cannot redirect output"
+msgstr ""
+
+#: redir.c:155
+#, c-format
+msgid "cannot create temp file for here document: %s"
+msgstr ""
+
+#: redir.c:509
+msgid "/dev/(tcp|udp)/host/port not supported without networking"
+msgstr ""
+
+#: redir.c:949
+msgid "redirection error: cannot duplicate fd"
+msgstr ""
+
+#: shell.c:302
+msgid "could not find /tmp, please create!"
+msgstr ""
+
+#: shell.c:306
+msgid "/tmp must be a valid directory name"
+msgstr ""
+
+#: shell.c:839
+#, c-format
+msgid "%c%c: invalid option"
+msgstr ""
+
+#: shell.c:1590
+msgid "I have no name!"
+msgstr ""
+
+#: shell.c:1725
+#, c-format
+msgid ""
+"Usage:\t%s [GNU long option] [option] ...\n"
+"\t%s [GNU long option] [option] script-file ...\n"
+msgstr ""
+
+#: shell.c:1727
+msgid "GNU long options:\n"
+msgstr ""
+
+#: shell.c:1731
+msgid "Shell options:\n"
+msgstr ""
+
+#: shell.c:1732
+msgid "\t-irsD or -c command or -O shopt_option\t\t(invocation only)\n"
+msgstr ""
+
+#: shell.c:1747
+#, c-format
+msgid "\t-%s or -o option\n"
+msgstr ""
+
+#: shell.c:1753
+#, c-format
+msgid "Type `%s -c \"help set\"' for more information about shell options.\n"
+msgstr ""
+
+#: shell.c:1754
+#, c-format
+msgid "Type `%s -c help' for more information about shell builtin commands.\n"
+msgstr ""
+
+#: shell.c:1755
+msgid "Use the `bashbug' command to report bugs.\n"
+msgstr ""
+
+#: sig.c:485
+#, c-format
+msgid "sigprocmask: %d: invalid operation"
+msgstr ""
+
+#: subst.c:1011
+#, c-format
+msgid "bad substitution: no closing `%s' in %s"
+msgstr ""
+
+#: subst.c:2020
+#, c-format
+msgid "%s: cannot assign list to array member"
+msgstr ""
+
+#: subst.c:3516 subst.c:3532
+msgid "cannot make pipe for process substitution"
+msgstr ""
+
+#: subst.c:3563
+msgid "cannot make child for process substitution"
+msgstr ""
+
+#: subst.c:3608
+#, c-format
+msgid "cannot open named pipe %s for reading"
+msgstr ""
+
+#: subst.c:3610
+#, c-format
+msgid "cannot open named pipe %s for writing"
+msgstr ""
+
+#: subst.c:3618
+#, c-format
+msgid "cannout reset nodelay mode for fd %d"
+msgstr ""
+
+#: subst.c:3628
+#, c-format
+msgid "cannot duplicate named pipe %s as fd %d"
+msgstr ""
+
+#: subst.c:3803
+msgid "cannot make pipe for command substitution"
+msgstr ""
+
+#: subst.c:3832
+msgid "cannot make child for command substitution"
+msgstr ""
+
+#: subst.c:3849
+msgid "command_substitute: cannot duplicate pipe as fd 1"
+msgstr ""
+
+#: subst.c:4284
+#, c-format
+msgid "%s: parameter null or not set"
+msgstr ""
+
+#: subst.c:4529
+#, c-format
+msgid "%s: substring expression < 0"
+msgstr ""
+
+#: subst.c:5209
+#, c-format
+msgid "%s: bad substitution"
+msgstr ""
+
+#: subst.c:5283
+#, c-format
+msgid "$%s: cannot assign in this way"
+msgstr ""
+
+#: subst.c:6652
+#, c-format
+msgid "no match: %s"
+msgstr ""
+
+#: test.c:154
+msgid "argument expected"
+msgstr ""
+
+#: test.c:163
+#, c-format
+msgid "%s: integer expression expected"
+msgstr ""
+
+#: test.c:361
+msgid "`)' expected"
+msgstr ""
+
+#: test.c:363
+#, c-format
+msgid "`)' expected, found %s"
+msgstr ""
+
+#: test.c:378 test.c:787 test.c:790
+#, c-format
+msgid "%s: unary operator expected"
+msgstr ""
+
+#: test.c:543 test.c:830
+#, c-format
+msgid "%s: binary operator expected"
+msgstr ""
+
+#: test.c:905
+msgid "missing `]'"
+msgstr ""
+
+#: trap.c:194
+msgid "invalid signal number"
+msgstr ""
+
+#: trap.c:309
+#, c-format
+msgid "run_pending_traps: bad value in trap_list[%d]: %p"
+msgstr ""
+
+#: trap.c:313
+#, c-format
+msgid ""
+"run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"
+msgstr ""
+
+#: trap.c:349
+#, c-format
+msgid "trap_handler: bad signal %d"
+msgstr ""
+
+#: variables.c:310
+#, c-format
+msgid "error importing function definition for `%s'"
+msgstr ""
+
+#: variables.c:670
+#, c-format
+msgid "shell level (%d) too high, resetting to 1"
+msgstr ""
+
+#: variables.c:1610
+msgid "make_local_variable: no function context at current scope"
+msgstr ""
+
+#: variables.c:2709
+msgid "all_local_variables: no function context at current scope"
+msgstr ""
+
+#: variables.c:2923 variables.c:2932
+#, c-format
+msgid "invalid character %d in exportstr for %s"
+msgstr ""
+
+#: variables.c:2938
+#, c-format
+msgid "no `=' in exportstr for %s"
+msgstr ""
+
+#: variables.c:3363
+msgid "pop_var_context: head of shell_variables not a function context"
+msgstr ""
+
+#: variables.c:3376
+msgid "pop_var_context: no global_variables context"
+msgstr ""
+
+#: variables.c:3442
+msgid "pop_scope: head of shell_variables not a temporary environment scope"
+msgstr ""
+
+#: version.c:82
+msgid "Copyright (C) 2004 Free Software Foundation, Inc.\n"
+msgstr ""
+
+#: xmalloc.c:93
+#, c-format
+msgid "xmalloc: cannot allocate %lu bytes (%lu bytes allocated)"
+msgstr ""
+
+#: xmalloc.c:95
+#, c-format
+msgid "xmalloc: cannot allocate %lu bytes"
+msgstr ""
+
+#: xmalloc.c:115
+#, c-format
+msgid "xrealloc: cannot reallocate %lu bytes (%lu bytes allocated)"
+msgstr ""
+
+#: xmalloc.c:117
+#, c-format
+msgid "xrealloc: cannot allocate %lu bytes"
+msgstr ""
+
+#: xmalloc.c:151
+#, c-format
+msgid "xmalloc: %s:%d: cannot allocate %lu bytes (%lu bytes allocated)"
+msgstr ""
+
+#: xmalloc.c:153
+#, c-format
+msgid "xmalloc: %s:%d: cannot allocate %lu bytes"
+msgstr ""
+
+#: xmalloc.c:175
+#, c-format
+msgid "xrealloc: %s:%d: cannot reallocate %lu bytes (%lu bytes allocated)"
+msgstr ""
+
+#: xmalloc.c:177
+#, c-format
+msgid "xrealloc: %s:%d: cannot allocate %lu bytes"
+msgstr ""
+
+#: builtins.c:244
+msgid "`alias' with no arguments or with the -p option prints the list"
+msgstr ""
+
+#: builtins.c:245
+msgid "of aliases in the form alias NAME=VALUE on standard output."
+msgstr ""
+
+#: builtins.c:246
+msgid "Otherwise, an alias is defined for each NAME whose VALUE is given."
+msgstr ""
+
+#: builtins.c:247
+msgid "A trailing space in VALUE causes the next word to be checked for"
+msgstr ""
+
+#: builtins.c:248
+msgid "alias substitution when the alias is expanded.  Alias returns"
+msgstr ""
+
+#: builtins.c:249
+msgid "true unless a NAME is given for which no alias has been defined."
+msgstr ""
+
+#: builtins.c:257
+msgid ""
+"Remove NAMEs from the list of defined aliases.  If the -a option is given,"
+msgstr ""
+
+#: builtins.c:258
+msgid "then remove all alias definitions."
+msgstr ""
+
+#: builtins.c:266
+msgid "Bind a key sequence to a Readline function or a macro, or set"
+msgstr ""
+
+#: builtins.c:267
+msgid "a Readline variable.  The non-option argument syntax is equivalent"
+msgstr ""
+
+#: builtins.c:268
+msgid "to that found in ~/.inputrc, but must be passed as a single argument:"
+msgstr ""
+
+#: builtins.c:269
+msgid "bind '\"\\C-x\\C-r\": re-read-init-file'."
+msgstr ""
+
+#: builtins.c:270
+msgid "bind accepts the following options:"
+msgstr ""
+
+#: builtins.c:271
+msgid ""
+"  -m  keymap         Use `keymap' as the keymap for the duration of this"
+msgstr ""
+
+#: builtins.c:272
+msgid "                     command.  Acceptable keymap names are emacs,"
+msgstr ""
+
+#: builtins.c:273
+msgid ""
+"                     emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,"
+msgstr ""
+
+#: builtins.c:274
+msgid "                     vi-command, and vi-insert."
+msgstr ""
+
+#: builtins.c:275
+msgid "  -l                 List names of functions."
+msgstr ""
+
+#: builtins.c:276
+msgid "  -P                 List function names and bindings."
+msgstr ""
+
+#: builtins.c:277
+msgid "  -p                 List functions and bindings in a form that can be"
+msgstr ""
+
+#: builtins.c:278
+msgid "                     reused as input."
+msgstr ""
+
+#: builtins.c:279
+msgid "  -r  keyseq         Remove the binding for KEYSEQ."
+msgstr ""
+
+#: builtins.c:280
+msgid "  -x  keyseq:shell-command\tCause SHELL-COMMAND to be executed when"
+msgstr ""
+
+#: builtins.c:281
+msgid "\t\t\t\tKEYSEQ is entered."
+msgstr ""
+
+#: builtins.c:282
+msgid "  -f  filename       Read key bindings from FILENAME."
+msgstr ""
+
+#: builtins.c:283
+msgid "  -q  function-name  Query about which keys invoke the named function."
+msgstr ""
+
+#: builtins.c:284
+msgid ""
+"  -u  function-name  Unbind all keys which are bound to the named function."
+msgstr ""
+
+#: builtins.c:285
+msgid "  -V                 List variable names and values"
+msgstr ""
+
+#: builtins.c:286
+msgid "  -v                 List variable names and values in a form that can"
+msgstr ""
+
+#: builtins.c:287
+msgid "                     be reused as input."
+msgstr ""
+
+#: builtins.c:288
+msgid ""
+"  -S                 List key sequences that invoke macros and their values"
+msgstr ""
+
+#: builtins.c:289
+msgid ""
+"  -s                 List key sequences that invoke macros and their values"
+msgstr ""
+
+#: builtins.c:290
+msgid "                     in a form that can be reused as input."
+msgstr ""
+
+#: builtins.c:297
+msgid "Exit from within a FOR, WHILE or UNTIL loop.  If N is specified,"
+msgstr ""
+
+#: builtins.c:298
+msgid "break N levels."
+msgstr ""
+
+#: builtins.c:304
+msgid "Resume the next iteration of the enclosing FOR, WHILE or UNTIL loop."
+msgstr ""
+
+#: builtins.c:305
+msgid "If N is specified, resume at the N-th enclosing loop."
+msgstr ""
+
+#: builtins.c:311
+msgid "Run a shell builtin.  This is useful when you wish to rename a"
+msgstr ""
+
+#: builtins.c:312
+msgid "shell builtin to be a function, but need the functionality of the"
+msgstr ""
+
+#: builtins.c:313
+msgid "builtin within the function itself."
+msgstr ""
+
+#: builtins.c:334
+msgid "Change the current directory to DIR.  The variable $HOME is the"
+msgstr ""
+
+#: builtins.c:335
+msgid "default DIR.  The variable CDPATH defines the search path for"
+msgstr ""
+
+#: builtins.c:336
+msgid "the directory containing DIR.  Alternative directory names in CDPATH"
+msgstr ""
+
+#: builtins.c:337
+msgid "are separated by a colon (:).  A null directory name is the same as"
+msgstr ""
+
+#: builtins.c:338
+msgid "the current directory, i.e. `.'.  If DIR begins with a slash (/),"
+msgstr ""
+
+#: builtins.c:339
+msgid "then CDPATH is not used.  If the directory is not found, and the"
+msgstr ""
+
+#: builtins.c:340
+msgid "shell option `cdable_vars' is set, then try the word as a variable"
+msgstr ""
+
+#: builtins.c:341
+msgid "name.  If that variable has a value, then cd to the value of that"
+msgstr ""
+
+#: builtins.c:342
+msgid "variable.  The -P option says to use the physical directory structure"
+msgstr ""
+
+#: builtins.c:343
+msgid ""
+"instead of following symbolic links; the -L option forces symbolic links"
+msgstr ""
+
+#: builtins.c:344
+msgid "to be followed."
+msgstr ""
+
+#: builtins.c:350
+msgid "Print the current working directory.  With the -P option, pwd prints"
+msgstr ""
+
+#: builtins.c:351
+msgid "the physical directory, without any symbolic links; the -L option"
+msgstr ""
+
+#: builtins.c:352
+msgid "makes pwd follow symbolic links."
+msgstr ""
+
+#: builtins.c:358
+msgid "No effect; the command does nothing.  A zero exit code is returned."
+msgstr ""
+
+#: builtins.c:364
+msgid "Return a successful result."
+msgstr ""
+
+#: builtins.c:370
+msgid "Return an unsuccessful result."
+msgstr ""
+
+#: builtins.c:376
+msgid "Runs COMMAND with ARGS ignoring shell functions.  If you have a shell"
+msgstr ""
+
+#: builtins.c:377
+msgid "function called `ls', and you wish to call the command `ls', you can"
+msgstr ""
+
+#: builtins.c:378
+msgid "say \"command ls\".  If the -p option is given, a default value is used"
+msgstr ""
+
+#: builtins.c:379
+msgid "for PATH that is guaranteed to find all of the standard utilities.  If"
+msgstr ""
+
+#: builtins.c:380
+msgid "the -V or -v option is given, a string is printed describing COMMAND."
+msgstr ""
+
+#: builtins.c:381
+msgid "The -V option produces a more verbose description."
+msgstr ""
+
+#: builtins.c:387
+msgid "Declare variables and/or give them attributes.  If no NAMEs are"
+msgstr ""
+
+#: builtins.c:388
+msgid "given, then display the values of variables instead.  The -p option"
+msgstr ""
+
+#: builtins.c:389
+msgid "will display the attributes and values of each NAME."
+msgstr ""
+
+#: builtins.c:391
+msgid "The flags are:"
+msgstr ""
+
+#: builtins.c:393
+msgid "  -a\tto make NAMEs arrays (if supported)"
+msgstr ""
+
+#: builtins.c:394
+msgid "  -f\tto select from among function names only"
+msgstr ""
+
+#: builtins.c:395
+msgid ""
+"  -F\tto display function names (and line number and source file name if"
+msgstr ""
+
+#: builtins.c:396
+msgid "\tdebugging) without definitions"
+msgstr ""
+
+#: builtins.c:397
+msgid "  -i\tto make NAMEs have the `integer' attribute"
+msgstr ""
+
+#: builtins.c:398
+msgid "  -r\tto make NAMEs readonly"
+msgstr ""
+
+#: builtins.c:399
+msgid "  -t\tto make NAMEs have the `trace' attribute"
+msgstr ""
+
+#: builtins.c:400
+msgid "  -x\tto make NAMEs export"
+msgstr ""
+
+#: builtins.c:402
+msgid "Variables with the integer attribute have arithmetic evaluation (see"
+msgstr ""
+
+#: builtins.c:403
+msgid "`let') done when the variable is assigned to."
+msgstr ""
+
+#: builtins.c:405
+msgid "When displaying values of variables, -f displays a function's name"
+msgstr ""
+
+#: builtins.c:406
+msgid "and definition.  The -F option restricts the display to function"
+msgstr ""
+
+#: builtins.c:407
+msgid "name only."
+msgstr ""
+
+#: builtins.c:409
+msgid "Using `+' instead of `-' turns off the given attribute instead.  When"
+msgstr ""
+
+#: builtins.c:410
+msgid "used in a function, makes NAMEs local, as with the `local' command."
+msgstr ""
+
+#: builtins.c:416
+msgid "Obsolete.  See `declare'."
+msgstr ""
+
+#: builtins.c:422
+msgid "Create a local variable called NAME, and give it VALUE.  LOCAL"
+msgstr ""
+
+#: builtins.c:423
+msgid "can only be used within a function; it makes the variable NAME"
+msgstr ""
+
+#: builtins.c:424
+msgid "have a visible scope restricted to that function and its children."
+msgstr ""
+
+#: builtins.c:431
+msgid "Output the ARGs.  If -n is specified, the trailing newline is"
+msgstr ""
+
+#: builtins.c:432
+msgid "suppressed.  If the -e option is given, interpretation of the"
+msgstr ""
+
+#: builtins.c:433
+msgid "following backslash-escaped characters is turned on:"
+msgstr ""
+
+#: builtins.c:434
+msgid "\t\\a\talert (bell)"
+msgstr ""
+
+#: builtins.c:435
+msgid "\t\\b\tbackspace"
+msgstr ""
+
+#: builtins.c:436
+msgid "\t\\c\tsuppress trailing newline"
+msgstr ""
+
+#: builtins.c:437
+msgid "\t\\E\tescape character"
+msgstr ""
+
+#: builtins.c:438
+msgid "\t\\f\tform feed"
+msgstr ""
+
+#: builtins.c:439
+msgid "\t\\n\tnew line"
+msgstr ""
+
+#: builtins.c:440
+msgid "\t\\r\tcarriage return"
+msgstr ""
+
+#: builtins.c:441
+msgid "\t\\t\thorizontal tab"
+msgstr ""
+
+#: builtins.c:442
+msgid "\t\\v\tvertical tab"
+msgstr ""
+
+#: builtins.c:443
+msgid "\t\\\\\tbackslash"
+msgstr ""
+
+#: builtins.c:444
+msgid "\t\\num\tthe character whose ASCII code is NUM (octal)."
+msgstr ""
+
+#: builtins.c:446
+msgid "You can explicitly turn off the interpretation of the above characters"
+msgstr ""
+
+#: builtins.c:447
+msgid "with the -E option."
+msgstr ""
+
+#: builtins.c:455
+msgid ""
+"Output the ARGs.  If -n is specified, the trailing newline is suppressed."
+msgstr ""
+
+#: builtins.c:462
+msgid "Enable and disable builtin shell commands.  This allows"
+msgstr ""
+
+#: builtins.c:463
+msgid "you to use a disk command which has the same name as a shell"
+msgstr ""
+
+#: builtins.c:464
+msgid "builtin without specifying a full pathname.  If -n is used, the"
+msgstr ""
+
+#: builtins.c:465
+msgid "NAMEs become disabled; otherwise NAMEs are enabled.  For example,"
+msgstr ""
+
+#: builtins.c:466
+msgid "to use the `test' found in $PATH instead of the shell builtin"
+msgstr ""
+
+#: builtins.c:467
+msgid "version, type `enable -n test'.  On systems supporting dynamic"
+msgstr ""
+
+#: builtins.c:468
+msgid "loading, the -f option may be used to load new builtins from the"
+msgstr ""
+
+#: builtins.c:469
+msgid "shared object FILENAME.  The -d option will delete a builtin"
+msgstr ""
+
+#: builtins.c:470
+msgid "previously loaded with -f.  If no non-option names are given, or"
+msgstr ""
+
+#: builtins.c:471
+msgid "the -p option is supplied, a list of builtins is printed.  The"
+msgstr ""
+
+#: builtins.c:472
+msgid "-a option means to print every builtin with an indication of whether"
+msgstr ""
+
+#: builtins.c:473
+msgid ""
+"or not it is enabled.  The -s option restricts the output to the POSIX.2"
+msgstr ""
+
+#: builtins.c:474
+msgid ""
+"`special' builtins.  The -n option displays a list of all disabled builtins."
+msgstr ""
+
+#: builtins.c:480
+msgid "Read ARGs as input to the shell and execute the resulting command(s)."
+msgstr ""
+
+#: builtins.c:486
+msgid "Getopts is used by shell procedures to parse positional parameters."
+msgstr ""
+
+#: builtins.c:488
+msgid "OPTSTRING contains the option letters to be recognized; if a letter"
+msgstr ""
+
+#: builtins.c:489
+msgid "is followed by a colon, the option is expected to have an argument,"
+msgstr ""
+
+#: builtins.c:490
+msgid "which should be separated from it by white space."
+msgstr ""
+
+#: builtins.c:492
+msgid "Each time it is invoked, getopts will place the next option in the"
+msgstr ""
+
+#: builtins.c:493
+msgid "shell variable $name, initializing name if it does not exist, and"
+msgstr ""
+
+#: builtins.c:494
+msgid "the index of the next argument to be processed into the shell"
+msgstr ""
+
+#: builtins.c:495
+msgid "variable OPTIND.  OPTIND is initialized to 1 each time the shell or"
+msgstr ""
+
+#: builtins.c:496
+msgid "a shell script is invoked.  When an option requires an argument,"
+msgstr ""
+
+#: builtins.c:497
+msgid "getopts places that argument into the shell variable OPTARG."
+msgstr ""
+
+#: builtins.c:499
+msgid "getopts reports errors in one of two ways.  If the first character"
+msgstr ""
+
+#: builtins.c:500
+msgid "of OPTSTRING is a colon, getopts uses silent error reporting.  In"
+msgstr ""
+
+#: builtins.c:501
+msgid "this mode, no error messages are printed.  If an invalid option is"
+msgstr ""
+
+#: builtins.c:502
+msgid "seen, getopts places the option character found into OPTARG.  If a"
+msgstr ""
+
+#: builtins.c:503
+msgid "required argument is not found, getopts places a ':' into NAME and"
+msgstr ""
+
+#: builtins.c:504
+msgid "sets OPTARG to the option character found.  If getopts is not in"
+msgstr ""
+
+#: builtins.c:505
+msgid "silent mode, and an invalid option is seen, getopts places '?' into"
+msgstr ""
+
+#: builtins.c:506
+msgid "NAME and unsets OPTARG.  If a required argument is not found, a '?'"
+msgstr ""
+
+#: builtins.c:507
+msgid "is placed in NAME, OPTARG is unset, and a diagnostic message is"
+msgstr ""
+
+#: builtins.c:508
+msgid "printed."
+msgstr ""
+
+#: builtins.c:510
+msgid "If the shell variable OPTERR has the value 0, getopts disables the"
+msgstr ""
+
+#: builtins.c:511
+msgid "printing of error messages, even if the first character of"
+msgstr ""
+
+#: builtins.c:512
+msgid "OPTSTRING is not a colon.  OPTERR has the value 1 by default."
+msgstr ""
+
+#: builtins.c:514
+msgid "Getopts normally parses the positional parameters ($0 - $9), but if"
+msgstr ""
+
+#: builtins.c:515
+msgid "more arguments are given, they are parsed instead."
+msgstr ""
+
+#: builtins.c:521
+msgid "Exec FILE, replacing this shell with the specified program."
+msgstr ""
+
+#: builtins.c:522
+msgid "If FILE is not specified, the redirections take effect in this"
+msgstr ""
+
+#: builtins.c:523
+msgid "shell.  If the first argument is `-l', then place a dash in the"
+msgstr ""
+
+#: builtins.c:524
+msgid "zeroth arg passed to FILE, as login does.  If the `-c' option"
+msgstr ""
+
+#: builtins.c:525
+msgid "is supplied, FILE is executed with a null environment.  The `-a'"
+msgstr ""
+
+#: builtins.c:526
+msgid "option means to make set argv[0] of the executed process to NAME."
+msgstr ""
+
+#: builtins.c:527
+msgid "If the file cannot be executed and the shell is not interactive,"
+msgstr ""
+
+#: builtins.c:528
+msgid "then the shell exits, unless the shell option `execfail' is set."
+msgstr ""
+
+#: builtins.c:534
+msgid "Exit the shell with a status of N.  If N is omitted, the exit status"
+msgstr ""
+
+#: builtins.c:535
+msgid "is that of the last command executed."
+msgstr ""
+
+#: builtins.c:541
+msgid "Logout of a login shell."
+msgstr ""
+
+#: builtins.c:548
+msgid ""
+"fc is used to list or edit and re-execute commands from the history list."
+msgstr ""
+
+#: builtins.c:549
+msgid "FIRST and LAST can be numbers specifying the range, or FIRST can be a"
+msgstr ""
+
+#: builtins.c:550
+msgid "string, which means the most recent command beginning with that"
+msgstr ""
+
+#: builtins.c:551
+msgid "string."
+msgstr ""
+
+#: builtins.c:553
+msgid ""
+"   -e ENAME selects which editor to use.  Default is FCEDIT, then EDITOR,"
+msgstr ""
+
+#: builtins.c:554
+msgid "      then vi."
+msgstr ""
+
+#: builtins.c:556
+msgid "   -l means list lines instead of editing."
+msgstr ""
+
+#: builtins.c:557
+msgid "   -n means no line numbers listed."
+msgstr ""
+
+#: builtins.c:558
+msgid ""
+"   -r means reverse the order of the lines (making it newest listed first)."
+msgstr ""
+
+#: builtins.c:560
+msgid "With the `fc -s [pat=rep ...] [command]' format, the command is"
+msgstr ""
+
+#: builtins.c:561
+msgid "re-executed after the substitution OLD=NEW is performed."
+msgstr ""
+
+#: builtins.c:563
+msgid "A useful alias to use with this is r='fc -s', so that typing `r cc'"
+msgstr ""
+
+#: builtins.c:564
+msgid "runs the last command beginning with `cc' and typing `r' re-executes"
+msgstr ""
+
+#: builtins.c:565
+msgid "the last command."
+msgstr ""
+
+#: builtins.c:573
+msgid "Place JOB_SPEC in the foreground, and make it the current job.  If"
+msgstr ""
+
+#: builtins.c:574
+msgid "JOB_SPEC is not present, the shell's notion of the current job is"
+msgstr ""
+
+#: builtins.c:575
+msgid "used."
+msgstr ""
+
+#: builtins.c:583
+msgid "Place JOB_SPEC in the background, as if it had been started with"
+msgstr ""
+
+#: builtins.c:584
+msgid "`&'.  If JOB_SPEC is not present, the shell's notion of the current"
+msgstr ""
+
+#: builtins.c:585
+msgid "job is used."
+msgstr ""
+
+#: builtins.c:592
+msgid "For each NAME, the full pathname of the command is determined and"
+msgstr ""
+
+#: builtins.c:593
+msgid "remembered.  If the -p option is supplied, PATHNAME is used as the"
+msgstr ""
+
+#: builtins.c:594
+msgid "full pathname of NAME, and no path search is performed.  The -r"
+msgstr ""
+
+#: builtins.c:595
+msgid "option causes the shell to forget all remembered locations.  The -d"
+msgstr ""
+
+#: builtins.c:596
+msgid "option causes the shell to forget the remembered location of each NAME."
+msgstr ""
+
+#: builtins.c:597
+msgid "If the -t option is supplied the full pathname to which each NAME"
+msgstr ""
+
+#: builtins.c:598
+msgid "corresponds is printed.  If multiple NAME arguments are supplied with"
+msgstr ""
+
+#: builtins.c:599
+msgid "-t, the NAME is printed before the hashed full pathname.  The -l option"
+msgstr ""
+
+#: builtins.c:600
+msgid "causes output to be displayed in a format that may be reused as input."
+msgstr ""
+
+#: builtins.c:601
+msgid ""
+"If no arguments are given, information about remembered commands is "
+"displayed."
+msgstr ""
+
+#: builtins.c:608
+msgid "Display helpful information about builtin commands.  If PATTERN is"
+msgstr ""
+
+#: builtins.c:609
+msgid "specified, gives detailed help on all commands matching PATTERN,"
+msgstr ""
+
+#: builtins.c:610
+msgid "otherwise a list of the builtins is printed.  The -s option"
+msgstr ""
+
+#: builtins.c:611
+msgid "restricts the output for each builtin command matching PATTERN to"
+msgstr ""
+
+#: builtins.c:612
+msgid "a short usage synopsis."
+msgstr ""
+
+#: builtins.c:620
+msgid "Display the history list with line numbers.  Lines listed with"
+msgstr ""
+
+#: builtins.c:621
+msgid "with a `*' have been modified.  Argument of N says to list only"
+msgstr ""
+
+#: builtins.c:622
+msgid "the last N lines.  The `-c' option causes the history list to be"
+msgstr ""
+
+#: builtins.c:623
+msgid "cleared by deleting all of the entries.  The `-d' option deletes"
+msgstr ""
+
+#: builtins.c:624
+msgid "the history entry at offset OFFSET.  The `-w' option writes out the"
+msgstr ""
+
+#: builtins.c:625
+msgid "current history to the history file;  `-r' means to read the file and"
+msgstr ""
+
+#: builtins.c:626
+msgid "append the contents to the history list instead.  `-a' means"
+msgstr ""
+
+#: builtins.c:627
+msgid "to append history lines from this session to the history file."
+msgstr ""
+
+#: builtins.c:628
+msgid "Argument `-n' means to read all history lines not already read"
+msgstr ""
+
+#: builtins.c:629
+msgid "from the history file and append them to the history list."
+msgstr ""
+
+#: builtins.c:631
+msgid "If FILENAME is given, then that is used as the history file else"
+msgstr ""
+
+#: builtins.c:632
+msgid "if $HISTFILE has a value, that is used, else ~/.bash_history."
+msgstr ""
+
+#: builtins.c:633
+msgid "If the -s option is supplied, the non-option ARGs are appended to"
+msgstr ""
+
+#: builtins.c:634
+msgid "the history list as a single entry.  The -p option means to perform"
+msgstr ""
+
+#: builtins.c:635
+msgid "history expansion on each ARG and display the result, without storing"
+msgstr ""
+
+#: builtins.c:636
+msgid "anything in the history list."
+msgstr ""
+
+#: builtins.c:638
+msgid "If the $HISTTIMEFORMAT variable is set and not null, its value is used"
+msgstr ""
+
+#: builtins.c:639
+msgid "as a format string for strftime(3) to print the time stamp associated"
+msgstr ""
+
+#: builtins.c:640
+msgid ""
+"with each displayed history entry.  No time stamps are printed otherwise."
+msgstr ""
+
+#: builtins.c:648
+msgid "Lists the active jobs.  The -l option lists process id's in addition"
+msgstr ""
+
+#: builtins.c:649
+msgid "to the normal information; the -p option lists process id's only."
+msgstr ""
+
+#: builtins.c:650
+msgid "If -n is given, only processes that have changed status since the last"
+msgstr ""
+
+#: builtins.c:651
+msgid "notification are printed.  JOBSPEC restricts output to that job.  The"
+msgstr ""
+
+#: builtins.c:652
+msgid "-r and -s options restrict output to running and stopped jobs only,"
+msgstr ""
+
+#: builtins.c:653
+msgid "respectively.  Without options, the status of all active jobs is"
+msgstr ""
+
+#: builtins.c:654
+msgid "printed.  If -x is given, COMMAND is run after all job specifications"
+msgstr ""
+
+#: builtins.c:655
+msgid ""
+"that appear in ARGS have been replaced with the process ID of that job's"
+msgstr ""
+
+#: builtins.c:656
+msgid "process group leader."
+msgstr ""
+
+#: builtins.c:664
+msgid ""
+"By default, removes each JOBSPEC argument from the table of active jobs."
+msgstr ""
+
+#: builtins.c:665
+msgid ""
+"If the -h option is given, the job is not removed from the table, but is"
+msgstr ""
+
+#: builtins.c:666
+msgid "marked so that SIGHUP is not sent to the job if the shell receives a"
+msgstr ""
+
+#: builtins.c:667
+msgid ""
+"SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all"
+msgstr ""
+
+#: builtins.c:668
+msgid ""
+"jobs from the job table; the -r option means to remove only running jobs."
+msgstr ""
+
+#: builtins.c:675
+msgid "Send the processes named by PID (or JOB) the signal SIGSPEC.  If"
+msgstr ""
+
+#: builtins.c:676
+msgid "SIGSPEC is not present, then SIGTERM is assumed.  An argument of `-l'"
+msgstr ""
+
+#: builtins.c:677
+msgid "lists the signal names; if arguments follow `-l' they are assumed to"
+msgstr ""
+
+#: builtins.c:678
+msgid "be signal numbers for which names should be listed.  Kill is a shell"
+msgstr ""
+
+#: builtins.c:679
+msgid "builtin for two reasons: it allows job IDs to be used instead of"
+msgstr ""
+
+#: builtins.c:680
+msgid "process IDs, and, if you have reached the limit on processes that"
+msgstr ""
+
+#: builtins.c:681
+msgid "you can create, you don't have to start a process to kill another one."
+msgstr ""
+
+#: builtins.c:687
+msgid "Each ARG is an arithmetic expression to be evaluated.  Evaluation"
+msgstr ""
+
+#: builtins.c:688
+msgid "is done in fixed-width integers with no check for overflow, though"
+msgstr ""
+
+#: builtins.c:689
+msgid "division by 0 is trapped and flagged as an error.  The following"
+msgstr ""
+
+#: builtins.c:690
+msgid "list of operators is grouped into levels of equal-precedence operators."
+msgstr ""
+
+#: builtins.c:691
+msgid "The levels are listed in order of decreasing precedence."
+msgstr ""
+
+#: builtins.c:693
+msgid "\tid++, id--\tvariable post-increment, post-decrement"
+msgstr ""
+
+#: builtins.c:694
+msgid "\t++id, --id\tvariable pre-increment, pre-decrement"
+msgstr ""
+
+#: builtins.c:695
+msgid "\t-, +\t\tunary minus, plus"
+msgstr ""
+
+#: builtins.c:696
+msgid "\t!, ~\t\tlogical and bitwise negation"
+msgstr ""
+
+#: builtins.c:697
+msgid "\t**\t\texponentiation"
+msgstr ""
+
+#: builtins.c:698
+msgid "\t*, /, %\t\tmultiplication, division, remainder"
+msgstr ""
+
+#: builtins.c:699
+msgid "\t+, -\t\taddition, subtraction"
+msgstr ""
+
+#: builtins.c:700
+msgid "\t<<, >>\t\tleft and right bitwise shifts"
+msgstr ""
+
+#: builtins.c:701
+msgid "\t<=, >=, <, >\tcomparison"
+msgstr ""
+
+#: builtins.c:702
+msgid "\t==, !=\t\tequality, inequality"
+msgstr ""
+
+#: builtins.c:703
+msgid "\t&\t\tbitwise AND"
+msgstr ""
+
+#: builtins.c:704
+msgid "\t^\t\tbitwise XOR"
+msgstr ""
+
+#: builtins.c:705
+msgid "\t|\t\tbitwise OR"
+msgstr ""
+
+#: builtins.c:706
+msgid "\t&&\t\tlogical AND"
+msgstr ""
+
+#: builtins.c:707
+msgid "\t||\t\tlogical OR"
+msgstr ""
+
+#: builtins.c:708
+msgid "\texpr ? expr : expr"
+msgstr ""
+
+#: builtins.c:709
+msgid "\t\t\tconditional operator"
+msgstr ""
+
+#: builtins.c:710
+msgid "\t=, *=, /=, %=,"
+msgstr ""
+
+#: builtins.c:711
+msgid "\t+=, -=, <<=, >>=,"
+msgstr ""
+
+#: builtins.c:712
+msgid "\t&=, ^=, |=\tassignment"
+msgstr ""
+
+#: builtins.c:714
+msgid "Shell variables are allowed as operands.  The name of the variable"
+msgstr ""
+
+#: builtins.c:715
+msgid "is replaced by its value (coerced to a fixed-width integer) within"
+msgstr ""
+
+#: builtins.c:716
+msgid "an expression.  The variable need not have its integer attribute"
+msgstr ""
+
+#: builtins.c:717
+msgid "turned on to be used in an expression."
+msgstr ""
+
+#: builtins.c:719
+msgid "Operators are evaluated in order of precedence.  Sub-expressions in"
+msgstr ""
+
+#: builtins.c:720
+msgid "parentheses are evaluated first and may override the precedence"
+msgstr ""
+
+#: builtins.c:721
+msgid "rules above."
+msgstr ""
+
+#: builtins.c:723
+msgid "If the last ARG evaluates to 0, let returns 1; 0 is returned"
+msgstr ""
+
+#: builtins.c:724
+msgid "otherwise."
+msgstr ""
+
+#: builtins.c:730
+msgid ""
+"One line is read from the standard input, or from file descriptor FD if the"
+msgstr ""
+
+#: builtins.c:731
+msgid ""
+"-u option is supplied, and the first word is assigned to the first NAME,"
+msgstr ""
+
+#: builtins.c:732
+msgid ""
+"the second word to the second NAME, and so on, with leftover words assigned"
+msgstr ""
+
+#: builtins.c:733
+msgid ""
+"to the last NAME.  Only the characters found in $IFS are recognized as word"
+msgstr ""
+
+#: builtins.c:734
+msgid ""
+"delimiters.  If no NAMEs are supplied, the line read is stored in the REPLY"
+msgstr ""
+
+#: builtins.c:735
+msgid "variable.  If the -r option is given, this signifies `raw' input, and"
+msgstr ""
+
+#: builtins.c:736
+msgid "backslash escaping is disabled.  The -d option causes read to continue"
+msgstr ""
+
+#: builtins.c:737
+msgid ""
+"until the first character of DELIM is read, rather than newline.  If the -p"
+msgstr ""
+
+#: builtins.c:738
+msgid ""
+"option is supplied, the string PROMPT is output without a trailing newline"
+msgstr ""
+
+#: builtins.c:739
+msgid ""
+"before attempting to read.  If -a is supplied, the words read are assigned"
+msgstr ""
+
+#: builtins.c:740
+msgid ""
+"to sequential indices of ARRAY, starting at zero.  If -e is supplied and"
+msgstr ""
+
+#: builtins.c:741
+msgid ""
+"the shell is interactive, readline is used to obtain the line.  If -n is"
+msgstr ""
+
+#: builtins.c:742
+msgid "supplied with a non-zero NCHARS argument, read returns after NCHARS"
+msgstr ""
+
+#: builtins.c:743
+msgid "characters have been read.  The -s option causes input coming from a"
+msgstr ""
+
+#: builtins.c:744
+msgid "terminal to not be echoed."
+msgstr ""
+
+#: builtins.c:746
+msgid ""
+"The -t option causes read to time out and return failure if a complete line"
+msgstr ""
+
+#: builtins.c:747
+msgid ""
+"of input is not read within TIMEOUT seconds.  If the TMOUT variable is set,"
+msgstr ""
+
+#: builtins.c:748
+msgid ""
+"its value is the default timeout.  The return code is zero, unless end-of-"
+"file"
+msgstr ""
+
+#: builtins.c:749
+msgid ""
+"is encountered, read times out, or an invalid file descriptor is supplied as"
+msgstr ""
+
+#: builtins.c:750
+msgid "the argument to -u."
+msgstr ""
+
+#: builtins.c:756
+msgid "Causes a function to exit with the return value specified by N.  If N"
+msgstr ""
+
+#: builtins.c:757
+msgid "is omitted, the return status is that of the last command."
+msgstr ""
+
+#: builtins.c:763
+msgid "    -a  Mark variables which are modified or created for export."
+msgstr ""
+
+#: builtins.c:764
+msgid "    -b  Notify of job termination immediately."
+msgstr ""
+
+#: builtins.c:765
+msgid "    -e  Exit immediately if a command exits with a non-zero status."
+msgstr ""
+
+#: builtins.c:766
+msgid "    -f  Disable file name generation (globbing)."
+msgstr ""
+
+#: builtins.c:767
+msgid "    -h  Remember the location of commands as they are looked up."
+msgstr ""
+
+#: builtins.c:768
+msgid "    -k  All assignment arguments are placed in the environment for a"
+msgstr ""
+
+#: builtins.c:769
+msgid "        command, not just those that precede the command name."
+msgstr ""
+
+#: builtins.c:770
+msgid "    -m  Job control is enabled."
+msgstr ""
+
+#: builtins.c:771
+msgid "    -n  Read commands but do not execute them."
+msgstr ""
+
+#: builtins.c:772
+msgid "    -o option-name"
+msgstr ""
+
+#: builtins.c:773
+msgid "        Set the variable corresponding to option-name:"
+msgstr ""
+
+#: builtins.c:774
+msgid "            allexport    same as -a"
+msgstr ""
+
+#: builtins.c:775
+msgid "            braceexpand  same as -B"
+msgstr ""
+
+#: builtins.c:777
+msgid "            emacs        use an emacs-style line editing interface"
+msgstr ""
+
+#: builtins.c:779
+msgid "            errexit      same as -e"
+msgstr ""
+
+#: builtins.c:780
+msgid "            errtrace     same as -E"
+msgstr ""
+
+#: builtins.c:781
+msgid "            functrace    same as -T"
+msgstr ""
+
+#: builtins.c:782
+msgid "            hashall      same as -h"
+msgstr ""
+
+#: builtins.c:784
+msgid "            histexpand   same as -H"
+msgstr ""
+
+#: builtins.c:787
+msgid "            history      enable command history"
+msgstr ""
+
+#: builtins.c:789
+msgid "            ignoreeof    the shell will not exit upon reading EOF"
+msgstr ""
+
+#: builtins.c:790
+msgid "            interactive-comments"
+msgstr ""
+
+#: builtins.c:791
+msgid ""
+"                         allow comments to appear in interactive commands"
+msgstr ""
+
+#: builtins.c:792
+msgid "            keyword      same as -k"
+msgstr ""
+
+#: builtins.c:793
+msgid "            monitor      same as -m"
+msgstr ""
+
+#: builtins.c:794
+msgid "            noclobber    same as -C"
+msgstr ""
+
+#: builtins.c:795
+msgid "            noexec       same as -n"
+msgstr ""
+
+#: builtins.c:796
+msgid "            noglob       same as -f"
+msgstr ""
+
+#: builtins.c:797
+msgid "            nolog        currently accepted but ignored"
+msgstr ""
+
+#: builtins.c:798
+msgid "            notify       same as -b"
+msgstr ""
+
+#: builtins.c:799
+msgid "            nounset      same as -u"
+msgstr ""
+
+#: builtins.c:800
+msgid "            onecmd       same as -t"
+msgstr ""
+
+#: builtins.c:801
+msgid "            physical     same as -P"
+msgstr ""
+
+#: builtins.c:802
+msgid ""
+"            pipefail     the return value of a pipeline is the status of"
+msgstr ""
+
+#: builtins.c:803
+msgid ""
+"                         the last command to exit with a non-zero status,"
+msgstr ""
+
+#: builtins.c:804
+msgid ""
+"                         or zero if no command exited with a non-zero status"
+msgstr ""
+
+#: builtins.c:805
+msgid "            posix        change the behavior of bash where the default"
+msgstr ""
+
+#: builtins.c:806
+msgid "                         operation differs from the 1003.2 standard to"
+msgstr ""
+
+#: builtins.c:807
+msgid "                         match the standard"
+msgstr ""
+
+#: builtins.c:808
+msgid "            privileged   same as -p"
+msgstr ""
+
+#: builtins.c:809
+msgid "            verbose      same as -v"
+msgstr ""
+
+#: builtins.c:811
+msgid "            vi           use a vi-style line editing interface"
+msgstr ""
+
+#: builtins.c:813
+msgid "            xtrace       same as -x"
+msgstr ""
+
+#: builtins.c:814
+msgid ""
+"    -p  Turned on whenever the real and effective user ids do not match."
+msgstr ""
+
+#: builtins.c:815
+msgid "        Disables processing of the $ENV file and importing of shell"
+msgstr ""
+
+#: builtins.c:816
+msgid ""
+"        functions.  Turning this option off causes the effective uid and"
+msgstr ""
+
+#: builtins.c:817
+msgid "        gid to be set to the real uid and gid."
+msgstr ""
+
+#: builtins.c:818
+msgid "    -t  Exit after reading and executing one command."
+msgstr ""
+
+#: builtins.c:819
+msgid "    -u  Treat unset variables as an error when substituting."
+msgstr ""
+
+#: builtins.c:820
+msgid "    -v  Print shell input lines as they are read."
+msgstr ""
+
+#: builtins.c:821
+msgid "    -x  Print commands and their arguments as they are executed."
+msgstr ""
+
+#: builtins.c:823
+msgid "    -B  the shell will perform brace expansion"
+msgstr ""
+
+#: builtins.c:825
+msgid "    -C  If set, disallow existing regular files to be overwritten"
+msgstr ""
+
+#: builtins.c:826
+msgid "        by redirection of output."
+msgstr ""
+
+#: builtins.c:827
+msgid "    -E  If set, the ERR trap is inherited by shell functions."
+msgstr ""
+
+#: builtins.c:829
+msgid "    -H  Enable ! style history substitution.  This flag is on"
+msgstr ""
+
+#: builtins.c:830
+msgid "        by default."
+msgstr ""
+
+#: builtins.c:832
+msgid "    -P  If set, do not follow symbolic links when executing commands"
+msgstr ""
+
+#: builtins.c:833
+msgid "        such as cd which change the current directory."
+msgstr ""
+
+#: builtins.c:834
+msgid "    -T  If set, the DEBUG trap is inherited by shell functions."
+msgstr ""
+
+#: builtins.c:836
+msgid "Using + rather than - causes these flags to be turned off.  The"
+msgstr ""
+
+#: builtins.c:837
+msgid "flags can also be used upon invocation of the shell.  The current"
+msgstr ""
+
+#: builtins.c:838
+msgid "set of flags may be found in $-.  The remaining n ARGs are positional"
+msgstr ""
+
+#: builtins.c:839
+msgid "parameters and are assigned, in order, to $1, $2, .. $n.  If no"
+msgstr ""
+
+#: builtins.c:840
+msgid "ARGs are given, all shell variables are printed."
+msgstr ""
+
+#: builtins.c:846
+msgid "For each NAME, remove the corresponding variable or function.  Given"
+msgstr ""
+
+#: builtins.c:847
+msgid "the `-v', unset will only act on variables.  Given the `-f' flag,"
+msgstr ""
+
+#: builtins.c:848
+msgid "unset will only act on functions.  With neither flag, unset first"
+msgstr ""
+
+#: builtins.c:849
+msgid "tries to unset a variable, and if that fails, then tries to unset a"
+msgstr ""
+
+#: builtins.c:850
+msgid "function.  Some variables cannot be unset; also see readonly."
+msgstr ""
+
+#: builtins.c:856
+msgid "NAMEs are marked for automatic export to the environment of"
+msgstr ""
+
+#: builtins.c:857
+msgid "subsequently executed commands.  If the -f option is given,"
+msgstr ""
+
+#: builtins.c:858
+msgid "the NAMEs refer to functions.  If no NAMEs are given, or if `-p'"
+msgstr ""
+
+#: builtins.c:859
+msgid "is given, a list of all names that are exported in this shell is"
+msgstr ""
+
+#: builtins.c:860
+msgid "printed.  An argument of `-n' says to remove the export property"
+msgstr ""
+
+#: builtins.c:861
+msgid "from subsequent NAMEs.  An argument of `--' disables further option"
+msgstr ""
+
+#: builtins.c:862 builtins.c:874
+msgid "processing."
+msgstr ""
+
+#: builtins.c:868
+msgid "The given NAMEs are marked readonly and the values of these NAMEs may"
+msgstr ""
+
+#: builtins.c:869
+msgid "not be changed by subsequent assignment.  If the -f option is given,"
+msgstr ""
+
+#: builtins.c:870
+msgid "then functions corresponding to the NAMEs are so marked.  If no"
+msgstr ""
+
+#: builtins.c:871
+msgid "arguments are given, or if `-p' is given, a list of all readonly names"
+msgstr ""
+
+#: builtins.c:872
+msgid "is printed.  The `-a' option means to treat each NAME as"
+msgstr ""
+
+#: builtins.c:873
+msgid "an array variable.  An argument of `--' disables further option"
+msgstr ""
+
+#: builtins.c:880
+msgid "The positional parameters from $N+1 ... are renamed to $1 ...  If N is"
+msgstr ""
+
+#: builtins.c:881
+msgid "not given, it is assumed to be 1."
+msgstr ""
+
+#: builtins.c:887 builtins.c:896
+msgid "Read and execute commands from FILENAME and return.  The pathnames"
+msgstr ""
+
+#: builtins.c:888 builtins.c:897
+msgid "in $PATH are used to find the directory containing FILENAME.  If any"
+msgstr ""
+
+#: builtins.c:889 builtins.c:898
+msgid "ARGUMENTS are supplied, they become the positional parameters when"
+msgstr ""
+
+#: builtins.c:890 builtins.c:899
+msgid "FILENAME is executed."
+msgstr ""
+
+#: builtins.c:906
+msgid "Suspend the execution of this shell until it receives a SIGCONT"
+msgstr ""
+
+#: builtins.c:907
+msgid "signal.  The `-f' if specified says not to complain about this"
+msgstr ""
+
+#: builtins.c:908
+msgid "being a login shell if it is; just suspend anyway."
+msgstr ""
+
+#: builtins.c:915
+msgid "Exits with a status of 0 (true) or 1 (false) depending on"
+msgstr ""
+
+#: builtins.c:916
+msgid "the evaluation of EXPR.  Expressions may be unary or binary.  Unary"
+msgstr ""
+
+#: builtins.c:917
+msgid "expressions are often used to examine the status of a file.  There"
+msgstr ""
+
+#: builtins.c:918
+msgid "are string operators as well, and numeric comparison operators."
+msgstr ""
+
+#: builtins.c:920
+msgid "File operators:"
+msgstr ""
+
+#: builtins.c:922
+msgid "    -a FILE        True if file exists."
+msgstr ""
+
+#: builtins.c:923
+msgid "    -b FILE        True if file is block special."
+msgstr ""
+
+#: builtins.c:924
+msgid "    -c FILE        True if file is character special."
+msgstr ""
+
+#: builtins.c:925
+msgid "    -d FILE        True if file is a directory."
+msgstr ""
+
+#: builtins.c:926
+msgid "    -e FILE        True if file exists."
+msgstr ""
+
+#: builtins.c:927
+msgid "    -f FILE        True if file exists and is a regular file."
+msgstr ""
+
+#: builtins.c:928
+msgid "    -g FILE        True if file is set-group-id."
+msgstr ""
+
+#: builtins.c:929
+msgid "    -h FILE        True if file is a symbolic link."
+msgstr ""
+
+#: builtins.c:930
+msgid "    -L FILE        True if file is a symbolic link."
+msgstr ""
+
+#: builtins.c:931
+msgid "    -k FILE        True if file has its `sticky' bit set."
+msgstr ""
+
+#: builtins.c:932
+msgid "    -p FILE        True if file is a named pipe."
+msgstr ""
+
+#: builtins.c:933
+msgid "    -r FILE        True if file is readable by you."
+msgstr ""
+
+#: builtins.c:934
+msgid "    -s FILE        True if file exists and is not empty."
+msgstr ""
+
+#: builtins.c:935
+msgid "    -S FILE        True if file is a socket."
+msgstr ""
+
+#: builtins.c:936
+msgid "    -t FD          True if FD is opened on a terminal."
+msgstr ""
+
+#: builtins.c:937
+msgid "    -u FILE        True if the file is set-user-id."
+msgstr ""
+
+#: builtins.c:938
+msgid "    -w FILE        True if the file is writable by you."
+msgstr ""
+
+#: builtins.c:939
+msgid "    -x FILE        True if the file is executable by you."
+msgstr ""
+
+#: builtins.c:940
+msgid "    -O FILE        True if the file is effectively owned by you."
+msgstr ""
+
+#: builtins.c:941
+msgid "    -G FILE        True if the file is effectively owned by your group."
+msgstr ""
+
+#: builtins.c:942
+msgid ""
+"    -N FILE        True if the file has been modified since it was last read."
+msgstr ""
+
+#: builtins.c:944
+msgid "  FILE1 -nt FILE2  True if file1 is newer than file2 (according to"
+msgstr ""
+
+#: builtins.c:945
+msgid "                   modification date)."
+msgstr ""
+
+#: builtins.c:947
+msgid "  FILE1 -ot FILE2  True if file1 is older than file2."
+msgstr ""
+
+#: builtins.c:949
+msgid "  FILE1 -ef FILE2  True if file1 is a hard link to file2."
+msgstr ""
+
+#: builtins.c:951
+msgid "String operators:"
+msgstr ""
+
+#: builtins.c:953
+msgid "    -z STRING      True if string is empty."
+msgstr ""
+
+#: builtins.c:955
+msgid "    -n STRING"
+msgstr ""
+
+#: builtins.c:956
+msgid "    STRING         True if string is not empty."
+msgstr ""
+
+#: builtins.c:958
+msgid "    STRING1 = STRING2"
+msgstr ""
+
+#: builtins.c:959
+msgid "                   True if the strings are equal."
+msgstr ""
+
+#: builtins.c:960
+msgid "    STRING1 != STRING2"
+msgstr ""
+
+#: builtins.c:961
+msgid "                   True if the strings are not equal."
+msgstr ""
+
+#: builtins.c:962
+msgid "    STRING1 < STRING2"
+msgstr ""
+
+#: builtins.c:963
+msgid ""
+"                   True if STRING1 sorts before STRING2 lexicographically."
+msgstr ""
+
+#: builtins.c:964
+msgid "    STRING1 > STRING2"
+msgstr ""
+
+#: builtins.c:965
+msgid ""
+"                   True if STRING1 sorts after STRING2 lexicographically."
+msgstr ""
+
+#: builtins.c:967
+msgid "Other operators:"
+msgstr ""
+
+#: builtins.c:969
+msgid "    -o OPTION      True if the shell option OPTION is enabled."
+msgstr ""
+
+#: builtins.c:970
+msgid "    ! EXPR         True if expr is false."
+msgstr ""
+
+#: builtins.c:971
+msgid "    EXPR1 -a EXPR2 True if both expr1 AND expr2 are true."
+msgstr ""
+
+#: builtins.c:972
+msgid "    EXPR1 -o EXPR2 True if either expr1 OR expr2 is true."
+msgstr ""
+
+#: builtins.c:974
+msgid "    arg1 OP arg2   Arithmetic tests.  OP is one of -eq, -ne,"
+msgstr ""
+
+#: builtins.c:975
+msgid "                   -lt, -le, -gt, or -ge."
+msgstr ""
+
+#: builtins.c:977
+msgid "Arithmetic binary operators return true if ARG1 is equal, not-equal,"
+msgstr ""
+
+#: builtins.c:978
+msgid "less-than, less-than-or-equal, greater-than, or greater-than-or-equal"
+msgstr ""
+
+#: builtins.c:979
+msgid "than ARG2."
+msgstr ""
+
+#: builtins.c:985
+msgid "This is a synonym for the \"test\" builtin, but the last"
+msgstr ""
+
+#: builtins.c:986
+msgid "argument must be a literal `]', to match the opening `['."
+msgstr ""
+
+#: builtins.c:992
+msgid "Print the accumulated user and system times for processes run from"
+msgstr ""
+
+#: builtins.c:993
+msgid "the shell."
+msgstr ""
+
+#: builtins.c:999
+msgid "The command ARG is to be read and executed when the shell receives"
+msgstr ""
+
+#: builtins.c:1000
+msgid "signal(s) SIGNAL_SPEC.  If ARG is absent all specified signals are"
+msgstr ""
+
+#: builtins.c:1001
+msgid "reset to their original values.  If ARG is the null string each"
+msgstr ""
+
+#: builtins.c:1002
+msgid "SIGNAL_SPEC is ignored by the shell and by the commands it invokes."
+msgstr ""
+
+#: builtins.c:1003
+msgid "If a SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from"
+msgstr ""
+
+#: builtins.c:1004
+msgid "the shell.  If a SIGNAL_SPEC is DEBUG, ARG is executed after every"
+msgstr ""
+
+#: builtins.c:1005
+msgid "command.  If ARG is `-p' then the trap commands associated with"
+msgstr ""
+
+#: builtins.c:1006
+msgid "each SIGNAL_SPEC are displayed.  If no arguments are supplied or if"
+msgstr ""
+
+#: builtins.c:1007
+msgid "only `-p' is given, trap prints the list of commands associated with"
+msgstr ""
+
+#: builtins.c:1008
+msgid ""
+"each signal number.  Each SIGNAL_SPEC is either a signal name in <signal.h>"
+msgstr ""
+
+#: builtins.c:1009
+msgid "or a signal number.  `trap -l' prints a list of signal names and their"
+msgstr ""
+
+#: builtins.c:1010
+msgid "corresponding numbers.  Note that a signal can be sent to the shell"
+msgstr ""
+
+#: builtins.c:1011
+msgid "with \"kill -signal $$\"."
+msgstr ""
+
+#: builtins.c:1017
+msgid "For each NAME, indicate how it would be interpreted if used as a"
+msgstr ""
+
+#: builtins.c:1018
+msgid "command name."
+msgstr ""
+
+#: builtins.c:1020
+msgid "If the -t option is used, `type' outputs a single word which is one of"
+msgstr ""
+
+#: builtins.c:1021
+msgid "`alias', `keyword', `function', `builtin', `file' or `', if NAME is an"
+msgstr ""
+
+#: builtins.c:1022
+msgid "alias, shell reserved word, shell function, shell builtin, disk file,"
+msgstr ""
+
+#: builtins.c:1023
+msgid "or unfound, respectively."
+msgstr ""
+
+#: builtins.c:1025
+msgid "If the -p flag is used, `type' either returns the name of the disk"
+msgstr ""
+
+#: builtins.c:1026
+msgid "file that would be executed, or nothing if `type -t NAME' would not"
+msgstr ""
+
+#: builtins.c:1027
+msgid "return `file'."
+msgstr ""
+
+#: builtins.c:1029
+msgid "If the -a flag is used, `type' displays all of the places that contain"
+msgstr ""
+
+#: builtins.c:1030
+msgid "an executable named `file'.  This includes aliases, builtins, and"
+msgstr ""
+
+#: builtins.c:1031
+msgid "functions, if and only if the -p flag is not also used."
+msgstr ""
+
+#: builtins.c:1033
+msgid "The -f flag suppresses shell function lookup."
+msgstr ""
+
+#: builtins.c:1035
+msgid "The -P flag forces a PATH search for each NAME, even if it is an alias,"
+msgstr ""
+
+#: builtins.c:1036
+msgid "builtin, or function, and returns the name of the disk file that would"
+msgstr ""
+
+#: builtins.c:1037
+msgid "be executed."
+msgstr ""
+
+#: builtins.c:1044
+msgid "Ulimit provides control over the resources available to processes"
+msgstr ""
+
+#: builtins.c:1045
+msgid "started by the shell, on systems that allow such control.  If an"
+msgstr ""
+
+#: builtins.c:1046
+msgid "option is given, it is interpreted as follows:"
+msgstr ""
+
+#: builtins.c:1048
+msgid "    -S\tuse the `soft' resource limit"
+msgstr ""
+
+#: builtins.c:1049
+msgid "    -H\tuse the `hard' resource limit"
+msgstr ""
+
+#: builtins.c:1050
+msgid "    -a\tall current limits are reported"
+msgstr ""
+
+#: builtins.c:1051
+msgid "    -c\tthe maximum size of core files created"
+msgstr ""
+
+#: builtins.c:1052
+msgid "    -d\tthe maximum size of a process's data segment"
+msgstr ""
+
+#: builtins.c:1053
+msgid "    -f\tthe maximum size of files created by the shell"
+msgstr ""
+
+#: builtins.c:1054
+msgid "    -l\tthe maximum size a process may lock into memory"
+msgstr ""
+
+#: builtins.c:1055
+msgid "    -m\tthe maximum resident set size"
+msgstr ""
+
+#: builtins.c:1056
+msgid "    -n\tthe maximum number of open file descriptors"
+msgstr ""
+
+#: builtins.c:1057
+msgid "    -p\tthe pipe buffer size"
+msgstr ""
+
+#: builtins.c:1058
+msgid "    -s\tthe maximum stack size"
+msgstr ""
+
+#: builtins.c:1059
+msgid "    -t\tthe maximum amount of cpu time in seconds"
+msgstr ""
+
+#: builtins.c:1060
+msgid "    -u\tthe maximum number of user processes"
+msgstr ""
+
+#: builtins.c:1061
+msgid "    -v\tthe size of virtual memory"
+msgstr ""
+
+#: builtins.c:1063
+msgid "If LIMIT is given, it is the new value of the specified resource;"
+msgstr ""
+
+#: builtins.c:1064
+msgid "the special LIMIT values `soft', `hard', and `unlimited' stand for"
+msgstr ""
+
+#: builtins.c:1065
+msgid ""
+"the current soft limit, the current hard limit, and no limit, respectively."
+msgstr ""
+
+#: builtins.c:1066
+msgid "Otherwise, the current value of the specified resource is printed."
+msgstr ""
+
+#: builtins.c:1067
+msgid "If no option is given, then -f is assumed.  Values are in 1024-byte"
+msgstr ""
+
+#: builtins.c:1068
+msgid "increments, except for -t, which is in seconds, -p, which is in"
+msgstr ""
+
+#: builtins.c:1069
+msgid "increments of 512 bytes, and -u, which is an unscaled number of"
+msgstr ""
+
+#: builtins.c:1070
+msgid "processes."
+msgstr ""
+
+#: builtins.c:1077
+msgid "The user file-creation mask is set to MODE.  If MODE is omitted, or if"
+msgstr ""
+
+#: builtins.c:1078
+msgid "`-S' is supplied, the current value of the mask is printed.  The `-S'"
+msgstr ""
+
+#: builtins.c:1079
+msgid "option makes the output symbolic; otherwise an octal number is output."
+msgstr ""
+
+#: builtins.c:1080
+msgid "If `-p' is supplied, and MODE is omitted, the output is in a form"
+msgstr ""
+
+#: builtins.c:1081
+msgid "that may be used as input.  If MODE begins with a digit, it is"
+msgstr ""
+
+#: builtins.c:1082
+msgid "interpreted as an octal number, otherwise it is a symbolic mode string"
+msgstr ""
+
+#: builtins.c:1083
+msgid "like that accepted by chmod(1)."
+msgstr ""
+
+#: builtins.c:1090 builtins.c:1102
+msgid "Wait for the specified process and report its termination status.  If"
+msgstr ""
+
+#: builtins.c:1091 builtins.c:1103
+msgid "N is not given, all currently active child processes are waited for,"
+msgstr ""
+
+#: builtins.c:1092
+msgid "and the return code is zero.  N may be a process ID or a job"
+msgstr ""
+
+#: builtins.c:1093
+msgid "specification; if a job spec is given, all processes in the job's"
+msgstr ""
+
+#: builtins.c:1094
+msgid "pipeline are waited for."
+msgstr ""
+
+#: builtins.c:1104
+msgid "and the return code is zero.  N is a process ID; if it is not given,"
+msgstr ""
+
+#: builtins.c:1105
+msgid "all child processes of the shell are waited for."
+msgstr ""
+
+#: builtins.c:1112
+msgid "The `for' loop executes a sequence of commands for each member in a"
+msgstr ""
+
+#: builtins.c:1113
+msgid "list of items.  If `in WORDS ...;' is not present, then `in \"$@\"' is"
+msgstr ""
+
+#: builtins.c:1114
+msgid "assumed.  For each element in WORDS, NAME is set to that element, and"
+msgstr ""
+
+#: builtins.c:1115
+msgid "the COMMANDS are executed."
+msgstr ""
+
+#: builtins.c:1121
+msgid "Equivalent to"
+msgstr ""
+
+#: builtins.c:1122
+msgid "\t(( EXP1 ))"
+msgstr ""
+
+#: builtins.c:1123
+msgid "\twhile (( EXP2 )); do"
+msgstr ""
+
+#: builtins.c:1124
+msgid "\t\tCOMMANDS"
+msgstr ""
+
+#: builtins.c:1125
+msgid "\t\t(( EXP3 ))"
+msgstr ""
+
+#: builtins.c:1126
+msgid "\tdone"
+msgstr ""
+
+#: builtins.c:1127
+msgid "EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is"
+msgstr ""
+
+#: builtins.c:1128
+msgid "omitted, it behaves as if it evaluates to 1."
+msgstr ""
+
+#: builtins.c:1134
+msgid "The WORDS are expanded, generating a list of words.  The"
+msgstr ""
+
+#: builtins.c:1135
+msgid "set of expanded words is printed on the standard error, each"
+msgstr ""
+
+#: builtins.c:1136
+msgid "preceded by a number.  If `in WORDS' is not present, `in \"$@\"'"
+msgstr ""
+
+#: builtins.c:1137
+msgid "is assumed.  The PS3 prompt is then displayed and a line read"
+msgstr ""
+
+#: builtins.c:1138
+msgid "from the standard input.  If the line consists of the number"
+msgstr ""
+
+#: builtins.c:1139
+msgid "corresponding to one of the displayed words, then NAME is set"
+msgstr ""
+
+#: builtins.c:1140
+msgid "to that word.  If the line is empty, WORDS and the prompt are"
+msgstr ""
+
+#: builtins.c:1141
+msgid "redisplayed.  If EOF is read, the command completes.  Any other"
+msgstr ""
+
+#: builtins.c:1142
+msgid "value read causes NAME to be set to null.  The line read is saved"
+msgstr ""
+
+#: builtins.c:1143
+msgid "in the variable REPLY.  COMMANDS are executed after each selection"
+msgstr ""
+
+#: builtins.c:1144
+msgid "until a break command is executed."
+msgstr ""
+
+#: builtins.c:1150
+msgid "Execute PIPELINE and print a summary of the real time, user CPU time,"
+msgstr ""
+
+#: builtins.c:1151
+msgid "and system CPU time spent executing PIPELINE when it terminates."
+msgstr ""
+
+#: builtins.c:1152
+msgid "The return status is the return status of PIPELINE.  The `-p' option"
+msgstr ""
+
+#: builtins.c:1153
+msgid "prints the timing summary in a slightly different format.  This uses"
+msgstr ""
+
+#: builtins.c:1154
+msgid "the value of the TIMEFORMAT variable as the output format."
+msgstr ""
+
+#: builtins.c:1160
+msgid "Selectively execute COMMANDS based upon WORD matching PATTERN.  The"
+msgstr ""
+
+#: builtins.c:1161
+msgid "`|' is used to separate multiple patterns."
+msgstr ""
+
+#: builtins.c:1167
+msgid ""
+"The if COMMANDS are executed.  If the exit status is zero, then the then"
+msgstr ""
+
+#: builtins.c:1168
+msgid ""
+"COMMANDS are executed.  Otherwise, each of the elif COMMANDS are executed"
+msgstr ""
+
+#: builtins.c:1169
+msgid ""
+"in turn, and if the exit status is zero, the corresponding then COMMANDS"
+msgstr ""
+
+#: builtins.c:1170
+msgid ""
+"are executed and the if command completes.  Otherwise, the else COMMANDS"
+msgstr ""
+
+#: builtins.c:1171
+msgid ""
+"are executed, if present.  The exit status is the exit status of the last"
+msgstr ""
+
+#: builtins.c:1172
+msgid "command executed, or zero if no condition tested true."
+msgstr ""
+
+#: builtins.c:1178 builtins.c:1185
+msgid "Expand and execute COMMANDS as long as the final command in the"
+msgstr ""
+
+#: builtins.c:1179
+msgid "`while' COMMANDS has an exit status of zero."
+msgstr ""
+
+#: builtins.c:1186
+msgid "`until' COMMANDS has an exit status which is not zero."
+msgstr ""
+
+#: builtins.c:1192
+msgid "Create a simple command invoked by NAME which runs COMMANDS."
+msgstr ""
+
+#: builtins.c:1193
+msgid "Arguments on the command line along with NAME are passed to the"
+msgstr ""
+
+#: builtins.c:1194
+msgid "function as $0 .. $n."
+msgstr ""
+
+#: builtins.c:1200
+msgid "Run a set of commands in a group.  This is one way to redirect an"
+msgstr ""
+
+#: builtins.c:1201
+msgid "entire set of commands."
+msgstr ""
+
+#: builtins.c:1207
+msgid "This is similar to the `fg' command.  Resume a stopped or background"
+msgstr ""
+
+#: builtins.c:1208
+msgid "job.  If you specifiy DIGITS, then that job is used.  If you specify"
+msgstr ""
+
+#: builtins.c:1209
+msgid "WORD, then the job whose name begins with WORD is used.  Following the"
+msgstr ""
+
+#: builtins.c:1210
+msgid "job specification with a `&' places the job in the background."
+msgstr ""
+
+#: builtins.c:1216
+msgid "The EXPRESSION is evaluated according to the rules for arithmetic"
+msgstr ""
+
+#: builtins.c:1217
+msgid "evaluation.  Equivalent to \"let EXPRESSION\"."
+msgstr ""
+
+#: builtins.c:1223
+msgid ""
+"Returns a status of 0 or 1 depending on the evaluation of the conditional"
+msgstr ""
+
+#: builtins.c:1224
+msgid ""
+"expression EXPRESSION.  Expressions are composed of the same primaries used"
+msgstr ""
+
+#: builtins.c:1225
+msgid ""
+"by the `test' builtin, and may be combined using the following operators"
+msgstr ""
+
+#: builtins.c:1227
+msgid "\t( EXPRESSION )\tReturns the value of EXPRESSION"
+msgstr ""
+
+#: builtins.c:1228
+msgid "\t! EXPRESSION\tTrue if EXPRESSION is false; else false"
+msgstr ""
+
+#: builtins.c:1229
+msgid "\tEXPR1 && EXPR2\tTrue if both EXPR1 and EXPR2 are true; else false"
+msgstr ""
+
+#: builtins.c:1230
+msgid "\tEXPR1 || EXPR2\tTrue if either EXPR1 or EXPR2 is true; else false"
+msgstr ""
+
+#: builtins.c:1232
+msgid ""
+"When the `==' and `!=' operators are used, the string to the right of the"
+msgstr ""
+
+#: builtins.c:1233
+msgid "operator is used as a pattern and pattern matching is performed.  The"
+msgstr ""
+
+#: builtins.c:1234
+msgid "&& and || operators do not evaluate EXPR2 if EXPR1 is sufficient to"
+msgstr ""
+
+#: builtins.c:1235
+msgid "determine the expression's value."
+msgstr ""
+
+#: builtins.c:1241
+msgid "BASH_VERSION    Version information for this Bash."
+msgstr ""
+
+#: builtins.c:1242
+msgid "CDPATH          A colon separated list of directories to search"
+msgstr ""
+
+#: builtins.c:1243
+msgid "\t\twhen the argument to `cd' is not found in the current"
+msgstr ""
+
+#: builtins.c:1244
+msgid "\t\tdirectory."
+msgstr ""
+
+#: builtins.c:1245
+msgid "GLOBIGNORE\tA colon-separated list of patterns describing filenames to"
+msgstr ""
+
+#: builtins.c:1246
+msgid "\t\tbe ignored by pathname expansion."
+msgstr ""
+
+#: builtins.c:1248
+msgid ""
+"HISTFILE        The name of the file where your command history is stored."
+msgstr ""
+
+#: builtins.c:1249
+msgid "HISTFILESIZE    The maximum number of lines this file can contain."
+msgstr ""
+
+#: builtins.c:1250
+msgid "HISTSIZE        The maximum number of history lines that a running"
+msgstr ""
+
+#: builtins.c:1251
+msgid "\t\tshell can access."
+msgstr ""
+
+#: builtins.c:1253
+msgid "HOME            The complete pathname to your login directory."
+msgstr ""
+
+#: builtins.c:1254
+msgid "HOSTNAME\tThe name of the current host."
+msgstr ""
+
+#: builtins.c:1255
+msgid "HOSTTYPE        The type of CPU this version of Bash is running under."
+msgstr ""
+
+#: builtins.c:1256
+msgid "IGNOREEOF       Controls the action of the shell on receipt of an EOF"
+msgstr ""
+
+#: builtins.c:1257
+msgid "\t\tcharacter as the sole input.  If set, then the value"
+msgstr ""
+
+#: builtins.c:1258
+msgid "\t\tof it is the number of EOF characters that can be seen"
+msgstr ""
+
+#: builtins.c:1259
+msgid "\t\tin a row on an empty line before the shell will exit"
+msgstr ""
+
+#: builtins.c:1260
+msgid "\t\t(default 10).  When unset, EOF signifies the end of input."
+msgstr ""
+
+#: builtins.c:1261
+msgid "MACHTYPE\tA string describing the current system Bash is running on."
+msgstr ""
+
+#: builtins.c:1262
+msgid "MAILCHECK\tHow often, in seconds, Bash checks for new mail."
+msgstr ""
+
+#: builtins.c:1263
+msgid "MAILPATH\tA colon-separated list of filenames which Bash checks"
+msgstr ""
+
+#: builtins.c:1264
+msgid "\t\tfor new mail."
+msgstr ""
+
+#: builtins.c:1265
+msgid "OSTYPE\t\tThe version of Unix this version of Bash is running on."
+msgstr ""
+
+#: builtins.c:1266
+msgid "PATH            A colon-separated list of directories to search when"
+msgstr ""
+
+#: builtins.c:1267
+msgid "\t\tlooking for commands."
+msgstr ""
+
+#: builtins.c:1268
+msgid "PROMPT_COMMAND  A command to be executed before the printing of each"
+msgstr ""
+
+#: builtins.c:1269
+msgid "\t\tprimary prompt."
+msgstr ""
+
+#: builtins.c:1270
+msgid "PS1             The primary prompt string."
+msgstr ""
+
+#: builtins.c:1271
+msgid "PS2             The secondary prompt string."
+msgstr ""
+
+#: builtins.c:1272
+msgid "PWD\t\tThe full pathname of the current directory."
+msgstr ""
+
+#: builtins.c:1273
+msgid "SHELLOPTS\tA colon-separated list of enabled shell options."
+msgstr ""
+
+#: builtins.c:1274
+msgid "TERM            The name of the current terminal type."
+msgstr ""
+
+#: builtins.c:1275
+msgid "TIMEFORMAT\tThe output format for timing statistics displayed by the"
+msgstr ""
+
+#: builtins.c:1276
+msgid "\t\t`time' reserved word."
+msgstr ""
+
+#: builtins.c:1277
+msgid "auto_resume     Non-null means a command word appearing on a line by"
+msgstr ""
+
+#: builtins.c:1278
+msgid "\t\titself is first looked for in the list of currently"
+msgstr ""
+
+#: builtins.c:1279
+msgid "\t\tstopped jobs.  If found there, that job is foregrounded."
+msgstr ""
+
+#: builtins.c:1280
+msgid "\t\tA value of `exact' means that the command word must"
+msgstr ""
+
+#: builtins.c:1281
+msgid "\t\texactly match a command in the list of stopped jobs.  A"
+msgstr ""
+
+#: builtins.c:1282
+msgid "\t\tvalue of `substring' means that the command word must"
+msgstr ""
+
+#: builtins.c:1283
+msgid "\t\tmatch a substring of the job.  Any other value means that"
+msgstr ""
+
+#: builtins.c:1284
+msgid "\t\tthe command must be a prefix of a stopped job."
+msgstr ""
+
+#: builtins.c:1287
+msgid "histchars       Characters controlling history expansion and quick"
+msgstr ""
+
+#: builtins.c:1288
+msgid "\t\tsubstitution.  The first character is the history"
+msgstr ""
+
+#: builtins.c:1289
+msgid "\t\tsubstitution character, usually `!'.  The second is"
+msgstr ""
+
+#: builtins.c:1290
+msgid "\t\tthe `quick substitution' character, usually `^'.  The"
+msgstr ""
+
+#: builtins.c:1291
+msgid "\t\tthird is the `history comment' character, usually `#'."
+msgstr ""
+
+#: builtins.c:1293
+msgid "HISTIGNORE\tA colon-separated list of patterns used to decide which"
+msgstr ""
+
+#: builtins.c:1294
+msgid "\t\tcommands should be saved on the history list."
+msgstr ""
+
+#: builtins.c:1306
+msgid "+N\tRotates the stack so that the Nth directory (counting"
+msgstr ""
+
+#: builtins.c:1307
+msgid "\tfrom the left of the list shown by `dirs', starting with"
+msgstr ""
+
+#: builtins.c:1308 builtins.c:1312
+msgid "\tzero) is at the top."
+msgstr ""
+
+#: builtins.c:1310
+msgid "-N\tRotates the stack so that the Nth directory (counting"
+msgstr ""
+
+#: builtins.c:1311
+msgid "\tfrom the right of the list shown by `dirs', starting with"
+msgstr ""
+
+#: builtins.c:1314
+msgid "-n\tsuppress the normal change of directory when adding directories"
+msgstr ""
+
+#: builtins.c:1315
+msgid "\tto the stack, so only the stack is manipulated."
+msgstr ""
+
+#: builtins.c:1317
+msgid "dir\tadds DIR to the directory stack at the top, making it the"
+msgstr ""
+
+#: builtins.c:1318
+msgid "\tnew current working directory."
+msgstr ""
+
+#: builtins.c:1332
+msgid "+N\tremoves the Nth entry counting from the left of the list"
+msgstr ""
+
+#: builtins.c:1333
+msgid "\tshown by `dirs', starting with zero.  For example: `popd +0'"
+msgstr ""
+
+#: builtins.c:1334
+msgid "\tremoves the first directory, `popd +1' the second."
+msgstr ""
+
+#: builtins.c:1336
+msgid "-N\tremoves the Nth entry counting from the right of the list"
+msgstr ""
+
+#: builtins.c:1337
+msgid "\tshown by `dirs', starting with zero.  For example: `popd -0'"
+msgstr ""
+
+#: builtins.c:1338
+msgid "\tremoves the last directory, `popd -1' the next to last."
+msgstr ""
+
+#: builtins.c:1340
+msgid "-n\tsuppress the normal change of directory when removing directories"
+msgstr ""
+
+#: builtins.c:1341
+msgid "\tfrom the stack, so only the stack is manipulated."
+msgstr ""
+
+#: builtins.c:1363
+msgid "+N\tdisplays the Nth entry counting from the left of the list shown by"
+msgstr ""
+
+#: builtins.c:1364 builtins.c:1367
+msgid "\tdirs when invoked without options, starting with zero."
+msgstr ""
+
+#: builtins.c:1366
+msgid "-N\tdisplays the Nth entry counting from the right of the list shown by"
+msgstr ""
+
+#: builtins.c:1374
+msgid "Toggle the values of variables controlling optional behavior."
+msgstr ""
+
+#: builtins.c:1375
+msgid "The -s flag means to enable (set) each OPTNAME; the -u flag"
+msgstr ""
+
+#: builtins.c:1376
+msgid "unsets each OPTNAME.  The -q flag suppresses output; the exit"
+msgstr ""
+
+#: builtins.c:1377
+msgid "status indicates whether each OPTNAME is set or unset.  The -o"
+msgstr ""
+
+#: builtins.c:1378
+msgid "option restricts the OPTNAMEs to those defined for use with"
+msgstr ""
+
+#: builtins.c:1379
+msgid "`set -o'.  With no options, or with the -p option, a list of all"
+msgstr ""
+
+#: builtins.c:1380
+msgid "settable options is displayed, with an indication of whether or"
+msgstr ""
+
+#: builtins.c:1381
+msgid "not each is set."
+msgstr ""
+
+#: builtins.c:1387
+msgid "printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT"
+msgstr ""
+
+#: builtins.c:1388
+msgid "is a character string which contains three types of objects: plain"
+msgstr ""
+
+#: builtins.c:1389
+msgid ""
+"characters, which are simply copied to standard output, character escape"
+msgstr ""
+
+#: builtins.c:1390
+msgid "sequences which are converted and copied to the standard output, and"
+msgstr ""
+
+#: builtins.c:1391
+msgid ""
+"format specifications, each of which causes printing of the next successive"
+msgstr ""
+
+#: builtins.c:1392
+msgid "argument.  In addition to the standard printf(1) formats, %b means to"
+msgstr ""
+
+#: builtins.c:1393
+msgid "expand backslash escape sequences in the corresponding argument, and %q"
+msgstr ""
+
+#: builtins.c:1394
+msgid "means to quote the argument in a way that can be reused as shell input."
+msgstr ""
+
+#: builtins.c:1401
+msgid "For each NAME, specify how arguments are to be completed."
+msgstr ""
+
+#: builtins.c:1402
+msgid "If the -p option is supplied, or if no options are supplied, existing"
+msgstr ""
+
+#: builtins.c:1403
+msgid "completion specifications are printed in a way that allows them to be"
+msgstr ""
+
+#: builtins.c:1404
+msgid "reused as input.  The -r option removes a completion specification for"
+msgstr ""
+
+#: builtins.c:1405
+msgid "each NAME, or, if no NAMEs are supplied, all completion specifications."
+msgstr ""
+
+#: builtins.c:1413
+msgid "Display the possible completions depending on the options.  Intended"
+msgstr ""
+
+#: builtins.c:1414
+msgid ""
+"to be used from within a shell function generating possible completions."
+msgstr ""
+
+#: builtins.c:1415
+msgid "If the optional WORD argument is supplied, matches against WORD are"
+msgstr ""
+
+#: builtins.c:1416
+msgid "generated."
+msgstr ""
index 29918c8..bdb36c1 100644 (file)
@@ -92,6 +92,11 @@ msgstr "no closing â€˜\e[1m%c\e[0m’ in %s"
 msgid "%s: missing colon separator"
 msgstr "%s: missing colon separator"
 
+#: builtins/alias.def:123
+#, fuzzy, c-format
+msgid "`%s': invalid alias name"
+msgstr "‘\e[1m%s\e[0m’: invalid keymap name"
+
 #: builtins/bind.def:194
 #, c-format
 msgid "`%s': invalid keymap name"
index eaa316c..3dff8f6 100644 (file)
@@ -89,6 +89,11 @@ msgstr "no closing â€˜%c’ in %s"
 msgid "%s: missing colon separator"
 msgstr "%s: missing colon separator"
 
+#: builtins/alias.def:123
+#, fuzzy, c-format
+msgid "`%s': invalid alias name"
+msgstr "‘%s’: invalid keymap name"
+
 #: builtins/bind.def:194
 #, c-format
 msgid "`%s': invalid keymap name"
diff --git a/subst.c b/subst.c
index e33a1dd..457b13e 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -2178,7 +2178,18 @@ pos_params (string, start, end, quoted)
 
   t->next = (WORD_LIST *)NULL;
   if (string[0] == '*')
+#if 0
     ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (quote_list (h)) : string_list (h);
+#else
+    {
+      if (quoted & Q_DOUBLE_QUOTES)
+       ret = string_list_dollar_star (quote_list (h));
+      else if (quoted & Q_HERE_DOCUMENT)
+       ret = string_list (quote_list (h));
+      else
+       ret = string_list (h);
+    }
+#endif
   else
     ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
   if (t != params)
@@ -3457,7 +3468,11 @@ list_remove_pattern (list, pattern, patspec, itype, quoted)
 
   l = REVERSE_LIST (new, WORD_LIST *);
   if (itype == '*')
+#if 0
     tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
+#else
+    tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
+#endif
   else
     tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
 
@@ -5835,7 +5850,11 @@ param_expand (string, sindex, quoted, expanded_something,
             quote the whole string, including the separators.  If IFS
             is unset, the parameters are separated by ' '; if $IFS is
             null, the parameters are concatenated. */
+#if 0
          temp = string_list_dollar_star (list);
+#else
+         temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
+#endif
          temp1 = quote_string (temp);
          free (temp);
          temp = temp1;
index 2c6a85d..e33a1dd 100644 (file)
@@ -210,8 +210,23 @@ static char *extract_dollar_brace_string __P((char *, int *, int, int));
 
 static char *pos_params __P((char *, int, int, int));
 
+static unsigned char *mb_getcharlens __P((char *, int));
+
+static char *remove_upattern __P((char *, char *, int));
+#if defined (HANDLE_MULTIBYTE)
+#  if !defined (HAVE_WCSDUP)
+static wchar_t *wcsdup __P((wchar_t *));
+#  endif
+static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
+#endif
 static char *remove_pattern __P((char *, char *, int));
+
 static int match_pattern_char __P((char *, char *));
+static int match_upattern __P((char *, char *, int, char **, char **));
+#if defined (HANDLE_MULTIBYTE)
+static int match_pattern_wchar __P((wchar_t *, wchar_t *));
+static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
+#endif
 static int match_pattern __P((char *, char *, int, char **, char **));
 static int getpatspec __P((int, char *));
 static char *getpattern __P((char *, int, int));
@@ -244,7 +259,8 @@ static intmax_t parameter_brace_expand_length __P((char *));
 
 static char *skiparith __P((char *, int));
 static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
-static int get_var_and_type __P((char *, char *, SHELL_VAR **, char **));
+static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
+static char *mb_substring __P((char *, int, int));
 static char *parameter_brace_substring __P((char *, char *, char *, int));
 
 static char *pos_params_pat_subst __P((char *, char *, char *, int));
@@ -1168,9 +1184,9 @@ de_backslash (string)
       prev_i = i;
       ADVANCE_CHAR (string, slen, i);
       if (j < prev_i)
-        do string[j++] = string[prev_i++]; while (prev_i < i);
+       do string[j++] = string[prev_i++]; while (prev_i < i);
       else
-        j = i;
+       j = i;
     }
   string[j] = '\0';
 
@@ -1562,6 +1578,10 @@ string_list_internal (list, sep)
   if (list == 0)
     return ((char *)NULL);
 
+  /* Short-circuit quickly if we don't need to separate anything. */
+  if (list->next == 0)
+    return (savestring (list->word->word));
+
   /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
   sep_len = STRLEN (sep);
   result_size = 0;
@@ -1957,8 +1977,9 @@ do_assignment_internal (string, expand)
   SHELL_VAR *entry;
 #if defined (ARRAY_VARS)
   char *t;
-  int ni, assign_list = 0;
+  int ni;
 #endif
+  int assign_list = 0;
 
   offset = assignment (string, 0);
   name = savestring (string);
@@ -2001,14 +2022,7 @@ do_assignment_internal (string, expand)
     }
 
   if (echo_command_at_execute)
-    {
-#if defined (ARRAY_VARS)
-      if (assign_list)
-       fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
-      else
-#endif
-      fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
-    }
+     xtrace_print_assignment (name, value, assign_list, 1);
 
 #define ASSIGN_RETURN(r)       do { FREE (value); free (name); return (r); } while (0)
 
@@ -2792,17 +2806,17 @@ remove_quoted_nulls (string)
   while (i < slen)
     {
       if (string[i] == CTLESC)
-        {
+       {
          /* Old code had j++, but we cannot assume that i == j at this
             point -- what if a CTLNUL has already been removed from the
             string?  We don't want to drop the CTLESC or recopy characters
             that we've already copied down. */
          i++; string[j++] = CTLESC;
-          if (i == slen)
-            break;
-        }
+         if (i == slen)
+           break;
+       }
       else if (string[i] == CTLNUL)
-        i++;
+       i++;
 
       prev_i = i;
       ADVANCE_CHAR (string, slen, i);
@@ -2836,6 +2850,33 @@ word_list_remove_quoted_nulls (list)
 /*                                                                 */
 /* **************************************************************** */
 
+#if defined (HANDLE_MULTIBYTE)
+#if 0 /* Currently unused */
+static unsigned char *
+mb_getcharlens (string, len)
+     char *string;
+     int len;
+{
+  int i, offset, last;
+  unsigned char *ret;
+  char *p;
+  DECLARE_MBSTATE;
+
+  i = offset = 0;
+  last = 0;
+  ret = (unsigned char *)xmalloc (len);
+  memset (ret, 0, len);
+  while (string[last])
+    {
+      ADVANCE_CHAR (string, len, offset);
+      ret[last] = offset - last;
+      last = offset;
+    }
+  return ret;
+}
+#endif
+#endif
+
 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
    can have one of 4 values:
        RP_LONG_LEFT    remove longest matching portion at start of PARAM
@@ -2850,7 +2891,7 @@ word_list_remove_quoted_nulls (list)
 #define RP_SHORT_RIGHT 4
 
 static char *
-remove_pattern (param, pattern, op)
+remove_upattern (param, pattern, op)
      char *param, *pattern;
      int op;
 {
@@ -2858,18 +2899,12 @@ remove_pattern (param, pattern, op)
   register char *end;
   register char *p, *ret, c;
 
-  if (param == NULL)
-    return (param);
-  if (*param == '\0' || pattern == NULL || *pattern == '\0')   /* minor optimization */
-    return (savestring (param));
-
   len = STRLEN (param);
   end = param + len;
 
   switch (op)
     {
       case RP_LONG_LEFT:       /* remove longest match at start */
-        /* BACKUP_CHAR_P (param, len, p); */
        for (p = end; p >= param; p--)
          {
            c = *p; *p = '\0';
@@ -2879,11 +2914,11 @@ remove_pattern (param, pattern, op)
                return (savestring (p));
              }
            *p = c;
+
          }
        break;
 
       case RP_SHORT_LEFT:      /* remove shortest match at start */
-        /* ADVANCE_CHAR_P (p, end - p),p++ */
        for (p = param; p <= end; p++)
          {
            c = *p; *p = '\0';
@@ -2897,7 +2932,6 @@ remove_pattern (param, pattern, op)
        break;
 
       case RP_LONG_RIGHT:      /* remove longest match at end */
-        /* ADVANCE_CHAR_P (p, end - p),p++ */
        for (p = param; p <= end; p++)
          {
            if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
@@ -2911,7 +2945,6 @@ remove_pattern (param, pattern, op)
        break;
 
       case RP_SHORT_RIGHT:     /* remove shortest match at end */
-        /* BACKUP_CHAR_P (param, len, p); */
        for (p = end; p >= param; p--)
          {
            if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
@@ -2924,9 +2957,144 @@ remove_pattern (param, pattern, op)
          }
        break;
     }
+
   return (savestring (param)); /* no match, return original string */
 }
 
+#if defined (HANDLE_MULTIBYTE)
+
+#if !defined (HAVE_WCSDUP)
+static wchar_t *
+wcsdup (ws)
+     wchar_t *ws;
+{
+  wchar_t *ret;
+  size_t len;
+
+  len = wcslen (ws);
+  ret = xmalloc ((len + 1) * sizeof (wchar_t));
+  if (ret == 0)
+    return ret;
+  return (wcscpy (ret, ws));
+}
+#endif /* !HAVE_WCSDUP */
+
+static wchar_t *
+remove_wpattern (wparam, wstrlen, wpattern, op)
+     wchar_t *wparam;
+     size_t wstrlen;
+     wchar_t *wpattern;
+     int op;
+{
+  wchar_t wc;
+  int n, n1;
+  wchar_t *ret;
+
+  switch (op)
+    {
+      case RP_LONG_LEFT:       /* remove longest match at start */
+        for (n = wstrlen; n >= 0; n--)
+         {
+           wc = wparam[n]; wparam[n] = L'\0';
+           if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+             {
+               wparam[n] = wc;
+               return (wcsdup (wparam + n));
+             }
+           wparam[n] = wc;
+         }
+       break;
+
+      case RP_SHORT_LEFT:      /* remove shortest match at start */
+       for (n = 0; n <= wstrlen; n++)
+         {
+           wc = wparam[n]; wparam[n] = L'\0';
+           if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+             {
+               wparam[n] = wc;
+               return (wcsdup (wparam + n));
+             }
+           wparam[n] = wc;
+         }
+       break;
+
+      case RP_LONG_RIGHT:      /* remove longest match at end */
+        for (n = 0; n <= wstrlen; n++)
+         {
+           if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+             {
+               wc = wparam[n]; wparam[n] = L'\0';
+               ret = wcsdup (wparam);
+               wparam[n] = wc;
+               return (ret);
+             }
+         }
+       break;
+
+      case RP_SHORT_RIGHT:     /* remove shortest match at end */
+       for (n = wstrlen; n >= 0; n--)
+         {
+           if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+             {
+               wc = wparam[n]; wparam[n] = L'\0';
+               ret = wcsdup (wparam);
+               wparam[n] = wc;
+               return (ret);
+             }
+         }
+       break;
+    }
+
+  return (wcsdup (wparam));    /* no match, return original string */
+}
+#endif /* HANDLE_MULTIBYTE */
+
+static char *
+remove_pattern (param, pattern, op)
+     char *param, *pattern;
+     int op;
+{
+  if (param == NULL)
+    return (param);
+  if (*param == '\0' || pattern == NULL || *pattern == '\0')   /* minor optimization */
+    return (savestring (param));
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1)
+    {
+      wchar_t *ret, *oret;
+      size_t n;
+      wchar_t *wparam, *wpattern;
+      mbstate_t ps;
+      char *xret;
+
+      n = xdupmbstowcs (&wpattern, NULL, pattern);
+      if (n == (size_t)-1)
+       return (remove_upattern (param, pattern, op));
+      n = xdupmbstowcs (&wparam, NULL, param);
+      if (n == (size_t)-1)
+       {
+         free (wpattern);
+         return (remove_upattern (param, pattern, op));
+       }
+      oret = ret = remove_wpattern (wparam, n, wpattern, op);
+
+      free (wparam);
+      free (wpattern);
+
+      n = strlen (param);
+      xret = xmalloc (n + 1);
+      memset (&ps, '\0', sizeof (mbstate_t));
+      n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
+      xret[n] = '\0';          /* just to make sure */
+      free (oret);
+      return xret;      
+    }
+  else
+#endif
+    return (remove_upattern (param, pattern, op));
+}
+
 /* Return 1 of the first character of STRING could match the first
    character of pattern PAT.  Used to avoid n2 calls to strmatch(). */
 static int
@@ -2964,7 +3132,7 @@ match_pattern_char (pat, string)
    MATCH_BEG and MATCH_END anchor the match at the beginning and end
    of the string, respectively.  The longest match is returned. */
 static int
-match_pattern (string, pat, mtype, sp, ep)
+match_upattern (string, pat, mtype, sp, ep)
      char *string, *pat;
      int mtype;
      char **sp, **ep;
@@ -2973,21 +3141,16 @@ match_pattern (string, pat, mtype, sp, ep)
   register char *p, *p1;
   char *end;
 
-  if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
-    return (0);
-
   len = STRLEN (string);
   end = string + len;
 
   switch (mtype)
     {
     case MATCH_ANY:
-      /* ADVANCE_CHAR_P (p, end - p),p++ */
       for (p = string; p <= end; p++)
        {
          if (match_pattern_char (pat, p))
            {
-             /* BACKUP_CHAR_P (p, end - p, p1) */
              for (p1 = end; p1 >= p; p1--)
                {
                  c = *p1; *p1 = '\0';
@@ -3002,12 +3165,13 @@ match_pattern (string, pat, mtype, sp, ep)
                }
            }
        }
+
       return (0);
 
     case MATCH_BEG:
       if (match_pattern_char (pat, string) == 0)
        return (0);
-      /* BACKUP_CHAR_P (string, len, p) */
+
       for (p = end; p >= string; p--)
        {
          c = *p; *p = '\0';
@@ -3020,22 +3184,179 @@ match_pattern (string, pat, mtype, sp, ep)
            }
          *p = c;
        }
+
       return (0);
 
     case MATCH_END:
-      /* ADVANCE_CHAR_P(p, end - p), p++ */
       for (p = string; p <= end; p++)
-       if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
-         {
-           *sp = p;
-           *ep = end;
-           return 1;
-         }
+       {
+         if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
+           {
+             *sp = p;
+             *ep = end;
+             return 1;
+           }
+
+       }
+
+      return (0);
+    }
+
+  return (0);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Return 1 of the first character of WSTRING could match the first
+   character of pattern WPAT.  Wide character version. */
+static int
+match_pattern_wchar (wpat, wstring)
+     wchar_t *wpat, *wstring;
+{
+  wchar_t wc;
+
+  if (*wstring == 0)
+    return (0);
+
+  switch (wc = *wpat++)
+    {
+    default:
+      return (*wstring == wc);
+    case L'\\':
+      return (*wstring == *wpat);
+    case L'?':
+      return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
+    case L'*':
+      return (1);
+    case L'+':
+    case L'!':
+    case L'@':
+      return (*wpat == LPAREN ? 1 : (*wstring == wc));
+    case L'[':
+      return (*wstring != L'\0');
+    }
+}
+
+/* Match WPAT anywhere in WSTRING and return the match boundaries.
+   This returns 1 in case of a successful match, 0 otherwise.  Wide
+   character version. */
+static int
+match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
+     wchar_t *wstring;
+     char **indices;
+     size_t wstrlen;
+     wchar_t *wpat;
+     int mtype;
+     char **sp, **ep;
+{
+  wchar_t wc;
+  int len;
+#if 0
+  size_t n, n1;        /* Apple's gcc seems to miscompile this badly */
+#else
+  int n, n1;
+#endif
+
+  switch (mtype)
+    {
+    case MATCH_ANY:
+      for (n = 0; n <= wstrlen; n++)
+       {
+         if (match_pattern_wchar (wpat, wstring + n))
+           {
+             for (n1 = wstrlen; n1 >= n; n1--)
+               {
+                 wc = wstring[n1]; wstring[n1] = L'\0';
+                 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
+                   {
+                     wstring[n1] = wc;
+                     *sp = indices[n];
+                     *ep = indices[n1];
+                     return 1;
+                   }
+                 wstring[n1] = wc;
+               }
+           }
+       }
+
+      return (0);
+
+    case MATCH_BEG:
+      if (match_pattern_wchar (wpat, wstring) == 0)
+       return (0);
+
+      for (n = wstrlen; n >= 0; n--)
+       {
+         wc = wstring[n]; wstring[n] = L'\0';
+         if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
+           {
+             wstring[n] = wc;
+             *sp = indices[0];
+             *ep = indices[n];
+             return 1;
+           }
+         wstring[n] = wc;
+       }
+
+      return (0);
+
+    case MATCH_END:
+      for (n = 0; n <= wstrlen; n++)
+       {
+         if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
+           {
+             *sp = indices[n];
+             *ep = indices[wstrlen];
+             return 1;
+           }
+       }
+
       return (0);
     }
 
   return (0);
 }
+#endif /* HANDLE_MULTIBYTE */
+
+static int
+match_pattern (string, pat, mtype, sp, ep)
+     char *string, *pat;
+     int mtype;
+     char **sp, **ep;
+{
+#if defined (HANDLE_MULTIBYTE)
+  int ret;
+  size_t n;
+  wchar_t *wstring, *wpat;
+  char **indices;
+#endif
+
+  if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
+    return (0);
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1)
+    {
+      n = xdupmbstowcs (&wpat, NULL, pat);
+      if (n == (size_t)-1)
+       return (match_upattern (string, pat, mtype, sp, ep));
+      n = xdupmbstowcs (&wstring, &indices, string);
+      if (n == (size_t)-1)
+       {
+         free (wpat);
+         return (match_upattern (string, pat, mtype, sp, ep));
+       }
+      ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
+
+      free (wpat);
+      free (wstring);
+      free (indices);
+
+      return (ret);
+    }
+  else
+#endif
+    return (match_upattern (string, pat, mtype, sp, ep));
+}
 
 static int
 getpatspec (c, value)
@@ -3203,7 +3524,7 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
 
   this_command_name = varname;
 
-  vtype = get_var_and_type (varname, value, &v, &val);
+  vtype = get_var_and_type (varname, value, quoted, &v, &val);
   if (vtype == -1)
     return ((char *)NULL);
 
@@ -4119,7 +4440,12 @@ parameter_brace_expand_word (name, var_is_special, quoted)
   if (legal_number (name, &arg_index))
     {
       tt = get_dollar_var_value (arg_index);
-      temp = tt ? quote_escapes (tt) : (char *)NULL;
+      if (tt)
+       temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+                 ? quote_string (tt)
+                 : quote_escapes (tt);
+      else
+        temp = (char *)NULL;
       FREE (tt);
     }
   else if (var_is_special)      /* ${@} */
@@ -4138,7 +4464,9 @@ parameter_brace_expand_word (name, var_is_special, quoted)
     {
       temp = array_value (name, quoted, &atype);
       if (atype == 0 && temp)
-       temp = quote_escapes (temp);
+       temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+                 ? quote_string (temp)
+                 : quote_escapes (temp);
     }
 #endif
   else if (var = find_variable (name))
@@ -4152,7 +4480,9 @@ parameter_brace_expand_word (name, var_is_special, quoted)
 #endif
 
          if (temp)
-           temp = quote_escapes (temp);
+           temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+                     ? quote_string (temp)
+                     : quote_escapes (temp);
        }
       else
        temp = (char *)NULL;
@@ -4174,6 +4504,15 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
   char *temp, *t;
 
   t = parameter_brace_expand_word (name, var_is_special, quoted);
+  /* Have to dequote here if necessary */
+  if (t)
+    {
+      temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+               ? dequote_string (t)
+               : dequote_escapes (t);
+      free (t);
+      t = temp;
+    }
   chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
   if (t == 0)
     return (t);
@@ -4224,11 +4563,16 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
   if (l)
     {
       /* The expansion of TEMP returned something.  We need to treat things
-         slightly differently if HASDOL is non-zero. */
-      temp = string_list (l);
+         slightly differently if HASDOL is non-zero.  If we have "$@", the
+         individual words have already been quoted.  We need to turn them
+         into a string with the words separated by the first character of
+         $IFS without any additional quoting, so string_list_dollar_at won't
+         do the right thing.  We use string_list_dollar_star instead. */
+      temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
+
       /* If l->next is not null, we know that TEMP contained "$@", since that
         is the only expansion that creates more than one word. */
-      if ((hasdol && quoted) || l->next)
+      if (qdollaratp && ((hasdol && quoted) || l->next))
        *qdollaratp = 1;
       dispose_words (l);
     }
@@ -4563,8 +4907,9 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
    characters in the value are quoted with CTLESC and takes appropriate
    steps.  For convenience, *VALP is set to the dequoted VALUE. */
 static int
-get_var_and_type (varname, value, varp, valp)
+get_var_and_type (varname, value, quoted, varp, valp)
      char *varname, *value;
+     int quoted;
      SHELL_VAR **varp;
      char **valp;
 {
@@ -4611,7 +4956,21 @@ get_var_and_type (varname, value, varp, valp)
     }
   else
 #endif
+#if 1
+    {
+      if (value && vtype == VT_VARIABLE)
+       {
+         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+           *valp = dequote_string (value);
+         else
+           *valp = dequote_escapes (value);
+       }
+      else
+       *valp = value;
+    }
+#else
   *valp = (value && vtype == VT_VARIABLE) ? dequote_escapes (value) : value;
+#endif
 
   return vtype;
 }
@@ -4622,6 +4981,35 @@ get_var_and_type (varname, value, varp, valp)
 /*                                                   */
 /******************************************************/
 
+#if defined (HANDLE_MULTIBYTE)
+/* Character-oriented rather than strictly byte-oriented substrings.  S and
+   E, rather being strict indices into STRING, indicate character (possibly
+   multibyte character) positions that require calculation.
+   Used by the ${param:offset[:length]} expansion. */
+static char *
+mb_substring (string, s, e)
+     char *string;
+     int s, e;
+{
+  char *tt;
+  int start, stop, i, slen;
+  DECLARE_MBSTATE;
+
+  start = 0;
+  slen = STRLEN (string);
+
+  i = s;
+  while (string[start] && i--)
+    ADVANCE_CHAR (string, slen, start);
+  stop = start;
+  i = e - s;
+  while (string[stop] && i--)
+    ADVANCE_CHAR (string, slen, stop);
+  tt = substring (string, start, stop);
+  return tt;
+}
+#endif
+  
 /* Process a variable substring expansion: ${name:e1[:e2]}.  If VARNAME
    is `@', use the positional parameters; otherwise, use the value of
    VARNAME.  If VARNAME is an array variable, use the array elements. */
@@ -4641,7 +5029,7 @@ parameter_brace_substring (varname, value, substr, quoted)
 
   this_command_name = varname;
 
-  vtype = get_var_and_type (varname, value, &v, &val);
+  vtype = get_var_and_type (varname, value, quoted, &v, &val);
   if (vtype == -1)
     return ((char *)NULL);
 
@@ -4656,7 +5044,13 @@ parameter_brace_substring (varname, value, substr, quoted)
     {
     case VT_VARIABLE:
     case VT_ARRAYMEMBER:
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1)
+       tt = mb_substring (val, e1, e2);
+      else
+#endif
       tt = substring (val, e1, e2);
+
       if (vtype == VT_VARIABLE)
        FREE (val);
       if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
@@ -4678,8 +5072,8 @@ parameter_brace_substring (varname, value, substr, quoted)
 #if defined (ARRAY_VARS)
     case VT_ARRAYVAR:
       /* We want E2 to be the number of elements desired (arrays can be sparse,
-         so verify_substring_values just returns the numbers specified and we
-         rely on array_subrange to understand how to deal with them). */
+        so verify_substring_values just returns the numbers specified and we
+        rely on array_subrange to understand how to deal with them). */
       tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
       if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
        {
@@ -4834,7 +5228,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
 
   this_command_name = varname;
 
-  vtype = get_var_and_type (varname, value, &v, &val);
+  vtype = get_var_and_type (varname, value, quoted, &v, &val);
   if (vtype == -1)
     return ((char *)NULL);
 
@@ -5369,7 +5763,16 @@ param_expand (string, sindex, quoted, expanded_something,
          last_command_exit_value = EXECUTION_FAILURE;
          return (interactive_shell ? &expand_param_error : &expand_param_fatal);
        }
+#if 1
+      if (temp1)
+       temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+                 ? quote_string (temp1)
+                 : quote_escapes (temp1);
+      else
+       temp = (char *)NULL;
+#else
       temp = temp1 ? quote_escapes (temp1) : (char *)NULL;
+#endif
       break;
 
     /* $$ -- pid of the invoking shell. */
@@ -5606,11 +6009,22 @@ comsub:
            {
              temp = array_reference (array_cell (var), 0);
              if (temp)
-               temp = quote_escapes (temp);
+               temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+                         ? quote_string (temp)
+                         : quote_escapes (temp);
+             else if (unbound_vars_is_error)
+               goto unbound_variable;
            }
          else
 #endif
-         temp = quote_escapes (value_cell (var));
+           {
+             temp = value_cell (var);
+
+             temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+                       ? quote_string (temp)
+                       : quote_escapes (temp);
+           }
+
          free (temp1);
 
          goto return0;
@@ -5618,6 +6032,7 @@ comsub:
 
       temp = (char *)NULL;
 
+unbound_variable:
       if (unbound_vars_is_error)
        err_unboundvar (temp1);
       else
@@ -5747,26 +6162,7 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
 #if HANDLE_MULTIBYTE
          if (MB_CUR_MAX > 1 && string[sindex])
            {
-             int i;
-             mbstate_t state_bak;
-             size_t mblength;
-
-             state_bak = state;
-             mblength = mbrlen (string + sindex, string_size - sindex, &state);
-             if (MB_INVALIDCH (mblength))
-               {
-                 state = state_bak;
-                 mblength = 1;
-               }
-             if (mblength < 1)
-               mblength = 1;
-             temp = (char *)xmalloc (mblength + 2);
-             temp[0] = CTLESC;
-             for (i = 0; i < mblength; i++)
-               temp[i+1] = string[sindex++];
-             temp[mblength + 1] = '\0';
-
-             goto add_string;
+             SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
            }
          else
 #endif
@@ -6106,31 +6502,12 @@ add_twochars:
              else
                {
 #if HANDLE_MULTIBYTE
-                 /* XXX - I'd like to use SCOPY_CHAR_I here. */
+                 if (MB_CUR_MAX > 1)
+                   sindex--;
+
                  if (MB_CUR_MAX > 1)
                    {
-                     int i;
-                     mbstate_t state_bak;
-                     size_t mblength;
-
-                     sindex--;
-                     state_bak = state;
-                     mblength = mbrlen (string + sindex, string_size - sindex, &state);
-                     if (MB_INVALIDCH (mblength))
-                       {
-                         state = state_bak;
-                         mblength = 1;
-                       }
-                     if (mblength < 1)
-                       mblength = 1;
-
-                     temp = (char *)xmalloc (mblength + 2);
-                     temp[0] = CTLESC;
-                     for (i = 0; i < mblength; i++)
-                       temp[i + 1] = string[sindex++];
-                     temp[mblength + 1] = '\0';
-
-                     goto add_string;
+                     SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
                    }
                  else
 #endif
index 4071350..95d42a6 100644 (file)
--- a/subst.c~
+++ b/subst.c~
@@ -2022,16 +2022,7 @@ do_assignment_internal (string, expand)
     }
 
   if (echo_command_at_execute)
-    {
-#if 0
-      if (assign_list)
-       fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
-      else
-       fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
-#else
-       xtrace_print_assignment (name, value, assign_list, 1);
-#endif
-    }
+     xtrace_print_assignment (name, value, assign_list, 1);
 
 #define ASSIGN_RETURN(r)       do { FREE (value); free (name); return (r); } while (0)
 
@@ -5844,7 +5835,11 @@ param_expand (string, sindex, quoted, expanded_something,
             quote the whole string, including the separators.  If IFS
             is unset, the parameters are separated by ' '; if $IFS is
             null, the parameters are concatenated. */
+#if 0
          temp = string_list_dollar_star (list);
+#else
+         temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
+#endif
          temp1 = quote_string (temp);
          free (temp);
          temp = temp1;
index 3db0f8a..8c4e1ec 100644 (file)
@@ -4,7 +4,7 @@
 #
 # The bug address depends on the release status of the shell.  Versions
 # with status `devel', `alpha', `beta', or `rc' mail bug reports to
-# chet@po.cwru.edu and, optionally, to bash-testers@po.cwru.edu.
+# chet@cwru.edu and, optionally, to bash-testers@cwru.edu.
 # Other versions send mail to bug-bash@gnu.org.
 #
 # Copyright (C) 1996-2004 Free Software Foundation, Inc.
@@ -39,35 +39,19 @@ MACHTYPE="!MACHTYPE!"
 PATH=/bin:/usr/bin:/usr/local/bin:$PATH
 export PATH
 
-# If the OS supplies a program to make temp files with semi-random names,
-# use it.
+# Check if TMPDIR is set, default to /tmp
 : ${TMPDIR:=/tmp}
-rm_tmp1=false
-rm_tmp2=false
-
-# if we don't have mktemp or tempfile, we don't want to see error messages
-# like `mktemp: not found', so temporarily redirect stderr using {...} while
-# trying to run them.  this may fail using old versions of the bourne shell
-# that run {...} blocks with redirections in subshells; in that case we're
-# no worse off than previous versions
-
-{ TEMPFILE1=`mktemp "$TMPDIR/bbug.XXXXXX" 2>/dev/null` ; } 2>/dev/null
-if [ -z "$TEMPFILE1" ]; then
-       { TEMPFILE1=`tempfile --prefix bbug --mode 600 2>/dev/null`; } 2>/dev/null
-fi
-if [ -z "$TEMPFILE1" ]; then
-       TEMPFILE1=$TMPDIR/bbug.$$
-       rm_tmp1=true
-fi
-{ TEMPFILE2=`mktemp "$TMPDIR/bbug.XXXXXX" 2>/dev/null`; } 2>/dev/null
-if [ -z "$TEMPFILE2" ]; then
-       { TEMPFILE2=`tempfile --prefix bbug --mode 600 2>/dev/null`; } 2>/dev/null
-fi
-if [ -z "$TEMPFILE2" ]; then
-       TEMPFILE2="$TMPDIR/bbug.$$.x"
-       rm_tmp2=true
-fi
 
+#Securely create a temporary directory for the temporary files
+TEMPDIR=$TMPDIR/bbug.$$
+(umask 077 && mkdir $TEMPDIR) || {
+       echo "$0: could not create temporary directory" >&2
+       exit 1
+}
+
+TEMPFILE1=$TEMPDIR/bbug1
+TEMPFILE2=$TEMPDIR/bbug2
+        
 USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]"
 VERSTR="GNU bashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}"
 
@@ -116,10 +100,10 @@ case "$N" in
 *)     n= c='\c' ;;
 esac
 
-BASHTESTERS="bash-testers@po.cwru.edu"
+BASHTESTERS="bash-testers@cwru.edu"
 
 case "$RELSTATUS" in
-alpha*|beta*|devel*|rc*)       BUGBASH=chet@po.cwru.edu ;;
+alpha*|beta*|devel*|rc*)       BUGBASH=chet@cwru.edu ;;
 *)                             BUGBASH=bug-bash@gnu.org ;;
 esac
 
@@ -166,8 +150,8 @@ fi
 
 : ${USER=${LOGNAME-`whoami`}}
 
-trap 'rm -f "$TEMPFILE1" "$TEMPFILE2"; exit 1' 1 2 3 13 15
-trap 'rm -f "$TEMPFILE1" "$TEMPFILE2"' 0
+trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15
+trap 'rm -rf "$TEMPDIR"' 0
 
 UN=
 if (uname) >/dev/null 2>&1; then
@@ -187,9 +171,6 @@ fi
 
 INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]'
 
-# this is raceable unless (hopefully) we used mktemp(1) or tempfile(1)
-$rm_tmp1 && rm -f "$TEMPFILE1"
-
 cat > "$TEMPFILE1" <<EOF
 From: ${USER}
 To: ${BUGADDR}
@@ -219,9 +200,6 @@ Fix:
        fix for the problem, don't include this section.]
 EOF
 
-# this is still raceable unless (hopefully) we used mktemp(1) or tempfile(1)
-$rm_tmp2 && rm -f "$TEMPFILE2"
-
 cp "$TEMPFILE1" "$TEMPFILE2"
 chmod u+w "$TEMPFILE1"
 
@@ -272,7 +250,7 @@ while [ $edstat -ne 0 ]; do
 
 done
 
-trap 'rm -f "$TEMPFILE1" "$TEMPFILE2"; exit 1' 2       # restore trap on SIGINT
+trap 'rm -rf "$TEMPDIR"; exit 1' 2     # restore trap on SIGINT
 
 if cmp -s "$TEMPFILE1" "$TEMPFILE2"
 then
diff --git a/support/bashbug.sh.orig b/support/bashbug.sh.orig
new file mode 100644 (file)
index 0000000..3db0f8a
--- /dev/null
@@ -0,0 +1,294 @@
+#!/bin/sh -
+#
+# bashbug - create a bug report and mail it to the bug address
+#
+# The bug address depends on the release status of the shell.  Versions
+# with status `devel', `alpha', `beta', or `rc' mail bug reports to
+# chet@po.cwru.edu and, optionally, to bash-testers@po.cwru.edu.
+# Other versions send mail to bug-bash@gnu.org.
+#
+# Copyright (C) 1996-2004 Free Software Foundation, Inc.
+#
+# This program 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 2, or (at your option)
+# any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+#
+# configuration section:
+#      these variables are filled in by the make target in Makefile
+#
+MACHINE="!MACHINE!"
+OS="!OS!"
+CC="!CC!"
+CFLAGS="!CFLAGS!"
+RELEASE="!RELEASE!"
+PATCHLEVEL="!PATCHLEVEL!"
+RELSTATUS="!RELSTATUS!"
+MACHTYPE="!MACHTYPE!"
+
+PATH=/bin:/usr/bin:/usr/local/bin:$PATH
+export PATH
+
+# If the OS supplies a program to make temp files with semi-random names,
+# use it.
+: ${TMPDIR:=/tmp}
+rm_tmp1=false
+rm_tmp2=false
+
+# if we don't have mktemp or tempfile, we don't want to see error messages
+# like `mktemp: not found', so temporarily redirect stderr using {...} while
+# trying to run them.  this may fail using old versions of the bourne shell
+# that run {...} blocks with redirections in subshells; in that case we're
+# no worse off than previous versions
+
+{ TEMPFILE1=`mktemp "$TMPDIR/bbug.XXXXXX" 2>/dev/null` ; } 2>/dev/null
+if [ -z "$TEMPFILE1" ]; then
+       { TEMPFILE1=`tempfile --prefix bbug --mode 600 2>/dev/null`; } 2>/dev/null
+fi
+if [ -z "$TEMPFILE1" ]; then
+       TEMPFILE1=$TMPDIR/bbug.$$
+       rm_tmp1=true
+fi
+{ TEMPFILE2=`mktemp "$TMPDIR/bbug.XXXXXX" 2>/dev/null`; } 2>/dev/null
+if [ -z "$TEMPFILE2" ]; then
+       { TEMPFILE2=`tempfile --prefix bbug --mode 600 2>/dev/null`; } 2>/dev/null
+fi
+if [ -z "$TEMPFILE2" ]; then
+       TEMPFILE2="$TMPDIR/bbug.$$.x"
+       rm_tmp2=true
+fi
+
+USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]"
+VERSTR="GNU bashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}"
+
+do_help= do_version=
+
+while [ $# -gt 0 ]; do
+       case "$1" in
+       --help)         shift ; do_help=y ;;
+       --version)      shift ; do_version=y ;;
+       --)             shift ; break ;;
+       -*)             echo "bashbug: ${1}: invalid option" >&2
+                       echo "$USAGE" >& 2
+                       exit 2 ;;
+       *)              break ;;
+       esac
+done
+
+if [ -n "$do_version" ]; then
+       echo "${VERSTR}"
+       exit 0
+fi
+
+if [ -n "$do_help" ]; then
+       echo "${VERSTR}"
+       echo "${USAGE}"
+       echo
+       cat << HERE_EOF
+Bashbug is used to send mail to the Bash maintainers
+for when Bash doesn't behave like you'd like, or expect.
+
+Bashbug will start up your editor (as defined by the shell's
+EDITOR environment variable) with a preformatted bug report
+template for you to fill in. The report will be mailed to the
+bash maintainers by default. See the manual for details.
+
+If you invoke bashbug by accident, just quit your editor without
+saving any changes to the template, and no bug report will be sent.
+HERE_EOF
+       exit 0
+fi
+
+# Figure out how to echo a string without a trailing newline
+N=`echo 'hi there\c'`
+case "$N" in
+*c)    n=-n c= ;;
+*)     n= c='\c' ;;
+esac
+
+BASHTESTERS="bash-testers@po.cwru.edu"
+
+case "$RELSTATUS" in
+alpha*|beta*|devel*|rc*)       BUGBASH=chet@po.cwru.edu ;;
+*)                             BUGBASH=bug-bash@gnu.org ;;
+esac
+
+case "$RELSTATUS" in
+alpha*|beta*|devel*|rc*)
+               echo "$0: This is a testing release.  Would you like your bug report"
+               echo "$0: to be sent to the bash-testers mailing list?"
+               echo $n "$0: Send to bash-testers? $c"
+               read ans
+               case "$ans" in
+               y*|Y*)  BUGBASH="${BUGBASH},${BASHTESTERS}" ;;
+               esac ;;
+esac
+
+BUGADDR="${1-$BUGBASH}"
+
+if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then
+       if [ -x /usr/bin/editor ]; then
+               DEFEDITOR=editor
+       elif [ -x /usr/local/bin/ce ]; then
+               DEFEDITOR=ce
+       elif [ -x /usr/local/bin/emacs ]; then
+               DEFEDITOR=emacs
+       elif [ -x /usr/contrib/bin/emacs ]; then
+               DEFEDITOR=emacs
+       elif [ -x /usr/bin/emacs ]; then
+               DEFEDITOR=emacs
+       elif [ -x /usr/bin/xemacs ]; then
+               DEFEDITOR=xemacs
+       elif [ -x /usr/contrib/bin/jove ]; then
+               DEFEDITOR=jove
+       elif [ -x /usr/local/bin/jove ]; then
+               DEFEDITOR=jove
+       elif [ -x /usr/bin/vi ]; then
+               DEFEDITOR=vi
+       else
+               echo "$0: No default editor found: attempting to use vi" >&2
+               DEFEDITOR=vi
+       fi
+fi
+
+
+: ${EDITOR=$DEFEDITOR}
+
+: ${USER=${LOGNAME-`whoami`}}
+
+trap 'rm -f "$TEMPFILE1" "$TEMPFILE2"; exit 1' 1 2 3 13 15
+trap 'rm -f "$TEMPFILE1" "$TEMPFILE2"' 0
+
+UN=
+if (uname) >/dev/null 2>&1; then
+       UN=`uname -a`
+fi
+
+if [ -f /usr/lib/sendmail ] ; then
+       RMAIL="/usr/lib/sendmail"
+       SMARGS="-i -t"
+elif [ -f /usr/sbin/sendmail ] ; then
+       RMAIL="/usr/sbin/sendmail"
+       SMARGS="-i -t"
+else
+       RMAIL=rmail
+       SMARGS="$BUGADDR"
+fi
+
+INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]'
+
+# this is raceable unless (hopefully) we used mktemp(1) or tempfile(1)
+$rm_tmp1 && rm -f "$TEMPFILE1"
+
+cat > "$TEMPFILE1" <<EOF
+From: ${USER}
+To: ${BUGADDR}
+Subject: ${INITIAL_SUBJECT}
+
+Configuration Information [Automatically generated, do not change]:
+Machine: $MACHINE
+OS: $OS
+Compiler: $CC
+Compilation CFLAGS: $CFLAGS
+uname output: $UN
+Machine Type: $MACHTYPE
+
+Bash Version: $RELEASE
+Patch Level: $PATCHLEVEL
+Release Status: $RELSTATUS
+
+Description:
+       [Detailed description of the problem, suggestion, or complaint.]
+
+Repeat-By:
+       [Describe the sequence of events that causes the problem
+       to occur.]
+
+Fix:
+       [Description of how to fix the problem.  If you don't know a
+       fix for the problem, don't include this section.]
+EOF
+
+# this is still raceable unless (hopefully) we used mktemp(1) or tempfile(1)
+$rm_tmp2 && rm -f "$TEMPFILE2"
+
+cp "$TEMPFILE1" "$TEMPFILE2"
+chmod u+w "$TEMPFILE1"
+
+trap '' 2              # ignore interrupts while in editor
+
+edstat=1
+while [ $edstat -ne 0 ]; do
+       $EDITOR "$TEMPFILE1"
+       edstat=$?
+
+       if [ $edstat -ne 0 ]; then
+               echo "$0: editor \`$EDITOR' exited with nonzero status."
+               echo "$0: Perhaps it was interrupted."
+               echo "$0: Type \`y' to give up, and lose your bug report;"
+               echo "$0: type \`n' to re-enter the editor."
+               echo $n "$0: Do you want to give up? $c"
+
+               read ans
+               case "$ans" in
+               [Yy]*) exit 1 ;;
+               esac
+
+               continue
+       fi
+
+       # find the subject from the temp file and see if it's been changed
+       CURR_SUB=`grep '^Subject: ' "$TEMPFILE1" | sed 's|^Subject:[    ]*||' | sed 1q`
+
+       case "$CURR_SUB" in
+       "${INITIAL_SUBJECT}")
+               echo
+               echo "$0: You have not changed the subject from the default."
+               echo "$0: Please use a more descriptive subject header."
+               echo "$0: Type \`y' to give up, and lose your bug report;"
+               echo "$0: type \`n' to re-enter the editor."
+               echo $n "$0: Do you want to give up? $c"
+
+               read ans
+               case "$ans" in
+               [Yy]*) exit 1 ;;
+               esac
+
+               echo "$0:  The editor will be restarted in five seconds."
+               sleep 5
+               edstat=1
+               ;;
+       esac
+
+done
+
+trap 'rm -f "$TEMPFILE1" "$TEMPFILE2"; exit 1' 2       # restore trap on SIGINT
+
+if cmp -s "$TEMPFILE1" "$TEMPFILE2"
+then
+       echo "File not changed, no bug report submitted."
+       exit
+fi
+
+echo $n "Send bug report? [y/n] $c"
+read ans
+case "$ans" in
+[Nn]*) exit 0 ;;
+esac
+
+${RMAIL} $SMARGS < "$TEMPFILE1" || {
+       cat "$TEMPFILE1" >> $HOME/dead.bashbug
+       echo "$0: mail failed: report saved in $HOME/dead.bashbug" >&2
+}
+
+exit 0
diff --git a/support/bashbug.sh~ b/support/bashbug.sh~
new file mode 100644 (file)
index 0000000..32b8fc5
--- /dev/null
@@ -0,0 +1,271 @@
+#!/bin/sh -
+#
+# bashbug - create a bug report and mail it to the bug address
+#
+# The bug address depends on the release status of the shell.  Versions
+# with status `devel', `alpha', `beta', or `rc' mail bug reports to
+# chet@cwru.edu and, optionally, to bash-testers@cwru.edu.
+# Other versions send mail to bug-bash@gnu.org.
+#
+# Copyright (C) 1996-2004 Free Software Foundation, Inc.
+#
+# This program 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 2, or (at your option)
+# any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+#
+# configuration section:
+#      these variables are filled in by the make target in Makefile
+#
+MACHINE="!MACHINE!"
+OS="!OS!"
+CC="!CC!"
+CFLAGS="!CFLAGS!"
+RELEASE="!RELEASE!"
+PATCHLEVEL="!PATCHLEVEL!"
+RELSTATUS="!RELSTATUS!"
+MACHTYPE="!MACHTYPE!"
+
+PATH=/bin:/usr/bin:/usr/local/bin:$PATH
+export PATH
+
+# Check if TMPDIR is set, default to /tmp
+: ${TMPDIR:=/tmp}
+
+#Securely create a temporary directory for the temporary files
+TEMPDIR=$TMPDIR/bbug.$$
+(umask 077 && mkdir $TEMPDIR) || {
+        echo "Could not create temporary directory. Exiting!"
+        exit 1
+        }
+TEMPFILE1=$TEMPDIR/bbug1
+TEMPFILE2=$TEMPDIR/bbug2
+        
+USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]"
+VERSTR="GNU bashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}"
+
+do_help= do_version=
+
+while [ $# -gt 0 ]; do
+       case "$1" in
+       --help)         shift ; do_help=y ;;
+       --version)      shift ; do_version=y ;;
+       --)             shift ; break ;;
+       -*)             echo "bashbug: ${1}: invalid option" >&2
+                       echo "$USAGE" >& 2
+                       exit 2 ;;
+       *)              break ;;
+       esac
+done
+
+if [ -n "$do_version" ]; then
+       echo "${VERSTR}"
+       exit 0
+fi
+
+if [ -n "$do_help" ]; then
+       echo "${VERSTR}"
+       echo "${USAGE}"
+       echo
+       cat << HERE_EOF
+Bashbug is used to send mail to the Bash maintainers
+for when Bash doesn't behave like you'd like, or expect.
+
+Bashbug will start up your editor (as defined by the shell's
+EDITOR environment variable) with a preformatted bug report
+template for you to fill in. The report will be mailed to the
+bash maintainers by default. See the manual for details.
+
+If you invoke bashbug by accident, just quit your editor without
+saving any changes to the template, and no bug report will be sent.
+HERE_EOF
+       exit 0
+fi
+
+# Figure out how to echo a string without a trailing newline
+N=`echo 'hi there\c'`
+case "$N" in
+*c)    n=-n c= ;;
+*)     n= c='\c' ;;
+esac
+
+BASHTESTERS="bash-testers@cwru.edu"
+
+case "$RELSTATUS" in
+alpha*|beta*|devel*|rc*)       BUGBASH=chet@cwru.edu ;;
+*)                             BUGBASH=bug-bash@gnu.org ;;
+esac
+
+case "$RELSTATUS" in
+alpha*|beta*|devel*|rc*)
+               echo "$0: This is a testing release.  Would you like your bug report"
+               echo "$0: to be sent to the bash-testers mailing list?"
+               echo $n "$0: Send to bash-testers? $c"
+               read ans
+               case "$ans" in
+               y*|Y*)  BUGBASH="${BUGBASH},${BASHTESTERS}" ;;
+               esac ;;
+esac
+
+BUGADDR="${1-$BUGBASH}"
+
+if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then
+       if [ -x /usr/bin/editor ]; then
+               DEFEDITOR=editor
+       elif [ -x /usr/local/bin/ce ]; then
+               DEFEDITOR=ce
+       elif [ -x /usr/local/bin/emacs ]; then
+               DEFEDITOR=emacs
+       elif [ -x /usr/contrib/bin/emacs ]; then
+               DEFEDITOR=emacs
+       elif [ -x /usr/bin/emacs ]; then
+               DEFEDITOR=emacs
+       elif [ -x /usr/bin/xemacs ]; then
+               DEFEDITOR=xemacs
+       elif [ -x /usr/contrib/bin/jove ]; then
+               DEFEDITOR=jove
+       elif [ -x /usr/local/bin/jove ]; then
+               DEFEDITOR=jove
+       elif [ -x /usr/bin/vi ]; then
+               DEFEDITOR=vi
+       else
+               echo "$0: No default editor found: attempting to use vi" >&2
+               DEFEDITOR=vi
+       fi
+fi
+
+
+: ${EDITOR=$DEFEDITOR}
+
+: ${USER=${LOGNAME-`whoami`}}
+
+trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15
+trap 'rm -rf "$TEMPDIR"' 0
+
+UN=
+if (uname) >/dev/null 2>&1; then
+       UN=`uname -a`
+fi
+
+if [ -f /usr/lib/sendmail ] ; then
+       RMAIL="/usr/lib/sendmail"
+       SMARGS="-i -t"
+elif [ -f /usr/sbin/sendmail ] ; then
+       RMAIL="/usr/sbin/sendmail"
+       SMARGS="-i -t"
+else
+       RMAIL=rmail
+       SMARGS="$BUGADDR"
+fi
+
+INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]'
+
+cat > "$TEMPFILE1" <<EOF
+From: ${USER}
+To: ${BUGADDR}
+Subject: ${INITIAL_SUBJECT}
+
+Configuration Information [Automatically generated, do not change]:
+Machine: $MACHINE
+OS: $OS
+Compiler: $CC
+Compilation CFLAGS: $CFLAGS
+uname output: $UN
+Machine Type: $MACHTYPE
+
+Bash Version: $RELEASE
+Patch Level: $PATCHLEVEL
+Release Status: $RELSTATUS
+
+Description:
+       [Detailed description of the problem, suggestion, or complaint.]
+
+Repeat-By:
+       [Describe the sequence of events that causes the problem
+       to occur.]
+
+Fix:
+       [Description of how to fix the problem.  If you don't know a
+       fix for the problem, don't include this section.]
+EOF
+
+cp "$TEMPFILE1" "$TEMPFILE2"
+chmod u+w "$TEMPFILE1"
+
+trap '' 2              # ignore interrupts while in editor
+
+edstat=1
+while [ $edstat -ne 0 ]; do
+       $EDITOR "$TEMPFILE1"
+       edstat=$?
+
+       if [ $edstat -ne 0 ]; then
+               echo "$0: editor \`$EDITOR' exited with nonzero status."
+               echo "$0: Perhaps it was interrupted."
+               echo "$0: Type \`y' to give up, and lose your bug report;"
+               echo "$0: type \`n' to re-enter the editor."
+               echo $n "$0: Do you want to give up? $c"
+
+               read ans
+               case "$ans" in
+               [Yy]*) exit 1 ;;
+               esac
+
+               continue
+       fi
+
+       # find the subject from the temp file and see if it's been changed
+       CURR_SUB=`grep '^Subject: ' "$TEMPFILE1" | sed 's|^Subject:[    ]*||' | sed 1q`
+
+       case "$CURR_SUB" in
+       "${INITIAL_SUBJECT}")
+               echo
+               echo "$0: You have not changed the subject from the default."
+               echo "$0: Please use a more descriptive subject header."
+               echo "$0: Type \`y' to give up, and lose your bug report;"
+               echo "$0: type \`n' to re-enter the editor."
+               echo $n "$0: Do you want to give up? $c"
+
+               read ans
+               case "$ans" in
+               [Yy]*) exit 1 ;;
+               esac
+
+               echo "$0:  The editor will be restarted in five seconds."
+               sleep 5
+               edstat=1
+               ;;
+       esac
+
+done
+
+trap 'rm -rf "$TEMPDIR"; exit 1' 2     # restore trap on SIGINT
+
+if cmp -s "$TEMPFILE1" "$TEMPFILE2"
+then
+       echo "File not changed, no bug report submitted."
+       exit
+fi
+
+echo $n "Send bug report? [y/n] $c"
+read ans
+case "$ans" in
+[Nn]*) exit 0 ;;
+esac
+
+${RMAIL} $SMARGS < "$TEMPFILE1" || {
+       cat "$TEMPFILE1" >> $HOME/dead.bashbug
+       echo "$0: mail failed: report saved in $HOME/dead.bashbug" >&2
+}
+
+exit 0
index 049d3cd..ad2bc19 100644 (file)
@@ -17,7 +17,7 @@ job 6 returns 0
 Waiting for job 7
 job 7 returns 0
 0
-./jobs.tests: line 15: wait: no job control
+./jobs.tests: line 15: wait: %1: no such job
 ./jobs.tests: line 20: fg: no job control
 wait-for-pid
 wait-errors
diff --git a/tests/jobs.right~ b/tests/jobs.right~
new file mode 100644 (file)
index 0000000..049d3cd
--- /dev/null
@@ -0,0 +1,97 @@
+./jobs2.sub: line 9: fg: job 1 started without job control
+fg: 1
+Waiting for job 0
+job 0 returns 0
+Waiting for job 1
+job 1 returns 0
+Waiting for job 2
+job 2 returns 0
+Waiting for job 3
+job 3 returns 0
+Waiting for job 4
+job 4 returns 0
+Waiting for job 5
+job 5 returns 0
+Waiting for job 6
+job 6 returns 0
+Waiting for job 7
+job 7 returns 0
+0
+./jobs.tests: line 15: wait: no job control
+./jobs.tests: line 20: fg: no job control
+wait-for-pid
+wait-errors
+./jobs.tests: line 33: wait: `1-1': not a pid or valid job spec
+./jobs.tests: line 34: wait: `-4': not a pid or valid job spec
+wait-for-background-pids
+async list wait-for-background-pids
+async list wait for child
+forked
+wait-when-no-children
+wait-for-job
+./jobs.tests: line 56: wait: %2: no such job
+127
+async list wait-for-job
+forked
+fg-bg 1
+sleep 5
+fg-bg 2
+sleep 5
+fg-bg 3
+sleep 5
+fg-bg 4
+sleep 5
+fg-bg 5
+./jobs.tests: line 83: fg: %2: no such job
+./jobs.tests: line 84: bg: job 1 already in background
+fg-bg 6
+./jobs.tests: line 91: fg: -s: invalid option
+fg: usage: fg [job_spec]
+./jobs.tests: line 92: bg: -s: invalid option
+bg: usage: bg [job_spec]
+./jobs.tests: line 97: disown: -s: invalid option
+disown: usage: disown [-h] [-ar] [jobspec ...]
+./jobs.tests: line 101: disown: %1: no such job
+./jobs.tests: line 104: disown: %2: no such job
+wait-for-non-child
+./jobs.tests: line 107: wait: pid 1 is not a child of this shell
+127
+3 -- 1 2 3 -- 1 - 2 - 3
+[1]   Running                 sleep 300 &
+[2]-  Running                 sleep 350 &
+[3]+  Running                 sleep 400 &
+running jobs:
+[1]   Running                 sleep 300 &
+[2]-  Running                 sleep 350 &
+[3]+  Running                 sleep 400 &
+./jobs.tests: line 123: kill: %4: no such job
+./jobs.tests: line 125: jobs: %4: no such job
+current job:
+[3]+  Running                 sleep 400 &
+previous job:
+[2]-  Running                 sleep 350 &
+after kill -STOP
+running jobs:
+[1]   Running                 sleep 300 &
+[3]-  Running                 sleep 400 &
+stopped jobs:
+[2]+  Stopped                 sleep 350
+after disown
+[2]+  Stopped                 sleep 350
+[3]-  Running                 sleep 400 &
+running jobs:
+[3]-  Running                 sleep 400 &
+stopped jobs:
+[2]+  Stopped                 sleep 350
+after kill -s CONT
+running jobs:
+[2]+  Running                 sleep 350 &
+[3]-  Running                 sleep 400 &
+stopped jobs:
+after kill -STOP, backgrounding %3:
+[3]+ sleep 400 &
+killing...
+done
+after KILL -STOP, foregrounding %1
+sleep 10
+done
index d54c1e9..904e1f0 100644 (file)
@@ -11,7 +11,7 @@ ${THIS_SH} ./jobs3.sub
 jobs
 echo $?
 
-# should be a job-control-not-enabled error
+# a no-such-job error, since we can use job control notation without job control
 wait %1
 
 # make sure we can't fg a job started when job control was not active
diff --git a/tests/jobs.tests~ b/tests/jobs.tests~
new file mode 100644 (file)
index 0000000..d54c1e9
--- /dev/null
@@ -0,0 +1,179 @@
+# test out %+, jobs -p, and $! agreement in a subshell first
+${THIS_SH} ./jobs1.sub
+
+# test out fg/bg failure in a subshell
+${THIS_SH} ./jobs2.sub
+
+# test out behavior of waiting for background pids -- bug in versions
+# before 2.03
+${THIS_SH} ./jobs3.sub
+
+jobs
+echo $?
+
+# should be a job-control-not-enabled error
+wait %1
+
+# make sure we can't fg a job started when job control was not active
+sleep 30 &
+pid=$!
+fg %1
+# make sure the killed processes don't cause a message
+exec 5>&2
+exec 2>/dev/null
+kill -n 9 $pid
+wait    # make sure we reap the processes while stderr is still redirected
+exec 2>&5
+
+echo wait-for-pid
+sleep 10 &
+wait $!
+
+echo wait-errors
+wait 1-1
+wait -- -4
+
+echo wait-for-background-pids
+sleep 5 &
+sleep 8 &
+wait
+
+echo async list wait-for-background-pids
+sleep 5 & sleep 8 &
+wait
+
+echo async list wait for child
+sleep 5 & echo forked
+wait
+
+echo wait-when-no-children
+wait
+
+set -m
+
+echo wait-for-job
+sleep 5 &
+wait %2                # this should be a no-such-job error
+echo $?
+wait %1
+
+echo async list wait-for-job
+sleep 5 & echo forked
+wait %1
+
+echo fg-bg 1
+sleep 5 &
+%1
+
+echo fg-bg 2
+sleep 5 &
+fg %%
+
+echo fg-bg 3
+sleep 5 &
+fg %s
+
+echo fg-bg 4
+sleep 5 &
+fg %?ee
+
+# these next two are error cases
+echo fg-bg 5
+sleep 15 &
+fg %2          # this should be a no-such-job error
+bg %1          # this should be a `bg background job?' error
+wait
+
+# these may someday mean to start the jobs, but not print the line
+# describing the status, but for now they are errors
+echo fg-bg 6
+sleep 5 &
+fg -s %1
+bg -s %1
+wait
+
+# someday this may mean to disown all stopped jobs, but for now it is
+# an error
+disown -s
+
+# this is an error -- the job with the pid that is the value of $! is
+# retained only until a `wait' is performed
+disown %1
+
+# this, however, is an error
+disown %2
+
+echo wait-for-non-child
+wait 1
+echo $?
+
+exit 1 | exit 2 | exit 3
+echo $? -- ${PIPESTATUS[@]} -- ${PIPESTATUS[0]} - ${PIPESTATUS[1]} - ${PIPESTATUS[2]}
+
+sleep 300 &
+sleep 350 &
+sleep 400 &
+
+jobs
+
+echo running jobs:
+jobs -r
+
+# should be an error
+kill -n 1 %4
+# should be an error
+jobs %4
+echo current job:
+jobs %+
+echo previous job:
+jobs %-
+
+kill -STOP %2
+sleep 5        # give time for the shell to get the stop notification
+echo after kill -STOP
+echo running jobs:
+jobs -r
+echo stopped jobs:
+jobs -s
+
+disown %1
+
+echo after disown
+jobs
+echo running jobs:
+jobs -r
+echo stopped jobs:
+jobs -s
+
+kill -s CONT %2
+echo after kill -s CONT
+echo running jobs:
+jobs -r
+echo stopped jobs:
+jobs -s
+
+kill -STOP %3
+sleep 5        # give time for the shell to get the stop notification
+echo after kill -STOP, backgrounding %3:
+bg %3
+
+disown -h %2
+
+# make sure the killed processes don't cause a message
+exec 5>&2
+exec 2>/dev/null
+
+echo killing...
+kill -n 9 %2 %3
+wait   # make sure we reap the processes while stderr is still redirected
+echo done
+
+exec 2>&5
+
+sleep 10 &
+kill -STOP %1
+sleep 5        # give time for the shell to get the stop notification
+echo after KILL -STOP, foregrounding %1
+fg %1
+
+echo done