commit bash-20200207 snapshot

This commit is contained in:
Chet Ramey
2020-02-10 09:19:37 -05:00
parent 10db656551
commit f65f3d5458
18 changed files with 312 additions and 55 deletions
+54 -1
View File
@@ -6891,7 +6891,7 @@ builtins/wait.def
variables.c
- check_unbind_variable: return -2 if the variable name is readonly
(change) or non-unsettable (new) to differentiate the return value
from -1 from makunboud (which means variable not found)
from -1 from makunbound (which means variable not found)
builtins/common.[ch]
- builtin_unbind_variable: identical to check_unbind_variable but calls
@@ -7249,6 +7249,9 @@ bashline.c
- bash_execute_unix_command: bind READLINE_MARK variable, exposing
the value of rl_mark to `bind -x' functions
doc/{bash.1,bashref.texi}
- READLINE_MARK: document new variable set by the shell
1/31
----
examples/loadables/accept.c
@@ -7261,3 +7264,53 @@ lib/readline/histfile.c
- history_do_write,history_truncate_file: translate the return value rv
to errno when histfile_restore returns -1 (e.g., if rename() fails).
Report and fix from A <auroralanes@protonmail.ch>
2/3
---
lib/sh/ufuncs.c
- fsleep: if pselect/select is interrupted by a signal, return -1 and
let the caller deal with it
lib/sh/timeval.c
- multimeval: new function, multiply a timeval by a constant integer
- divtimeval: new function, divide a timeval by a constant integer
lib/sh/uconvert.c
- uconvert: new additional argument: EP. If non-null, it gets the
address of the first non-digit that ends conversion (like strtod);
we try to do as much of the conversion as possible if EP is set so
the caller can clean up
2/4
---
examples/loadables/mkfifo.c
- mkfifo: new loadable builtin
2/6
---
variables.c
- make_local_variable: make sure local variables that have the same
names as variables found in the temporary environment are marked as
local. From Grisha Levit <grishalevit@gmail.com> back in 12/2018
2/7
---
sig.[ch]
- restore_sigmask: function to restore top-level signal mask using
sigprocmask
{sig,eval,jobs,nojobs}.c
- replace calls to sigprocmask with restore_sigmask(); remove extern
declarations of top_level_mask
sig.c
- initialize_shell_signals: if SIGCHLD is blocked at shell startup,
not only remove it from top_level_mask but make sure it's unblocked
execute_cmd.c
- execute_pipeline: if lastpipe is enabled and we're executing the
rightmost pipeline element in the current shell, make sure to unblock
SIGCHLD before calling execute_command, in case `return' or `exec'
is run and that call doesn't return. From a report by
Harald van Dijk <harald@gigawatt.nl> following up to a report
by Martijn Dekker <martijn@inlv.org>
+1
View File
@@ -740,6 +740,7 @@ examples/loadables/whoami.c f
examples/loadables/uname.c f
examples/loadables/sync.c f
examples/loadables/mkdir.c f
examples/loadables/mkfifo.c f
examples/loadables/mktemp.c f
examples/loadables/ln.c f
examples/loadables/mypid.c f
+2 -2
View File
@@ -274,7 +274,7 @@ read_builtin (list)
break;
#endif
case 't':
code = uconvert (list_optarg, &ival, &uval);
code = uconvert (list_optarg, &ival, &uval, (char **)NULL);
if (code == 0 || ival < 0 || uval < 0)
{
builtin_error (_("%s: invalid timeout specification"), list_optarg);
@@ -377,7 +377,7 @@ read_builtin (list)
/* $TMOUT, if set, is the default timeout for read. */
if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
{
code = uconvert (e, &ival, &uval);
code = uconvert (e, &ival, &uval, (char **)NULL);
if (code == 0 || ival < 0 || uval < 0)
tmsec = tmusec = 0;
else
+2 -7
View File
@@ -48,10 +48,6 @@
# include "bashhist.h"
#endif
#if defined (HAVE_POSIX_SIGNALS)
extern sigset_t top_level_mask;
#endif
static void send_pwd_to_eterm __P((void));
static sighandler alrm_catcher __P((int));
@@ -121,9 +117,8 @@ reader_loop ()
dispose_command (current_command);
current_command = (COMMAND *)NULL;
}
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
#endif
restore_sigmask ();
break;
default:
+7 -3
View File
@@ -101,9 +101,10 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins -I${srcdir} \
ALLPROG = print truefalse sleep finfo logname basename dirname fdflags \
tty pathchk tee head mkdir rmdir mktemp printenv id whoami \
uname sync push ln unlink realpath strftime mypid setpgid seq rm
OTHERPROG = necho hello cat pushd stat accept
tty pathchk tee head mkdir rmdir mkfifo mktemp printenv id whoami \
uname sync push ln unlink realpath strftime mypid setpgid seq rm \
accept
OTHERPROG = necho hello cat pushd stat
all: $(SHOBJ_STATUS)
@@ -178,6 +179,9 @@ mkdir: mkdir.o
rmdir: rmdir.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
mkfifo: mkfifo.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkfifo.o $(SHOBJ_LIBS)
mktemp: mktemp.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mktemp.o $(SHOBJ_LIBS)
+2 -1
View File
@@ -1,4 +1,5 @@
cmp
wc
mkfifo
paste
cut
+146
View File
@@ -0,0 +1,146 @@
/* mkfifo - make FIFOs */
/* See Makefile for compilation details. */
/*
Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "bashtypes.h"
#include "posixstat.h"
#include <errno.h>
#include <stdio.h>
#include "bashansi.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
#endif
#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
extern int parse_symbolic_mode ();
static int original_umask;
int
mkfifo_builtin (list)
WORD_LIST *list;
{
int opt, mflag, omode, rval, nmode, basemode;
char *mode;
WORD_LIST *l;
mflag = 0;
mode = (char *)NULL;
reset_internal_getopt ();
while ((opt = internal_getopt(list, "m:")) != -1)
switch (opt)
{
case 'm':
mflag = 1;
mode = list_optarg;
break;
CASE_HELPOPT;
default:
builtin_usage();
return (EX_USAGE);
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
basemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if (mode == NULL)
omode = basemode;
else if (ISOCTAL (*mode)) /* octal number */
{
omode = read_octal (mode);
if (omode < 0)
{
builtin_error ("invalid file mode: %s", mode);
return (EXECUTION_FAILURE);
}
}
else /* symbolic mode */
{
/* initial bits are a=rwx; the mode argument modifies them */
omode = parse_symbolic_mode (mode, basemode);
if (omode < 0)
{
builtin_error ("invalid file mode: %s", mode);
return (EXECUTION_FAILURE);
}
}
/* Make the new mode */
original_umask = umask (0);
umask (original_umask);
nmode = basemode & ~original_umask;
/* Adjust new mode based on mode argument */
nmode &= omode;
for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
{
if (mkfifo (l->word->word, nmode) < 0)
{
builtin_error ("cannot create FIFO `%s': %s", l->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
}
}
return rval;
}
char *mkfifo_doc[] = {
"Create FIFOs (named pipes).",
"",
"Make FIFOs. Create the FIFOs named as arguments, in",
"the order specified, using mode a=rw as modified by the current",
"umask (see `help umask'). The -m option causes the file permission",
"bits of the final FIFO to be MODE. The MODE argument may be",
"an octal number or a symbolic mode like that used by chmod(1). If",
"a symbolic mode is used, the operations are interpreted relative to",
"an initial mode of \"a=rw\". mkfifo returns 0 if the FIFOs are",
"umask, plus write and search permissions for the owner. mkdir",
"created successfully, and non-zero if an error occurs.",
(char *)NULL
};
struct builtin mkfifo_struct = {
"mkfifo",
mkfifo_builtin,
BUILTIN_ENABLED,
mkfifo_doc,
"mkfifo [-m mode] fifo_name [fifo_name ...]",
0
};
+9 -2
View File
@@ -5,7 +5,7 @@
*/
/*
Copyright (C) 1999-2009 Free Software Foundation, Inc.
Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
@@ -53,6 +53,9 @@ sleep_builtin (list)
WORD_LIST *list;
{
long sec, usec;
char *ep;
int r, mul;
time_t t;
if (list == 0) {
builtin_usage();
@@ -68,8 +71,12 @@ WORD_LIST *list;
return (EX_USAGE);
}
if (uconvert(list->word->word, &sec, &usec)) {
r = uconvert(list->word->word, &sec, &usec, &ep);
/* Maybe postprocess conversion failures here based on EP */
if (r) {
fsleep(sec, usec);
QUIT;
return(EXECUTION_SUCCESS);
}
+3
View File
@@ -2563,6 +2563,9 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
old_frozen = freeze_jobs_list ();
lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL); /* XXX */
add_unwind_protect (lastpipe_cleanup, old_frozen);
#if defined (JOB_CONTROL)
UNBLOCK_CHILD (oset); /* XXX */
#endif
}
if (cmd)
cmd->flags |= CMD_LASTPIPE;
+1 -1
View File
@@ -481,7 +481,7 @@ extern int sh_mktmpfd __P((char *, int, char **));
extern char *sh_mktmpdir __P((char *, int));
/* declarations for functions defined in lib/sh/uconvert.c */
extern int uconvert __P((char *, long *, long *));
extern int uconvert __P((char *, long *, long *, char **));
/* declarations for functions defined in lib/sh/ufuncs.c */
extern unsigned int falarm __P((unsigned int, unsigned int));
+2 -3
View File
@@ -165,7 +165,6 @@ extern int killpg PARAMS((pid_t, int));
typedef int sh_job_map_func_t PARAMS((JOB *, int, int, int));
/* Variables used here but defined in other files. */
extern sigset_t top_level_mask;
extern WORD_LIST *subst_assign_varlist;
extern SigHandler **original_signals;
@@ -2210,8 +2209,8 @@ make_child (command, async_p)
CLRINTERRUPT; /* XXX - children have their own interrupt state */
/* Restore top-level signal mask. */
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
restore_sigmask ();
if (job_control)
{
/* All processes in this pipeline belong in the same
+27
View File
@@ -67,6 +67,32 @@ addtimeval (d, t1, t2)
return d;
}
struct timeval *
multimeval (d, m)
struct timeval *d;
int m;
{
time_t t;
t = d->tv_usec * m;
d->tv_sec = d->tv_sec * m + t / 1000000;
d->tv_usec = t % 1000000;
return d;
}
struct timeval *
divtimeval (d, m)
struct timeval *d;
int m;
{
time_t t;
t = d->tv_sec;
d->tv_sec = t / m;
d->tv_usec = (d->tv_usec + 1000000 * (t % m)) / m;
return d;
}
/* Do "cpu = ((user + sys) * 10000) / real;" with timevals.
Barely-tested code from Deven T. Corzine <deven@ties.org>. */
int
@@ -149,4 +175,5 @@ print_timeval (fp, tvp)
fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint (), seconds_fraction);
}
#endif /* HAVE_TIMEVAL */
+20 -3
View File
@@ -1,7 +1,7 @@
/* uconvert - convert string representations of decimal numbers into whole
number/fractional value pairs. */
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
/* Copyright (C) 2008,2009,2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -50,6 +50,7 @@
do { \
if (ip) *ip = ipart * mult; \
if (up) *up = upart; \
if (ep) *ep = p; \
return (x); \
} while (0)
@@ -61,12 +62,14 @@ static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 };
/* Take a decimal number int-part[.[micro-part]] and convert it to the whole
and fractional portions. The fractional portion is returned in
millionths (micro); callers are responsible for multiplying appropriately.
EP, if non-null, gets the address of the character where conversion stops.
Return 1 if value converted; 0 if invalid integer for either whole or
fractional parts. */
int
uconvert(s, ip, up)
uconvert(s, ip, up, ep)
char *s;
long *ip, *up;
char **ep;
{
int n, mult;
long ipart, upart;
@@ -102,7 +105,14 @@ uconvert(s, ip, up)
for (n = 0; n < 6 && p[n]; n++)
{
if (DIGIT(p[n]) == 0)
RETURN(0);
{
if (ep)
{
upart *= multiplier[n];
p += n; /* To set EP */
}
RETURN(0);
}
upart = (upart * 10) + (p[n] - '0');
}
@@ -112,5 +122,12 @@ uconvert(s, ip, up)
if (n == 6 && p[6] >= '5' && p[6] <= '9')
upart++; /* round up 1 */
if (ep)
{
p += n;
while (DIGIT(*p))
p++;
}
RETURN(1);
}
+1 -1
View File
@@ -130,7 +130,7 @@ fsleep(sec, usec)
#endif
e = errno;
if (r < 0 && errno == EINTR)
QUIT; /* just signals, no traps */
return -1; /* caller will handle */
errno = e;
}
while (r < 0 && errno == EINTR);
+1 -7
View File
@@ -74,10 +74,6 @@
extern int errno;
#endif /* !errno */
#if defined (HAVE_POSIX_SIGNALS)
extern sigset_t top_level_mask;
#endif
extern void set_original_signal __P((int, SigHandler *));
volatile pid_t last_made_pid = NO_PID;
@@ -557,10 +553,8 @@ make_child (command, async_p)
CLRINTERRUPT; /* XXX - children have their own interrupt state */
#if defined (HAVE_POSIX_SIGNALS)
/* Restore top-level signal mask. */
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
#endif
restore_sigmask ();
#if 0
/* Ignore INT and QUIT in asynchronous children. */
+14 -4
View File
@@ -309,7 +309,11 @@ initialize_shell_signals ()
sigemptyset (&top_level_mask);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
# if defined (SIGCHLD)
sigdelset (&top_level_mask, SIGCHLD);
if (sigismember (&top_level_mask, SIGCHLD))
{
sigdelset (&top_level_mask, SIGCHLD);
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
}
# endif
#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
@@ -425,11 +429,9 @@ throw_to_top_level ()
give_terminal_to (shell_pgrp, 0);
#endif /* JOB_CONTROL */
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
/* This needs to stay because jobs.c:make_child() uses it without resetting
the signal mask. */
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
#endif
restore_sigmask ();
reset_parser ();
@@ -469,6 +471,14 @@ jump_to_top_level (value)
sh_longjmp (top_level, value);
}
void
restore_sigmask ()
{
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
#endif
}
sighandler
termsig_sighandler (sig)
int sig;
+19 -18
View File
@@ -32,7 +32,7 @@
#endif
#define sighandler RETSIGTYPE
typedef RETSIGTYPE SigHandler __P((int));
typedef RETSIGTYPE SigHandler PARAMS((int));
#if defined (VOID_SIGHANDLER)
# define SIGRETURN(n) return
@@ -46,7 +46,7 @@ typedef RETSIGTYPE SigHandler __P((int));
#if !defined (HAVE_POSIX_SIGNALS)
# define set_signal_handler(sig, handler) (SigHandler *)signal (sig, handler)
#else
extern SigHandler *set_signal_handler __P((int, SigHandler *)); /* in sig.c */
extern SigHandler *set_signal_handler PARAMS((int, SigHandler *)); /* in sig.c */
#endif /* _POSIX_VERSION */
#if !defined (SIGCHLD) && defined (SIGCLD)
@@ -113,25 +113,26 @@ extern int interrupt_immediately; /* no longer used */
extern int terminate_immediately;
/* Functions from sig.c. */
extern sighandler termsig_sighandler __P((int));
extern void termsig_handler __P((int));
extern sighandler sigint_sighandler __P((int));
extern void initialize_signals __P((int));
extern void initialize_terminating_signals __P((void));
extern void reset_terminating_signals __P((void));
extern void top_level_cleanup __P((void));
extern void throw_to_top_level __P((void));
extern void jump_to_top_level __P((int)) __attribute__((__noreturn__));
extern sighandler termsig_sighandler PARAMS((int));
extern void termsig_handler PARAMS((int));
extern sighandler sigint_sighandler PARAMS((int));
extern void initialize_signals PARAMS((int));
extern void initialize_terminating_signals PARAMS((void));
extern void reset_terminating_signals PARAMS((void));
extern void top_level_cleanup PARAMS((void));
extern void throw_to_top_level PARAMS((void));
extern void jump_to_top_level PARAMS((int)) __attribute__((__noreturn__));
extern void restore_sigmask PARAMS((void));
extern sighandler sigwinch_sighandler __P((int));
extern void set_sigwinch_handler __P((void));
extern void unset_sigwinch_handler __P((void));
extern sighandler sigwinch_sighandler PARAMS((int));
extern void set_sigwinch_handler PARAMS((void));
extern void unset_sigwinch_handler PARAMS((void));
extern sighandler sigterm_sighandler __P((int));
extern sighandler sigterm_sighandler PARAMS((int));
/* Functions defined in trap.c. */
extern SigHandler *set_sigint_handler __P((void));
extern SigHandler *trap_to_sighandler __P((int));
extern sighandler trap_handler __P((int));
extern SigHandler *set_sigint_handler PARAMS((void));
extern SigHandler *trap_to_sighandler PARAMS((int));
extern sighandler trap_handler PARAMS((int));
#endif /* _SIG_H_ */
+1 -2
View File
@@ -2771,7 +2771,6 @@ make_local_variable (name, flags)
if (was_tmpvar && old_var->context == variable_context && last_table_searched != temporary_env)
{
VUNSETATTR (old_var, att_invisible); /* XXX */
#if 0 /* TAG:bash-5.1 */
/* We still want to flag this variable as local, though, and set things
up so that it gets treated as a local variable. */
new_var = old_var;
@@ -2781,7 +2780,7 @@ make_local_variable (name, flags)
if (vc_isfuncenv (vc) && vc->scope == variable_context)
break;
goto set_local_var_flags;
#endif
return (old_var);
}