From: Chet Ramey Date: Mon, 25 Mar 2019 13:36:24 +0000 (-0400) Subject: commit bash-20190322 snapshot X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=31321bf1b28b94d630157b788df12b2d6a3942d2;p=thirdparty%2Fbash.git commit bash-20190322 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index ab18ef22e..398d4abe3 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -5626,3 +5626,35 @@ execute_cmd.c do it at the beginning -- look at this more closely). Only do it for loops to avoid fd exhaustion. Fixes bug reported by sunnycemetery@gmail.com + + 3/22 + ---- +lib/readline/{rlprivate.h,signals.c} + - _rl_interrupt_immediately: removed as no longer used + +redir.c + - heredoc_expand: new function, called for both here-documents and + here-strings, takes care of expanding the document and returns a + string + - write_here_document: use heredoc_expand, call write(2) once on the + entire document; structure is now very similar to write_here_string + + 3/23 + ---- +redir.c + - here_document_to_fd: expand the here document/here string first, + using heredoc_expand, then decide what to do; remove calls to + write_here_document/write_here_string in favor of calling + heredoc_write directly + - here_document_to_fd: if the expanded document is of zero length, + just open /dev/null right away and return it -- idea from yash + - here_document_to_fd: if the length of the expanded document is + between 1 and PIPESIZE (pipe capacity, computed by builtins/psize.aux + and stored in builtins/pipesize.h), try to use a pipe: write + the document to the write end and return the read end. Prompted by a + report from Daniel Kahn Gillmor + +builtins/enable.def + - dyn_load_builtin: add warning if dynamic builtin with a load function + is loaded more than once, before running the load function a second + time. From a suggestion by Stan Marsh diff --git a/Makefile.in b/Makefile.in index 2a83c4b7f..4391c4067 100644 --- a/Makefile.in +++ b/Makefile.in @@ -742,6 +742,9 @@ ${DEFDIR}/bashgetopt.o: $(BUILTIN_SRCDIR)/bashgetopt.c ${DEFDIR}/builtext.h: $(BUILTIN_DEFS) @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) builtext.h ) || exit 1 +${DEFDIR}/pipesize.h: + @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) pipesize.h ) || exit 1 + $(SDIR)/man2html$(EXEEXT): ${SUPPORT_SRC}/man2html.c @(cd $(SDIR) && $(MAKE) $(MFLAGS) all ) || exit 1 @@ -1111,6 +1114,7 @@ redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posix redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h redir.o: flags.h execute_cmd.h redir.h input.h +redir.o: ${DEFDIR}/pipesize.h shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h diff --git a/builtins/enable.def b/builtins/enable.def index 39c366982..42af0e69c 100644 --- a/builtins/enable.def +++ b/builtins/enable.def @@ -362,6 +362,8 @@ dyn_load_builtin (list, flags, filename) strcpy (struct_name, name); strcpy (struct_name + size, STRUCT_SUFFIX); + old_builtin = builtin_address_internal (name, 1); + b = (struct builtin *)dlsym (handle, struct_name); if (b == 0) { @@ -381,6 +383,9 @@ dyn_load_builtin (list, flags, filename) loadfunc = (sh_load_func_t *)dlsym (handle, funcname); if (loadfunc) { + /* Add warning if running an init function more than once */ + if (old_builtin && (old_builtin->flags & STATIC_BUILTIN) == 0) + builtin_warning (_("%s: dynamic builtin already loaded"), name); r = (*loadfunc) (name); if (r == 0) { @@ -396,7 +401,7 @@ dyn_load_builtin (list, flags, filename) b->flags |= SPECIAL_BUILTIN; b->handle = handle; - if (old_builtin = builtin_address_internal (name, 1)) + if (old_builtin) { replaced++; FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin)); diff --git a/doc/bash.1 b/doc/bash.1 index a25e50dfe..542730a07 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,12 +5,12 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Tue Feb 26 09:46:20 EST 2019 +.\" Last Change: Sun Mar 24 14:05:55 EDT 2019 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2019 February 26" "GNU Bash 5.0" +.TH BASH 1 "2019 March 24" "GNU Bash 5.0" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -5212,7 +5212,7 @@ jobs are terminated. .PP When the shell is waiting for a job or process using the \fBwait\fP builtin, and job control is enabled, \fBwait\fP will return when the -job changes state. The \fB\-f\fP option will force \fBwait\fP to wait +job changes state. The \fB\-f\fP option causes \fBwait\fP to wait until the job or process terminates before returning. .SH PROMPTING When executing interactively, @@ -10761,9 +10761,9 @@ is not given, all currently active child processes are waited for, and the return status is zero. If the \fB\-n\fP option is supplied, \fBwait\fP waits for any job to terminate and returns its exit status. -If the \fB\-f\fP option is supplied, and job control is enabled, -\fBwait\fP forces \fIid\fP to terminate before returning its status, -instead of returning when it changes status. +Supplying the \fB\-f\fP option, when job control is enabled, +forces \fBwait\fP to wait for \fIid\fP to terminate before returning +its status, instead of returning when it changes status. If .I id specifies a non-existent process or job, the return status is diff --git a/doc/bashref.texi b/doc/bashref.texi index 1d59bf643..70ab6473b 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -7988,7 +7988,7 @@ Bash does not print another warning, and any stopped jobs are terminated. When the shell is waiting for a job or process using the @code{wait} builtin, and job control is enabled, @code{wait} will return when the -job changes state. The @option{-f} option will force @code{wait} to wait +job changes state. The @option{-f} option causes @code{wait} to wait until the job or process terminates before returning. @node Job Control Builtins @@ -8098,9 +8098,10 @@ If no arguments are given, all currently active child processes are waited for, and the return status is zero. If the @option{-n} option is supplied, @code{wait} waits for any job to terminate and returns its exit status. -If the @option{-f} option is supplied, and job control is enabled, -@code{wait} forces each @var{pid} or @var{jobspec} to terminate before -returning its status, intead of returning when it changes status. +Supplying the @option{-f} option, when job control is enabled, +forces @code{wait} to wait for each @var{pid} or @var{jobspec} to +terminate before returning its status, intead of returning when it changes +status. If neither @var{jobspec} nor @var{pid} specifies an active child process of the shell, the return status is 127. diff --git a/doc/version.texi b/doc/version.texi index d0de6f957..b98da0940 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,10 @@ Copyright (C) 1988-2019 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Tue Feb 26 09:46:37 EST 2019 +@set LASTCHANGE Sun Mar 24 14:05:55 EDT 2019 @set EDITION 5.0 @set VERSION 5.0 -@set UPDATED 26 February 2019 -@set UPDATED-MONTH February 2019 +@set UPDATED 24 March 2019 +@set UPDATED-MONTH March 2019 diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 11da43cec..38e1dc79b 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -526,7 +526,6 @@ extern int _rl_executing_keyseq_size; extern _rl_search_cxt *_rl_nscxt; /* signals.c */ -extern int _rl_interrupt_immediately; extern int volatile _rl_caught_signal; extern _rl_sigcleanup_func_t *_rl_sigcleanup; diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 76c5c4733..d738db4ef 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -99,7 +99,6 @@ int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */ #endif /* Private variables. */ -int _rl_interrupt_immediately = 0; int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including everywhere */ /* If non-zero, print characters corresponding to received signals as long as @@ -163,14 +162,7 @@ _rl_signal_handler (int sig) static RETSIGTYPE rl_signal_handler (int sig) { - if (_rl_interrupt_immediately) - { - _rl_interrupt_immediately = 0; - _rl_handle_signal (sig); - } - else - _rl_caught_signal = sig; - + _rl_caught_signal = sig; SIGHANDLER_RETURN; } diff --git a/redir.c b/redir.c index 0c0c9f2ba..40ea6f2d1 100644 --- a/redir.c +++ b/redir.c @@ -1,6 +1,6 @@ /* redir.c -- Functions to perform input and output redirection. */ -/* Copyright (C) 1997-2016 Free Software Foundation, Inc. +/* Copyright (C) 1997-2019 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -58,6 +58,17 @@ extern int errno; # include "input.h" #endif +#include "builtins/pipesize.h" + +/* Normally set by a build process command that computes pipe capacity */ +#ifndef PIPESIZE +# ifdef PIPE_BUF +# define PIPESIZE PIPE_BUF +# else +# define PIPESIZE 4096 +# endif +#endif + #define SHELL_FD_BASE 10 int expanding_redir; @@ -74,8 +85,8 @@ static int stdin_redirection __P((enum r_instruction, int)); static int undoablefd __P((int)); static int do_redirection_internal __P((REDIRECT *, int)); -static int write_here_document __P((int, WORD_DESC *)); -static int write_here_string __P((int, WORD_DESC *)); +static char *heredoc_expand __P((WORD_DESC *, enum r_instruction, size_t *)); +static int heredoc_write __P((int, char *, size_t)); static int here_document_to_fd __P((WORD_DESC *, enum r_instruction)); static int redir_special_open __P((int, char *, int, int, enum r_instruction)); @@ -309,19 +320,45 @@ redirection_expand (word) return (result); } -static int -write_here_string (fd, redirectee) - int fd; +/* Expand a here-document or here-string (determined by RI) contained in + REDIRECTEE and return the expanded document. If LENP is non-zero, put + the length of the returned string into *LENP. + + This captures everything about expanding here-documents and here-strings: + the returned document should be written directly to whatever file + descriptor is specified. In particular, it adds a newline to the end of + a here-string to preserve previous semantics. */ +static char * +heredoc_expand (redirectee, ri, lenp) WORD_DESC *redirectee; + enum r_instruction ri; + size_t *lenp; { - char *herestr; - int herelen, n, e, old; + char *document; + size_t dlen; + int old; + + if (redirectee->word == 0 || redirectee->word[0] == '\0') + { + if (lenp) + *lenp = 0; + return (redirectee->word); + } + /* Quoted here documents are not expanded */ + if (ri != r_reading_string && (redirectee->flags & W_QUOTED)) + { + if (lenp) + *lenp = STRLEN (redirectee->word); + return (redirectee->word); + } + expanding_redir = 1; /* Now that we've changed the variable search order to ignore the temp environment, see if we need to change the cached IFS values. */ sv_ifs ("IFS"); - herestr = expand_string_unsplit_to_string (redirectee->word, 0); + document = (ri == r_reading_string) ? expand_string_unsplit_to_string (redirectee->word, 0) + : expand_string_to_string (redirectee->word, Q_HERE_DOCUMENT); expanding_redir = 0; /* Now we need to change the variable search order back to include the temp environment. We force the temp environment search by forcing @@ -332,136 +369,108 @@ write_here_string (fd, redirectee) sv_ifs ("IFS"); executing_builtin = old; - herelen = STRLEN (herestr); - - n = write (fd, herestr, herelen); - if (n == herelen) + dlen = STRLEN (document); + /* XXX - Add trailing newline to here-string */ + if (ri == r_reading_string) { - n = write (fd, "\n", 1); - herelen = 1; + document = xrealloc (document, dlen + 2); + document[dlen++] = '\n'; + document[dlen] = '\0'; } + if (lenp) + *lenp = dlen; + + return document; +} + +/* Write HEREDOC (of length HDLEN) to FD, returning 0 on success and ERRNO on + error. Don't handle interrupts. */ +static int +heredoc_write (fd, heredoc, herelen) + int fd; + char *heredoc; + size_t herelen; +{ + ssize_t nw; + int e; + + errno = 0; + nw = write (fd, heredoc, herelen); e = errno; - FREE (herestr); - if (n != herelen) + if (nw != herelen) { if (e == 0) e = ENOSPC; return e; } return 0; -} +} -/* Write the text of the here document pointed to by REDIRECTEE to the file - descriptor FD, which is already open to a temp file. Return 0 if the - write is successful, otherwise return errno. */ +/* Create a temporary file or pipe holding the text of the here document + pointed to by REDIRECTEE, and return a file descriptor open for reading + to it. Return -1 on any error, and make sure errno is set appropriately. */ static int -write_here_document (fd, redirectee) - int fd; +here_document_to_fd (redirectee, ri) WORD_DESC *redirectee; + enum r_instruction ri; { + char *filename; + int r, fd, fd2, herepipe[2]; char *document; - int document_len, fd2, old; - FILE *fp; - register WORD_LIST *t, *tlist; + size_t document_len; - /* Expand the text if the word that was specified had - no quoting. The text that we expand is treated - exactly as if it were surrounded by double quotes. */ + /* Expand the here-document/here-string first and then decide what to do. */ + document = heredoc_expand (redirectee, ri, &document_len); - if (redirectee->flags & W_QUOTED) + /* If we have a zero-length document, don't mess with a temp file */ + if (document_len == 0) { - document = redirectee->word; - document_len = strlen (document); - /* Set errno to something reasonable if the write fails. */ - if (write (fd, document, document_len) < document_len) - { - if (errno == 0) - errno = ENOSPC; - return (errno); - } - else - return 0; + fd = open ("/dev/null", O_RDONLY); + r = errno; + if (document != redirectee->word) + FREE (document); + errno = r; + return fd; } - expanding_redir = 1; - /* Now that we've changed the variable search order to ignore the temp - environment, see if we need to change the cached IFS values. */ - sv_ifs ("IFS"); - tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT); - expanding_redir = 0; - /* Now we need to change the variable search order back to include the temp - environment. We force the temp environment search by forcing - executing_builtin to 1. This is what makes `read' get the right values - for the IFS-related cached variables, for example. */ - old = executing_builtin; - executing_builtin = 1; - sv_ifs ("IFS"); - executing_builtin = old; - - if (tlist) +#if defined (PIPESIZE) + /* Try to use a pipe internal to this process if the document is shorter + than the system's pipe capacity (computed at build time). We want to + write the entire document without write blocking. */ + if (document_len <= PIPESIZE) { - /* Try using buffered I/O (stdio) and writing a word - at a time, letting stdio do the work of buffering - for us rather than managing our own strings. Most - stdios are not particularly fast, however -- this - may need to be reconsidered later. */ - if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL) - { - old = errno; - if (fd2 >= 0) - close (fd2); - dispose_words (tlist); - errno = old; - return (errno); - } - errno = 0; - for (t = tlist; t; t = t->next) + if (pipe (herepipe) < 0) { - /* This is essentially the body of - string_list_internal expanded inline. */ - document = t->word->word; - document_len = strlen (document); - if (t != tlist) - putc (' ', fp); /* separator */ - fwrite (document, document_len, 1, fp); - if (ferror (fp)) - { - if (errno == 0) - errno = ENOSPC; - fd2 = errno; - fclose(fp); - dispose_words (tlist); - return (fd2); - } + r = errno; + if (document != redirectee->word) + free (document); + errno = r; + return (-1); } - dispose_words (tlist); - if (fclose (fp) != 0) + r = heredoc_write (herepipe[1], document, document_len); + if (document != redirectee->word) + free (document); + close (herepipe[1]); + if (r) /* write error */ { - if (errno == 0) - errno = ENOSPC; - return (errno); + close (herepipe[0]); + errno = r; + return (-1); } + return (herepipe[0]); } - return 0; -} - -/* Create a temporary file holding the text of the here document pointed to - by REDIRECTEE, and return a file descriptor open for reading to the temp - file. Return -1 on any error, and make sure errno is set appropriately. */ -static int -here_document_to_fd (redirectee, ri) - WORD_DESC *redirectee; - enum r_instruction ri; -{ - char *filename; - int r, fd, fd2; +#endif fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename); /* If we failed for some reason other than the file existing, abort */ if (fd < 0) { + r = errno; FREE (filename); + if (document != redirectee->word) + FREE (document); + errno = r; return (fd); } @@ -469,10 +478,9 @@ here_document_to_fd (redirectee, ri) SET_CLOSE_ON_EXEC (fd); errno = r = 0; /* XXX */ - /* write_here_document returns 0 on success, errno on failure. */ - if (redirectee->word) - r = (ri != r_reading_string) ? write_here_document (fd, redirectee) - : write_here_string (fd, redirectee); + r = heredoc_write (fd, document, document_len); + if (document != redirectee->word) + FREE (document); if (r) { diff --git a/tests/heredoc.right b/tests/heredoc.right index f6541dcaf..be68f9b72 100644 --- a/tests/heredoc.right +++ b/tests/heredoc.right @@ -1,3 +1,11 @@ +a +b +c +a +$PS4 + + + there one - alpha two - beta @@ -93,6 +101,6 @@ argv[1] = argv[2] = argv[3] = comsub here-string -./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF') +./heredoc.tests: line 133: warning: here-document at line 131 delimited by end-of-file (wanted `EOF') hi there diff --git a/tests/heredoc.tests b/tests/heredoc.tests index 303949f48..6cbc4f808 100644 --- a/tests/heredoc.tests +++ b/tests/heredoc.tests @@ -1,5 +1,33 @@ -# check order and content of multiple here docs +# basics +cat <