Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • rindeal-mirrors/dash
1 result
Show changes
Commits on Source (21)
  • Denys Vlasenko's avatar
    trap: Globally rename pendingsigs to pending_sig · 53dab360
    Denys Vlasenko authored
    
    This variable does not contain "sigs" (plural).
    It contains either 0 or (one) signal number of a pending signal.
    
    For someone unfamiliar with this code, "pendingsigs" name is confusing -
    it hints at being an array or bit mask of pending singnals.
    
    Signed-off-by: default avatarDenys Vlasenko <dvlasenk@redhat.com>
    CC: dash@vger.kernel.org
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    53dab360
  • Harald van Dijk's avatar
    builtin: describe_command - fix incorrect path · f19f3b39
    Harald van Dijk authored
    
    Hi,
    
    On 26/05/17 09:04, Youfu Zhang wrote:
    > $ PATH=/extra/path:/usr/sbin:/usr/bin:/sbin:/bin \
    >> sh -xc 'command -V ls; command -V ls; command -Vp ls; command -vp ls'
    > + command -V ls
    > ls is /bin/ls
    > + command -V ls
    > ls is a tracked alias for /bin/ls
    > + command -Vp ls
    > ls is a tracked alias for (null)
    > + command -vp ls
    > Segmentation fault (core dumped)
    >
    > describe_command should respect `path' argument. Looking up in the hash table
    > may gives incorrect index in entry.u.index and finally causes incorrect output
    > or SIGSEGV.
    
    True, but only when a path is passed in. If the default path is used,
    looking up in the hash table is correct, and printing tracked aliases is
    intentional.
    
    If it's desirable to drop that feature, then it should be dropped
    completely, code shouldn't be left in that can no longer be used. But
    it's possible to keep it working: how about this instead?
    
    Signed-off-by: default avatarHarald van Dijk <harald@gigawatt.nl>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    f19f3b39
  • Larry Hynes's avatar
    man: Small cleanup for Command Line Editing · 68dac4c5
    Larry Hynes authored
    
    Jilles Tjoelker <jilles@stack.nl> wrote:
    > On Sat, Jun 17, 2017 at 03:53:26PM +0100, Larry Hynes wrote:
    >> src/dash.1, under Command Line Editing, states:
    
    >>       It's similar to vi: typing <ESC> will throw you into command
    >>       VI command mode.
    
    >> - There appears to be no need for both occurrences of 'command'
    >> - I can't see a reason for VI to be capitalised
    >> - 'will throw you into' seems a little... enthusiastic
    
    >> Following diff changes it to
    
    >>       It's similar to vi: typing <ESC> enters vi command mode.
    
    >> diff --git a/src/dash.1 b/src/dash.1
    >> index 8b8026d..f35d89d 100644
    >> --- a/src/dash.1
    >> +++ b/src/dash.1
    >> @@ -2232,7 +2232,7 @@ enabled, sh can be switched between insert mode and command mode.
    >>  The editor is not described in full here, but will be in a later document.
    >>  It's similar to vi: typing
    >>  .Aq ESC
    >> -will throw you into command VI command mode.
    >> +enters vi command mode.
    >>  Hitting
    >>  .Aq return
    >>  while in command mode will pass the line to the shell.
    
    > I agree. If you're changing things here anyway, I suggest getting rid of
    > the contraction as well (changing It's to It is). The fairly formal
    > style of man pages avoids contractions, just like it avoids "you".
    
    > The reference to the "later document" can probably be removed as well,
    > since said document does not exist yet after many years.
    
    Hi
    
    Revised diff, below, expands the contraction, deletes reference to
    'later document' and changes 'place' to 'places' in the following:
    
    	The command ‘set -o vi’ enables vi-mode editing and place sh
    	into vi insert mode.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    68dac4c5
  • Harald van Dijk's avatar
    input: Fix here-document redirection with vi/emacs on · 7f31919c
    Harald van Dijk authored
    
    On 27/06/17 16:29, Zando Fardones wrote:
    > Hello,
    >
    > I think I've found a bug when using the here-document redirection in
    > an interactive shell. What basically happens is that you can't see the
    > command output if you set the "vi" or "emacs" options.
    
    That's not quite what happens: the here-document contents got lost, so
    there is no command output to see. Nice find.
    
    The problem is that getprompt() is implicitly called by el_gets(). This
    messes with the memory used by the parser to store the here-document's
    contents. In the non-emacs/vi case, the prompt is explicitly written by
    setprompt(), which wraps the getprompt() call in a
    pushstackmark()/popstackmark() pair to restore the state so that parsing
    can continue. But when getprompt() is called by el_gets(), it knows
    nothing about this.
    
    The whole call to el_gets() can be surrounded by another
    pushstackmark()/popstackmark() pair to solve the problem, as attached.
    
    Cheers,
    Harald van Dijk
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    7f31919c
  • Rink Springer's avatar
    expand: Remove dependency on fmatch.h if it does not exit · 556e2f03
    Rink Springer authored
    
    [ Ugh; forgot to attach patch - apologies, I need more coffee ]
    
    Dear all,
    
    Attached is a trivial patch that removes the assumption that fnmatch.h
    is available - the configure script already checks for fnmatch(3) and
    supplies its own implementation if necessary, but fnmatch.h is always
    included.
    
    Let me know what you think.
    
    Regards,
    Rink
    
    Do not assume we can include fnmatch.h
    
    Signed-off-by: default avatarRink Springer <rink@rink.nu>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    556e2f03
  • Baruch Siach's avatar
    histedit: fix build with musl libc · 523d2487
    Baruch Siach authored
    
    musl libc defines the optreset BSD extension only in getopt.h. This
    fixes the following build failure:
    
    histedit.c: In function 'histcmd':
    histedit.c:220:2: error: 'optreset' undeclared (first use in this function)
      optreset = 1; optind = 1; /* initialize getopt */
      ^~~~~~~~
    
    Signed-off-by: default avatarBaruch Siach <baruch@tkos.co.il>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    523d2487
  • Martijn Dekker's avatar
    expand: 'nolog' and 'debug' options cause "$-" to wreak havoc · 81a501b7
    Martijn Dekker authored
    
    Op 29-03-17 om 20:02 schreef Martijn Dekker:
    > Bug: if either the 'nolog' or the 'debug' option is set, trying to
    > expand "$-" silently aborts parsing of an entire argument.
    >
    > $ dash -o nolog -c 'set -fuC; echo "|$- are the options|"; \
    > 	set +o nolog; echo "|$- are the options|"'
    > |
    > |uCf are the options|
    > $ dash -o debug -c 'set -fuC; echo "|$- are the options|"; \
    > 	set +o debug; echo "|$- are the options|"'
    > |
    > |uCf are the options|
    
    This turned out to be easy to fix. The routine producing the "$-"
    expansion failed to skip options for which there is no option letter,
    but only a long-form name. In dash, 'nolog' and 'debug' are currently
    the only two such options. Patch below.
    
    - Martijn
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    81a501b7
  • Martijn Dekker's avatar
    mystring: fix "Illegal number" on FreeBSD & macOS for x=; echo $((x)) · 2b3fb53c
    Martijn Dekker authored
    
    Op 07-03-18 om 06:26 schreef Herbert Xu:
    > Martijn Dekker <martijn@inlv.org> wrote:
    >>
    >>> Since base is always a constant 0 or a constant 10, never a
    >>> user-provided value, the only error that strtoimax will ever report on
    >>> glibc systems is ERANGE. Checking only ERANGE therefore preserves the
    >>> glibc behaviour, and allows the exact same set of errors to be detected
    >>> on non-glibc systems.
    >>
    >> That makes sense, thanks.
    >
    > Could you resend your patch with this change please?
    
    OK, see below.
    
    - M.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    2b3fb53c
  • Martijn Dekker's avatar
    builtin: Greater resolution in test -nt / test -ot · fc914153
    Martijn Dekker authored
    
    Op 07-03-18 om 15:46 schreef Martijn Dekker:
    > Op 06-03-18 om 09:19 schreef Herbert Xu:
    >> On Thu, Jun 22, 2017 at 10:30:02AM +0200, Petr Skočík wrote:
    >>> would you be willing to pull something like this?
    > [...]
    >>> I could use greater resolution in `test -nt` / `test -ot`, and st_mtim
    >>> field is standardized under POSIX.1-2008 (or so stat(2) says).
    >>
    >> Sure.  But your patch is corrupted.
    >
    > Fixed patch attached.
    >
    > But I wouldn't apply it as is. My system does not have st_mtim. So I
    > think it needs a configure test and a fallback to the old method.
    
    Here's an attempt to make that happen. See attached.
    
    - M.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    fc914153
  • Harald van Dijk's avatar
    parser: use pgetc_eatbnl() in more places · 6bbc71d8
    Harald van Dijk authored
    
    dash has a pgetc_eatbnl function in parser.c which skips any
    backslash-newline combinations. It's not used everywhere it could be.
    There is also some duplicated backslash-newline handling elsewhere in
    parser.c. Replace most of the calls to pgetc() with calls to
    pgetc_eatbnl() and remove the duplicated backslash-newline handling.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    6bbc71d8
  • Herbert Xu's avatar
    parser: Add syntax stack for recursive parsing · ab1cecb4
    Herbert Xu authored
    
    Without a stack of syntaxes we cannot correctly these two cases
    together:
    
            "${a#'$$'}"
            "${a#"${b-'$$'}"}"
    
    A recursive parser also helps in some other corner cases such
    as nested arithmetic expansion with paratheses.
    
    This patch adds a syntax stack allocated from the stack using
    alloca.  As a side-effect this allows us to remove the naked
    backslashes for patterns within double-quotes, which means that
    EXP_QPAT also has to go.
    
    This patch also fixes removes any backslashes that precede right
    braces when they are present within a parameter expansion context,
    and backslashes that precede double quotes within inner double
    quotes inside a parameter expansion in a here-document context.
    
    The idea of a recursive parser is based on a patch by Harald van
    Dijk.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    ab1cecb4
  • Herbert Xu's avatar
    parser: Fix single-quoted patterns in here-documents · 9ee33439
    Herbert Xu authored
    
    The script
    
    	x=*
    	cat <<- EOF
    		${x#'*'}
    	EOF
    
    prints * instead of nothing as it should.  The problem is that
    when we're in sqsyntax context in a here-document, we won't add
    CTLESC as we should.  This patch fixes it:
    
    Reported-by: default avatarHarald van Dijk <harald@gigawatt.nl>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    9ee33439
  • Martijn Dekker's avatar
    shell: provide .gitignore · e006ef83
    Martijn Dekker authored
    
    Here's a .gitignore file for the convenience of casual git users.
    
    - M.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    e006ef83
  • Herbert Xu's avatar
    parser: Fix backquote support in here-document EOF mark · c166b718
    Herbert Xu authored
    
    Currently using backquotes in a here-document EOF mark is broken
    because dash tries to do command substitution on it.  This patch
    fixes it by checking whether we're looking for an EOF mark during
    tokenisation.
    
    Reported-by: default avatarHarald van Dijk <harald@gigawatt.nl>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    c166b718
  • Herbert Xu's avatar
    Revert "[BUILTIN] Remove unnecessary restoration of format string in printf" · fcb3864e
    Herbert Xu authored
    
    This reverts commit 7bb41325.
    
    The commit breaks printf with more than argument.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    fcb3864e
  • Herbert Xu's avatar
    expand: Fix bugs with words connected to the right of $@ · f8807824
    Herbert Xu authored
    
    On Sun, Mar 04, 2018 at 12:44:59PM +0100, Harald van Dijk wrote:
    >
    > command:      set -- a ""; space=" "; printf "<%s>" "$@"$space
    > bash:         <a><>
    > dash 0.5.8:   <a>< >
    > dash 0.5.9.1: <a>< >
    > dash patched: <a><>
    
    This is actually composed of two bugs.  First of all our tracking
    of quotemark is wrong so anything after "$@" becomes quoted.  Once
    we fix that then the problem is that the first space character
    after "$@" is not recognised as an IFS.
    
    This patch fixes both.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    f8807824
  • Herbert Xu's avatar
    parser: Allow newlines within parameter substitution · dad1cb18
    Herbert Xu authored
    
    On Fri, Mar 16, 2018 at 11:27:22AM +0800, Herbert Xu wrote:
    > On Thu, Mar 15, 2018 at 10:49:15PM +0100, Harald van Dijk wrote:
    > >
    > > Okay, it can be trivially modified to something that does work in other
    > > shells (even if it were actually executed), but gets rejected at parse time
    > > by dash:
    > >
    > >   if false; then
    > >     : ${$+
    > >   }
    > >   fi
    >
    > That's just a bug in dash's parser with ${} in general, because
    > it bombs out without the if clause too:
    >
    > 	: ${$+
    > 	}
    
    This patch fixes the parsing of newlines with parameter substitution.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    dad1cb18
  • Herbert Xu's avatar
    expand: Fix ghost fields with unquoted $@/$* · 36128c90
    Herbert Xu authored
    
    Harald van Dijk <harald@gigawatt.nl> wrote:
    > On 22/03/2018 22:38, Martijn Dekker wrote:
    >> Op 22-03-18 om 20:28 schreef Harald van Dijk:
    >>> On 22/03/2018 03:40, Martijn Dekker wrote:
    >>>> This patch fixes the bug that, given no positional parameters, unquoted
    >>>> $@ and $* incorrectly generate one empty field (they should generate no
    >>>> fields). Apparently that was a side effect of the above.
    >>>
    >>> This seems weird though. If you want to remove the recording of empty
    >>> regions because they are pointless, then how does removing them fix a
    >>> bug? Doesn't this show that empty regions do have an effect? Perhaps
    >>> they're not supposed to have any effect, perhaps it's a specific
    >>> combination of empty regions and something else that triggers some bug,
    >>> and perhaps that combination can no longer occur with your patch.
    >>
    >> The latter is my guess, but I haven't had time to investigate it.
    >
    > Looking into it again:
    >
    > When IFS is set to an empty string, sepc is set to '\0' in varvalue().
    > This then causes *quotedp to be set to true, meaning evalvar()'s quoted
    > variable is turned on. quoted is then passed to recordregion() as the
    > nulonly parameter.
    >
    > ifsp->nulonly has a bigger effect than merely selecting whether to use
    > $IFS or whether to only split on null bytes: in ifsbreakup(), nulonly
    > also causes string termination to be suppressed. That's correct: that
    > special treatment is required to preserve empty fields in "$@"
    > expansion. But it should *only* be used when $@ is quoted: ifsbreakup()
    > takes nulonly from the last IFS region, even if it's empty, so having an
    > additional zero-length region with nulonly enabled causes confusion.
    >
    > Passing quoted by value to varvalue() and not attempting to modify it
    > should therefore, and in my quick testing does, also work to fix the
    > original $@ bug.
    
    You're right.  The proper fix to this is to ensure that nulonly
    is not set in varvalue for $*.  It should only be set for $@ when
    it's inside double quotes.
    
    In fact there is another bug while we're playing with $@/$*.
    When IFS is set to a non-whitespace character such as :, $*
    outside quotes won't remove empty fields as it should.
    
    This patch fixes both problems.
    
    Reported-by: default avatarMartijn Dekker <martijn@inlv.org>
    Suggested-by: default avatarHarald van Dijk <harald@gigawatt.nl>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    36128c90
  • Herbert Xu's avatar
    builtin: Fix echo performance regression · 42b730b0
    Herbert Xu authored
    
    The commit d6c0e1e2 ("[BUILTIN]
    Handle embedded NULs correctly in printf") caused a performance
    regression in the echo built-in because every echo call now goes
    through the printf %b slow path where the string is always printed
    twice to ensure the space padding is correct in the presence of
    NUL characters.  In fact this regression applies to printf %b as
    well.
    
    This is easily fixed by making printf %b take the fast path when
    no precision/field width modifiers are present.
    
    This patch also changes the second strchurnul call to strspn which
    generates slightly better code.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    42b730b0
  • Herbert Xu's avatar
    builtin: Move echo space/nl handling into print_escape_str · 325a460c
    Herbert Xu authored
    
    Currently echocmd uses print_escape_str to do everything apart
    from printing the spaces/newlines separating its arguments.  This
    patch moves the actual printing into print_escape_str as well
    using the format parameter.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    325a460c
  • Herbert Xu's avatar
    expand: Fix buffer overflow in expandmeta · 0f3806dd
    Herbert Xu authored
    
    The native version of expandmeta allocates a buffer that may be
    overrun for two reasons.  First of all the size is 1 byte too small
    but this is normally hidden because the minimum size is rounded
    up to 2048 bytes.  Secondly, if the directory level is deep enough,
    any buffer can be overrun.
    
    This patch fixes both problems by calling realloc when necessary.
    
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    0f3806dd
# .gitignore for dash
# generated by autogen.sh
Makefile.in
/aclocal.m4
/autom4te.cache/
/compile
/config.h.in
/configure
/depcomp
/install-sh
/missing
# generated by configure
Makefile
/config.cache
/config.h
/config.log
/config.status
/src/.deps/
/stamp-h1
# generated by make
/src/token_vars.h
# Apple debug symbol bundles
*.dSYM/
# backups and patch artefacts
*~
*.bak
*.orig
*.rej
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight*
.Trash*
*[Tt]humbs.db
Loading
Loading
@@ -149,6 +149,20 @@ AC_CHECK_FUNC(open64,, [
AC_DEFINE(open64, open, [64-bit operations are the same as 32-bit])
])
 
dnl Check if struct stat has st_mtim.
AC_MSG_CHECKING(for stat::st_mtim)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>],
[struct stat foo; return sizeof(foo.st_mtim.tv_sec)])],
have_st_mtim=yes, have_st_mtim=no)
AC_MSG_RESULT($have_st_mtim)
if test "$have_st_mtim" = "yes"; then
AC_DEFINE([HAVE_ST_MTIM], [1],
[Define if your `struct stat' has `st_mtim'])
fi
AC_ARG_WITH(libedit, AS_HELP_STRING(--with-libedit, [Compile with libedit support]))
use_libedit=
if test "$with_libedit" = "yes"; then
Loading
Loading
Loading
Loading
@@ -98,20 +98,27 @@ static int print_escape_str(const char *f, int *param, int *array, char *s)
int total;
 
setstackmark(&smark);
done = conv_escape_str(s, &p);
q = stackblock();
len = p - q;
done = conv_escape_str(s, &q);
p = stackblock();
len = q - p;
total = len - 1;
q[-1] = (!!((f[1] - 's') | done) - 1) & f[2];
total += !!q[-1];
if (f[1] == 's')
goto easy;
 
p = makestrspace(len, p);
memset(p, 'X', len - 1);
p[len - 1] = 0;
p = makestrspace(len, q);
memset(p, 'X', total);
p[total] = 0;
 
q = stackblock();
total = ASPF(&p, f, p);
 
len = strchrnul(p, 'X') - p;
memcpy(p + len, q, strchrnul(p + len, ' ') - (p + len));
memcpy(p + len, q, strspn(p + len, "X"));
 
easy:
out1mem(p, total);
 
popstackmark(&smark);
Loading
Loading
@@ -209,6 +216,7 @@ pc:
if (print_escape_str(start, param, array,
getstr()))
goto out;
*fmt = 'b';
break;
case 'c': {
int p = getchr();
Loading
Loading
@@ -449,21 +457,22 @@ check_conversion(const char *s, const char *ep)
int
echocmd(int argc, char **argv)
{
const char *lastfmt = snlfmt;
int nonl;
 
nonl = *++argv ? equal(*argv, "-n") : 0;
argv += nonl;
if (*++argv && equal(*argv, "-n")) {
argv++;
lastfmt = "%s";
}
 
do {
int c;
const char *fmt = "%s ";
char *s = *argv;
 
if (likely(*argv))
nonl += print_escape_str("%s", NULL, NULL, *argv++);
if (likely((nonl + !*argv) > 1))
break;
if (!s || !*++argv)
fmt = lastfmt;
 
c = *argv ? ' ' : '\n';
out1c(c);
} while (*argv);
nonl = print_escape_str(fmt, NULL, NULL, s ?: nullstr);
} while (!nonl && *argv);
return 0;
}
Loading
Loading
@@ -476,9 +476,17 @@ newerf (const char *f1, const char *f2)
{
struct stat b1, b2;
 
#ifdef HAVE_ST_MTIM
return (stat (f1, &b1) == 0 &&
stat (f2, &b2) == 0 &&
( b1.st_mtim.tv_sec > b2.st_mtim.tv_sec ||
(b1.st_mtim.tv_sec == b2.st_mtim.tv_sec && (b1.st_mtim.tv_nsec > b2.st_mtim.tv_nsec )))
);
#else
return (stat (f1, &b1) == 0 &&
stat (f2, &b2) == 0 &&
b1.st_mtime > b2.st_mtime);
#endif
}
 
static int
Loading
Loading
@@ -486,9 +494,17 @@ olderf (const char *f1, const char *f2)
{
struct stat b1, b2;
 
#ifdef HAVE_ST_MTIM
return (stat (f1, &b1) == 0 &&
stat (f2, &b2) == 0 &&
(b1.st_mtim.tv_sec < b2.st_mtim.tv_sec ||
(b1.st_mtim.tv_sec == b2.st_mtim.tv_sec && (b1.st_mtim.tv_nsec < b2.st_mtim.tv_nsec )))
);
#else
return (stat (f1, &b1) == 0 &&
stat (f2, &b2) == 0 &&
b1.st_mtime < b2.st_mtime);
#endif
}
 
static int
Loading
Loading
Loading
Loading
@@ -2226,13 +2226,12 @@ This mode uses commands, described below,
similar to a subset of those described in the vi man page.
The command
.Ql set -o vi
enables vi-mode editing and place sh into vi insert mode.
enables vi-mode editing and places sh into vi insert mode.
With vi-mode
enabled, sh can be switched between insert mode and command mode.
The editor is not described in full here, but will be in a later document.
It's similar to vi: typing
It is similar to vi: typing
.Aq ESC
will throw you into command VI command mode.
enters vi command mode.
Hitting
.Aq return
while in command mode will pass the line to the shell.
Loading
Loading
Loading
Loading
@@ -743,8 +743,6 @@ describe_command(out, command, path, verbose)
struct tblentry *cmdp;
const struct alias *ap;
 
path = path ?: pathval();
if (verbose) {
outstr(command, out);
}
Loading
Loading
@@ -767,8 +765,17 @@ describe_command(out, command, path, verbose)
goto out;
}
 
/* Then check if it is a tracked alias */
if ((cmdp = cmdlookup(command, 0)) != NULL) {
/* Then if the standard search path is used, check if it is
* a tracked alias.
*/
if (path == NULL) {
path = pathval();
cmdp = cmdlookup(command, 0);
} else {
cmdp = NULL;
}
if (cmdp != NULL) {
entry.cmdtype = cmdp->cmdtype;
entry.u = cmdp->param;
} else {
Loading
Loading
Loading
Loading
@@ -45,7 +45,9 @@
#include <inttypes.h>
#include <limits.h>
#include <string.h>
#ifdef HAVE_FNMATCH
#include <fnmatch.h>
#endif
#ifdef HAVE_GLOB
#include <glob.h>
#endif
Loading
Loading
@@ -83,7 +85,7 @@
#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
 
/* Add CTLESC when necessary. */
#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT)
#define QUOTES_ESC (EXP_FULL | EXP_CASE)
/* Do not skip NUL characters. */
#define QUOTES_KEEPNUL EXP_TILDE
 
Loading
Loading
@@ -117,12 +119,12 @@ STATIC const char *subevalvar(char *, char *, int, int, int, int, int);
STATIC char *evalvar(char *, int);
STATIC size_t strtodest(const char *, const char *, int);
STATIC void memtodest(const char *, size_t, const char *, int);
STATIC ssize_t varvalue(char *, int, int, int *);
STATIC ssize_t varvalue(char *, int, int, int);
STATIC void expandmeta(struct strlist *, int);
#ifdef HAVE_GLOB
STATIC void addglob(const glob_t *);
#else
STATIC void expmeta(char *, char *);
STATIC void expmeta(char *, unsigned, unsigned);
STATIC struct strlist *expsort(struct strlist *);
STATIC struct strlist *msort(struct strlist *, int);
#endif
Loading
Loading
@@ -316,13 +318,13 @@ start:
case CTLENDVAR: /* ??? */
goto breakloop;
case CTLQUOTEMARK:
inquotes ^= EXP_QUOTED;
/* "$@" syntax adherence hack */
if (inquotes && !memcmp(p, dolatstr + 1,
DOLATSTRLEN - 1)) {
p = evalvar(p + 1, flag | inquotes) + 1;
if (!inquotes && !memcmp(p, dolatstr + 1,
DOLATSTRLEN - 1)) {
p = evalvar(p + 1, flag | EXP_QUOTED) + 1;
goto start;
}
inquotes ^= EXP_QUOTED;
addquote:
if (flag & QUOTES_ESC) {
p--;
Loading
Loading
@@ -333,16 +335,6 @@ addquote:
case CTLESC:
startloc++;
length++;
/*
* Quoted parameter expansion pattern: remove quote
* unless inside inner quotes or we have a literal
* backslash.
*/
if (((flag | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
EXP_QPAT && *p != '\\')
break;
goto addquote;
case CTLVAR:
p = evalvar(p, flag | inquotes);
Loading
Loading
@@ -651,8 +643,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varfla
char *(*scan)(char *, char *, char *, char *, int , int);
 
argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
(flag & (EXP_QUOTED | EXP_QPAT) ?
EXP_QPAT : EXP_CASE) : 0));
EXP_CASE : 0));
STPUTC('\0', expdest);
argbackq = saveargbackq;
startp = stackblock() + startloc;
Loading
Loading
@@ -721,7 +712,6 @@ evalvar(char *p, int flag)
int c;
int startloc;
ssize_t varlen;
int easy;
int quoted;
 
varflags = *p++;
Loading
Loading
@@ -732,12 +722,11 @@ evalvar(char *p, int flag)
 
quoted = flag & EXP_QUOTED;
var = p;
easy = (!quoted || (*var == '@' && shellparam.nparam));
startloc = expdest - (char *)stackblock();
p = strchr(p, '=') + 1;
 
again:
varlen = varvalue(var, varflags, flag, &quoted);
varlen = varvalue(var, varflags, flag, quoted);
if (varflags & VSNUL)
varlen--;
 
Loading
Loading
@@ -780,8 +769,11 @@ vsplus:
 
if (subtype == VSNORMAL) {
record:
if (!easy)
goto end;
if (quoted) {
quoted = *var == '@' && shellparam.nparam;
if (!quoted)
goto end;
}
recordregion(startloc, expdest - (char *)stackblock(), quoted);
goto end;
}
Loading
Loading
@@ -887,7 +879,7 @@ strtodest(p, syntax, quotes)
*/
 
STATIC ssize_t
varvalue(char *name, int varflags, int flags, int *quotedp)
varvalue(char *name, int varflags, int flags, int quoted)
{
int num;
char *p;
Loading
Loading
@@ -896,11 +888,11 @@ varvalue(char *name, int varflags, int flags, int *quotedp)
char sepc;
char **ap;
char const *syntax;
int quoted = *quotedp;
int subtype = varflags & VSTYPE;
int discard = subtype == VSPLUS || subtype == VSLENGTH;
int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
ssize_t len = 0;
char c;
 
sep = (flags & EXP_FULL) << CHAR_BIT;
syntax = quoted ? DQSYNTAX : BASESYNTAX;
Loading
Loading
@@ -925,7 +917,7 @@ numvar:
case '-':
p = makestrspace(NOPTS, expdest);
for (i = NOPTS - 1; i >= 0; i--) {
if (optlist[i]) {
if (optlist[i] && optletters[i]) {
USTPUTC(optletters[i], p);
len++;
}
Loading
Loading
@@ -937,12 +929,25 @@ numvar:
goto param;
/* fall through */
case '*':
if (quoted)
sep = 0;
sep |= ifsset() ? ifsval()[0] : ' ';
/* We will set c to 0 or ~0 depending on whether
* we're doing field splitting. We won't do field
* splitting if either we're quoted or sep is zero.
*
* Instead of testing (quoted || !sep) the following
* trick optimises away any branches by using the
* fact that EXP_QUOTED (which is the only bit that
* can be set in quoted) is the same as EXP_FULL <<
* CHAR_BIT (which is the only bit that can be set
* in sep).
*/
#if EXP_QUOTED >> CHAR_BIT != EXP_FULL
#error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
#endif
c = !((quoted | ~sep) & EXP_QUOTED) - 1;
sep &= ~quoted;
sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
param:
sepc = sep;
*quotedp = !sepc;
if (!(ap = shellparam.p))
return -1;
while ((p = *ap++)) {
Loading
Loading
@@ -1041,7 +1046,10 @@ ifsbreakup(char *string, int maxargs, struct arglist *arglist)
realifs = ifsset() ? ifsval() : defifs;
ifsp = &ifsfirst;
do {
int afternul;
p = string + ifsp->begoff;
afternul = nulonly;
nulonly = ifsp->nulonly;
ifs = nulonly ? nullstr : realifs;
ifsspc = 0;
Loading
Loading
@@ -1106,7 +1114,7 @@ ifsbreakup(char *string, int maxargs, struct arglist *arglist)
}
 
if (isifs) {
if (!nulonly)
if (!(afternul || nulonly))
ifsspc = isdefifs;
/* Ignore IFS whitespace at start */
if (q == start && ifsspc) {
Loading
Loading
@@ -1238,6 +1246,7 @@ addglob(pglob)
 
#else /* HAVE_GLOB */
STATIC char *expdir;
STATIC unsigned expdir_max;
 
 
STATIC void
Loading
Loading
@@ -1252,6 +1261,7 @@ expandmeta(struct strlist *str, int flag)
struct strlist **savelastp;
struct strlist *sp;
char *p;
unsigned len;
 
if (fflag)
goto nometa;
Loading
Loading
@@ -1261,12 +1271,11 @@ expandmeta(struct strlist *str, int flag)
 
INTOFF;
p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
{
int i = strlen(str->text);
expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
}
len = strlen(p);
expdir_max = len + PATH_MAX;
expdir = ckmalloc(expdir_max);
 
expmeta(expdir, p);
expmeta(p, len, 0);
ckfree(expdir);
if (p != str->text)
ckfree(p);
Loading
Loading
@@ -1296,8 +1305,9 @@ nometa:
*/
 
STATIC void
expmeta(char *enddir, char *name)
expmeta(char *name, unsigned name_len, unsigned expdir_len)
{
char *enddir = expdir + expdir_len;
char *p;
const char *cp;
char *start;
Loading
Loading
@@ -1340,15 +1350,15 @@ expmeta(char *enddir, char *name)
}
}
if (metaflag == 0) { /* we've reached the end of the file name */
if (enddir != expdir)
metaflag++;
if (!expdir_len)
return;
p = name;
do {
if (*p == '\\')
p++;
*enddir++ = *p;
} while (*p++);
if (metaflag == 0 || lstat64(expdir, &statb) >= 0)
if (lstat64(expdir, &statb) >= 0)
addfname(expdir);
return;
}
Loading
Loading
@@ -1361,18 +1371,13 @@ expmeta(char *enddir, char *name)
*enddir++ = *p++;
} while (p < start);
}
if (enddir == expdir) {
*enddir = 0;
cp = expdir;
expdir_len = enddir - cp;
if (!expdir_len)
cp = ".";
} else if (enddir == expdir + 1 && *expdir == '/') {
cp = "/";
} else {
cp = expdir;
enddir[-1] = '\0';
}
if ((dirp = opendir(cp)) == NULL)
return;
if (enddir != expdir)
enddir[-1] = '/';
if (*endname == 0) {
atend = 1;
} else {
Loading
Loading
@@ -1380,6 +1385,7 @@ expmeta(char *enddir, char *name)
*endname = '\0';
endname += esc + 1;
}
name_len -= endname - name;
matchdot = 0;
p = start;
if (*p == '\\')
Loading
Loading
@@ -1394,11 +1400,22 @@ expmeta(char *enddir, char *name)
scopy(dp->d_name, enddir);
addfname(expdir);
} else {
for (p = enddir, cp = dp->d_name;
(*p++ = *cp++) != '\0';)
continue;
p[-1] = '/';
expmeta(p, endname);
unsigned offset;
unsigned len;
p = stpcpy(enddir, dp->d_name);
*p = '/';
offset = p - expdir + 1;
len = offset + name_len + NAME_MAX;
if (len > expdir_max) {
len += PATH_MAX;
expdir = ckrealloc(expdir, len);
expdir_max = len;
}
expmeta(endname, name_len, offset);
enddir = expdir + expdir_len;
}
}
}
Loading
Loading
@@ -1644,7 +1661,6 @@ char *
_rmescapes(char *str, int flag)
{
char *p, *q, *r;
unsigned inquotes;
int notescaped;
int globbing;
 
Loading
Loading
@@ -1674,24 +1690,23 @@ _rmescapes(char *str, int flag)
q = mempcpy(q, str, len);
}
}
inquotes = 0;
globbing = flag & RMESCAPE_GLOB;
notescaped = globbing;
while (*p) {
if (*p == (char)CTLQUOTEMARK) {
inquotes = ~inquotes;
p++;
notescaped = globbing;
continue;
}
if (*p == '\\') {
/* naked back slash */
notescaped = 0;
goto copy;
}
if (*p == (char)CTLESC) {
p++;
if (notescaped)
*q++ = '\\';
} else if (*p == '\\' && !inquotes) {
/* naked back slash */
notescaped = 0;
goto copy;
}
notescaped = globbing;
copy:
Loading
Loading
Loading
Loading
@@ -55,7 +55,6 @@ struct arglist {
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
#define EXP_QPAT 0x20 /* pattern in quoted parameter expansion */
#define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
#define EXP_WORD 0x80 /* expand word in parameter expansion */
#define EXP_QUOTED 0x100 /* expand word in double quotes */
Loading
Loading
Loading
Loading
@@ -39,6 +39,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
/*
* Editline and history functions (and glue).
*/
Loading
Loading
Loading
Loading
@@ -147,8 +147,12 @@ retry:
static const char *rl_cp;
static int el_len;
 
if (rl_cp == NULL)
if (rl_cp == NULL) {
struct stackmark smark;
pushstackmark(&smark, stackblocksize());
rl_cp = el_gets(el, &el_len);
popstackmark(&smark);
}
if (rl_cp == NULL)
nr = 0;
else {
Loading
Loading
Loading
Loading
@@ -648,7 +648,7 @@ out:
return retval;
 
sigout:
retval = 128 + pendingsigs;
retval = 128 + pending_sig;
goto out;
}
 
Loading
Loading
@@ -1147,7 +1147,7 @@ waitproc(int block, int *status)
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, &oldmask);
 
while (!gotsigchld && !pendingsigs)
while (!gotsigchld && !pending_sig)
sigsuspend(&oldmask);
 
sigclearmask();
Loading
Loading
Loading
Loading
@@ -152,7 +152,7 @@ readcmd(int argc, char **argv)
case 1:
break;
default:
if (errno == EINTR && !pendingsigs)
if (errno == EINTR && !pending_sig)
continue;
/* fall through */
case 0:
Loading
Loading
Loading
Loading
@@ -125,7 +125,7 @@ intmax_t atomax(const char *s, int base)
errno = 0;
r = strtoimax(s, &p, base);
 
if (errno != 0)
if (errno == ERANGE)
badnum(s);
 
/*
Loading
Loading
Loading
Loading
@@ -80,6 +80,18 @@ struct heredoc {
int striptabs; /* if set, strip leading tabs */
};
 
struct synstack {
const char *syntax;
struct synstack *prev;
struct synstack *next;
int innerdq;
int varpushed;
int dblquote;
int varnest; /* levels of variables expansion */
int parenlevel; /* levels of parens in arithmetic */
int dqvarnest; /* levels of variables expansion within double quotes */
};
 
 
struct heredoc *heredoclist; /* list of here documents to read */
Loading
Loading
@@ -106,6 +118,7 @@ STATIC void parseheredoc(void);
STATIC int peektoken(void);
STATIC int readtoken(void);
STATIC int xxreadtoken(void);
STATIC int pgetc_eatbnl();
STATIC int readtoken1(int, char const *, char *, int);
STATIC void synexpect(int) __attribute__((__noreturn__));
STATIC void synerror(const char *) __attribute__((__noreturn__));
Loading
Loading
@@ -656,8 +669,10 @@ parseheredoc(void)
if (needprompt) {
setprompt(2);
}
readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
here->eofmark, here->striptabs);
if (here->here->type == NHERE)
readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
else
readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
n = (union node *)stalloc(sizeof (struct narg));
n->narg.type = NARG;
n->narg.next = NULL;
Loading
Loading
@@ -782,7 +797,7 @@ xxreadtoken(void)
setprompt(2);
}
for (;;) { /* until token or start of word found */
c = pgetc();
c = pgetc_eatbnl();
switch (c) {
case ' ': case '\t':
case PEOA:
Loading
Loading
@@ -791,30 +806,23 @@ xxreadtoken(void)
while ((c = pgetc()) != '\n' && c != PEOF);
pungetc();
continue;
case '\\':
if (pgetc() == '\n') {
nlprompt();
continue;
}
pungetc();
goto breakloop;
case '\n':
nlnoprompt();
RETURN(TNL);
case PEOF:
RETURN(TEOF);
case '&':
if (pgetc() == '&')
if (pgetc_eatbnl() == '&')
RETURN(TAND);
pungetc();
RETURN(TBACKGND);
case '|':
if (pgetc() == '|')
if (pgetc_eatbnl() == '|')
RETURN(TOR);
pungetc();
RETURN(TPIPE);
case ';':
if (pgetc() == ';')
if (pgetc_eatbnl() == ';')
RETURN(TENDCASE);
pungetc();
RETURN(TSEMI);
Loading
Loading
@@ -822,11 +830,9 @@ xxreadtoken(void)
RETURN(TLP);
case ')':
RETURN(TRP);
default:
goto breakloop;
}
break;
}
breakloop:
return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
#undef RETURN
}
Loading
Loading
@@ -836,7 +842,7 @@ static int pgetc_eatbnl(void)
int c;
 
while ((c = pgetc()) == '\\') {
if (pgetc() != '\n') {
if (pgetc2() != '\n') {
pungetc();
break;
}
Loading
Loading
@@ -847,6 +853,21 @@ static int pgetc_eatbnl(void)
return c;
}
 
static void synstack_push(struct synstack **stack, struct synstack *next,
const char *syntax)
{
memset(next, 0, sizeof(*next));
next->syntax = syntax;
next->next = *stack;
(*stack)->prev = next;
*stack = next;
}
static void synstack_pop(struct synstack **stack)
{
*stack = (*stack)->next;
}
 
 
/*
Loading
Loading
@@ -876,24 +897,15 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
size_t len;
struct nodelist *bqlist;
int quotef;
int dblquote;
int varnest; /* levels of variables expansion */
int arinest; /* levels of arithmetic expansion */
int parenlevel; /* levels of parens in arithmetic */
int dqvarnest; /* levels of variables expansion within double quotes */
int oldstyle;
/* syntax before arithmetic */
char const *uninitialized_var(prevsyntax);
/* syntax stack */
struct synstack synbase = { .syntax = syntax };
struct synstack *synstack = &synbase;
 
dblquote = 0;
if (syntax == DQSYNTAX)
dblquote = 1;
synstack->dblquote = 1;
quotef = 0;
bqlist = NULL;
varnest = 0;
arinest = 0;
parenlevel = 0;
dqvarnest = 0;
 
STARTSTACKSTR(out);
loop: { /* for each line, until end of word */
Loading
Loading
@@ -901,28 +913,30 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
if (c == '\034' && doprompt
&& attyset() && ! equal(termval(), "emacs")) {
attyline();
if (syntax == BASESYNTAX)
if (synstack->syntax == BASESYNTAX)
return readtoken();
c = pgetc();
c = syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
goto loop;
}
#endif
CHECKEND(); /* set c to PEOF if at end of here document */
for (;;) { /* until end of line or end of word */
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
switch(syntax[c]) {
switch(synstack->syntax[c]) {
case CNL: /* '\n' */
if (syntax == BASESYNTAX)
if (synstack->syntax == BASESYNTAX &&
!synstack->varnest)
goto endword; /* exit outer loop */
USTPUTC(c, out);
nlprompt();
c = pgetc();
c = syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
goto loop; /* continue outer loop */
case CWORD:
USTPUTC(c, out);
break;
case CCTL:
if (eofmark == NULL || dblquote)
if ((!eofmark) | synstack->dblquote |
synstack->varnest)
USTPUTC(CTLESC, out);
USTPUTC(c, out);
break;
Loading
Loading
@@ -933,17 +947,20 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
USTPUTC(CTLESC, out);
USTPUTC('\\', out);
pungetc();
} else if (c == '\n') {
nlprompt();
} else {
if (
dblquote &&
synstack->dblquote &&
c != '\\' && c != '`' &&
c != '$' && (
c != '"' ||
eofmark != NULL
(eofmark != NULL &&
!synstack->varnest)
) && (
c != '}' ||
!synstack->varnest
)
) {
USTPUTC(CTLESC, out);
USTPUTC('\\', out);
}
USTPUTC(CTLESC, out);
Loading
Loading
@@ -952,55 +969,64 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
}
break;
case CSQUOTE:
syntax = SQSYNTAX;
synstack->syntax = SQSYNTAX;
quotemark:
if (eofmark == NULL) {
USTPUTC(CTLQUOTEMARK, out);
}
break;
case CDQUOTE:
syntax = DQSYNTAX;
dblquote = 1;
synstack->syntax = DQSYNTAX;
synstack->dblquote = 1;
toggledq:
if (synstack->varnest)
synstack->innerdq ^= 1;
goto quotemark;
case CENDQUOTE:
if (eofmark && !varnest)
if (eofmark && !synstack->varnest) {
USTPUTC(c, out);
else {
if (dqvarnest == 0) {
syntax = BASESYNTAX;
dblquote = 0;
}
quotef++;
goto quotemark;
break;
}
break;
if (synstack->dqvarnest == 0) {
synstack->syntax = BASESYNTAX;
synstack->dblquote = 0;
}
quotef++;
if (c == '"')
goto toggledq;
goto quotemark;
case CVAR: /* '$' */
PARSESUB(); /* parse substitution */
break;
case CENDVAR: /* '}' */
if (varnest > 0) {
varnest--;
if (dqvarnest > 0) {
dqvarnest--;
}
if (!synstack->innerdq &&
synstack->varnest > 0) {
if (!--synstack->varnest &&
synstack->varpushed)
synstack_pop(&synstack);
else if (synstack->dqvarnest > 0)
synstack->dqvarnest--;
USTPUTC(CTLENDVAR, out);
} else {
USTPUTC(c, out);
}
break;
case CLP: /* '(' in arithmetic */
parenlevel++;
synstack->parenlevel++;
USTPUTC(c, out);
break;
case CRP: /* ')' in arithmetic */
if (parenlevel > 0) {
if (synstack->parenlevel > 0) {
USTPUTC(c, out);
--parenlevel;
--synstack->parenlevel;
} else {
if (pgetc() == ')') {
if (pgetc_eatbnl() == ')') {
USTPUTC(CTLENDARI, out);
if (!--arinest)
syntax = prevsyntax;
synstack_pop(&synstack);
} else {
/*
* unbalanced parens
Loading
Loading
@@ -1012,6 +1038,11 @@ quotemark:
}
break;
case CBQUOTE: /* '`' */
if (checkkwd & CHKEOFMARK) {
USTPUTC('`', out);
break;
}
PARSEBACKQOLD();
break;
case CEOF:
Loading
Loading
@@ -1019,21 +1050,21 @@ quotemark:
case CIGN:
break;
default:
if (varnest == 0)
if (synstack->varnest == 0)
goto endword; /* exit outer loop */
if (c != PEOA) {
USTPUTC(c, out);
}
}
c = pgetc();
c = syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
}
}
endword:
if (syntax == ARISYNTAX)
if (synstack->syntax == ARISYNTAX)
synerror("Missing '))'");
if (syntax != BASESYNTAX && eofmark == NULL)
if (synstack->syntax != BASESYNTAX && eofmark == NULL)
synerror("Unterminated quoted string");
if (varnest != 0) {
if (synstack->varnest != 0) {
/* { */
synerror("Missing '}'");
}
Loading
Loading
@@ -1132,7 +1163,7 @@ parseredir: {
np = (union node *)stalloc(sizeof (struct nfile));
if (c == '>') {
np->nfile.fd = 1;
c = pgetc();
c = pgetc_eatbnl();
if (c == '>')
np->type = NAPPEND;
else if (c == '|')
Loading
Loading
@@ -1145,7 +1176,7 @@ parseredir: {
}
} else { /* c == '<' */
np->nfile.fd = 0;
switch (c = pgetc()) {
switch (c = pgetc_eatbnl()) {
case '<':
if (sizeof (struct nfile) != sizeof (struct nhere)) {
np = (union node *)stalloc(sizeof (struct nhere));
Loading
Loading
@@ -1154,7 +1185,7 @@ parseredir: {
np->type = NHERE;
heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
heredoc->here = np;
if ((c = pgetc()) == '-') {
if ((c = pgetc_eatbnl()) == '-') {
heredoc->striptabs = 1;
} else {
heredoc->striptabs = 0;
Loading
Loading
@@ -1210,6 +1241,8 @@ parsesub: {
PARSEBACKQNEW();
}
} else {
const char *newsyn = synstack->syntax;
USTPUTC(CTLVAR, out);
typeloc = out - (char *)stackblock();
STADJUST(1, out);
Loading
Loading
@@ -1260,6 +1293,8 @@ varname:
}
 
if (subtype == 0) {
int cc = c;
switch (c) {
case ':':
subtype = VSNUL;
Loading
Loading
@@ -1273,27 +1308,40 @@ varname:
break;
case '%':
case '#':
{
int cc = c;
subtype = c == '#' ? VSTRIMLEFT :
VSTRIMRIGHT;
c = pgetc_eatbnl();
if (c == cc)
subtype++;
else
pungetc();
break;
}
subtype = c == '#' ? VSTRIMLEFT :
VSTRIMRIGHT;
c = pgetc_eatbnl();
if (c == cc)
subtype++;
else
pungetc();
newsyn = BASESYNTAX;
break;
}
} else {
badsub:
pungetc();
}
if (newsyn == ARISYNTAX && subtype > VSNORMAL)
newsyn = DQSYNTAX;
if (newsyn != synstack->syntax) {
synstack_push(&synstack,
synstack->prev ?:
alloca(sizeof(*synstack)),
newsyn);
synstack->varpushed++;
synstack->dblquote = newsyn != BASESYNTAX;
}
*((char *)stackblock() + typeloc) = subtype;
if (subtype != VSNORMAL) {
varnest++;
if (dblquote)
dqvarnest++;
synstack->varnest++;
if (synstack->dblquote)
synstack->dqvarnest++;
}
STPUTC('=', out);
}
Loading
Loading
@@ -1336,23 +1384,14 @@ parsebackq: {
if (needprompt) {
setprompt(2);
}
switch (pc = pgetc()) {
switch (pc = pgetc_eatbnl()) {
case '`':
goto done;
 
case '\\':
if ((pc = pgetc()) == '\n') {
nlprompt();
/*
* If eating a newline, avoid putting
* the newline into the new character
* stream (via the STPUTC after the
* switch).
*/
continue;
}
pc = pgetc_eatbnl();
if (pc != '\\' && pc != '`' && pc != '$'
&& (!dblquote || pc != '"'))
&& (!synstack->dblquote || pc != '"'))
STPUTC('\\', pout);
if (pc > PEOA) {
break;
Loading
Loading
@@ -1428,10 +1467,10 @@ done:
*/
parsearith: {
 
if (++arinest == 1) {
prevsyntax = syntax;
syntax = ARISYNTAX;
}
synstack_push(&synstack,
synstack->prev ?: alloca(sizeof(*synstack)),
ARISYNTAX);
synstack->dblquote = 1;
USTPUTC(CTLARI, out);
goto parsearith_return;
}
Loading
Loading
@@ -1529,7 +1568,7 @@ expandstr(const char *ps)
saveprompt = doprompt;
doprompt = 0;
 
readtoken1(pgetc(), DQSYNTAX, FAKEEOFMARK, 0);
readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK, 0);
 
doprompt = saveprompt;
 
Loading
Loading
Loading
Loading
@@ -73,7 +73,7 @@ char sigmode[NSIG - 1];
/* indicates specified signal received */
static char gotsig[NSIG - 1];
/* last pending signal */
volatile sig_atomic_t pendingsigs;
volatile sig_atomic_t pending_sig;
/* received SIGCHLD */
int gotsigchld;
 
Loading
Loading
@@ -291,7 +291,7 @@ onsig(int signo)
}
 
gotsig[signo - 1] = 1;
pendingsigs = signo;
pending_sig = signo;
 
if (signo == SIGINT && !trap[SIGINT]) {
if (!suppressint)
Loading
Loading
@@ -314,7 +314,7 @@ void dotrap(void)
int i;
int status, last_status;
 
if (!pendingsigs)
if (!pending_sig)
return;
 
status = savestatus;
Loading
Loading
@@ -323,7 +323,7 @@ void dotrap(void)
status = exitstatus;
savestatus = status;
}
pendingsigs = 0;
pending_sig = 0;
barrier();
 
for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
Loading
Loading
@@ -331,7 +331,7 @@ void dotrap(void)
continue;
 
if (evalskip) {
pendingsigs = i + 1;
pending_sig = i + 1;
break;
}
 
Loading
Loading
Loading
Loading
@@ -38,7 +38,7 @@
 
extern int trapcnt;
extern char sigmode[];
extern volatile sig_atomic_t pendingsigs;
extern volatile sig_atomic_t pending_sig;
extern int gotsigchld;
 
int trapcmd(int, char **);
Loading
Loading