summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-10-13 10:49:35 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-10-13 10:49:35 +0900
commite31a2fb64fa509b9d22b7437b1833d6b0d62ee48 (patch)
tree0af002f5f8523176440deccb21b312aa5a83b0fc
parentc90fa15cbf2fc4380c58ff1b32f31d9ad6f57f81 (diff)
downloaddash-e31a2fb64fa509b9d22b7437b1833d6b0d62ee48.tar.gz
dash-e31a2fb64fa509b9d22b7437b1833d6b0d62ee48.tar.bz2
dash-e31a2fb64fa509b9d22b7437b1833d6b0d62ee48.zip
Imported Upstream version 0.5.10upstream/0.5.10
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure49
-rw-r--r--configure.ac18
-rw-r--r--src/Makefile.in88
-rw-r--r--src/bltin/printf.c43
-rw-r--r--src/bltin/test.c16
-rw-r--r--src/dash.115
-rw-r--r--src/eval.c17
-rw-r--r--src/exec.c15
-rw-r--r--src/expand.c151
-rw-r--r--src/expand.h1
-rw-r--r--src/histedit.c1
-rw-r--r--src/input.c16
-rw-r--r--src/input.h1
-rw-r--r--src/jobs.c12
-rw-r--r--src/miscbltin.c2
-rw-r--r--src/mystring.c2
-rw-r--r--src/parser.c249
-rw-r--r--src/redir.c2
-rw-r--r--src/trap.c10
-rw-r--r--src/trap.h2
21 files changed, 419 insertions, 294 deletions
diff --git a/config.h.in b/config.h.in
index 7a2b262..38274d2 100644
--- a/config.h.in
+++ b/config.h.in
@@ -79,6 +79,9 @@
/* Define to 1 if you have the `strtoumax' function. */
#undef HAVE_STRTOUMAX
+/* Define if your `struct stat' has `st_mtim' */
+#undef HAVE_ST_MTIM
+
/* Define to 1 if you have the `sysconf' function. */
#undef HAVE_SYSCONF
diff --git a/configure b/configure
index d5da219..7910897 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dash 0.5.9.1.
+# Generated by GNU Autoconf 2.69 for dash 0.5.10.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='dash'
PACKAGE_TARNAME='dash'
-PACKAGE_VERSION='0.5.9.1'
-PACKAGE_STRING='dash 0.5.9.1'
+PACKAGE_VERSION='0.5.10'
+PACKAGE_STRING='dash 0.5.10'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1269,7 +1269,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures dash 0.5.9.1 to adapt to many kinds of systems.
+\`configure' configures dash 0.5.10 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1335,7 +1335,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of dash 0.5.9.1:";;
+ short | recursive ) echo "Configuration of dash 0.5.10:";;
esac
cat <<\_ACEOF
@@ -1440,7 +1440,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-dash configure 0.5.9.1
+dash configure 0.5.10
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2034,7 +2034,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by dash $as_me 0.5.9.1, which was
+It was created by dash $as_me 0.5.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2849,7 +2849,7 @@ fi
# Define the identity of the package.
PACKAGE='dash'
- VERSION='0.5.9.1'
+ VERSION='0.5.10'
cat >>confdefs.h <<_ACEOF
@@ -4715,6 +4715,35 @@ $as_echo "#define open64 open" >>confdefs.h
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stat::st_mtim" >&5
+$as_echo_n "checking for stat::st_mtim... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat foo; return sizeof(foo.st_mtim.tv_sec)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ have_st_mtim=yes
+else
+ have_st_mtim=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_st_mtim" >&5
+$as_echo "$have_st_mtim" >&6; }
+if test "$have_st_mtim" = "yes"; then
+
+$as_echo "#define HAVE_ST_MTIM 1" >>confdefs.h
+
+fi
+
# Check whether --with-libedit was given.
if test "${with_libedit+set}" = set; then :
@@ -5313,7 +5342,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by dash $as_me 0.5.9.1, which was
+This file was extended by dash $as_me 0.5.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -5379,7 +5408,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-dash config.status 0.5.9.1
+dash config.status 0.5.10
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 9c4ced8..c36f949 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
-AC_INIT(dash, 0.5.9.1)
-AM_INIT_AUTOMAKE([foreign])
+AC_INIT(dash, 0.5.10)
+AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS(config.h)
@@ -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
diff --git a/src/Makefile.in b/src/Makefile.in
index 0bd9ad1..059c6e1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -62,6 +62,7 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
PROGRAMS = $(bin_PROGRAMS)
+am__dirstamp = $(am__leading_dot)dirstamp
am__objects_1 = alias.$(OBJEXT) arith_yacc.$(OBJEXT) \
arith_yylex.$(OBJEXT) cd.$(OBJEXT) error.$(OBJEXT) \
eval.$(OBJEXT) exec.$(OBJEXT) expand.$(OBJEXT) \
@@ -69,8 +70,8 @@ am__objects_1 = alias.$(OBJEXT) arith_yacc.$(OBJEXT) \
mail.$(OBJEXT) main.$(OBJEXT) memalloc.$(OBJEXT) \
miscbltin.$(OBJEXT) mystring.$(OBJEXT) options.$(OBJEXT) \
parser.$(OBJEXT) redir.$(OBJEXT) show.$(OBJEXT) trap.$(OBJEXT) \
- output.$(OBJEXT) printf.$(OBJEXT) system.$(OBJEXT) \
- test.$(OBJEXT) times.$(OBJEXT) var.$(OBJEXT)
+ output.$(OBJEXT) bltin/printf.$(OBJEXT) system.$(OBJEXT) \
+ bltin/test.$(OBJEXT) bltin/times.$(OBJEXT) var.$(OBJEXT)
am_dash_OBJECTS = $(am__objects_1)
dash_OBJECTS = $(am_dash_OBJECTS)
dash_DEPENDENCIES = builtins.o init.o nodes.o signames.o syntax.o
@@ -329,12 +330,27 @@ uninstall-binPROGRAMS:
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+bltin/$(am__dirstamp):
+ @$(MKDIR_P) bltin
+ @: > bltin/$(am__dirstamp)
+bltin/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) bltin/$(DEPDIR)
+ @: > bltin/$(DEPDIR)/$(am__dirstamp)
+bltin/printf.$(OBJEXT): bltin/$(am__dirstamp) \
+ bltin/$(DEPDIR)/$(am__dirstamp)
+bltin/test.$(OBJEXT): bltin/$(am__dirstamp) \
+ bltin/$(DEPDIR)/$(am__dirstamp)
+bltin/times.$(OBJEXT): bltin/$(am__dirstamp) \
+ bltin/$(DEPDIR)/$(am__dirstamp)
dash$(EXEEXT): $(dash_OBJECTS) $(dash_DEPENDENCIES) $(EXTRA_dash_DEPENDENCIES)
@rm -f dash$(EXEEXT)
$(LINK) $(dash_OBJECTS) $(dash_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
+ -rm -f bltin/printf.$(OBJEXT)
+ -rm -f bltin/test.$(OBJEXT)
+ -rm -f bltin/times.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@@ -358,70 +374,30 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redir.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/show.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/times.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bltin/$(DEPDIR)/printf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bltin/$(DEPDIR)/test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bltin/$(DEPDIR)/times.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-printf.o: bltin/printf.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT printf.o -MD -MP -MF $(DEPDIR)/printf.Tpo -c -o printf.o `test -f 'bltin/printf.c' || echo '$(srcdir)/'`bltin/printf.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/printf.Tpo $(DEPDIR)/printf.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bltin/printf.c' object='printf.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o printf.o `test -f 'bltin/printf.c' || echo '$(srcdir)/'`bltin/printf.c
-
-printf.obj: bltin/printf.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT printf.obj -MD -MP -MF $(DEPDIR)/printf.Tpo -c -o printf.obj `if test -f 'bltin/printf.c'; then $(CYGPATH_W) 'bltin/printf.c'; else $(CYGPATH_W) '$(srcdir)/bltin/printf.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/printf.Tpo $(DEPDIR)/printf.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bltin/printf.c' object='printf.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o printf.obj `if test -f 'bltin/printf.c'; then $(CYGPATH_W) 'bltin/printf.c'; else $(CYGPATH_W) '$(srcdir)/bltin/printf.c'; fi`
-
-test.o: bltin/test.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test.o -MD -MP -MF $(DEPDIR)/test.Tpo -c -o test.o `test -f 'bltin/test.c' || echo '$(srcdir)/'`bltin/test.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test.Tpo $(DEPDIR)/test.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bltin/test.c' object='test.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test.o `test -f 'bltin/test.c' || echo '$(srcdir)/'`bltin/test.c
-
-test.obj: bltin/test.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test.obj -MD -MP -MF $(DEPDIR)/test.Tpo -c -o test.obj `if test -f 'bltin/test.c'; then $(CYGPATH_W) 'bltin/test.c'; else $(CYGPATH_W) '$(srcdir)/bltin/test.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test.Tpo $(DEPDIR)/test.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bltin/test.c' object='test.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test.obj `if test -f 'bltin/test.c'; then $(CYGPATH_W) 'bltin/test.c'; else $(CYGPATH_W) '$(srcdir)/bltin/test.c'; fi`
-
-times.o: bltin/times.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT times.o -MD -MP -MF $(DEPDIR)/times.Tpo -c -o times.o `test -f 'bltin/times.c' || echo '$(srcdir)/'`bltin/times.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/times.Tpo $(DEPDIR)/times.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bltin/times.c' object='times.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o times.o `test -f 'bltin/times.c' || echo '$(srcdir)/'`bltin/times.c
-
-times.obj: bltin/times.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT times.obj -MD -MP -MF $(DEPDIR)/times.Tpo -c -o times.obj `if test -f 'bltin/times.c'; then $(CYGPATH_W) 'bltin/times.c'; else $(CYGPATH_W) '$(srcdir)/bltin/times.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/times.Tpo $(DEPDIR)/times.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bltin/times.c' object='times.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o times.obj `if test -f 'bltin/times.c'; then $(CYGPATH_W) 'bltin/times.c'; else $(CYGPATH_W) '$(srcdir)/bltin/times.c'; fi`
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
install-man1: $(man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
@@ -597,6 +573,8 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f bltin/$(DEPDIR)/$(am__dirstamp)
+ -rm -f bltin/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -607,7 +585,7 @@ clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR)
+ -rm -rf ./$(DEPDIR) bltin/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -653,7 +631,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
+ -rm -rf ./$(DEPDIR) bltin/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/src/bltin/printf.c b/src/bltin/printf.c
index a626cee..7785735 100644
--- a/src/bltin/printf.c
+++ b/src/bltin/printf.c
@@ -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);
@@ -209,6 +216,7 @@ pc:
if (print_escape_str(start, param, array,
getstr()))
goto out;
+ *fmt = 'b';
break;
case 'c': {
int p = getchr();
@@ -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;
}
diff --git a/src/bltin/test.c b/src/bltin/test.c
index 58c05fe..d1458df 100644
--- a/src/bltin/test.c
+++ b/src/bltin/test.c
@@ -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
@@ -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
diff --git a/src/dash.1 b/src/dash.1
index 8b8026d..c452c3f 100644
--- a/src/dash.1
+++ b/src/dash.1
@@ -606,11 +606,11 @@ and
.Dq ||
are AND-OR list operators.
.Dq &&
-executes the first command, and then executes the second command iff the
-exit status of the first command is zero.
+executes the first command, and then executes the second command if and only
+if the exit status of the first command is zero.
.Dq ||
-is similar, but executes the second command iff the exit status of the first
-command is nonzero.
+is similar, but executes the second command if and only if the exit status
+of the first command is nonzero.
.Dq &&
and
.Dq ||
@@ -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.
diff --git a/src/eval.c b/src/eval.c
index 7498f9d..a27d657 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -694,6 +694,7 @@ evalcommand(union node *cmd, int flags)
#endif
{
struct localvar_list *localvar_stop;
+ struct parsefile *file_stop;
struct redirtab *redir_stop;
struct stackmark smark;
union node *argp;
@@ -722,6 +723,7 @@ evalcommand(union node *cmd, int flags)
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
setstackmark(&smark);
localvar_stop = pushlocalvars();
+ file_stop = parsefile;
back_exitstatus = 0;
cmdentry.cmdtype = CMDBUILTIN;
@@ -848,6 +850,8 @@ bail:
goto out;
}
+ jp = NULL;
+
/* Execute the command. */
switch (cmdentry.cmdtype) {
default:
@@ -856,7 +860,6 @@ bail:
INTOFF;
jp = makejob(cmd, 1);
if (forkshell(jp, cmd, FORK_FG) != 0) {
- status = waitforjob(jp);
INTON;
break;
}
@@ -875,26 +878,26 @@ bail:
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
if (exception == EXERROR && spclbltin <= 0) {
FORCEINTON;
- goto readstatus;
+ break;
}
raise:
longjmp(handler->loc, 1);
}
- goto readstatus;
+ break;
case CMDFUNCTION:
- poplocalvars(1);
if (evalfun(cmdentry.u.func, argc, argv, flags))
goto raise;
-readstatus:
- status = exitstatus;
break;
}
+ status = waitforjob(jp);
+
out:
if (cmd->ncmd.redirect)
popredir(execcmd);
unwindredir(redir_stop);
+ unwindfiles(file_stop);
unwindlocalvars(localvar_stop);
if (lastarg)
/* dsl: I think this is intended to be used to support
@@ -967,9 +970,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
shellparam.p = argv + 1;
shellparam.optind = 1;
shellparam.optoff = -1;
- pushlocalvars();
evaltree(func->n.ndefun.body, flags & EV_TESTED);
- poplocalvars(0);
funcdone:
INTOFF;
loopnest = saveloopnest;
diff --git a/src/exec.c b/src/exec.c
index ec0eadd..e9e29b7 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -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);
}
@@ -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 {
diff --git a/src/expand.c b/src/expand.c
index 2a50830..7ed259a 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -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
@@ -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
@@ -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
@@ -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--;
@@ -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);
@@ -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;
@@ -721,7 +712,6 @@ evalvar(char *p, int flag)
int c;
int startloc;
ssize_t varlen;
- int easy;
int quoted;
varflags = *p++;
@@ -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--;
@@ -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;
}
@@ -857,8 +849,7 @@ memtodest(const char *p, size_t len, const char *syntax, int quotes) {
if (c) {
if ((quotes & QUOTES_ESC) &&
((syntax[c] == CCTL) ||
- (((quotes & EXP_FULL) || syntax != BASESYNTAX) &&
- syntax[c] == CBACK)))
+ (syntax != BASESYNTAX && syntax[c] == CBACK)))
USTPUTC(CTLESC, q);
} else if (!(quotes & QUOTES_KEEPNUL))
continue;
@@ -887,7 +878,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;
@@ -896,11 +887,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;
@@ -925,7 +916,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++;
}
@@ -937,12 +928,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++)) {
@@ -1041,7 +1045,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;
@@ -1106,7 +1113,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) {
@@ -1197,7 +1204,8 @@ expandmeta(str, flag)
ckfree(p);
switch (i) {
case 0:
- if (!(pglob.gl_flags & GLOB_MAGCHAR))
+ if ((pglob.gl_flags & (GLOB_NOMAGIC | GLOB_NOCHECK)) ==
+ (GLOB_NOMAGIC | GLOB_NOCHECK))
goto nometa2;
addglob(&pglob);
globfree(&pglob);
@@ -1238,6 +1246,7 @@ addglob(pglob)
#else /* HAVE_GLOB */
STATIC char *expdir;
+STATIC unsigned expdir_max;
STATIC void
@@ -1252,6 +1261,7 @@ expandmeta(struct strlist *str, int flag)
struct strlist **savelastp;
struct strlist *sp;
char *p;
+ unsigned len;
if (fflag)
goto nometa;
@@ -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);
@@ -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;
@@ -1330,7 +1340,7 @@ expmeta(char *enddir, char *name)
}
}
} else {
- if (*p == '\\')
+ if (*p == '\\' && p[1])
esc++;
if (p[esc] == '/') {
if (metaflag)
@@ -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 == '\\')
+ if (*p == '\\' && p[1])
p++;
*enddir++ = *p;
} while (*p++);
- if (metaflag == 0 || lstat64(expdir, &statb) >= 0)
+ if (lstat64(expdir, &statb) >= 0)
addfname(expdir);
return;
}
@@ -1356,23 +1366,18 @@ expmeta(char *enddir, char *name)
if (name < start) {
p = name;
do {
- if (*p == '\\')
+ if (*p == '\\' && p[1])
p++;
*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 {
@@ -1380,6 +1385,7 @@ expmeta(char *enddir, char *name)
*endname = '\0';
endname += esc + 1;
}
+ name_len -= endname - name;
matchdot = 0;
p = start;
if (*p == '\\')
@@ -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;
}
}
}
@@ -1644,7 +1661,6 @@ char *
_rmescapes(char *str, int flag)
{
char *p, *q, *r;
- unsigned inquotes;
int notescaped;
int globbing;
@@ -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:
diff --git a/src/expand.h b/src/expand.h
index 26dc5b4..90f5328 100644
--- a/src/expand.h
+++ b/src/expand.h
@@ -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 */
diff --git a/src/histedit.c b/src/histedit.c
index 94465d7..f5c90ab 100644
--- a/src/histedit.c
+++ b/src/histedit.c
@@ -39,6 +39,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <getopt.h>
/*
* Editline and history functions (and glue).
*/
diff --git a/src/input.c b/src/input.c
index 06c08d4..ae0c4c8 100644
--- a/src/input.c
+++ b/src/input.c
@@ -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 {
@@ -475,6 +479,13 @@ popfile(void)
}
+void unwindfiles(struct parsefile *stop)
+{
+ while (parsefile != stop)
+ popfile();
+}
+
+
/*
* Return to top level.
*/
@@ -482,8 +493,7 @@ popfile(void)
void
popallfiles(void)
{
- while (parsefile != &basepf)
- popfile();
+ unwindfiles(&basepf);
}
diff --git a/src/input.h b/src/input.h
index ec97c1d..a9c0517 100644
--- a/src/input.h
+++ b/src/input.h
@@ -97,5 +97,6 @@ void popstring(void);
int setinputfile(const char *, int);
void setinputstring(char *);
void popfile(void);
+void unwindfiles(struct parsefile *);
void popallfiles(void);
void closescript(void);
diff --git a/src/jobs.c b/src/jobs.c
index 4f02e38..1a97c54 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -53,6 +53,7 @@
#include <termios.h>
#undef CEOF /* syntax.h redefines this */
#endif
+#include "eval.h"
#include "redir.h"
#include "show.h"
#include "main.h"
@@ -648,7 +649,7 @@ out:
return retval;
sigout:
- retval = 128 + pendingsigs;
+ retval = 128 + pending_sig;
goto out;
}
@@ -973,10 +974,11 @@ waitforjob(struct job *jp)
{
int st;
- TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
- while (jp->state == JOBRUNNING) {
+ TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
+ while ((jp && jp->state == JOBRUNNING) || gotsigchld)
dowait(DOWAIT_BLOCK, jp);
- }
+ if (!jp)
+ return exitstatus;
st = getstatus(jp);
#if JOBS
if (jp->jobctl) {
@@ -1147,7 +1149,7 @@ waitproc(int block, int *status)
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, &oldmask);
- while (!gotsigchld && !pendingsigs)
+ while (!gotsigchld && !pending_sig)
sigsuspend(&oldmask);
sigclearmask();
diff --git a/src/miscbltin.c b/src/miscbltin.c
index 39b9c47..5ccbbcb 100644
--- a/src/miscbltin.c
+++ b/src/miscbltin.c
@@ -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:
diff --git a/src/mystring.c b/src/mystring.c
index 0106bd2..de624b8 100644
--- a/src/mystring.c
+++ b/src/mystring.c
@@ -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);
/*
diff --git a/src/parser.c b/src/parser.c
index 382658e..8e40781 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -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 */
@@ -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__));
@@ -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;
@@ -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:
@@ -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);
@@ -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
}
@@ -836,7 +842,7 @@ static int pgetc_eatbnl(void)
int c;
while ((c = pgetc()) == '\\') {
- if (pgetc() != '\n') {
+ if (pgetc2() != '\n') {
pungetc();
break;
}
@@ -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;
+}
+
/*
@@ -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 */
@@ -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;
@@ -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);
@@ -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
@@ -1012,6 +1038,11 @@ quotemark:
}
break;
case CBQUOTE: /* '`' */
+ if (checkkwd & CHKEOFMARK) {
+ USTPUTC('`', out);
+ break;
+ }
+
PARSEBACKQOLD();
break;
case CEOF:
@@ -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 '}'");
}
@@ -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 == '|')
@@ -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));
@@ -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;
@@ -1210,6 +1241,8 @@ parsesub: {
PARSEBACKQNEW();
}
} else {
+ const char *newsyn = synstack->syntax;
+
USTPUTC(CTLVAR, out);
typeloc = out - (char *)stackblock();
STADJUST(1, out);
@@ -1229,7 +1262,7 @@ varname:
STPUTC(c, out);
c = pgetc_eatbnl();
} while (is_digit(c));
- } else {
+ } else if (c != '}') {
int cc = c;
c = pgetc_eatbnl();
@@ -1257,9 +1290,12 @@ varname:
}
USTPUTC(cc, out);
- }
+ } else
+ goto badsub;
if (subtype == 0) {
+ int cc = c;
+
switch (c) {
case ':':
subtype = VSNUL;
@@ -1273,27 +1309,41 @@ 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)
+ newsyn = DQSYNTAX;
+
+ if ((newsyn != synstack->syntax || synstack->innerdq) &&
+ subtype != VSNORMAL) {
+ 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);
}
@@ -1336,23 +1386,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;
@@ -1428,10 +1469,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;
}
@@ -1529,7 +1570,7 @@ expandstr(const char *ps)
saveprompt = doprompt;
doprompt = 0;
- readtoken1(pgetc(), DQSYNTAX, FAKEEOFMARK, 0);
+ readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK, 0);
doprompt = saveprompt;
diff --git a/src/redir.c b/src/redir.c
index f96a76b..71b0f77 100644
--- a/src/redir.c
+++ b/src/redir.c
@@ -192,7 +192,7 @@ openredirect(union node *redir)
} else if (!S_ISREG(sb.st_mode)) {
if ((f = open64(fname, O_WRONLY, 0666)) < 0)
goto ecreate;
- if (fstat64(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
+ if (!fstat64(f, &sb) && S_ISREG(sb.st_mode)) {
close(f);
errno = EEXIST;
goto ecreate;
diff --git a/src/trap.c b/src/trap.c
index edb9938..69eb8ab 100644
--- a/src/trap.c
+++ b/src/trap.c
@@ -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;
@@ -291,7 +291,7 @@ onsig(int signo)
}
gotsig[signo - 1] = 1;
- pendingsigs = signo;
+ pending_sig = signo;
if (signo == SIGINT && !trap[SIGINT]) {
if (!suppressint)
@@ -314,7 +314,7 @@ void dotrap(void)
int i;
int status, last_status;
- if (!pendingsigs)
+ if (!pending_sig)
return;
status = savestatus;
@@ -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++) {
@@ -331,7 +331,7 @@ void dotrap(void)
continue;
if (evalskip) {
- pendingsigs = i + 1;
+ pending_sig = i + 1;
break;
}
diff --git a/src/trap.h b/src/trap.h
index 7573fd7..b9dfcf2 100644
--- a/src/trap.h
+++ b/src/trap.h
@@ -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 **);