commit bash-20200316 snapshot

This commit is contained in:
Chet Ramey
2020-03-20 09:26:56 -04:00
parent 9e6c30de85
commit cf58e12ce6
22 changed files with 214 additions and 90 deletions
+60
View File
@@ -7540,3 +7540,63 @@ subst.c
we are returning a quoted null string to the caller by setting we are returning a quoted null string to the caller by setting
W_HASQUOTEDNULL. Fixes bug reported by Martin Castillo W_HASQUOTEDNULL. Fixes bug reported by Martin Castillo
<castilma@uni-bremen.de> <castilma@uni-bremen.de>
3/17
----
lib/readline/histfile.c
- history_truncate_file: only chown the file if we really need to. From
alex@lisas.de via https://savannah.gnu.org/support/?110207
lib/readline/bind.c
- rl_unbind_function_in_map: since we are looking for functions, not
key sequences, descend into keymaps attached to the keymap passed
as an argument. From a report from lockywolf@gmail.com back on 2/27,
TENTATIVE CHANGE
variables.h
- MKLOC_ARRAYOK,MKLOC_ASSOCOK: new flags values for
make_local_{array,assoc}_variable so we can avoid hard-coded values
of 1 and make it possible to eventually pass in additional flags
builtins/declare.def
- declare_internal: make_local_array_variable: pass MKLOC_ASSOCOK
- declare_internal: make_local_assoc_variable: pass MKLOC_ARRAYOK
variables.c
- make_local_{array,assoc}_variable: understand new flags, pass
MKLOC_INHERIT to make_local_variable if it appears in the flags
argument
builtins/declare.def
- declare_internal: add a new -I option for local and declare that
inherits attributes and value from a variable with the same name
at a previous scope. Inspired by netbsd sh
- if -I option is supplied, pass MKLOC_INHERIT to make_local_variable
and its array counterparts make_local_{array,assoc}_variable
subst.c
- shell_expand_word_list: pass -I to declare if constructing a declare
command with make_local_declare, meaning we have an array or assoc
compound assignment. (Slighty unsatisfactory, but ok for now) Fix
for bug report from Kevin Locke <kevin@kevinlocke.name>,
https://savannah.gnu.org/support/index.php?109669
3/18
----
examples/loadables/basename.c
- basename_builtin: handle -- option without crashing. Report by Peng Yu
<pengyu.ut@gmail.com>
jobs.c
- notify_of_job_status: if in posix-mode shell is started with -c,
jobs should print the status of completed jobs. From a report by
Robert Elz <kre@munnari.oz.au> back in 12/18
3/19
----
variables.c
- assign_in_env: if we're assigning POSIXLY_CORRECT or POSIX_PEDANTIC
in the temporary environment, save the values of the options
affected by posix mode so we can restore them when we restore the
old value of the variable after the command executes. Suggested by
Martijn Dekker <martijn@inlv.org>
+14 -9
View File
@@ -34,6 +34,8 @@ Options:
source file when debugging) source file when debugging)
-g create global variables when used in a shell function; otherwise -g create global variables when used in a shell function; otherwise
ignored ignored
-I if creating a local variable, inherit the attributes and value
of a variable with the same name at a previous scope
-p display the attributes and value of each NAME -p display the attributes and value of each NAME
Options which set attributes: Options which set attributes:
@@ -135,9 +137,9 @@ local_builtin (list)
} }
#if defined (ARRAY_VARS) #if defined (ARRAY_VARS)
# define DECLARE_OPTS "+acfgilnprtuxAFG" # define DECLARE_OPTS "+acfgilnprtuxAFGI"
#else #else
# define DECLARE_OPTS "+cfgilnprtuxFG" # define DECLARE_OPTS "+cfgilnprtuxFGI"
#endif #endif
static SHELL_VAR * static SHELL_VAR *
@@ -168,13 +170,13 @@ declare_internal (list, local_var)
{ {
int flags_on, flags_off, *flags; int flags_on, flags_off, *flags;
int any_failed, assign_error, pflag, nodefs, opt, onref, offref; int any_failed, assign_error, pflag, nodefs, opt, onref, offref;
int mkglobal, chklocal; int mkglobal, chklocal, inherit_flag;
char *t, *subscript_start; char *t, *subscript_start;
SHELL_VAR *var, *refvar, *v; SHELL_VAR *var, *refvar, *v;
FUNCTION_DEF *shell_fn; FUNCTION_DEF *shell_fn;
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0; flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
mkglobal = chklocal = 0; mkglobal = chklocal = inherit_flag = 0;
refvar = (SHELL_VAR *)NULL; refvar = (SHELL_VAR *)NULL;
reset_internal_getopt (); reset_internal_getopt ();
while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1) while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1)
@@ -255,6 +257,9 @@ declare_internal (list, local_var)
flags_off |= att_capcase|att_lowercase; flags_off |= att_capcase|att_lowercase;
break; break;
#endif /* CASEMOD_ATTRS */ #endif /* CASEMOD_ATTRS */
case 'I':
inherit_flag = MKLOC_INHERIT;
break;
CASE_HELPOPT; CASE_HELPOPT;
default: default:
builtin_usage (); builtin_usage ();
@@ -452,9 +457,9 @@ restart_new_var_name:
return an existing {array,assoc} variable to be flagged as an return an existing {array,assoc} variable to be flagged as an
error below. */ error below. */
if (flags_on & att_assoc) if (flags_on & att_assoc)
var = make_local_assoc_variable (newname, 1); var = make_local_assoc_variable (newname, MKLOC_ARRAYOK|inherit_flag);
else if ((flags_on & att_array) || making_array_special) else if ((flags_on & att_array) || making_array_special)
var = make_local_array_variable (newname, 1); var = make_local_array_variable (newname, MKLOC_ASSOCOK|inherit_flag);
else else
#endif #endif
if (offset == 0 && (flags_on & att_nameref)) if (offset == 0 && (flags_on & att_nameref))
@@ -468,18 +473,18 @@ restart_new_var_name:
if (refvar && refvar->context != variable_context) if (refvar && refvar->context != variable_context)
{ {
refvar = 0; refvar = 0;
var = make_local_variable (name, 0); var = make_local_variable (name, inherit_flag);
} }
else if (refvar && refvar->context == variable_context) else if (refvar && refvar->context == variable_context)
var = refvar; var = refvar;
/* Maybe we just want to create a new local variable */ /* Maybe we just want to create a new local variable */
else if (var == 0 || var->context != variable_context) else if (var == 0 || var->context != variable_context)
var = make_local_variable (name, 0); var = make_local_variable (name, inherit_flag);
/* otherwise we have a var at the right context */ /* otherwise we have a var at the right context */
} }
else else
/* XXX - check name for validity here with valid_nameref_value */ /* XXX - check name for validity here with valid_nameref_value */
var = make_local_variable ((flags_on & att_nameref) ? name : newname, 0); /* sets att_invisible for new vars */ var = make_local_variable ((flags_on & att_nameref) ? name : newname, inherit_flag); /* sets att_invisible for new vars */
if (var == 0) if (var == 0)
{ {
+11 -4
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University .\" Case Western Reserve University
.\" chet.ramey@case.edu .\" chet.ramey@case.edu
.\" .\"
.\" Last Change: Wed Jan 29 14:00:16 EST 2020 .\" Last Change: Tue Mar 17 18:27:36 EDT 2020
.\" .\"
.\" bash_builtins, strip all but Built-Ins section .\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ .if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY .if \n(zY=1 .ig zY
.TH BASH 1 "2020 January 29" "GNU Bash 5.0" .TH BASH 1 "2020 March 17" "GNU Bash 5.0"
.\" .\"
.\" There's some problem with having a `@' .\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros. .\" in a tagged paragraph with the BSD man macros.
@@ -8023,10 +8023,10 @@ is greater than the number of enclosing loops, the last enclosing loop
(the ``top-level'' loop) is resumed. (the ``top-level'' loop) is resumed.
The return value is 0 unless \fIn\fP is not greater than or equal to 1. The return value is 0 unless \fIn\fP is not greater than or equal to 1.
.TP .TP
\fBdeclare\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] \fBdeclare\fP [\fB\-aAfFgiIlnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
.PD 0 .PD 0
.TP .TP
\fBtypeset\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] \fBtypeset\fP [\fB\-aAfFgiIlnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
.PD .PD
Declare variables and/or give them attributes. Declare variables and/or give them attributes.
If no \fIname\fPs are given then display the values of variables. If no \fIname\fPs are given then display the values of variables.
@@ -8061,6 +8061,13 @@ The
option forces variables to be created or modified at the global scope, option forces variables to be created or modified at the global scope,
even when \fBdeclare\fP is executed in a shell function. even when \fBdeclare\fP is executed in a shell function.
It is ignored in all other cases. It is ignored in all other cases.
The
.B \-I
option causes local variables to inherit the attributes
(except the \fInameref\fP attribute)
and value of any existing variable with the same
\fIname\fP at a surrounding scope.
If there is no existing variable, the local variable is initially unset.
The following options can The following options can
be used to restrict output to variables with the specified attribute or be used to restrict output to variables with the specified attribute or
to give variables attributes: to give variables attributes:
+7 -1
View File
@@ -4142,7 +4142,7 @@ zero if @var{command} is found, and non-zero if not.
@item declare @item declare
@btindex declare @btindex declare
@example @example
declare [-aAfFgilnrtux] [-p] [@var{name}[=@var{value}] @dots{}] declare [-aAfFgiIlnrtux] [-p] [@var{name}[=@var{value}] @dots{}]
@end example @end example
Declare variables and give them attributes. If no @var{name}s Declare variables and give them attributes. If no @var{name}s
@@ -4171,6 +4171,12 @@ The @option{-g} option forces variables to be created or modified at
the global scope, even when @code{declare} is executed in a shell function. the global scope, even when @code{declare} is executed in a shell function.
It is ignored in all other cases. It is ignored in all other cases.
The @option{-I} option causes local variables to inherit the attributes
(except the @var{nameref} attribute)
and value of any existing variable with the same
@var{name} at a surrounding scope.
If there is no existing variable, the local variable is initially unset.
The following options can be used to restrict output to variables with The following options can be used to restrict output to variables with
the specified attributes or to give variables attributes: the specified attributes or to give variables attributes:
+3 -3
View File
@@ -2,10 +2,10 @@
Copyright (C) 1988-2020 Free Software Foundation, Inc. Copyright (C) 1988-2020 Free Software Foundation, Inc.
@end ignore @end ignore
@set LASTCHANGE Wed Jan 29 13:59:06 EST 2020 @set LASTCHANGE Tue Mar 17 18:27:12 EDT 2020
@set EDITION 5.0 @set EDITION 5.0
@set VERSION 5.0 @set VERSION 5.0
@set UPDATED 29 January 2020 @set UPDATED 17 March 2020
@set UPDATED-MONTH January 2020 @set UPDATED-MONTH March 2020
+1 -1
View File
@@ -85,7 +85,7 @@ accept_builtin (list)
if (tmoutarg) if (tmoutarg)
{ {
long ival, uval; long ival, uval;
opt = uconvert (tmoutarg, &ival, &uval); opt = uconvert (tmoutarg, &ival, &uval, (char **)0);
if (opt == 0 || ival < 0 || uval < 0) if (opt == 0 || ival < 0 || uval < 0)
{ {
builtin_error ("%s: invalid timeout specification", tmoutarg); builtin_error ("%s: invalid timeout specification", tmoutarg);
+4 -5
View File
@@ -3,7 +3,7 @@
/* See Makefile for compilation details. */ /* See Makefile for compilation details. */
/* /*
Copyright (C) 1999-2009 Free Software Foundation, Inc. Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash. This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify Bash is free software: you can redistribute it and/or modify
@@ -39,16 +39,15 @@ basename_builtin (list)
int slen, sufflen, off; int slen, sufflen, off;
char *string, *suffix, *fn; char *string, *suffix, *fn;
if (no_options (list))
return (EX_USAGE);
list = loptend;
if (list == 0) if (list == 0)
{ {
builtin_usage (); builtin_usage ();
return (EX_USAGE); return (EX_USAGE);
} }
if (no_options (list))
return (EX_USAGE);
list = loptend;
string = list->word->word; string = list->word->word;
suffix = (char *)NULL; suffix = (char *)NULL;
if (list->next) if (list->next)
+5 -3
View File
@@ -34,6 +34,7 @@
#include "builtins.h" #include "builtins.h"
#include "shell.h" #include "shell.h"
#include "common.h" #include "common.h"
#include "bashgetopt.h"
int int
strftime_builtin (list) strftime_builtin (list)
@@ -46,15 +47,16 @@ strftime_builtin (list)
int n; int n;
intmax_t i; intmax_t i;
if (no_options (list))
return (EX_USAGE);
list = loptend;
if (list == 0) if (list == 0)
{ {
builtin_usage (); builtin_usage ();
return (EX_USAGE); return (EX_USAGE);
} }
if (no_options (list))
return (EX_USAGE);
format = list->word->word; format = list->word->word;
if (format == 0 || *format == 0) if (format == 0 || *format == 0)
{ {
+1 -2
View File
@@ -1606,8 +1606,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (should_redir_stdin && stdin_redir == 0) if (should_redir_stdin && stdin_redir == 0)
async_redirect_stdin (); async_redirect_stdin ();
#if 0 #if 0 /* XXX - TAG:bash-5.1 */
/* XXX - TAG:bash-5.1 */
if (user_subshell && command->type == cm_subshell) if (user_subshell && command->type == cm_subshell)
optimize_subshell_command (command->value.Subshell->command); optimize_subshell_command (command->value.Subshell->command);
#endif #endif
-5
View File
@@ -4265,14 +4265,9 @@ notify_of_job_status ()
substitution, so don't print anything. substitution, so don't print anything.
Otherwise, if the shell is not interactive, POSIX says that `jobs' Otherwise, if the shell is not interactive, POSIX says that `jobs'
is the only way to notify of job status. */ is the only way to notify of job status. */
#if 1
if ((job_control == 0 && interactive_shell) ||
(startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)))
#else /* TAG:bash-5.1 */
if ((job_control == 0 && interactive_shell) || if ((job_control == 0 && interactive_shell) ||
(startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)) || (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)) ||
(startup_state == 2 && posixly_correct && (subshell_environment & SUBSHELL_COMSUB) == 0)) (startup_state == 2 && posixly_correct && (subshell_environment & SUBSHELL_COMSUB) == 0))
#endif
{ {
/* POSIX.2 compatibility: if the shell is not interactive, /* POSIX.2 compatibility: if the shell is not interactive,
hang onto the job corresponding to the last asynchronous hang onto the job corresponding to the last asynchronous
+7
View File
@@ -262,6 +262,13 @@ rl_unbind_function_in_map (rl_command_func_t *func, Keymap map)
map[i].function = (rl_command_func_t *)NULL; map[i].function = (rl_command_func_t *)NULL;
rval = 1; rval = 1;
} }
else if (map[i].type == ISKMAP) /* TAG:readline-8.1 */
{
int r;
r = rl_unbind_function_in_map (func, FUNCTION_TO_KEYMAP (map, i));
if (r == 1)
rval = 1;
}
} }
return rval; return rval;
} }
+15 -7
View File
@@ -507,6 +507,12 @@ histfile_restore (const char *backup, const char *orig)
return (history_rename (backup, orig)); return (history_rename (backup, orig));
} }
/* Should we call chown, based on whether finfo and nfinfo describe different
files with different owners? */
#define SHOULD_CHOWN(finfo, nfinfo) \
(finfo.st_uid != nfinfo.st_uid || finfo.st_gid != nfinfo.st_gid)
/* Truncate the history file FNAME, leaving only LINES trailing lines. /* Truncate the history file FNAME, leaving only LINES trailing lines.
If FNAME is NULL, then use ~/.history. Writes a new file and renames If FNAME is NULL, then use ~/.history. Writes a new file and renames
it to the original name. Returns 0 on success, errno on failure. */ it to the original name. Returns 0 on success, errno on failure. */
@@ -515,7 +521,7 @@ history_truncate_file (const char *fname, int lines)
{ {
char *buffer, *filename, *tempname, *bp, *bp1; /* bp1 == bp+1 */ char *buffer, *filename, *tempname, *bp, *bp1; /* bp1 == bp+1 */
int file, chars_read, rv, orig_lines, exists, r; int file, chars_read, rv, orig_lines, exists, r;
struct stat finfo; struct stat finfo, nfinfo;
size_t file_size; size_t file_size;
history_lines_written_to_file = 0; history_lines_written_to_file = 0;
@@ -536,6 +542,9 @@ history_truncate_file (const char *fname, int lines)
} }
exists = 1; exists = 1;
nfinfo.st_uid = finfo.st_uid;
nfinfo.st_gid = finfo.st_gid;
if (S_ISREG (finfo.st_mode) == 0) if (S_ISREG (finfo.st_mode) == 0)
{ {
close (file); close (file);
@@ -624,6 +633,9 @@ history_truncate_file (const char *fname, int lines)
if (write (file, bp, chars_read - (bp - buffer)) < 0) if (write (file, bp, chars_read - (bp - buffer)) < 0)
rv = errno; rv = errno;
if (fstat (file, &nfinfo) < 0 && rv == 0)
rv = errno;
if (close (file) < 0 && rv == 0) if (close (file) < 0 && rv == 0)
rv = errno; rv = errno;
} }
@@ -651,7 +663,7 @@ history_truncate_file (const char *fname, int lines)
user is running this, it's a no-op. If the shell is running after sudo user is running this, it's a no-op. If the shell is running after sudo
with a shared history file, we don't want to leave the history file with a shared history file, we don't want to leave the history file
owned by root. */ owned by root. */
if (rv == 0 && exists) if (rv == 0 && exists && SHOULD_CHOWN (finfo, nfinfo))
r = chown (filename, finfo.st_uid, finfo.st_gid); r = chown (filename, finfo.st_uid, finfo.st_gid);
#endif #endif
@@ -670,7 +682,7 @@ history_do_write (const char *filename, int nelements, int overwrite)
register int i; register int i;
char *output, *tempname, *histname; char *output, *tempname, *histname;
int file, mode, rv, exists; int file, mode, rv, exists;
struct stat finfo; struct stat finfo, nfinfo;
#ifdef HISTORY_USE_MMAP #ifdef HISTORY_USE_MMAP
size_t cursize; size_t cursize;
@@ -715,15 +727,11 @@ history_do_write (const char *filename, int nelements, int overwrite)
the_history = history_list (); the_history = history_list ();
/* Calculate the total number of bytes to write. */ /* Calculate the total number of bytes to write. */
for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
#if 0
buffer_size += 2 + HISTENT_BYTES (the_history[i]);
#else
{ {
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0]) if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
buffer_size += strlen (the_history[i]->timestamp) + 1; buffer_size += strlen (the_history[i]->timestamp) + 1;
buffer_size += strlen (the_history[i]->line) + 1; buffer_size += strlen (the_history[i]->line) + 1;
} }
#endif
/* Allocate the buffer, and fill it. */ /* Allocate the buffer, and fill it. */
#ifdef HISTORY_USE_MMAP #ifdef HISTORY_USE_MMAP
+9 -4
View File
@@ -7448,8 +7448,7 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p)
from end of positional parameters? */ from end of positional parameters? */
#if 1 #if 1
if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0) if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0)
#else #else /* XXX - TAG: bash-5.1 */
/* XXX - TAG: bash-5.1 */
if (vtype == VT_ARRAYVAR && *e2p < 0) if (vtype == VT_ARRAYVAR && *e2p < 0)
#endif #endif
{ {
@@ -11517,14 +11516,20 @@ shell_expand_word_list (tlist, eflags)
opts[opti++] = 'A'; opts[opti++] = 'A';
} }
else if (tlist->word->flags & W_ASSIGNASSOC) else if (tlist->word->flags & W_ASSIGNASSOC)
opts[opti++] = 'A'; {
opts[opti++] = 'A';
opts[opti++] = 'I';
}
else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL)) else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL))
{ {
opts[opti++] = 'g'; opts[opti++] = 'g';
opts[opti++] = 'a'; opts[opti++] = 'a';
} }
else if (tlist->word->flags & W_ASSIGNARRAY) else if (tlist->word->flags & W_ASSIGNARRAY)
opts[opti++] = 'a'; {
opts[opti++] = 'a';
opts[opti++] = 'I';
}
else if (tlist->word->flags & W_ASSNGLOBAL) else if (tlist->word->flags & W_ASSNGLOBAL)
opts[opti++] = 'g'; opts[opti++] = 'g';
+1
View File
@@ -54,6 +54,7 @@
#define ASS_NOEXPAND 0x0080 /* don't expand associative array subscripts */ #define ASS_NOEXPAND 0x0080 /* don't expand associative array subscripts */
#define ASS_NOEVAL 0x0100 /* don't evaluate value as expression */ #define ASS_NOEVAL 0x0100 /* don't evaluate value as expression */
#define ASS_NOLONGJMP 0x0200 /* don't longjmp on fatal assignment error */ #define ASS_NOLONGJMP 0x0200 /* don't longjmp on fatal assignment error */
#define ASS_NOINVIS 0x0400 /* don't resolve local invisible variables */
/* Flags for the string extraction functions. */ /* Flags for the string extraction functions. */
#define SX_NOALLOC 0x0001 /* just skip; don't return substring */ #define SX_NOALLOC 0x0001 /* just skip; don't return substring */
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR PATH=$PATH:$BUILD_DIR
+13
View File
@@ -0,0 +1,13 @@
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH="$BUILD_DIR/bash -x"
PATH=$PATH:$BUILD_DIR
export THIS_SH PATH BUILD_DIR
: ${TMPDIR:=/tmp}
export TMPDIR
export BASH_TSTOUT=/tmp/xx
rm -f ${BASH_TSTOUT}
/bin/sh -x "$@"
+18 -16
View File
@@ -40,33 +40,35 @@ async list wait-for-background-pids
async list wait for child async list wait for child
forked forked
wait-when-no-children wait-when-no-children
posix jobs output
[1]+ Done sleep 1
wait-for-job wait-for-job
./jobs.tests: line 79: wait: %2: no such job ./jobs.tests: line 82: wait: %2: no such job
127 127
async list wait-for-job async list wait-for-job
forked forked
fg-bg 1 fg-bg 1
sleep 5 sleep 2
fg-bg 2 fg-bg 2
sleep 5 sleep 2
fg-bg 3 fg-bg 3
sleep 5 sleep 2
fg-bg 4 fg-bg 4
sleep 5 sleep 2
fg-bg 5 fg-bg 5
./jobs.tests: line 106: fg: %2: no such job ./jobs.tests: line 109: fg: %2: no such job
./jobs.tests: line 107: bg: job 1 already in background ./jobs.tests: line 110: bg: job 1 already in background
fg-bg 6 fg-bg 6
./jobs.tests: line 114: fg: -s: invalid option ./jobs.tests: line 117: fg: -s: invalid option
fg: usage: fg [job_spec] fg: usage: fg [job_spec]
./jobs.tests: line 115: bg: -s: invalid option ./jobs.tests: line 118: bg: -s: invalid option
bg: usage: bg [job_spec ...] bg: usage: bg [job_spec ...]
./jobs.tests: line 120: disown: -s: invalid option ./jobs.tests: line 123: disown: -s: invalid option
disown: usage: disown [-h] [-ar] [jobspec ... | pid ...] disown: usage: disown [-h] [-ar] [jobspec ... | pid ...]
./jobs.tests: line 124: disown: %1: no such job ./jobs.tests: line 127: disown: %1: no such job
./jobs.tests: line 127: disown: %2: no such job ./jobs.tests: line 130: disown: %2: no such job
wait-for-non-child wait-for-non-child
./jobs.tests: line 130: wait: pid 1 is not a child of this shell ./jobs.tests: line 133: wait: pid 1 is not a child of this shell
127 127
3 -- 1 2 3 -- 1 - 2 - 3 3 -- 1 2 3 -- 1 - 2 - 3
[1] Running sleep 300 & [1] Running sleep 300 &
@@ -76,8 +78,8 @@ running jobs:
[1] Running sleep 300 & [1] Running sleep 300 &
[2]- Running sleep 350 & [2]- Running sleep 350 &
[3]+ Running sleep 400 & [3]+ Running sleep 400 &
./jobs.tests: line 147: kill: %4: no such job ./jobs.tests: line 150: kill: %4: no such job
./jobs.tests: line 149: jobs: %4: no such job ./jobs.tests: line 152: jobs: %4: no such job
current job: current job:
[3]+ Running sleep 400 & [3]+ Running sleep 400 &
previous job: previous job:
@@ -105,5 +107,5 @@ after kill -STOP, backgrounding %3:
killing... killing...
done done
after KILL -STOP, foregrounding %1 after KILL -STOP, foregrounding %1
sleep 10 sleep 4
done done
+20 -17
View File
@@ -49,7 +49,7 @@ wait # make sure we reap the processes while stderr is still redirected
exec 2>&5 exec 2>&5
echo wait-for-pid echo wait-for-pid
sleep 10 & sleep 4 &
wait $! wait $!
echo wait-errors echo wait-errors
@@ -57,52 +57,55 @@ wait 1-1
wait -- -4 wait -- -4
echo wait-for-background-pids echo wait-for-background-pids
sleep 5 & sleep 2 &
sleep 8 & sleep 4 &
wait wait
echo async list wait-for-background-pids echo async list wait-for-background-pids
sleep 5 & sleep 8 & sleep 2 & sleep 4 &
wait wait
echo async list wait for child echo async list wait for child
sleep 5 & echo forked sleep 2 & echo forked
wait wait
echo wait-when-no-children echo wait-when-no-children
wait wait
echo posix jobs output
${THIS_SH} -o posix -c 'sleep 1 & P=$! ; sleep 2; jobs; wait'
set -m set -m
echo wait-for-job echo wait-for-job
sleep 5 & sleep 3 &
wait %2 # this should be a no-such-job error wait %2 # this should be a no-such-job error
echo $? echo $?
wait %1 wait %1
echo async list wait-for-job echo async list wait-for-job
sleep 5 & echo forked sleep 2 & echo forked
wait %1 wait %1
echo fg-bg 1 echo fg-bg 1
sleep 5 & sleep 2 &
%1 %1
echo fg-bg 2 echo fg-bg 2
sleep 5 & sleep 2 &
fg %% fg %%
echo fg-bg 3 echo fg-bg 3
sleep 5 & sleep 2 &
fg %s fg %s
echo fg-bg 4 echo fg-bg 4
sleep 5 & sleep 2 &
fg %?ee fg %?ee
# these next two are error cases # these next two are error cases
echo fg-bg 5 echo fg-bg 5
sleep 15 & sleep 2 &
fg %2 # this should be a no-such-job error fg %2 # this should be a no-such-job error
bg %1 # this should be a `bg background job?' error bg %1 # this should be a `bg background job?' error
wait wait
@@ -110,7 +113,7 @@ wait
# these may someday mean to start the jobs, but not print the line # these may someday mean to start the jobs, but not print the line
# describing the status, but for now they are errors # describing the status, but for now they are errors
echo fg-bg 6 echo fg-bg 6
sleep 5 & sleep 2 &
fg -s %1 fg -s %1
bg -s %1 bg -s %1
wait wait
@@ -153,7 +156,7 @@ echo previous job:
jobs %- jobs %-
kill -STOP %2 kill -STOP %2
sleep 5 # give time for the shell to get the stop notification sleep 3 # give time for the shell to get the stop notification
echo after kill -STOP echo after kill -STOP
echo running jobs: echo running jobs:
jobs -r jobs -r
@@ -177,7 +180,7 @@ echo stopped jobs:
jobs -s jobs -s
kill -STOP %3 kill -STOP %3
sleep 5 # give time for the shell to get the stop notification sleep 3 # give time for the shell to get the stop notification
echo after kill -STOP, backgrounding %3: echo after kill -STOP, backgrounding %3:
bg %3 bg %3
@@ -195,9 +198,9 @@ echo done
exec 2>&5 exec 2>&5
sleep 10 & sleep 4 &
kill -STOP %1 kill -STOP %1
sleep 5 # give time for the shell to get the stop notification sleep 2 # give time for the shell to get the stop notification
echo after KILL -STOP, foregrounding %1 echo after KILL -STOP, foregrounding %1
fg %1 fg %1
+2
View File
@@ -294,3 +294,5 @@ xtrace off
-- --
./shopt.tests: line 106: shopt: xyz1: invalid shell option name ./shopt.tests: line 106: shopt: xyz1: invalid shell option name
./shopt.tests: line 107: shopt: xyz1: invalid option name ./shopt.tests: line 107: shopt: xyz1: invalid option name
expand_aliases on
expand_aliases on
+4
View File
@@ -107,3 +107,7 @@ shopt -p xyz1
shopt -o -p xyz1 shopt -o -p xyz1
${THIS_SH} ./shopt1.sub ${THIS_SH} ./shopt1.sub
# test whether or not temporary variable assignments that manipulate posix
# mode restore the previous state or the default non-posix state
${THIS_SH} -c 'shopt -s expand_aliases ; shopt expand_aliases ; POSIXLY_CORRECT=y true ; shopt expand_aliases'
+12 -8
View File
@@ -2951,14 +2951,17 @@ make_new_array_variable (name)
} }
SHELL_VAR * SHELL_VAR *
make_local_array_variable (name, assoc_ok) make_local_array_variable (name, flags)
char *name; char *name;
int assoc_ok; int flags;
{ {
SHELL_VAR *var; SHELL_VAR *var;
ARRAY *array; ARRAY *array;
int assoc_ok;
var = make_local_variable (name, 0); /* XXX for now */ assoc_ok = flags & MKLOC_ASSOCOK;
var = make_local_variable (name, flags & MKLOC_INHERIT); /* XXX for now */
/* If ASSOC_OK is non-zero, assume that we are ok with letting an assoc /* If ASSOC_OK is non-zero, assume that we are ok with letting an assoc
variable return to the caller without converting it. The caller will variable return to the caller without converting it. The caller will
either flag an error or do the conversion itself. */ either flag an error or do the conversion itself. */
@@ -3004,14 +3007,17 @@ make_new_assoc_variable (name)
} }
SHELL_VAR * SHELL_VAR *
make_local_assoc_variable (name, array_ok) make_local_assoc_variable (name, flags)
char *name; char *name;
int array_ok; int flags;
{ {
SHELL_VAR *var; SHELL_VAR *var;
HASH_TABLE *hash; HASH_TABLE *hash;
int array_ok;
var = make_local_variable (name, 0); /* XXX for now */ array_ok = flags & MKLOC_ARRAYOK;
var = make_local_variable (name, flags & MKLOC_INHERIT); /* XXX for now */
/* If ARRAY_OK is non-zero, assume that we are ok with letting an array /* If ARRAY_OK is non-zero, assume that we are ok with letting an array
variable return to the caller without converting it. The caller will variable return to the caller without converting it. The caller will
either flag an error or do the conversion itself. */ either flag an error or do the conversion itself. */
@@ -3791,10 +3797,8 @@ assign_in_env (word, flags)
if (flags) if (flags)
{ {
#if 0 /* TAG:bash-5.1 from Martijn Dekker */
if (STREQ (newname, "POSIXLY_CORRECT") || STREQ (newname, "POSIX_PEDANDTIC")) if (STREQ (newname, "POSIXLY_CORRECT") || STREQ (newname, "POSIX_PEDANDTIC"))
save_posix_options (); /* XXX one level of saving right now */ save_posix_options (); /* XXX one level of saving right now */
#endif
stupidly_hack_special_variables (newname); stupidly_hack_special_variables (newname);
} }
+4 -2
View File
@@ -221,8 +221,10 @@ typedef struct _vlist {
#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0') #define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
/* Flag values for make_local_variable */ /* Flag values for make_local_variable and its array counterparts */
#define MKLOC_INHERIT 0x01 #define MKLOC_ASSOCOK 0x01
#define MKLOC_ARRAYOK 0x02
#define MKLOC_INHERIT 0x04
/* Special value for nameref with invalid value for creation or assignment */ /* Special value for nameref with invalid value for creation or assignment */
extern SHELL_VAR nameref_invalid_value; extern SHELL_VAR nameref_invalid_value;