[Midnightbsd-cvs] src [10240] trunk/bin/sh: sync with freebsd 10 stable
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Jun 2 17:06:59 EDT 2018
Revision: 10240
http://svnweb.midnightbsd.org/src/?rev=10240
Author: laffer1
Date: 2018-06-02 17:06:59 -0400 (Sat, 02 Jun 2018)
Log Message:
-----------
sync with freebsd 10 stable
Modified Paths:
--------------
trunk/bin/sh/Makefile
trunk/bin/sh/TOUR
trunk/bin/sh/alias.c
trunk/bin/sh/alias.h
trunk/bin/sh/arith.h
trunk/bin/sh/arith_yacc.c
trunk/bin/sh/arith_yacc.h
trunk/bin/sh/arith_yylex.c
trunk/bin/sh/builtins.def
trunk/bin/sh/cd.c
trunk/bin/sh/cd.h
trunk/bin/sh/error.c
trunk/bin/sh/error.h
trunk/bin/sh/eval.c
trunk/bin/sh/eval.h
trunk/bin/sh/exec.c
trunk/bin/sh/exec.h
trunk/bin/sh/expand.c
trunk/bin/sh/expand.h
trunk/bin/sh/funcs/cmv
trunk/bin/sh/funcs/dirs
trunk/bin/sh/funcs/login
trunk/bin/sh/funcs/newgrp
trunk/bin/sh/funcs/popd
trunk/bin/sh/funcs/pushd
trunk/bin/sh/funcs/suspend
trunk/bin/sh/histedit.c
trunk/bin/sh/input.c
trunk/bin/sh/input.h
trunk/bin/sh/jobs.c
trunk/bin/sh/jobs.h
trunk/bin/sh/mail.c
trunk/bin/sh/mail.h
trunk/bin/sh/main.c
trunk/bin/sh/main.h
trunk/bin/sh/memalloc.c
trunk/bin/sh/memalloc.h
trunk/bin/sh/miscbltin.c
trunk/bin/sh/mkbuiltins
trunk/bin/sh/mknodes.c
trunk/bin/sh/mksyntax.c
trunk/bin/sh/mktokens
trunk/bin/sh/myhistedit.h
trunk/bin/sh/mystring.c
trunk/bin/sh/mystring.h
trunk/bin/sh/nodes.c.pat
trunk/bin/sh/nodetypes
trunk/bin/sh/options.c
trunk/bin/sh/options.h
trunk/bin/sh/output.c
trunk/bin/sh/output.h
trunk/bin/sh/parser.c
trunk/bin/sh/parser.h
trunk/bin/sh/redir.c
trunk/bin/sh/redir.h
trunk/bin/sh/sh.1
trunk/bin/sh/shell.h
trunk/bin/sh/show.c
trunk/bin/sh/show.h
trunk/bin/sh/trap.c
trunk/bin/sh/trap.h
trunk/bin/sh/var.c
trunk/bin/sh/var.h
Property Changed:
----------------
trunk/bin/sh/TOUR
trunk/bin/sh/builtins.def
trunk/bin/sh/funcs/cmv
trunk/bin/sh/funcs/dirs
trunk/bin/sh/funcs/login
trunk/bin/sh/funcs/newgrp
trunk/bin/sh/funcs/popd
trunk/bin/sh/funcs/pushd
trunk/bin/sh/funcs/suspend
trunk/bin/sh/mkbuiltins
trunk/bin/sh/mktokens
trunk/bin/sh/nodes.c.pat
trunk/bin/sh/nodetypes
trunk/bin/sh/sh.1
Modified: trunk/bin/sh/Makefile
===================================================================
--- trunk/bin/sh/Makefile 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/Makefile 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,6 +1,9 @@
+# $MidnightBSD$
# @(#)Makefile 8.4 (Berkeley) 5/5/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/Makefile 262951 2014-03-09 17:04:31Z jmmv $
+.include <bsd.own.mk>
+
PROG= sh
INSTALLFLAGS= -S
SHSRCS= alias.c arith_yacc.c arith_yylex.c cd.c echo.c error.c eval.c \
@@ -8,7 +11,7 @@
histedit.c input.c jobs.c kill.c mail.c main.c memalloc.c miscbltin.c \
mystring.c options.c output.c parser.c printf.c redir.c show.c \
test.c trap.c var.c
-GENSRCS= builtins.c init.c nodes.c syntax.c
+GENSRCS= builtins.c nodes.c syntax.c
GENHDRS= builtins.h nodes.h syntax.h token.h
SRCS= ${SHSRCS} ${GENSRCS} ${GENHDRS}
@@ -30,26 +33,21 @@
${.CURDIR}/../test \
${.CURDIR}/../../usr.bin/printf
-CLEANFILES+= mkinit mkinit.o mknodes mknodes.o \
+CLEANFILES+= mknodes mknodes.o \
mksyntax mksyntax.o
CLEANFILES+= ${GENSRCS} ${GENHDRS}
-build-tools: mkinit mknodes mksyntax
+build-tools: mknodes mksyntax
.ORDER: builtins.c builtins.h
builtins.c builtins.h: mkbuiltins builtins.def
- cd ${.CURDIR}; sh mkbuiltins ${.OBJDIR}
+ sh ${.CURDIR}/mkbuiltins ${.CURDIR}
-init.c: mkinit alias.c eval.c exec.c input.c jobs.c options.c parser.c \
- redir.c trap.c var.c
- ./mkinit ${.ALLSRC:S/^mkinit$//}
-
# XXX this is just to stop the default .c rule being used, so that the
# intermediate object has a fixed name.
# XXX we have a default .c rule, but no default .o rule.
.o:
${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
-mkinit: mkinit.o
mknodes: mknodes.o
mksyntax: mksyntax.o
@@ -64,7 +62,8 @@
token.h: mktokens
sh ${.CURDIR}/mktokens
-regress:
- cd ${.CURDIR}/../../tools/regression/bin/sh && ${MAKE} SH=${.OBJDIR}/sh
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
.include <bsd.prog.mk>
Modified: trunk/bin/sh/TOUR
===================================================================
--- trunk/bin/sh/TOUR 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/TOUR 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,5 +1,5 @@
# @(#)TOUR 8.1 (Berkeley) 5/31/93
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/TOUR 253650 2013-07-25 15:08:41Z jilles $
NOTE -- This is the original TOUR paper distributed with ash and
does not represent the current state of the shell. It is provided anyway
@@ -25,43 +25,12 @@
program input files generates
------- ----------- ---------
mkbuiltins builtins builtins.h builtins.c
- mkinit *.c init.c
mknodes nodetypes nodes.h nodes.c
mksyntax - syntax.h syntax.c
mktokens - token.h
-There are undoubtedly too many of these. Mkinit searches all the
-C source files for entries looking like:
+There are undoubtedly too many of these.
- INIT {
- x = 1; /* executed during initialization */
- }
-
- RESET {
- x = 2; /* executed when the shell does a longjmp
- back to the main command loop */
- }
-
-It pulls this code out into routines which are when particular
-events occur. The intent is to improve modularity by isolating
-the information about which modules need to be explicitly
-initialized/reset within the modules themselves.
-
-Mkinit recognizes several constructs for placing declarations in
-the init.c file.
- INCLUDE "file.h"
-includes a file. The storage class MKINIT makes a declaration
-available in the init.c file, for example:
- MKINIT int funcnest; /* depth of function calls */
-MKINIT alone on a line introduces a structure or union declara-
-tion:
- MKINIT
- struct redirtab {
- short renamed[10];
- };
-Preprocessor #define statements are copied to init.c without any
-special action to request this.
-
EXCEPTIONS: Code for dealing with exceptions appears in
exceptions.c. The C language doesn't include exception handling,
so I implement it using setjmp and longjmp. The global variable
Property changes on: trunk/bin/sh/TOUR
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/alias.c
===================================================================
--- trunk/bin/sh/alias.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/alias.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/alias.c 286813 2015-08-15 19:58:00Z jilles $");
#include <stdlib.h>
#include "shell.h"
@@ -68,18 +69,7 @@
if (equal(name, ap->name)) {
INTOFF;
ckfree(ap->val);
- /* See HACK below. */
-#ifdef notyet
ap->val = savestr(val);
-#else
- {
- size_t len = strlen(val);
- ap->val = ckmalloc(len + 2);
- memcpy(ap->val, val, len);
- ap->val[len] = ' ';
- ap->val[len+1] = '\0';
- }
-#endif
INTON;
return;
}
@@ -88,34 +78,7 @@
INTOFF;
ap = ckmalloc(sizeof (struct alias));
ap->name = savestr(name);
- /*
- * XXX - HACK: in order that the parser will not finish reading the
- * alias value off the input before processing the next alias, we
- * dummy up an extra space at the end of the alias. This is a crock
- * and should be re-thought. The idea (if you feel inclined to help)
- * is to avoid alias recursions. The mechanism used is: when
- * expanding an alias, the value of the alias is pushed back on the
- * input as a string and a pointer to the alias is stored with the
- * string. The alias is marked as being in use. When the input
- * routine finishes reading the string, it marks the alias not
- * in use. The problem is synchronization with the parser. Since
- * it reads ahead, the alias is marked not in use before the
- * resulting token(s) is next checked for further alias sub. The
- * H A C K is that we add a little fluff after the alias value
- * so that the string will not be exhausted. This is a good
- * idea ------- ***NOT***
- */
-#ifdef notyet
ap->val = savestr(val);
-#else /* hack */
- {
- size_t len = strlen(val);
- ap->val = ckmalloc(len + 2);
- memcpy(ap->val, val, len);
- ap->val[len] = ' '; /* fluff */
- ap->val[len+1] = '\0';
- }
-#endif
ap->flag = 0;
ap->next = *app;
*app = ap;
@@ -207,14 +170,8 @@
static void
printalias(const struct alias *a)
{
- char *p;
-
out1fmt("%s=", a->name);
- /* Don't print the space added above. */
- p = a->val + strlen(a->val) - 1;
- *p = '\0';
out1qstr(a->val);
- *p = ' ';
out1c('\n');
}
@@ -224,6 +181,7 @@
int i, j;
struct alias **sorted, *ap;
+ INTOFF;
sorted = ckmalloc(aliases * sizeof(*sorted));
j = 0;
for (i = 0; i < ATABSIZE; i++)
@@ -231,23 +189,29 @@
if (*ap->name != '\0')
sorted[j++] = ap;
qsort(sorted, aliases, sizeof(*sorted), comparealiases);
- for (i = 0; i < aliases; i++)
+ for (i = 0; i < aliases; i++) {
printalias(sorted[i]);
+ if (int_pending())
+ break;
+ }
ckfree(sorted);
+ INTON;
}
int
-aliascmd(int argc, char **argv)
+aliascmd(int argc __unused, char **argv __unused)
{
char *n, *v;
int ret = 0;
struct alias *ap;
- if (argc == 1) {
+ nextopt("");
+
+ if (*argptr == NULL) {
printaliases();
return (0);
}
- while ((n = *++argv) != NULL) {
+ while ((n = *argptr++) != NULL) {
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
if ((ap = lookupalias(n, 0)) == NULL) {
warning("%s: not found", n);
@@ -285,7 +249,7 @@
{
unsigned int hashval;
- hashval = *p << 4;
+ hashval = (unsigned char)*p << 4;
while (*p)
hashval+= *p++;
return &atab[hashval % ATABSIZE];
Modified: trunk/bin/sh/alias.h
===================================================================
--- trunk/bin/sh/alias.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/alias.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)alias.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/alias.h 223060 2011-06-13 21:03:27Z jilles $
*/
#define ALIASINUSE 1
Modified: trunk/bin/sh/arith.h
===================================================================
--- trunk/bin/sh/arith.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/arith.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
@@ -27,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)arith.h 1.1 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/arith.h 223060 2011-06-13 21:03:27Z jilles $
*/
#include "shell.h"
Modified: trunk/bin/sh/arith_yacc.c
===================================================================
--- trunk/bin/sh/arith_yacc.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/arith_yacc.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -33,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/arith_yacc.c 230530 2012-01-25 08:42:19Z charnier $");
#include <limits.h>
#include <errno.h>
@@ -84,6 +85,8 @@
#define ARITH_MAX_PREC 8
+int letcmd(int, char **);
+
static __dead2 void yyerror(const char *s)
{
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
@@ -131,11 +134,11 @@
yyerror("divide error");
return op == ARITH_REM ? a % b : a / b;
case ARITH_MUL:
- return a * b;
+ return (uintmax_t)a * (uintmax_t)b;
case ARITH_ADD:
- return a + b;
+ return (uintmax_t)a + (uintmax_t)b;
case ARITH_SUB:
- return a - b;
+ return (uintmax_t)a - (uintmax_t)b;
case ARITH_LSHIFT:
return a << b;
case ARITH_RSHIFT:
@@ -377,4 +380,3 @@
out1fmt(ARITH_FORMAT_STR "\n", i);
return !i;
}
-
Modified: trunk/bin/sh/arith_yacc.h
===================================================================
--- trunk/bin/sh/arith_yacc.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/arith_yacc.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -31,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/arith_yacc.h 218466 2011-02-08 23:18:06Z jilles $
*/
#define ARITH_ASS 1
Modified: trunk/bin/sh/arith_yylex.c
===================================================================
--- trunk/bin/sh/arith_yylex.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/arith_yylex.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2002
* Herbert Xu.
@@ -33,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/arith_yylex.c 254806 2013-08-24 20:06:00Z jilles $");
#include <inttypes.h>
#include <stdlib.h>
@@ -53,7 +54,7 @@
extern const char *arith_buf;
int
-yylex()
+yylex(void)
{
int value;
const char *buf = arith_buf;
@@ -218,9 +219,13 @@
value += ARITH_REM - '%';
goto checkeq;
case '+':
+ if (buf[1] == '+')
+ return ARITH_BAD;
value += ARITH_ADD - '+';
goto checkeq;
case '-':
+ if (buf[1] == '-')
+ return ARITH_BAD;
value += ARITH_SUB - '-';
goto checkeq;
case '~':
Modified: trunk/bin/sh/builtins.def
===================================================================
--- trunk/bin/sh/builtins.def 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/builtins.def 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/builtins.def 289938 2015-10-25 17:17:50Z jilles $
#
# This file lists all the builtin commands. The first column is the name
@@ -65,6 +65,7 @@
#exprcmd expr
falsecmd false
fgcmd -j fg
+freebsd_wordexpcmd freebsd_wordexp
getoptscmd getopts
hashcmd hash
histcmd -h fc
Property changes on: trunk/bin/sh/builtins.def
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/cd.c
===================================================================
--- trunk/bin/sh/cd.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/cd.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/cd.c 297749 2016-04-09 14:09:14Z jilles $");
#include <sys/types.h>
#include <sys/stat.h>
@@ -79,7 +80,7 @@
static char *cdcomppath;
int
-cdcmd(int argc, char **argv)
+cdcmd(int argc __unused, char **argv __unused)
{
const char *dest;
const char *path;
@@ -89,9 +90,8 @@
int rc;
int errno1 = ENOENT;
- optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
phys = Pflag;
- while ((ch = getopt(argc, argv, "eLP")) != -1) {
+ while ((ch = nextopt("eLP")) != '\0') {
switch (ch) {
case 'e':
getcwderr = 1;
@@ -102,18 +102,13 @@
case 'P':
phys = 1;
break;
- default:
- error("unknown option: -%c", optopt);
- break;
}
}
- argc -= optind;
- argv += optind;
- if (argc > 1)
+ if (*argptr != NULL && argptr[1] != NULL)
error("too many arguments");
- if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
+ if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
error("HOME not set");
if (*dest == '\0')
dest = ".";
@@ -195,8 +190,7 @@
* next time we get the value of the current directory.
*/
badstat = 0;
- cdcomppath = stalloc(strlen(dest) + 1);
- scopy(dest, cdcomppath);
+ cdcomppath = stsavestr(dest);
STARTSTACKSTR(p);
if (*dest == '/') {
STPUTC('/', p);
@@ -289,8 +283,7 @@
*/
if (dir == NULL || curdir == NULL)
return getpwd2();
- cdcomppath = stalloc(strlen(dir) + 1);
- scopy(dir, cdcomppath);
+ cdcomppath = stsavestr(dir);
STARTSTACKSTR(new);
if (*dir != '/') {
STPUTS(curdir, new);
@@ -330,14 +323,13 @@
}
int
-pwdcmd(int argc, char **argv)
+pwdcmd(int argc __unused, char **argv __unused)
{
char *p;
int ch, phys;
- optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
phys = Pflag;
- while ((ch = getopt(argc, argv, "LP")) != -1) {
+ while ((ch = nextopt("LP")) != '\0') {
switch (ch) {
case 'L':
phys = 0;
@@ -345,15 +337,10 @@
case 'P':
phys = 1;
break;
- default:
- error("unknown option: -%c", optopt);
- break;
}
}
- argc -= optind;
- argv += optind;
- if (argc != 0)
+ if (*argptr != NULL)
error("too many arguments");
if (!phys && getpwd()) {
Modified: trunk/bin/sh/cd.h
===================================================================
--- trunk/bin/sh/cd.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/cd.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
@@ -26,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/cd.h 223060 2011-06-13 21:03:27Z jilles $
*/
void pwd_init(int);
Modified: trunk/bin/sh/error.c
===================================================================
--- trunk/bin/sh/error.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/error.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/error.c 216622 2010-12-21 20:47:06Z jilles $");
/*
* Errors and exceptions.
Modified: trunk/bin/sh/error.h
===================================================================
--- trunk/bin/sh/error.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/error.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)error.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/error.h 220978 2011-04-23 22:28:56Z jilles $
*/
/*
Modified: trunk/bin/sh/eval.c
===================================================================
--- trunk/bin/sh/eval.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/eval.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/eval.c 287750 2015-09-13 13:43:08Z jilles $");
#include <paths.h>
#include <signal.h>
@@ -76,7 +77,7 @@
int evalskip; /* set if we are skipping commands */
int skipcount; /* number of levels to skip */
-MKINIT int loopnest; /* current loop nesting level */
+static int loopnest; /* current loop nesting level */
int funcnest; /* depth of function calls */
static int builtin_flags; /* evalcommand flags for builtins */
@@ -89,9 +90,10 @@
static void evalloop(union node *, int);
static void evalfor(union node *, int);
-static void evalcase(union node *, int);
+static union node *evalcase(union node *);
static void evalsubshell(union node *, int);
static void evalredir(union node *, int);
+static void exphere(union node *, struct arglist *);
static void expredir(union node *);
static void evalpipe(union node *);
static int is_valid_fast_cmdsubst(union node *n);
@@ -103,18 +105,14 @@
* Called to reset things after an exception.
*/
-#ifdef mkinit
-INCLUDE "eval.h"
-
-RESET {
+void
+reseteval(void)
+{
evalskip = 0;
loopnest = 0;
- funcnest = 0;
}
-#endif
-
/*
* The eval command.
*/
@@ -173,6 +171,7 @@
any = 1;
}
popstackmark(&smark);
+ setstackmark(&smark);
}
popfile();
popstackmark(&smark);
@@ -193,7 +192,9 @@
{
int do_etest;
union node *next;
+ struct stackmark smark;
+ setstackmark(&smark);
do_etest = 0;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
@@ -256,8 +257,19 @@
evalfor(n, flags & ~EV_EXIT);
break;
case NCASE:
- evalcase(n, flags);
+ next = evalcase(n);
break;
+ case NCLIST:
+ next = n->nclist.body;
+ break;
+ case NCLISTFALLTHRU:
+ if (n->nclist.body) {
+ evaltree(n->nclist.body, flags & ~EV_EXIT);
+ if (evalskip)
+ goto out;
+ }
+ next = n->nclist.next;
+ break;
case NDEFUN:
defun(n->narg.text, n->narg.next);
exitstatus = 0;
@@ -264,6 +276,8 @@
break;
case NNOT:
evaltree(n->nnot.com, EV_TESTED);
+ if (evalskip)
+ goto out;
exitstatus = !exitstatus;
break;
@@ -281,9 +295,12 @@
break;
}
n = next;
+ popstackmark(&smark);
+ setstackmark(&smark);
} while (n != NULL);
out:
- if (pendingsigs)
+ popstackmark(&smark);
+ if (pendingsig)
dotrap();
if (eflag && exitstatus != 0 && do_etest)
exitshell(exitstatus);
@@ -300,15 +317,16 @@
loopnest++;
status = 0;
for (;;) {
- evaltree(n->nbinary.ch1, EV_TESTED);
+ if (!evalskip)
+ evaltree(n->nbinary.ch1, EV_TESTED);
if (evalskip) {
-skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
+ if (evalskip == SKIPCONT && --skipcount <= 0) {
evalskip = 0;
continue;
}
if (evalskip == SKIPBREAK && --skipcount <= 0)
evalskip = 0;
- if (evalskip == SKIPFUNC || evalskip == SKIPFILE)
+ if (evalskip == SKIPRETURN)
status = exitstatus;
break;
}
@@ -321,8 +339,6 @@
}
evaltree(n->nbinary.ch2, flags);
status = exitstatus;
- if (evalskip)
- goto skipping;
}
loopnest--;
exitstatus = status;
@@ -336,23 +352,21 @@
struct arglist arglist;
union node *argp;
struct strlist *sp;
- struct stackmark smark;
+ int status;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
oexitstatus = exitstatus;
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
- if (evalskip)
- goto out;
}
*arglist.lastp = NULL;
- exitstatus = 0;
loopnest++;
+ status = 0;
for (sp = arglist.list ; sp ; sp = sp->next) {
setvar(n->nfor.var, sp->text, 0);
evaltree(n->nfor.body, flags);
+ status = exitstatus;
if (evalskip) {
if (evalskip == SKIPCONT && --skipcount <= 0) {
evalskip = 0;
@@ -364,45 +378,44 @@
}
}
loopnest--;
-out:
- popstackmark(&smark);
+ exitstatus = status;
}
+/*
+ * Evaluate a case statement, returning the selected tree.
+ *
+ * The exit status needs care to get right.
+ */
-static void
-evalcase(union node *n, int flags)
+static union node *
+evalcase(union node *n)
{
union node *cp;
union node *patp;
struct arglist arglist;
- struct stackmark smark;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
oexitstatus = exitstatus;
- exitstatus = 0;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
- for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
+ for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
while (cp->nclist.next &&
- cp->type == NCLISTFALLTHRU) {
- if (evalskip != 0)
- break;
- evaltree(cp->nclist.body,
- flags & ~EV_EXIT);
+ cp->type == NCLISTFALLTHRU &&
+ cp->nclist.body == NULL)
cp = cp->nclist.next;
- }
- if (evalskip == 0) {
- evaltree(cp->nclist.body, flags);
- }
- goto out;
+ if (cp->nclist.next &&
+ cp->type == NCLISTFALLTHRU)
+ return (cp);
+ if (cp->nclist.body == NULL)
+ exitstatus = 0;
+ return (cp->nclist.body);
}
}
}
-out:
- popstackmark(&smark);
+ exitstatus = 0;
+ return (NULL);
}
@@ -476,6 +489,37 @@
}
+static void
+exphere(union node *redir, struct arglist *fn)
+{
+ struct jmploc jmploc;
+ struct jmploc *savehandler;
+ struct localvar *savelocalvars;
+ int need_longjmp = 0;
+
+ redir->nhere.expdoc = nullstr;
+ savelocalvars = localvars;
+ localvars = NULL;
+ forcelocal++;
+ savehandler = handler;
+ if (setjmp(jmploc.loc))
+ need_longjmp = exception != EXERROR && exception != EXEXEC;
+ else {
+ handler = &jmploc;
+ expandarg(redir->nhere.doc, fn, 0);
+ redir->nhere.expdoc = fn->list->text;
+ INTOFF;
+ }
+ handler = savehandler;
+ forcelocal--;
+ poplocalvars();
+ localvars = savelocalvars;
+ if (need_longjmp)
+ longjmp(handler->loc, 1);
+ INTON;
+}
+
+
/*
* Compute the names of the files in a redirection list.
*/
@@ -494,16 +538,19 @@
case NFROMTO:
case NAPPEND:
case NCLOBBER:
- expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+ expandarg(redir->nfile.fname, &fn, EXP_TILDE);
redir->nfile.expfname = fn.list->text;
break;
case NFROMFD:
case NTOFD:
if (redir->ndup.vname) {
- expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
+ expandarg(redir->ndup.vname, &fn, EXP_TILDE);
fixredir(redir, fn.list->text, 1);
}
break;
+ case NXHERE:
+ exphere(redir, &fn);
+ break;
}
}
}
@@ -538,7 +585,8 @@
pip[1] = -1;
if (lp->next) {
if (pipe(pip) < 0) {
- close(prevfd);
+ if (prevfd >= 0)
+ close(prevfd);
error("Pipe call failed: %s", strerror(errno));
}
}
@@ -595,12 +643,11 @@
{
int pip[2];
struct job *jp;
- struct stackmark smark; /* unnecessary */
+ struct stackmark smark;
struct jmploc jmploc;
struct jmploc *savehandler;
struct localvar *savelocalvars;
- setstackmark(&smark);
result->fd = -1;
result->buf = NULL;
result->nleft = 0;
@@ -607,10 +654,11 @@
result->jp = NULL;
if (n == NULL) {
exitstatus = 0;
- goto out;
+ return;
}
+ setstackmark(&smark);
+ exitstatus = oexitstatus;
if (is_valid_fast_cmdsubst(n)) {
- exitstatus = oexitstatus;
savelocalvars = localvars;
localvars = NULL;
forcelocal++;
@@ -634,7 +682,6 @@
poplocalvars();
localvars = savelocalvars;
} else {
- exitstatus = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
jp = makejob(n, 1);
@@ -651,12 +698,96 @@
result->fd = pip[0];
result->jp = jp;
}
-out:
popstackmark(&smark);
TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
result->fd, result->buf, result->nleft, result->jp));
}
+static int
+mustexpandto(const char *argtext, const char *mask)
+{
+ for (;;) {
+ if (*argtext == CTLQUOTEMARK || *argtext == CTLQUOTEEND) {
+ argtext++;
+ continue;
+ }
+ if (*argtext == CTLESC)
+ argtext++;
+ else if (BASESYNTAX[(int)*argtext] == CCTL)
+ return (0);
+ if (*argtext != *mask)
+ return (0);
+ if (*argtext == '\0')
+ return (1);
+ argtext++;
+ mask++;
+ }
+}
+
+static int
+isdeclarationcmd(struct narg *arg)
+{
+ int have_command = 0;
+
+ if (arg == NULL)
+ return (0);
+ while (mustexpandto(arg->text, "command")) {
+ have_command = 1;
+ arg = &arg->next->narg;
+ if (arg == NULL)
+ return (0);
+ /*
+ * To also allow "command -p" and "command --" as part of
+ * a declaration command, add code here.
+ * We do not do this, as ksh does not do it either and it
+ * is not required by POSIX.
+ */
+ }
+ return (mustexpandto(arg->text, "export") ||
+ mustexpandto(arg->text, "readonly") ||
+ (mustexpandto(arg->text, "local") &&
+ (have_command || !isfunc("local"))));
+}
+
+static void
+xtracecommand(struct arglist *varlist, struct arglist *arglist)
+{
+ struct strlist *sp;
+ char sep = 0;
+ const char *p, *ps4;
+
+ ps4 = expandstr(ps4val());
+ out2str(ps4 != NULL ? ps4 : ps4val());
+ for (sp = varlist->list ; sp ; sp = sp->next) {
+ if (sep != 0)
+ out2c(' ');
+ p = strchr(sp->text, '=');
+ if (p != NULL) {
+ p++;
+ outbin(sp->text, p - sp->text, out2);
+ out2qstr(p);
+ } else
+ out2qstr(sp->text);
+ sep = ' ';
+ }
+ for (sp = arglist->list ; sp ; sp = sp->next) {
+ if (sep != 0)
+ out2c(' ');
+ /* Disambiguate command looking like assignment. */
+ if (sp == arglist->list &&
+ strchr(sp->text, '=') != NULL &&
+ strchr(sp->text, '\'') == NULL) {
+ out2c('\'');
+ out2str(sp->text);
+ out2c('\'');
+ } else
+ out2qstr(sp->text);
+ sep = ' ';
+ }
+ out2c('\n');
+ flushout(&errout);
+}
+
/*
* Check if a builtin can safely be executed in the same process,
* even though it should be in a subshell (command substitution).
@@ -691,7 +822,6 @@
static void
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
{
- struct stackmark smark;
union node *argp;
struct arglist arglist;
struct arglist varlist;
@@ -718,7 +848,6 @@
/* First expand the arguments. */
TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
- setstackmark(&smark);
arglist.lastp = &arglist.list;
varlist.lastp = &varlist.list;
varflag = 1;
@@ -728,11 +857,12 @@
exitstatus = 0;
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
if (varflag && isassignment(argp->narg.text)) {
- expandarg(argp, &varlist, EXP_VARTILDE);
+ expandarg(argp, varflag == 1 ? &varlist : &arglist,
+ EXP_VARTILDE);
continue;
- }
+ } else if (varflag == 1)
+ varflag = isdeclarationcmd(&argp->narg) ? 2 : 0;
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
- varflag = 0;
}
*arglist.lastp = NULL;
*varlist.lastp = NULL;
@@ -755,40 +885,8 @@
argv -= argc;
/* Print the command if xflag is set. */
- if (xflag) {
- char sep = 0;
- const char *p, *ps4;
- ps4 = expandstr(ps4val());
- out2str(ps4 != NULL ? ps4 : ps4val());
- for (sp = varlist.list ; sp ; sp = sp->next) {
- if (sep != 0)
- out2c(' ');
- p = strchr(sp->text, '=');
- if (p != NULL) {
- p++;
- outbin(sp->text, p - sp->text, out2);
- out2qstr(p);
- } else
- out2qstr(sp->text);
- sep = ' ';
- }
- for (sp = arglist.list ; sp ; sp = sp->next) {
- if (sep != 0)
- out2c(' ');
- /* Disambiguate command looking like assignment. */
- if (sp == arglist.list &&
- strchr(sp->text, '=') != NULL &&
- strchr(sp->text, '\'') == NULL) {
- out2c('\'');
- out2str(sp->text);
- out2c('\'');
- } else
- out2qstr(sp->text);
- sep = ' ';
- }
- out2c('\n');
- flushout(&errout);
- }
+ if (xflag)
+ xtracecommand(&varlist, &arglist);
/* Now locate the command. */
if (argc == 0) {
@@ -976,7 +1074,7 @@
funcnest--;
popredir();
INTON;
- if (evalskip == SKIPFUNC) {
+ if (evalskip == SKIPRETURN) {
evalskip = 0;
skipcount = 0;
}
@@ -1008,6 +1106,7 @@
}
handler = &jmploc;
redirect(cmd->ncmd.redirect, mode);
+ outclearerror(out1);
/*
* If there is no command word, redirection errors should
* not be fatal but assignment errors should.
@@ -1023,6 +1122,11 @@
builtin_flags = flags;
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
flushall();
+ if (outiserror(out1)) {
+ warning("write error on stdout");
+ if (exitstatus == 0 || exitstatus == 1)
+ exitstatus = 2;
+ }
cmddone:
if (argc > 0)
bltinunsetlocale();
@@ -1082,7 +1186,6 @@
setvar("_", lastarg, 0);
if (do_clearcmdentry)
clearcmdentry();
- popstackmark(&smark);
}
@@ -1161,7 +1264,7 @@
* The `command' command.
*/
int
-commandcmd(int argc, char **argv)
+commandcmd(int argc __unused, char **argv __unused)
{
const char *path;
int ch;
@@ -1169,9 +1272,7 @@
path = bltinlookup("PATH", 1);
- optind = optreset = 1;
- opterr = 0;
- while ((ch = getopt(argc, argv, "pvV")) != -1) {
+ while ((ch = nextopt("pvV")) != '\0') {
switch (ch) {
case 'p':
path = _PATH_STDPATH;
@@ -1182,20 +1283,15 @@
case 'V':
cmd = TYPECMD_BIGV;
break;
- case '?':
- default:
- error("unknown option: -%c", optopt);
}
}
- argc -= optind;
- argv += optind;
if (cmd != -1) {
- if (argc != 1)
+ if (*argptr == NULL || argptr[1] != NULL)
error("wrong number of arguments");
- return typecmd_impl(2, argv - 1, cmd, path);
+ return typecmd_impl(2, argptr - 1, cmd, path);
}
- if (argc != 0)
+ if (*argptr != NULL)
error("commandcmd bad call");
/*
@@ -1215,14 +1311,8 @@
{
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
- if (funcnest) {
- evalskip = SKIPFUNC;
- skipcount = 1;
- } else {
- /* skip the rest of the file */
- evalskip = SKIPFILE;
- skipcount = 1;
- }
+ evalskip = SKIPRETURN;
+ skipcount = 1;
return ret;
}
Modified: trunk/bin/sh/eval.h
===================================================================
--- trunk/bin/sh/eval.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/eval.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)eval.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/eval.h 255215 2013-09-04 22:10:16Z jilles $
*/
extern char *commandname; /* currently executing command */
@@ -46,6 +47,8 @@
struct job *jp; /* job structure for command */
};
+void reseteval(void);
+
/* flags in argument to evaltree/evalstring */
#define EV_EXIT 01 /* exit after evaluating tree */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
@@ -65,5 +68,4 @@
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
#define SKIPCONT 2
-#define SKIPFUNC 3
-#define SKIPFILE 4
+#define SKIPRETURN 3
Modified: trunk/bin/sh/exec.c
===================================================================
--- trunk/bin/sh/exec.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/exec.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/exec.c 286813 2015-08-15 19:58:00Z jilles $");
#include <sys/types.h>
#include <sys/stat.h>
@@ -70,7 +71,6 @@
#include "syntax.h"
#include "memalloc.h"
#include "error.h"
-#include "init.h"
#include "mystring.h"
#include "show.h"
#include "jobs.h"
@@ -78,7 +78,6 @@
#define CMDTABLESIZE 31 /* should be prime */
-#define ARB 1 /* actual size determined at run time */
@@ -86,13 +85,13 @@
struct tblentry *next; /* next entry in hash chain */
union param param; /* definition of builtin function */
int special; /* flag for special builtin commands */
- short cmdtype; /* index identifying command */
- char rehash; /* if set, cd done since entry created */
- char cmdname[ARB]; /* name of command */
+ signed char cmdtype; /* index identifying command */
+ char cmdname[]; /* name of command */
};
static struct tblentry *cmdtable[CMDTABLESIZE];
+static int cmdtable_cd = 0; /* cmdtable contains cd-dependent entries */
int exerrno = 0; /* Last exec error */
@@ -166,7 +165,7 @@
}
}
*argv = cmd;
- *--argv = _PATH_BSHELL;
+ *--argv = __DECONST(char *, _PATH_BSHELL);
execve(_PATH_BSHELL, argv, envp);
}
errno = e;
@@ -189,7 +188,7 @@
{
const char *p, *start;
char *q;
- int len;
+ size_t len, namelen;
if (*path == NULL)
return NULL;
@@ -196,7 +195,8 @@
start = *path;
for (p = start; *p && *p != ':' && *p != '%'; p++)
; /* nothing */
- len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
+ namelen = strlen(name);
+ len = p - start + namelen + 2; /* "2" is for '/' and '\0' */
STARTSTACKSTR(q);
CHECKSTRSPACE(len, q);
if (p != start) {
@@ -204,7 +204,7 @@
q += p - start;
*q++ = '/';
}
- strcpy(q, name);
+ memcpy(q, name, namelen + 1);
pathopt = NULL;
if (*p == '%') {
pathopt = ++p;
@@ -231,7 +231,9 @@
int verbose;
struct cmdentry entry;
char *name;
+ int errors;
+ errors = 0;
verbose = 0;
while ((c = nextopt("rv")) != '\0') {
if (c == 'r') {
@@ -254,19 +256,21 @@
&& cmdp->cmdtype == CMDNORMAL)
delete_cmd_entry();
find_command(name, &entry, DO_ERR, pathval());
- if (verbose) {
- if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
- cmdp = cmdlookup(name, 0);
- if (cmdp != NULL)
- printentry(cmdp, verbose);
- else
- outfmt(out2, "%s: not found\n", name);
+ if (entry.cmdtype == CMDUNKNOWN)
+ errors = 1;
+ else if (verbose) {
+ cmdp = cmdlookup(name, 0);
+ if (cmdp != NULL)
+ printentry(cmdp, verbose);
+ else {
+ outfmt(out2, "%s: not found\n", name);
+ errors = 1;
}
flushall();
}
argptr++;
}
- return 0;
+ return errors;
}
@@ -302,8 +306,6 @@
error("internal error: cmdtype %d", cmdp->cmdtype);
#endif
}
- if (cmdp->rehash)
- out1c('*');
out1c('\n');
}
@@ -320,12 +322,12 @@
{
struct tblentry *cmdp, loc_cmd;
int idx;
- int prev;
char *fullname;
struct stat statb;
int e;
int i;
int spec;
+ int cd;
/* If name contains a slash, don't use the hash table */
if (strchr(name, '/') != NULL) {
@@ -334,8 +336,10 @@
return;
}
+ cd = 0;
+
/* If name is in the table, and not invalidated by cd, we're done */
- if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
+ if ((cmdp = cmdlookup(name, 0)) != NULL) {
if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC)
cmdp = NULL;
else
@@ -356,13 +360,6 @@
}
/* We have to search path. */
- prev = -1; /* where to start */
- if (cmdp) { /* doing a rehash */
- if (cmdp->cmdtype == CMDBUILTIN)
- prev = -1;
- else
- prev = cmdp->param.index;
- }
e = ENOENT;
idx = -1;
@@ -377,13 +374,8 @@
goto loop; /* ignore unimplemented options */
}
}
- /* if rehash, don't redo absolute path names */
- if (fullname[0] == '/' && idx <= prev) {
- if (idx < prev)
- goto loop;
- TRACE(("searchexec \"%s\": no change\n", name));
- goto success;
- }
+ if (fullname[0] != '/')
+ cd = 1;
if (stat(fullname, &statb) < 0) {
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
@@ -423,9 +415,6 @@
goto success;
}
- /* We failed. If there was an entry for this command, delete it */
- if (cmdp && cmdp->cmdtype != CMDFUNCTION)
- delete_cmd_entry();
if (act & DO_ERR) {
if (e == ENOENT || e == ENOTDIR)
outfmt(out2, "%s: not found\n", name);
@@ -437,7 +426,8 @@
return;
success:
- cmdp->rehash = 0;
+ if (cd)
+ cmdtable_cd = 1;
entry->cmdtype = cmdp->cmdtype;
entry->u = cmdp->param;
entry->special = cmdp->special;
@@ -466,22 +456,15 @@
/*
- * Called when a cd is done. Marks all commands so the next time they
- * are executed they will be rehashed.
+ * Called when a cd is done. If any entry in cmdtable depends on the current
+ * directory, simply clear cmdtable completely.
*/
void
hashcd(void)
{
- struct tblentry **pp;
- struct tblentry *cmdp;
-
- for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
- for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
- if (cmdp->cmdtype == CMDNORMAL)
- cmdp->rehash = 1;
- }
- }
+ if (cmdtable_cd)
+ clearcmdentry();
}
@@ -493,7 +476,7 @@
*/
void
-changepath(const char *newval)
+changepath(const char *newval __unused)
{
clearcmdentry();
}
@@ -523,6 +506,7 @@
}
}
}
+ cmdtable_cd = 0;
INTON;
}
@@ -541,16 +525,16 @@
static struct tblentry *
cmdlookup(const char *name, int add)
{
- int hashval;
+ unsigned int hashval;
const char *p;
struct tblentry *cmdp;
struct tblentry **pp;
+ size_t len;
p = name;
- hashval = *p << 4;
+ hashval = (unsigned char)*p << 4;
while (*p)
hashval += *p++;
- hashval &= 0x7FFF;
pp = &cmdtable[hashval % CMDTABLESIZE];
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
if (equal(cmdp->cmdname, name))
@@ -559,12 +543,11 @@
}
if (add && cmdp == NULL) {
INTOFF;
- cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
- + strlen(name) + 1);
+ len = strlen(name);
+ cmdp = *pp = ckmalloc(sizeof (struct tblentry) + len + 1);
cmdp->next = NULL;
cmdp->cmdtype = CMDUNKNOWN;
- cmdp->rehash = 0;
- strcpy(cmdp->cmdname, name);
+ memcpy(cmdp->cmdname, name, len + 1);
INTON;
}
lastcmdentry = pp;
@@ -629,6 +612,7 @@
/*
* Delete a function if it exists.
+ * Called with interrupts off.
*/
int
@@ -644,7 +628,20 @@
return (0);
}
+
/*
+ * Check if a function by a certain name exists.
+ */
+int
+isfunc(const char *name)
+{
+ struct tblentry *cmdp;
+ cmdp = cmdlookup(name, 0);
+ return (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION);
+}
+
+
+/*
* Shared code for the following builtin commands:
* type, command -v, command -V
*/
@@ -678,9 +675,11 @@
/* Then look at the aliases */
if ((ap = lookupalias(argv[i], 1)) != NULL) {
- if (cmd == TYPECMD_SMALLV)
- out1fmt("alias %s='%s'\n", argv[i], ap->val);
- else
+ if (cmd == TYPECMD_SMALLV) {
+ out1fmt("alias %s=", argv[i]);
+ out1qstr(ap->val);
+ outcslow('\n', out1);
+ } else
out1fmt("%s is an alias for %s\n", argv[i],
ap->val);
continue;
@@ -768,5 +767,7 @@
int
typecmd(int argc, char **argv)
{
+ if (argc > 2 && strcmp(argv[1], "--") == 0)
+ argc--, argv++;
return typecmd_impl(argc, argv, TYPECMD_TYPE, bltinlookup("PATH", 1));
}
Modified: trunk/bin/sh/exec.h
===================================================================
--- trunk/bin/sh/exec.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/exec.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)exec.h 8.3 (Berkeley) 6/8/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/exec.h 238468 2012-07-15 10:19:43Z jilles $
*/
/* values of cmdtype */
@@ -72,5 +73,6 @@
void changepath(const char *);
void defun(const char *, union node *);
int unsetfunc(const char *);
+int isfunc(const char *);
int typecmd_impl(int, char **, int, const char *);
void clearcmdentry(void);
Modified: trunk/bin/sh/expand.c
===================================================================
--- trunk/bin/sh/expand.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/expand.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -38,7 +39,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/expand.c 320510 2017-06-30 21:32:48Z jilles $");
#include <sys/types.h>
#include <sys/time.h>
@@ -98,17 +99,19 @@
static struct ifsregion *ifslastp; /* last struct in list */
static struct arglist exparg; /* holds expanded arg list */
-static void argstr(char *, int);
+static char *argstr(char *, int);
static char *exptilde(char *, int);
+static char *expari(char *);
static void expbackq(union node *, int, int);
static int subevalvar(char *, char *, int, int, int, int, int);
static char *evalvar(char *, int);
-static int varisset(char *, int);
-static void varvalue(char *, int, int, int);
+static int varisset(const char *, int);
+static void strtodest(const char *, int, int, int);
+static void varvalue(const char *, int, int, int);
static void recordregion(int, int, int);
static void removerecordregions(int);
static void ifsbreakup(char *, struct arglist *);
-static void expandmeta(struct strlist *, int);
+static void expandmeta(struct strlist *);
static void expmeta(char *, char *);
static void addfname(char *);
static struct strlist *expsort(struct strlist *);
@@ -127,19 +130,6 @@
return (wcscoll(s1, s2));
}
-/*
- * Expand shell variables and backquotes inside a here document.
- * union node *arg the document
- * int fd; where to write the expanded version
- */
-
-void
-expandhere(union node *arg, int fd)
-{
- expandarg(arg, (struct arglist *)NULL, 0);
- xwrite(fd, stackblock(), expdest - stackblock());
-}
-
static char *
stputs_quotes(const char *data, const char *syntax, char *p)
{
@@ -183,17 +173,12 @@
STPUTC('\0', expdest);
p = grabstackstr(expdest);
exparg.lastp = &exparg.list;
- /*
- * TODO - EXP_REDIR
- */
if (flag & EXP_FULL) {
ifsbreakup(p, &exparg);
*exparg.lastp = NULL;
exparg.lastp = &exparg.list;
- expandmeta(exparg.list, flag);
+ expandmeta(exparg.list);
} else {
- if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
- rmescapes(p);
sp = (struct strlist *)stalloc(sizeof (struct strlist));
sp->text = p;
*exparg.lastp = sp;
@@ -219,17 +204,17 @@
/*
* Perform parameter expansion, command substitution and arithmetic
* expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE.
- * Processing ends at a CTLENDVAR character as well as '\0'.
+ * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'.
* This is used to expand word in ${var+word} etc.
- * If EXP_FULL, EXP_CASE or EXP_REDIR are set, keep and/or generate CTLESC
+ * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC
* characters to allow for further processing.
* If EXP_FULL is set, also preserve CTLQUOTEMARK characters.
*/
-static void
+static char *
argstr(char *p, int flag)
{
char c;
- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
+ int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
int firsteq = 1;
int split_lit;
int lit_quoted;
@@ -243,8 +228,10 @@
CHECKSTRSPACE(2, expdest);
switch (c = *p++) {
case '\0':
+ return (p - 1);
case CTLENDVAR:
- goto breakloop;
+ case CTLENDARI:
+ return (p);
case CTLQUOTEMARK:
lit_quoted = 1;
/* "$@" syntax adherence hack */
@@ -274,8 +261,8 @@
expbackq(argbackq->n, c & CTLQUOTE, flag);
argbackq = argbackq->next;
break;
- case CTLENDARI:
- expari(flag);
+ case CTLARI:
+ p = expari(p);
break;
case ':':
case '=':
@@ -301,7 +288,6 @@
expdest - stackblock(), 0);
}
}
-breakloop:;
}
/*
@@ -314,9 +300,9 @@
char c, *startp = p;
struct passwd *pw;
char *home;
- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
- while ((c = *p) != '\0') {
+ for (;;) {
+ c = *p;
switch(c) {
case CTLESC: /* This means CTL* are always considered quoted. */
case CTLVAR:
@@ -327,36 +313,27 @@
case CTLQUOTEMARK:
return (startp);
case ':':
- if (flag & EXP_VARTILDE)
- goto done;
- break;
+ if ((flag & EXP_VARTILDE) == 0)
+ break;
+ /* FALLTHROUGH */
+ case '\0':
case '/':
case CTLENDVAR:
- goto done;
+ *p = '\0';
+ if (*(startp+1) == '\0') {
+ home = lookupvar("HOME");
+ } else {
+ pw = getpwnam(startp+1);
+ home = pw != NULL ? pw->pw_dir : NULL;
+ }
+ *p = c;
+ if (home == NULL || *home == '\0')
+ return (startp);
+ strtodest(home, flag, VSNORMAL, 1);
+ return (p);
}
p++;
}
-done:
- *p = '\0';
- if (*(startp+1) == '\0') {
- if ((home = lookupvar("HOME")) == NULL)
- goto lose;
- } else {
- if ((pw = getpwnam(startp+1)) == NULL)
- goto lose;
- home = pw->pw_dir;
- }
- if (*home == '\0')
- goto lose;
- *p = c;
- if (quotes)
- STPUTS_QUOTES(home, SQSYNTAX, expdest);
- else
- STPUTS(home, expdest);
- return (p);
-lose:
- *p = c;
- return (startp);
}
@@ -400,59 +377,40 @@
}
/*
- * Expand arithmetic expression. Backup to start of expression,
- * evaluate, place result in (backed up) result, adjust string position.
+ * Expand arithmetic expression.
+ * Note that flag is not required as digits never require CTLESC characters.
*/
-void
-expari(int flag)
+static char *
+expari(char *p)
{
- char *p, *q, *start;
+ char *q, *start;
arith_t result;
int begoff;
- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
int quoted;
+ int adj;
- /*
- * This routine is slightly over-complicated for
- * efficiency. First we make sure there is
- * enough space for the result, which may be bigger
- * than the expression. Next we
- * scan backwards looking for the start of arithmetic. If the
- * next previous character is a CTLESC character, then we
- * have to rescan starting from the beginning since CTLESC
- * characters have to be processed left to right.
- */
- CHECKSTRSPACE(DIGITS(result) - 2, expdest);
- USTPUTC('\0', expdest);
- start = stackblock();
- p = expdest - 2;
- while (p >= start && *p != CTLARI)
- --p;
- if (p < start || *p != CTLARI)
- error("missing CTLARI (shouldn't happen)");
- if (p > start && *(p - 1) == CTLESC)
- for (p = start; *p != CTLARI; p++)
- if (*p == CTLESC)
- p++;
+ quoted = *p++ == '"';
+ begoff = expdest - stackblock();
+ p = argstr(p, 0);
+ removerecordregions(begoff);
+ STPUTC('\0', expdest);
+ start = stackblock() + begoff;
- if (p[1] == '"')
- quoted=1;
- else
- quoted=0;
- begoff = p - start;
- removerecordregions(begoff);
- if (quotes)
- rmescapes(p+2);
q = grabstackstr(expdest);
- result = arith(p+2);
+ result = arith(start);
ungrabstackstr(q, expdest);
- fmtstr(p, DIGITS(result), ARITH_FORMAT_STR, result);
- while (*p++)
- ;
- if (quoted == 0)
- recordregion(begoff, p - 1 - start, 0);
- result = expdest - p + 1;
- STADJUST(-result, expdest);
+
+ start = stackblock() + begoff;
+ adj = start - expdest;
+ STADJUST(adj, expdest);
+
+ CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest);
+ fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result);
+ adj = strlen(expdest);
+ STADJUST(adj, expdest);
+ if (!quoted)
+ recordregion(begoff, expdest - stackblock(), 0);
+ return p;
}
@@ -472,8 +430,8 @@
char lastc;
int startloc = dest - stackblock();
char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
- int nnl;
+ int quotes = flag & (EXP_FULL | EXP_CASE);
+ size_t nnl;
INTOFF;
saveifs = ifsfirst;
@@ -482,9 +440,6 @@
p = grabstackstr(dest);
evalbackcmd(cmd, &in);
ungrabstackstr(p, dest);
- ifsfirst = saveifs;
- ifslastp = savelastp;
- argbackq = saveargbackq;
p = in.buf;
lastc = '\0';
@@ -522,14 +477,20 @@
close(in.fd);
if (in.buf)
ckfree(in.buf);
- if (in.jp)
+ if (in.jp) {
+ p = grabstackstr(dest);
exitstatus = waitforjob(in.jp, (int *)NULL);
- if (quoted == 0)
- recordregion(startloc, dest - stackblock(), 0);
+ ungrabstackstr(p, dest);
+ }
TRACE(("expbackq: size=%td: \"%.*s\"\n",
((dest - stackblock()) - startloc),
(int)((dest - stackblock()) - startloc),
stackblock() + startloc));
+ ifsfirst = saveifs;
+ ifslastp = savelastp;
+ if (quoted == 0)
+ recordregion(startloc, dest - stackblock(), 0);
+ argbackq = saveargbackq;
expdest = dest;
INTON;
}
@@ -536,6 +497,17 @@
+static void
+recordleft(const char *str, const char *loc, char *startp)
+{
+ int amount;
+
+ amount = ((str - 1) - (loc - startp)) - expdest;
+ STADJUST(amount, expdest);
+ while (loc != str - 1)
+ *startp++ = *loc++;
+}
+
static int
subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
int varflags, int quotes)
@@ -580,7 +552,8 @@
*loc = '\0';
if (patmatch(str, startp, quotes)) {
*loc = c;
- goto recordleft;
+ recordleft(str, loc, startp);
+ return 1;
}
*loc = c;
if (quotes && *loc == CTLESC)
@@ -594,7 +567,8 @@
*loc = '\0';
if (patmatch(str, startp, quotes)) {
*loc = c;
- goto recordleft;
+ recordleft(str, loc, startp);
+ return 1;
}
*loc = c;
loc--;
@@ -642,13 +616,6 @@
default:
abort();
}
-
-recordleft:
- amount = ((str - 1) - (loc - startp)) - expdest;
- STADJUST(amount, expdest);
- while (loc != str - 1)
- *startp++ = *loc++;
- return 1;
}
@@ -663,7 +630,7 @@
int subtype;
int varflags;
char *var;
- char *val;
+ const char *val;
int patloc;
int c;
int set;
@@ -672,7 +639,8 @@
int varlen;
int varlenb;
int easy;
- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
+ int quotes = flag & (EXP_FULL | EXP_CASE);
+ int record = 0;
varflags = (unsigned char)*p++;
subtype = varflags & VSTYPE;
@@ -684,10 +652,8 @@
again: /* jump here after setting a variable with ${var=text} */
if (varflags & VSLINENO) {
set = 1;
- special = 0;
- val = var;
- p[-1] = '\0'; /* temporarily overwrite '=' to have \0
- terminated string */
+ special = 1;
+ val = NULL;
} else if (special) {
set = varisset(var, varflags & VSNUL);
val = NULL;
@@ -716,7 +682,10 @@
if (set && subtype != VSPLUS) {
/* insert the value of the variable */
if (special) {
- varvalue(var, varflags & VSQUOTE, subtype, flag);
+ if (varflags & VSLINENO)
+ STPUTBIN(var, p - var - 1, expdest);
+ else
+ varvalue(var, varflags & VSQUOTE, subtype, flag);
if (subtype == VSLENGTH) {
varlenb = expdest - stackblock() - startloc;
varlen = varlenb;
@@ -729,9 +698,6 @@
STADJUST(-varlenb, expdest);
}
} else {
- char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
- : BASESYNTAX;
-
if (subtype == VSLENGTH) {
for (;*val; val++)
if (!localeisutf8 ||
@@ -738,13 +704,9 @@
(*val & 0xC0) != 0x80)
varlen++;
}
- else {
- if (quotes)
- STPUTS_QUOTES(val, syntax, expdest);
- else
- STPUTS(val, expdest);
-
- }
+ else
+ strtodest(val, flag, subtype,
+ varflags & VSQUOTE);
}
}
@@ -758,15 +720,11 @@
switch (subtype) {
case VSLENGTH:
expdest = cvtnum(varlen, expdest);
- goto record;
+ record = 1;
+ break;
case VSNORMAL:
- if (!easy)
- break;
-record:
- recordregion(startloc, expdest - stackblock(),
- varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' &&
- (*var == '@' || *var == '*')));
+ record = easy;
break;
case VSPLUS:
@@ -776,8 +734,7 @@
(varflags & VSQUOTE ? EXP_LIT_QUOTED : 0));
break;
}
- if (easy)
- goto record;
+ record = easy;
break;
case VSTRIMLEFT:
@@ -784,8 +741,10 @@
case VSTRIMLEFTMAX:
case VSTRIMRIGHT:
case VSTRIMRIGHTMAX:
- if (!set)
+ if (!set) {
+ set = 1;
break;
+ }
/*
* Terminate the string and start recording the pattern
* right after it
@@ -799,7 +758,8 @@
}
/* Remove any recorded regions beyond start of variable */
removerecordregions(startloc);
- goto record;
+ record = 1;
+ break;
case VSASSIGN:
case VSQUESTION:
@@ -816,8 +776,7 @@
}
break;
}
- if (easy)
- goto record;
+ record = easy;
break;
case VSERROR:
@@ -828,8 +787,12 @@
default:
abort();
}
- p[-1] = '='; /* recover overwritten '=' */
+ if (record)
+ recordregion(startloc, expdest - stackblock(),
+ varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' &&
+ (*var == '@' || *var == '*')));
+
if (subtype != VSNORMAL) { /* skip to end of alternative */
int nesting = 1;
for (;;) {
@@ -857,7 +820,7 @@
*/
static int
-varisset(char *name, int nulok)
+varisset(const char *name, int nulok)
{
if (*name == '!')
@@ -876,9 +839,11 @@
}
} else if (is_digit(*name)) {
char *ap;
- int num = atoi(name);
+ long num;
- if (num > shellparam.nparam)
+ errno = 0;
+ num = strtol(name, NULL, 10);
+ if (errno != 0 || num > shellparam.nparam)
return 0;
if (num == 0)
@@ -906,7 +871,7 @@
*/
static void
-varvalue(char *name, int quoted, int subtype, int flag)
+varvalue(const char *name, int quoted, int subtype, int flag)
{
int num;
char *p;
@@ -986,6 +951,7 @@
{
struct ifsregion *ifsp;
+ INTOFF;
if (ifslastp == NULL) {
ifsp = &ifsfirst;
} else {
@@ -993,6 +959,7 @@
&& ifslastp->inquotes == inquotes) {
/* extend previous area */
ifslastp->endoff = end;
+ INTON;
return;
}
ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
@@ -1003,6 +970,7 @@
ifslastp->begoff = start;
ifslastp->endoff = end;
ifslastp->inquotes = inquotes;
+ INTON;
}
@@ -1127,13 +1095,12 @@
* The results are stored in the list exparg.
*/
static void
-expandmeta(struct strlist *str, int flag __unused)
+expandmeta(struct strlist *str)
{
char *p;
struct strlist **savelastp;
struct strlist *sp;
char c;
- /* TODO - EXP_REDIR */
while (str) {
if (fflag)
@@ -1176,9 +1143,9 @@
static void
expmeta(char *enddir, char *name)
{
- char *p;
- char *q;
- char *start;
+ const char *p;
+ const char *q;
+ const char *start;
char *endname;
int metaflag;
struct stat statb;
@@ -1187,6 +1154,7 @@
int atend;
int matchdot;
int esc;
+ int namlen;
metaflag = 0;
start = name;
@@ -1241,7 +1209,7 @@
addfname(expdir);
return;
}
- endname = p;
+ endname = name + (p - name);
if (start != name) {
p = name;
while (p < start) {
@@ -1285,17 +1253,22 @@
if (dp->d_name[0] == '.' && ! matchdot)
continue;
if (patmatch(start, dp->d_name, 0)) {
- if (enddir + dp->d_namlen + 1 > expdir_end)
+ namlen = dp->d_namlen;
+ if (enddir + namlen + 1 > expdir_end)
continue;
- memcpy(enddir, dp->d_name, dp->d_namlen + 1);
+ memcpy(enddir, dp->d_name, namlen + 1);
if (atend)
addfname(expdir);
else {
- if (enddir + dp->d_namlen + 2 > expdir_end)
+ if (dp->d_type != DT_UNKNOWN &&
+ dp->d_type != DT_DIR &&
+ dp->d_type != DT_LNK)
continue;
- enddir[dp->d_namlen] = '/';
- enddir[dp->d_namlen + 1] = '\0';
- expmeta(enddir + dp->d_namlen + 1, endname);
+ if (enddir + namlen + 2 > expdir_end)
+ continue;
+ enddir[namlen] = '/';
+ enddir[namlen + 1] = '\0';
+ expmeta(enddir + namlen + 1, endname);
}
}
}
@@ -1315,8 +1288,7 @@
char *p;
struct strlist *sp;
- p = stalloc(strlen(name) + 1);
- scopy(name, p);
+ p = stsavestr(name);
sp = (struct strlist *)stalloc(sizeof *sp);
sp->text = p;
*exparg.lastp = sp;
@@ -1419,7 +1391,8 @@
*end = NULL;
p++;
nameend = strstr(p, ":]");
- if (nameend == NULL || nameend - p >= sizeof(name) || nameend == p)
+ if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) ||
+ nameend == p)
return 0;
memcpy(name, p, nameend - p);
name[nameend - p] = '\0';
@@ -1498,23 +1471,11 @@
bt_q = q;
break;
case '[': {
- const char *endp;
+ const char *savep, *saveq;
int invert, found;
wchar_t chr;
- endp = p;
- if (*endp == '!' || *endp == '^')
- endp++;
- for (;;) {
- while (*endp == CTLQUOTEMARK)
- endp++;
- if (*endp == 0)
- goto dft; /* no matching ] */
- if (*endp == CTLESC)
- endp++;
- if (*++endp == ']')
- break;
- }
+ savep = p, saveq = q;
invert = 0;
if (*p == '!' || *p == '^') {
invert++;
@@ -1533,6 +1494,11 @@
chr = (unsigned char)*q++;
c = *p++;
do {
+ if (c == '\0') {
+ p = savep, q = saveq;
+ c = '[';
+ goto dft;
+ }
if (c == CTLQUOTEMARK)
continue;
if (c == '[' && *p == ':') {
@@ -1697,3 +1663,57 @@
outbin(argv[i], strlen(argv[i]) + 1, out1);
return (0);
}
+
+/*
+ * Do most of the work for wordexp(3), new version.
+ */
+
+int
+freebsd_wordexpcmd(int argc __unused, char **argv __unused)
+{
+ struct arglist arglist;
+ union node *args, *n;
+ struct strlist *sp;
+ size_t count, len;
+ int ch;
+ int protected = 0;
+ int fd = -1;
+
+ while ((ch = nextopt("f:p")) != '\0') {
+ switch (ch) {
+ case 'f':
+ fd = number(shoptarg);
+ break;
+ case 'p':
+ protected = 1;
+ break;
+ }
+ }
+ if (*argptr != NULL)
+ error("wrong number of arguments");
+ if (fd < 0)
+ error("missing fd");
+ INTOFF;
+ setinputfd(fd, 1);
+ INTON;
+ args = parsewordexp();
+ popfile(); /* will also close fd */
+ if (protected)
+ for (n = args; n != NULL; n = n->narg.next) {
+ if (n->narg.backquote != NULL) {
+ outcslow('C', out1);
+ error("command substitution disabled");
+ }
+ }
+ outcslow(' ', out1);
+ arglist.lastp = &arglist.list;
+ for (n = args; n != NULL; n = n->narg.next)
+ expandarg(n, &arglist, EXP_FULL | EXP_TILDE);
+ *arglist.lastp = NULL;
+ for (sp = arglist.list, count = len = 0; sp; sp = sp->next)
+ count++, len += strlen(sp->text);
+ out1fmt("%016zx %016zx", count, len);
+ for (sp = arglist.list; sp; sp = sp->next)
+ outbin(sp->text, strlen(sp->text) + 1, out1);
+ return (0);
+}
Modified: trunk/bin/sh/expand.h
===================================================================
--- trunk/bin/sh/expand.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/expand.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)expand.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/expand.h 276365 2014-12-29 15:33:20Z jilles $
*/
struct strlist {
@@ -50,7 +51,6 @@
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
#define EXP_TILDE 0x2 /* do normal tilde expansion */
#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_SPLIT_LIT 0x20 /* IFS split literal text ${v+-a b c} */
#define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */
@@ -57,8 +57,6 @@
union node;
-void expandhere(union node *, int);
void expandarg(union node *, struct arglist *, int);
-void expari(int);
void rmescapes(char *);
int casematch(union node *, const char *);
Modified: trunk/bin/sh/funcs/cmv
===================================================================
--- trunk/bin/sh/funcs/cmv 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/cmv 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)cmv 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/cmv 139969 2005-01-10 08:39:26Z imp $
# Conditional move--don't replace an existing file.
Property changes on: trunk/bin/sh/funcs/cmv
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/funcs/dirs
===================================================================
--- trunk/bin/sh/funcs/dirs 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/dirs 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)dirs 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/dirs 139969 2005-01-10 08:39:26Z imp $
# pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
Property changes on: trunk/bin/sh/funcs/dirs
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/funcs/login
===================================================================
--- trunk/bin/sh/funcs/login 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/login 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)login 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/login 139969 2005-01-10 08:39:26Z imp $
# replaces the login builtin in the BSD shell
login () exec login "$@"
Property changes on: trunk/bin/sh/funcs/login
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/funcs/newgrp
===================================================================
--- trunk/bin/sh/funcs/newgrp 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/newgrp 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,6 +32,6 @@
# SUCH DAMAGE.
#
# @(#)newgrp 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/newgrp 139969 2005-01-10 08:39:26Z imp $
newgrp() exec newgrp "$@"
Property changes on: trunk/bin/sh/funcs/newgrp
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/funcs/popd
===================================================================
--- trunk/bin/sh/funcs/popd 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/popd 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)popd 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/popd 139969 2005-01-10 08:39:26Z imp $
# pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
Property changes on: trunk/bin/sh/funcs/popd
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/funcs/pushd
===================================================================
--- trunk/bin/sh/funcs/pushd 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/pushd 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)pushd 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/pushd 139969 2005-01-10 08:39:26Z imp $
# pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
Property changes on: trunk/bin/sh/funcs/pushd
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/funcs/suspend
===================================================================
--- trunk/bin/sh/funcs/suspend 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/funcs/suspend 2018-06-02 21:06:59 UTC (rev 10240)
@@ -30,7 +30,7 @@
# SUCH DAMAGE.
#
# @(#)suspend 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/funcs/suspend 215268 2010-11-13 22:20:46Z jilles $
suspend() {
local -
Property changes on: trunk/bin/sh/funcs/suspend
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/histedit.c
===================================================================
--- trunk/bin/sh/histedit.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/histedit.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/histedit.c 240541 2012-09-15 21:56:30Z jilles $");
#include <sys/param.h>
#include <limits.h>
@@ -160,8 +161,7 @@
void
-sethistsize(hs)
- const char *hs;
+sethistsize(const char *hs)
{
int histsize;
HistEvent he;
@@ -183,7 +183,7 @@
}
int
-histcmd(int argc, char **argv)
+histcmd(int argc, char **argv __unused)
{
int ch;
const char *editor = NULL;
@@ -207,13 +207,10 @@
if (argc == 1)
error("missing history argument");
- optreset = 1; optind = 1; /* initialize getopt */
- opterr = 0;
- while (not_fcnumber(argv[optind]) &&
- (ch = getopt(argc, argv, ":e:lnrs")) != -1)
+ while (not_fcnumber(*argptr) && (ch = nextopt("e:lnrs")) != '\0')
switch ((char)ch) {
case 'e':
- editor = optarg;
+ editor = shoptarg;
break;
case 'l':
lflg = 1;
@@ -227,13 +224,7 @@
case 's':
sflg = 1;
break;
- case ':':
- error("option -%c expects argument", optopt);
- case '?':
- default:
- error("unknown option: -%c", optopt);
}
- argc -= optind, argv += optind;
savehandler = handler;
/*
@@ -277,31 +268,26 @@
/*
* If executing, parse [old=new] now
*/
- if (lflg == 0 && argc > 0 &&
- ((repl = strchr(argv[0], '=')) != NULL)) {
- pat = argv[0];
+ if (lflg == 0 && *argptr != NULL &&
+ ((repl = strchr(*argptr, '=')) != NULL)) {
+ pat = *argptr;
*repl++ = '\0';
- argc--, argv++;
+ argptr++;
}
/*
* determine [first] and [last]
*/
- switch (argc) {
- case 0:
+ if (*argptr == NULL) {
firststr = lflg ? "-16" : "-1";
laststr = "-1";
- break;
- case 1:
- firststr = argv[0];
- laststr = lflg ? "-1" : argv[0];
- break;
- case 2:
- firststr = argv[0];
- laststr = argv[1];
- break;
- default:
+ } else if (argptr[1] == NULL) {
+ firststr = argptr[0];
+ laststr = lflg ? "-1" : argptr[0];
+ } else if (argptr[2] == NULL) {
+ firststr = argptr[0];
+ laststr = argptr[1];
+ } else
error("too many arguments");
- }
/*
* Turn into event numbers.
*/
Modified: trunk/bin/sh/input.c
===================================================================
--- trunk/bin/sh/input.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/input.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/input.c 262951 2014-03-09 17:04:31Z jmmv $");
#include <stdio.h> /* defines BUFSIZ */
#include <fcntl.h>
@@ -64,10 +65,9 @@
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
-MKINIT
struct strpush {
struct strpush *prev; /* preceding string on stack */
- char *prevstring;
+ const char *prevstring;
int prevnleft;
int prevlleft;
struct alias *ap; /* if push was associated with an alias */
@@ -78,7 +78,6 @@
* contains information about the current file being read.
*/
-MKINIT
struct parsefile {
struct parsefile *prev; /* preceding file on stack */
int linno; /* current line */
@@ -85,7 +84,7 @@
int fd; /* file descriptor (or -1 if string) */
int nleft; /* number of chars left in this line */
int lleft; /* number of lines left in this buffer */
- char *nextc; /* next char in buffer */
+ const char *nextc; /* next char in buffer */
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */
@@ -94,12 +93,14 @@
int plinno = 1; /* input line number */
int parsenleft; /* copy of parsefile->nleft */
-MKINIT int parselleft; /* copy of parsefile->lleft */
-char *parsenextc; /* copy of parsefile->nextc */
-MKINIT struct parsefile basepf; /* top level input file */
-char basebuf[BUFSIZ]; /* buffer for top level input file */
+static int parselleft; /* copy of parsefile->lleft */
+const char *parsenextc; /* copy of parsefile->nextc */
+static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
+static struct parsefile basepf = { /* top level input file */
+ .nextc = basebuf,
+ .buf = basebuf
+};
static struct parsefile *parsefile = &basepf; /* current input file */
-int init_editline = 0; /* editline library initialized? */
int whichprompt; /* 1 == PS1, 2 == PS2 */
EditLine *el; /* cookie for editline package */
@@ -108,21 +109,12 @@
static int preadfd(void);
static void popstring(void);
-#ifdef mkinit
-INCLUDE "input.h"
-INCLUDE "error.h"
-
-MKINIT char basebuf[];
-
-INIT {
- basepf.nextc = basepf.buf = basebuf;
-}
-
-RESET {
+void
+resetinput(void)
+{
popallfiles();
parselleft = parsenleft = 0; /* clear input buffer */
}
-#endif
/*
@@ -171,12 +163,6 @@
int nr;
parsenextc = parsefile->buf;
-#ifndef NO_HISTORY
- if (el != NULL && gotwinch) {
- gotwinch = 0;
- el_resize(el);
- }
-#endif
retry:
#ifndef NO_HISTORY
if (parsefile->fd == 0 && el) {
@@ -183,15 +169,17 @@
static const char *rl_cp;
static int el_len;
- if (rl_cp == NULL)
+ if (rl_cp == NULL) {
+ el_resize(el);
rl_cp = el_gets(el, &el_len);
+ }
if (rl_cp == NULL)
nr = el_len == 0 ? 0 : -1;
else {
nr = el_len;
- if (nr > BUFSIZ - 1)
- nr = BUFSIZ - 1;
- memcpy(parsenextc, rl_cp, nr);
+ if (nr > BUFSIZ)
+ nr = BUFSIZ;
+ memcpy(parsefile->buf, rl_cp, nr);
if (nr != el_len) {
el_len -= nr;
rl_cp += nr;
@@ -200,7 +188,7 @@
}
} else
#endif
- nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
+ nr = read(parsefile->fd, parsefile->buf, BUFSIZ);
if (nr <= 0) {
if (nr < 0) {
@@ -237,10 +225,16 @@
{
char *p, *q;
int more;
- int something;
char savec;
- if (parsefile->strpush) {
+ while (parsefile->strpush) {
+ /*
+ * Add a space to the end of an alias to ensure that the
+ * alias remains in use while parsing its last word.
+ * This avoids alias recursions.
+ */
+ if (parsenleft == -1 && parsefile->strpush->ap != NULL)
+ return ' ';
popstring();
if (--parsenleft >= 0)
return (*parsenextc++);
@@ -258,10 +252,9 @@
}
}
- q = p = parsenextc;
+ q = p = parsefile->buf + (parsenextc - parsefile->buf);
/* delete nul characters */
- something = 0;
for (more = 1; more;) {
switch (*p) {
case '\0':
@@ -268,10 +261,6 @@
p++; /* Skip nul */
goto check;
- case '\t':
- case ' ':
- break;
-
case '\n':
parsenleft = q - parsenextc;
more = 0; /* Stop processing here */
@@ -278,7 +267,6 @@
break;
default:
- something = 1;
break;
}
@@ -297,7 +285,8 @@
*q = '\0';
#ifndef NO_HISTORY
- if (parsefile->fd == 0 && hist && something) {
+ if (parsefile->fd == 0 && hist &&
+ parsenextc[strspn(parsenextc, " \t\n")] != '\0') {
HistEvent he;
INTOFF;
history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
@@ -350,7 +339,7 @@
* We handle aliases this way.
*/
void
-pushstring(char *s, int len, void *ap)
+pushstring(char *s, int len, struct alias *ap)
{
struct strpush *sp;
@@ -365,9 +354,9 @@
sp->prevstring = parsenextc;
sp->prevnleft = parsenleft;
sp->prevlleft = parselleft;
- sp->ap = (struct alias *)ap;
+ sp->ap = ap;
if (ap)
- ((struct alias *)ap)->flag |= ALIASINUSE;
+ ap->flag |= ALIASINUSE;
parsenextc = s;
parsenleft = len;
INTON;
@@ -379,12 +368,16 @@
struct strpush *sp = parsefile->strpush;
INTOFF;
+ if (sp->ap) {
+ if (parsenextc != sp->ap->val &&
+ (parsenextc[-1] == ' ' || parsenextc[-1] == '\t'))
+ forcealias();
+ sp->ap->flag &= ~ALIASINUSE;
+ }
parsenextc = sp->prevstring;
parsenleft = sp->prevnleft;
parselleft = sp->prevlleft;
/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
- if (sp->ap)
- sp->ap->flag &= ~ALIASINUSE;
parsefile->strpush = sp->prev;
if (sp != &(parsefile->basestrpush))
ckfree(sp);
@@ -403,10 +396,10 @@
int fd2;
INTOFF;
- if ((fd = open(fname, O_RDONLY)) < 0)
+ if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0)
error("cannot open %s: %s", fname, strerror(errno));
if (fd < 10) {
- fd2 = fcntl(fd, F_DUPFD, 10);
+ fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
close(fd);
if (fd2 < 0)
error("Out of file descriptors");
@@ -418,23 +411,22 @@
/*
- * Like setinputfile, but takes an open file descriptor. Call this with
- * interrupts off.
+ * Like setinputfile, but takes an open file descriptor (which should have
+ * its FD_CLOEXEC flag already set). Call this with interrupts off.
*/
void
setinputfd(int fd, int push)
{
- (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
if (push) {
pushfile();
- parsefile->buf = ckmalloc(BUFSIZ);
+ parsefile->buf = ckmalloc(BUFSIZ + 1);
}
if (parsefile->fd > 0)
close(parsefile->fd);
parsefile->fd = fd;
if (parsefile->buf == NULL)
- parsefile->buf = ckmalloc(BUFSIZ);
+ parsefile->buf = ckmalloc(BUFSIZ + 1);
parselleft = parsenleft = 0;
plinno = 1;
}
@@ -445,7 +437,7 @@
*/
void
-setinputstring(char *string, int push)
+setinputstring(const char *string, int push)
{
INTOFF;
if (push)
Modified: trunk/bin/sh/input.h
===================================================================
--- trunk/bin/sh/input.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/input.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)input.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/input.h 253650 2013-07-25 15:08:41Z jilles $
*/
/* PEOF (the end of file marker) is defined in syntax.h */
@@ -42,20 +43,21 @@
*/
extern int plinno;
extern int parsenleft; /* number of characters left in input buffer */
-extern char *parsenextc; /* next character in input buffer */
-extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
+extern const char *parsenextc; /* next character in input buffer */
+struct alias;
struct parsefile;
+void resetinput(void);
char *pfgets(char *, int);
int pgetc(void);
int preadbuffer(void);
int preadateof(void);
void pungetc(void);
-void pushstring(char *, int, void *);
+void pushstring(char *, int, struct alias *);
void setinputfile(const char *, int);
void setinputfd(int, int);
-void setinputstring(char *, int);
+void setinputstring(const char *, int);
void popfile(void);
struct parsefile *getcurrentfile(void);
void popfilesupto(struct parsefile *);
Modified: trunk/bin/sh/jobs.c
===================================================================
--- trunk/bin/sh/jobs.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/jobs.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/jobs.c 287750 2015-09-13 13:43:08Z jilles $");
#include <sys/ioctl.h>
#include <sys/param.h>
@@ -77,24 +78,28 @@
static struct job *jobtab; /* array of jobs */
static int njobs; /* size of array */
-MKINIT pid_t backgndpid = -1; /* pid of last background process */
-MKINIT struct job *bgjob = NULL; /* last background process */
+static pid_t backgndpid = -1; /* pid of last background process */
+static struct job *bgjob = NULL; /* last background process */
#if JOBS
static struct job *jobmru; /* most recently used job list */
static pid_t initialpgrp; /* pgrp of shell on invocation */
#endif
-int in_waitcmd = 0; /* are we in waitcmd()? */
-int in_dowait = 0; /* are we in dowait()? */
-volatile sig_atomic_t breakwaitcmd = 0; /* should wait be terminated? */
static int ttyfd = -1;
+/* mode flags for dowait */
+#define DOWAIT_BLOCK 0x1 /* wait until a child exits */
+#define DOWAIT_SIG 0x2 /* if DOWAIT_BLOCK, abort on SIGINT/SIGQUIT */
+#define DOWAIT_SIG_ANY 0x4 /* if DOWAIT_SIG, abort on any signal */
+
#if JOBS
static void restartjob(struct job *);
#endif
static void freejob(struct job *);
-static struct job *getjob(char *);
+static int waitcmdloop(struct job *);
+pid_t getjobpgrp(char *);
+static struct job *getjob_nonotfound(const char *);
+static struct job *getjob(const char *);
static pid_t dowait(int, struct job *);
-static pid_t waitproc(int, int *);
static void checkzombies(void);
static void cmdtxt(union node *);
static void cmdputs(const char *);
@@ -111,7 +116,7 @@
* Turn job control on and off.
*/
-MKINIT int jobctl;
+static int jobctl;
#if JOBS
void
@@ -124,11 +129,12 @@
if (on) {
if (ttyfd != -1)
close(ttyfd);
- if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
+ if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
i = 0;
while (i <= 2 && !isatty(i))
i++;
- if (i > 2 || (ttyfd = fcntl(i, F_DUPFD, 10)) < 0)
+ if (i > 2 ||
+ (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0)
goto out;
}
if (ttyfd < 10) {
@@ -136,7 +142,7 @@
* Keep our TTY file descriptor out of the way of
* the user's redirections.
*/
- if ((i = fcntl(ttyfd, F_DUPFD, 10)) < 0) {
+ if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
close(ttyfd);
ttyfd = -1;
goto out;
@@ -144,11 +150,6 @@
close(ttyfd);
ttyfd = i;
}
- if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
- close(ttyfd);
- ttyfd = -1;
- goto out;
- }
do { /* while we are in the background */
initialpgrp = tcgetpgrp(ttyfd);
if (initialpgrp < 0) {
@@ -182,13 +183,14 @@
#if JOBS
int
-fgcmd(int argc __unused, char **argv)
+fgcmd(int argc __unused, char **argv __unused)
{
struct job *jp;
pid_t pgrp;
int status;
- jp = getjob(argv[1]);
+ nextopt("");
+ jp = getjob(*argptr);
if (jp->jobctl == 0)
error("job not created under job control");
printjobcmd(jp);
@@ -209,8 +211,9 @@
{
struct job *jp;
+ nextopt("");
do {
- jp = getjob(*++argv);
+ jp = getjob(*argptr);
if (jp->jobctl == 0)
error("job not created under job control");
if (jp->state == JOBDONE)
@@ -219,7 +222,7 @@
jp->foreground = 0;
out1fmt("[%td] ", jp - jobtab + 1);
printjobcmd(jp);
- } while (--argc > 1);
+ } while (*argptr != NULL && *++argptr != NULL);
return 0;
}
@@ -247,15 +250,13 @@
int
-jobscmd(int argc, char *argv[])
+jobscmd(int argc __unused, char *argv[] __unused)
{
char *id;
int ch, mode;
- optind = optreset = 1;
- opterr = 0;
mode = SHOWJOBS_DEFAULT;
- while ((ch = getopt(argc, argv, "lps")) != -1) {
+ while ((ch = nextopt("lps")) != '\0') {
switch (ch) {
case 'l':
mode = SHOWJOBS_VERBOSE;
@@ -266,18 +267,13 @@
case 's':
mode = SHOWJOBS_PIDS;
break;
- case '?':
- default:
- error("unknown option: -%c", optopt);
}
}
- argc -= optind;
- argv += optind;
- if (argc == 0)
+ if (*argptr == NULL)
showjobs(0, mode);
else
- while ((id = *argv++) != NULL)
+ while ((id = *argptr++) != NULL)
showjob(getjob(id), mode);
return (0);
@@ -302,6 +298,7 @@
{
char s[64];
char statestr[64];
+ const char *sigstr;
struct procstat *ps;
struct job *j;
int col, curr, i, jobno, prev, procno;
@@ -328,8 +325,9 @@
i = WSTOPSIG(ps->status);
else
i = -1;
- if (i > 0 && i < sys_nsig && sys_siglist[i])
- strcpy(statestr, sys_siglist[i]);
+ sigstr = strsignal(i);
+ if (sigstr != NULL)
+ strcpy(statestr, sigstr);
else
strcpy(statestr, "Suspended");
#endif
@@ -341,21 +339,22 @@
WEXITSTATUS(ps->status));
} else {
i = WTERMSIG(ps->status);
- if (i > 0 && i < sys_nsig && sys_siglist[i])
- strcpy(statestr, sys_siglist[i]);
+ sigstr = strsignal(i);
+ if (sigstr != NULL)
+ strcpy(statestr, sigstr);
else
- fmtstr(statestr, 64, "Signal %d", i);
+ strcpy(statestr, "Unknown signal");
if (WCOREDUMP(ps->status))
strcat(statestr, " (core dumped)");
}
- for (ps = jp->ps ; ; ps++) { /* for each process */
+ for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */
if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
out1fmt("%d\n", (int)ps->pid);
- goto skip;
+ continue;
}
if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
- goto skip;
+ continue;
if (jobno == curr && ps == jp->ps)
c = '+';
else if (jobno == prev && ps == jp->ps)
@@ -386,8 +385,6 @@
out1c('\n');
} else
printjobcmd(jp);
-skip: if (--procno <= 0)
- break;
}
}
@@ -418,13 +415,15 @@
if (change && ! jp->changed)
continue;
showjob(jp, mode);
- jp->changed = 0;
- /* Hack: discard jobs for which $! has not been referenced
- * in interactive mode when they terminate.
- */
- if (jp->state == JOBDONE && !jp->remembered &&
- (iflag || jp != bgjob)) {
- freejob(jp);
+ if (mode == SHOWJOBS_DEFAULT || mode == SHOWJOBS_VERBOSE) {
+ jp->changed = 0;
+ /* Hack: discard jobs for which $! has not been
+ * referenced in interactive mode when they terminate.
+ */
+ if (jp->state == JOBDONE && !jp->remembered &&
+ (iflag || jp != bgjob)) {
+ freejob(jp);
+ }
}
}
}
@@ -462,32 +461,41 @@
waitcmd(int argc __unused, char **argv __unused)
{
struct job *job;
- int status, retval;
- struct job *jp;
+ int retval;
nextopt("");
- if (*argptr != NULL) {
- job = getjob(*argptr);
- } else {
- job = NULL;
- }
+ if (*argptr == NULL)
+ return (waitcmdloop(NULL));
+ do {
+ job = getjob_nonotfound(*argptr);
+ if (job == NULL)
+ retval = 127;
+ else
+ retval = waitcmdloop(job);
+ argptr++;
+ } while (*argptr != NULL);
+
+ return (retval);
+}
+
+static int
+waitcmdloop(struct job *job)
+{
+ int status, retval, sig;
+ struct job *jp;
+
/*
* Loop until a process is terminated or stopped, or a SIGINT is
* received.
*/
- in_waitcmd++;
do {
if (job != NULL) {
- if (job->state) {
+ if (job->state == JOBDONE) {
status = job->ps[job->nprocs - 1].status;
if (WIFEXITED(status))
retval = WEXITSTATUS(status);
-#if JOBS
- else if (WIFSTOPPED(status))
- retval = WSTOPSIG(status) + 128;
-#endif
else
retval = WTERMSIG(status) + 128;
if (! iflag || ! job->changed)
@@ -497,7 +505,6 @@
if (job == bgjob)
bgjob = NULL;
}
- in_waitcmd--;
return retval;
}
} else {
@@ -513,7 +520,6 @@
}
for (jp = jobtab ; ; jp++) {
if (jp >= jobtab + njobs) { /* no running procs */
- in_waitcmd--;
return 0;
}
if (jp->used && jp->state == 0)
@@ -520,21 +526,23 @@
break;
}
}
- } while (dowait(1, (struct job *)NULL) != -1);
- in_waitcmd--;
+ } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1);
- return 0;
+ sig = pendingsig_waitcmd;
+ pendingsig_waitcmd = 0;
+ return sig + 128;
}
int
-jobidcmd(int argc __unused, char **argv)
+jobidcmd(int argc __unused, char **argv __unused)
{
struct job *jp;
int i;
- jp = getjob(argv[1]);
+ nextopt("");
+ jp = getjob(*argptr);
for (i = 0 ; i < jp->nprocs ; ) {
out1fmt("%d", (int)jp->ps[i].pid);
out1c(++i < jp->nprocs? ' ' : '\n');
@@ -549,7 +557,7 @@
*/
static struct job *
-getjob(char *name)
+getjob_nonotfound(const char *name)
{
int jobno;
struct job *found, *jp;
@@ -614,12 +622,22 @@
return jp;
}
}
- error("No such job: %s", name);
- /*NOTREACHED*/
return NULL;
}
+static struct job *
+getjob(const char *name)
+{
+ struct job *jp;
+
+ jp = getjob_nonotfound(name);
+ if (jp == NULL)
+ error("No such job: %s", name);
+ return (jp);
+}
+
+
pid_t
getjobpgrp(char *name)
{
@@ -669,7 +687,8 @@
jobtab = jp;
}
jp = jobtab + njobs;
- for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
+ for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0)
+ ;
INTON;
break;
}
@@ -958,7 +977,6 @@
waitforjob(struct job *jp, int *origstatus)
{
#if JOBS
- pid_t mypgrp = getpgrp();
int propagate_int = jp->jobctl && jp->foreground;
#endif
int status;
@@ -967,11 +985,12 @@
INTOFF;
TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
while (jp->state == 0)
- if (dowait(1, jp) == -1)
+ if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG |
+ DOWAIT_SIG_ANY : 0), jp) == -1)
dotrap();
#if JOBS
if (jp->jobctl) {
- if (tcsetpgrp(ttyfd, mypgrp) < 0)
+ if (tcsetpgrp(ttyfd, rootpid) < 0)
error("tcsetpgrp failed, errno=%d\n", errno);
}
if (jp->state == JOBSTOPPED)
@@ -1005,6 +1024,10 @@
}
+static void
+dummy_handler(int sig __unused)
+{
+}
/*
* Wait for a process to terminate.
@@ -1011,32 +1034,67 @@
*/
static pid_t
-dowait(int block, struct job *job)
+dowait(int mode, struct job *job)
{
+ struct sigaction sa, osa;
+ sigset_t mask, omask;
pid_t pid;
int status;
struct procstat *sp;
struct job *jp;
struct job *thisjob;
+ const char *sigstr;
int done;
int stopped;
int sig;
int coredump;
+ int wflags;
+ int restore_sigchld;
- in_dowait++;
- TRACE(("dowait(%d) called\n", block));
+ TRACE(("dowait(%d, %p) called\n", mode, job));
+ restore_sigchld = 0;
+ if ((mode & DOWAIT_SIG) != 0) {
+ sigfillset(&mask);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+ INTOFF;
+ if (!issigchldtrapped()) {
+ restore_sigchld = 1;
+ sa.sa_handler = dummy_handler;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGCHLD, &sa, &osa);
+ }
+ }
do {
- pid = waitproc(block, &status);
+#if JOBS
+ if (iflag)
+ wflags = WUNTRACED | WCONTINUED;
+ else
+#endif
+ wflags = 0;
+ if ((mode & (DOWAIT_BLOCK | DOWAIT_SIG)) != DOWAIT_BLOCK)
+ wflags |= WNOHANG;
+ pid = wait3(&status, wflags, (struct rusage *)NULL);
TRACE(("wait returns %d, status=%d\n", (int)pid, status));
- } while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) ||
- (pid > 0 && WIFSTOPPED(status) && !iflag));
- in_dowait--;
+ if (pid == 0 && (mode & DOWAIT_SIG) != 0) {
+ pid = -1;
+ if (((mode & DOWAIT_SIG_ANY) != 0 ?
+ pendingsig : pendingsig_waitcmd) != 0) {
+ errno = EINTR;
+ break;
+ }
+ sigsuspend(&omask);
+ if (int_pending())
+ break;
+ }
+ } while (pid == -1 && errno == EINTR);
if (pid == -1 && errno == ECHILD && job != NULL)
job->state = JOBDONE;
- if (breakwaitcmd != 0) {
- breakwaitcmd = 0;
- if (pid <= 0)
- return -1;
+ if ((mode & DOWAIT_SIG) != 0) {
+ if (restore_sigchld)
+ sigaction(SIGCHLD, &osa, NULL);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ INTON;
}
if (pid <= 0)
return pid;
@@ -1053,7 +1111,11 @@
TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
(int)pid, sp->status,
status));
- sp->status = status;
+ if (WIFCONTINUED(status)) {
+ sp->status = -1;
+ jp->state = 0;
+ } else
+ sp->status = status;
thisjob = jp;
}
if (sp->status == -1)
@@ -1092,10 +1154,11 @@
coredump = WCOREDUMP(sp->status);
}
if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
- if (sig < sys_nsig && sys_siglist[sig])
- out2str(sys_siglist[sig]);
+ sigstr = strsignal(sig);
+ if (sigstr != NULL)
+ out2str(sigstr);
else
- outfmt(out2, "Signal %d", sig);
+ out2str("Unknown signal");
if (coredump)
out2str(" (core dumped)");
out2c('\n');
@@ -1111,26 +1174,6 @@
/*
- * Do a wait system call. If job control is compiled in, we accept
- * stopped processes. If block is zero, we return a value of zero
- * rather than blocking.
- */
-static pid_t
-waitproc(int block, int *status)
-{
- int flags;
-
-#if JOBS
- flags = WUNTRACED;
-#else
- flags = 0;
-#endif
- if (block == 0)
- flags |= WNOHANG;
- return wait3(status, flags, (struct rusage *)NULL);
-}
-
-/*
* return 1 if there are stopped jobs, otherwise 0
*/
int job_warning = 0;
@@ -1276,6 +1319,10 @@
cmdputs(n->narg.text);
cmdputs("() ...");
break;
+ case NNOT:
+ cmdputs("! ");
+ cmdtxt(n->nnot.com);
+ break;
case NCMD:
for (np = n->ncmd.args ; np ; np = np->narg.next) {
cmdtxt(np);
Modified: trunk/bin/sh/jobs.h
===================================================================
--- trunk/bin/sh/jobs.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/jobs.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/jobs.h 255157 2013-09-02 21:57:46Z jilles $
*/
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
@@ -84,9 +84,6 @@
};
extern int job_warning; /* user was warned about stopped jobs */
-extern int in_waitcmd; /* are we in waitcmd()? */
-extern int in_dowait; /* are we in dowait()? */
-extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
void setjobctl(int);
void showjobs(int, int);
Modified: trunk/bin/sh/mail.c
===================================================================
--- trunk/bin/sh/mail.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mail.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/mail.c 213760 2010-10-13 04:01:01Z obrien $");
/*
* Routines to check for mail. (Perhaps make part of main.c?)
Modified: trunk/bin/sh/mail.h
===================================================================
--- trunk/bin/sh/mail.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mail.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)mail.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/mail.h 127958 2004-04-06 20:06:54Z markm $
*/
void chkmail(int);
Modified: trunk/bin/sh/main.c
===================================================================
--- trunk/bin/sh/main.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/main.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -42,7 +43,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/main.c 255215 2013-09-04 22:10:16Z jilles $");
#include <stdio.h>
#include <signal.h>
@@ -68,10 +69,10 @@
#include "show.h"
#include "memalloc.h"
#include "error.h"
-#include "init.h"
#include "mystring.h"
#include "exec.h"
#include "cd.h"
+#include "redir.h"
#include "builtins.h"
int rootpid;
@@ -79,8 +80,9 @@
struct jmploc main_handler;
int localeisutf8, initial_localeisutf8;
+static void reset(void);
static void cmdloop(int);
-static void read_profile(char *);
+static void read_profile(const char *);
static char *find_dot_file(char *);
/*
@@ -139,7 +141,7 @@
#endif
rootpid = getpid();
rootshell = 1;
- init();
+ initvar();
setstackmark(&smark);
setstackmark(&smark2);
procargs(argc, argv);
@@ -170,8 +172,8 @@
if (minusc) {
evalstring(minusc, sflag ? 0 : EV_EXIT);
}
+state4:
if (sflag || minusc == NULL) {
-state4: /* XXX ??? - why isn't this before the "if" statement */
cmdloop(1);
}
exitshell(exitstatus);
@@ -179,6 +181,12 @@
return 0;
}
+static void
+reset(void)
+{
+ reseteval();
+ resetinput();
+}
/*
* Read and execute commands. "Top" is nonzero for the top level command
@@ -196,7 +204,7 @@
TRACE(("cmdloop(%d) called\n", top));
setstackmark(&smark);
for (;;) {
- if (pendingsigs)
+ if (pendingsig)
dotrap();
inter = 0;
if (iflag && top) {
@@ -224,7 +232,7 @@
popstackmark(&smark);
setstackmark(&smark);
if (evalskip != 0) {
- if (evalskip == SKIPFILE)
+ if (evalskip == SKIPRETURN)
evalskip = 0;
break;
}
@@ -239,7 +247,7 @@
*/
static void
-read_profile(char *name)
+read_profile(const char *name)
{
int fd;
const char *expandedname;
@@ -248,7 +256,7 @@
if (expandedname == NULL)
return;
INTOFF;
- if ((fd = open(expandedname, O_RDONLY)) >= 0)
+ if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0)
setinputfd(fd, 1);
INTON;
if (fd < 0)
Modified: trunk/bin/sh/main.h
===================================================================
--- trunk/bin/sh/main.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/main.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)main.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/main.h 229220 2012-01-01 22:17:12Z jilles $
*/
extern int rootpid; /* pid of main shell */
Modified: trunk/bin/sh/memalloc.c
===================================================================
--- trunk/bin/sh/memalloc.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/memalloc.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/memalloc.c 297749 2016-04-09 14:09:14Z jilles $");
#include <sys/param.h>
#include "shell.h"
@@ -98,9 +99,11 @@
savestr(const char *s)
{
char *p;
+ size_t len;
- p = ckmalloc(strlen(s) + 1);
- scopy(s, p);
+ len = strlen(s);
+ p = ckmalloc(len + 1);
+ memcpy(p, s, len + 1);
return p;
}
@@ -124,7 +127,6 @@
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
static struct stack_block *stackp;
-static struct stackmark *markp;
char *stacknxt;
int stacknleft;
char *sstrend;
@@ -179,7 +181,19 @@
}
+char *
+stsavestr(const char *s)
+{
+ char *p;
+ size_t len;
+ len = strlen(s);
+ p = stalloc(len + 1);
+ memcpy(p, s, len + 1);
+ return p;
+}
+
+
void
setstackmark(struct stackmark *mark)
{
@@ -186,8 +200,9 @@
mark->stackp = stackp;
mark->stacknxt = stacknxt;
mark->stacknleft = stacknleft;
- mark->marknext = markp;
- markp = mark;
+ /* Ensure this block stays in place. */
+ if (stackp != NULL && stacknxt == SPACE(stackp))
+ stalloc(1);
}
@@ -197,7 +212,6 @@
struct stack_block *sp;
INTOFF;
- markp = mark->marknext;
while (stackp != mark->stackp) {
sp = stackp;
stackp = sp->prev;
@@ -229,11 +243,11 @@
int oldlen;
struct stack_block *sp;
struct stack_block *oldstackp;
- struct stackmark *xmark;
if (min < stacknleft)
min = stacknleft;
- if (min >= INT_MAX / 2 - ALIGN(sizeof(struct stack_block)))
+ if ((unsigned int)min >=
+ INT_MAX / 2 - ALIGN(sizeof(struct stack_block)))
error("Out of space");
min += stacknleft;
min += ALIGN(sizeof(struct stack_block));
@@ -253,18 +267,6 @@
stacknxt = SPACE(sp);
stacknleft = newlen - (stacknxt - (char*)sp);
sstrend = stacknxt + stacknleft;
-
- /*
- * Stack marks pointing to the start of the old block
- * must be relocated to point to the new block
- */
- xmark = markp;
- while (xmark != NULL && xmark->stackp == oldstackp) {
- xmark->stackp = stackp;
- xmark->stacknxt = stacknxt;
- xmark->stacknleft = stacknleft;
- xmark = xmark->marknext;
- }
INTON;
} else {
newlen -= ALIGN(sizeof(struct stack_block));
@@ -327,7 +329,7 @@
char *
-stputbin(const char *data, int len, char *p)
+stputbin(const char *data, size_t len, char *p)
{
CHECKSTRSPACE(len, p);
memcpy(p, data, len);
Modified: trunk/bin/sh/memalloc.h
===================================================================
--- trunk/bin/sh/memalloc.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/memalloc.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/memalloc.h 297749 2016-04-09 14:09:14Z jilles $
*/
#include <string.h>
@@ -39,7 +40,6 @@
struct stack_block *stackp;
char *stacknxt;
int stacknleft;
- struct stackmark *marknext;
};
@@ -53,11 +53,12 @@
char *savestr(const char *);
pointer stalloc(int);
void stunalloc(pointer);
+char *stsavestr(const char *);
void setstackmark(struct stackmark *);
void popstackmark(struct stackmark *);
char *growstackstr(void);
char *makestrspace(int, char *);
-char *stputbin(const char *data, int len, char *p);
+char *stputbin(const char *data, size_t len, char *p);
char *stputs(const char *data, char *p);
@@ -67,7 +68,7 @@
#define grabstackblock(n) stalloc(n)
#define STARTSTACKSTR(p) p = stackblock()
#define STPUTC(c, p) do { if (p == sstrend) p = growstackstr(); *p++ = (c); } while(0)
-#define CHECKSTRSPACE(n, p) { if (sstrend - p < n) p = makestrspace(n, p); }
+#define CHECKSTRSPACE(n, p) { if ((size_t)(sstrend - p) < n) p = makestrspace(n, p); }
#define USTPUTC(c, p) (*p++ = (c))
/*
* STACKSTRNUL's use is where we want to be able to turn a stack
Modified: trunk/bin/sh/miscbltin.c
===================================================================
--- trunk/bin/sh/miscbltin.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/miscbltin.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/miscbltin.c 250214 2013-05-03 15:28:31Z jilles $");
/*
* Miscellaneous builtins.
@@ -47,12 +48,10 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
-#include <ctype.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <termios.h>
#include "shell.h"
#include "options.h"
@@ -61,6 +60,8 @@
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
+#include "syntax.h"
+#include "trap.h"
#undef eflag
@@ -103,6 +104,8 @@
struct timeval tv;
char *tvptr;
fd_set ifds;
+ ssize_t nread;
+ int sig;
rflag = 0;
prompt = NULL;
@@ -157,8 +160,10 @@
/*
* If there's nothing ready, return an error.
*/
- if (status <= 0)
- return(1);
+ if (status <= 0) {
+ sig = pendingsig;
+ return (128 + (sig != 0 ? sig : SIGALRM));
+ }
}
status = 0;
@@ -166,7 +171,19 @@
backslash = 0;
STARTSTACKSTR(p);
for (;;) {
- if (read(STDIN_FILENO, &c, 1) != 1) {
+ nread = read(STDIN_FILENO, &c, 1);
+ if (nread == -1) {
+ if (errno == EINTR) {
+ sig = pendingsig;
+ if (sig == 0)
+ continue;
+ status = 128 + sig;
+ break;
+ }
+ warning("read error: %s", strerror(errno));
+ status = 2;
+ break;
+ } else if (nread != 1) {
status = 1;
break;
}
@@ -308,7 +325,7 @@
out1fmt("%.4o\n", mask);
}
} else {
- if (isdigit(*ap)) {
+ if (is_digit(*ap)) {
mask = 0;
do {
if (*ap >= '8' || *ap < '0')
@@ -389,9 +406,6 @@
#ifdef RLIMIT_NPTS
{ "pseudo-terminals", (char *)0, RLIMIT_NPTS, 1, 'p' },
#endif
-#ifdef RLIMIT_KQUEUES
- { "kqueues", (char *)0, RLIMIT_KQUEUES, 1, 'k' },
-#endif
{ (char *) 0, (char *)0, 0, 0, '\0' }
};
@@ -408,7 +422,7 @@
struct rlimit limit;
what = 'f';
- while ((optc = nextopt("HSatfdsmcnuvlbpwk")) != '\0')
+ while ((optc = nextopt("HSatfdsmcnuvlbpw")) != '\0')
switch (optc) {
case 'H':
how = HARD;
Modified: trunk/bin/sh/mkbuiltins
===================================================================
--- trunk/bin/sh/mkbuiltins 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mkbuiltins 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,20 +32,20 @@
# SUCH DAMAGE.
#
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/mkbuiltins 235927 2012-05-24 19:48:15Z marcel $
temp=`/usr/bin/mktemp -t ka`
-havejobs=0
-if grep '^#define[ ]*JOBS[ ]*1' shell.h > /dev/null
-then havejobs=1
-fi
havehist=1
if [ "X$1" = "X-h" ]; then
havehist=0
shift
fi
-objdir=$1
-exec > ${objdir}/builtins.c
+srcdir=$1
+havejobs=0
+if grep '^#define[ ]*JOBS[ ]*1' $srcdir/shell.h > /dev/null
+then havejobs=1
+fi
+exec > builtins.c
cat <<\!
/*
* This file was generated by the mkbuiltins program.
@@ -57,7 +57,7 @@
!
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
- print $0}' builtins.def | sed 's/-[hj]//' > $temp
+ print $0}' $srcdir/builtins.def | sed 's/-[hj]//' > $temp
echo 'int (*const builtinfunc[])(int, char **) = {'
awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
echo '};
@@ -74,7 +74,7 @@
echo ' { NULL, 0, 0 }
};'
-exec > ${objdir}/builtins.h
+exec > builtins.h
cat <<\!
/*
* This file was generated by the mkbuiltins program.
Property changes on: trunk/bin/sh/mkbuiltins
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Modified: trunk/bin/sh/mknodes.c
===================================================================
--- trunk/bin/sh/mknodes.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mknodes.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -43,7 +43,7 @@
#endif /* not lint */
#endif
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/mknodes.c 292786 2015-12-27 17:53:39Z jilles $");
/*
* This program reads the nodetypes file and nodes.c.pat file. It generates
@@ -90,7 +90,6 @@
static int nstr; /* number of structures */
static struct str str[MAXTYPES]; /* the structures */
static struct str *curstr; /* current structure */
-static FILE *infp;
static char line[1024];
static int linno;
static char *linep;
@@ -103,7 +102,7 @@
static void indent(int, FILE *);
static int nextfield(char *);
static void skipbl(void);
-static int readline(void);
+static int readline(FILE *);
static void error(const char *, ...) __printf0like(1, 2) __dead2;
static char *savestr(const char *);
@@ -111,17 +110,19 @@
int
main(int argc, char *argv[])
{
+ FILE *infp;
+
if (argc != 3)
error("usage: mknodes file");
- infp = stdin;
if ((infp = fopen(argv[1], "r")) == NULL)
error("Can't open %s: %s", argv[1], strerror(errno));
- while (readline()) {
+ while (readline(infp)) {
if (line[0] == ' ' || line[0] == '\t')
parsefield();
else if (line[0] != '\0')
parsenode();
}
+ fclose(infp);
output(argv[2]);
exit(0);
}
@@ -254,6 +255,10 @@
fputs("union node *getfuncnode(struct funcdef *);\n", hfile);
fputs("void reffunc(struct funcdef *);\n", hfile);
fputs("void unreffunc(struct funcdef *);\n", hfile);
+ if (ferror(hfile))
+ error("Can't write to nodes.h");
+ if (fclose(hfile))
+ error("Can't close nodes.h");
fputs(writer, cfile);
while (fgets(line, sizeof line, patfile) != NULL) {
@@ -267,6 +272,11 @@
else
fputs(line, cfile);
}
+ fclose(patfile);
+ if (ferror(cfile))
+ error("Can't write to nodes.c");
+ if (fclose(cfile))
+ error("Can't close nodes.c");
}
@@ -402,7 +412,7 @@
static int
-readline(void)
+readline(FILE *infp)
{
char *p;
Modified: trunk/bin/sh/mksyntax.c
===================================================================
--- trunk/bin/sh/mksyntax.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mksyntax.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -43,7 +43,7 @@
#endif /* not lint */
#endif
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/mksyntax.c 246522 2013-02-07 22:42:33Z jilles $");
/*
* This program creates syntax.h and syntax.c.
@@ -190,8 +190,8 @@
add("`", "CBQUOTE");
add("$", "CVAR");
add("}", "CENDVAR");
- /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
- add("!*?[=~:/-", "CCTL");
+ /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
+ add("!*?[]=~:/-^", "CCTL");
finish();
fputs("\n/* syntax table used when in single quotes */\n", cfile);
@@ -200,8 +200,8 @@
add("\n", "CNL");
add("\\", "CSBACK");
add("'", "CENDQUOTE");
- /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
- add("!*?[=~:/-", "CCTL");
+ /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
+ add("!*?[]=~:/-^", "CCTL");
finish();
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
Modified: trunk/bin/sh/mktokens
===================================================================
--- trunk/bin/sh/mktokens 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mktokens 2018-06-02 21:06:59 UTC (rev 10240)
@@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)mktokens 8.1 (Berkeley) 5/31/93
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/mktokens 223186 2011-06-17 13:03:49Z jilles $
# The following is a list of tokens. The second column is nonzero if the
# token marks the end of a list. The third column is the name to print in
Property changes on: trunk/bin/sh/mktokens
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/myhistedit.h
===================================================================
--- trunk/bin/sh/myhistedit.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/myhistedit.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -28,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/myhistedit.h 229220 2012-01-01 22:17:12Z jilles $
*/
#include <histedit.h>
Modified: trunk/bin/sh/mystring.c
===================================================================
--- trunk/bin/sh/mystring.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mystring.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,13 +37,12 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/mystring.c 262951 2014-03-09 17:04:31Z jmmv $");
/*
* String functions.
*
* equal(s1, s2) Return true if strings are equal.
- * scopy(from, to) Copy a string.
* number(s) Convert a string of digits to an integer.
* is_number(s) Return true if s is a string of digits.
*/
@@ -60,11 +60,7 @@
* equal - #defined in mystring.h
*/
-/*
- * scopy - #defined in mystring.h
- */
-
/*
* prefix -- see if pfx is a prefix of string.
*/
Modified: trunk/bin/sh/mystring.h
===================================================================
--- trunk/bin/sh/mystring.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/mystring.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/mystring.h 262951 2014-03-09 17:04:31Z jmmv $
*/
#include <string.h>
@@ -40,4 +41,3 @@
int is_number(const char *);
#define equal(s1, s2) (strcmp(s1, s2) == 0)
-#define scopy(s1, s2) ((void)strcpy(s2, s1))
Modified: trunk/bin/sh/nodes.c.pat
===================================================================
--- trunk/bin/sh/nodes.c.pat 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/nodes.c.pat 2018-06-02 21:06:59 UTC (rev 10240)
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/nodes.c.pat 249235 2013-04-07 16:28:36Z jilles $
*/
#include <sys/param.h>
@@ -58,7 +58,7 @@
static void sizenodelist(struct nodelist *);
static union node *copynode(union node *);
static struct nodelist *copynodelist(struct nodelist *);
-static char *nodesavestr(char *);
+static char *nodesavestr(const char *);
struct funcdef {
@@ -147,9 +147,9 @@
static char *
-nodesavestr(char *s)
+nodesavestr(const char *s)
{
- char *p = s;
+ const char *p = s;
char *q = funcstring;
char *rtn = funcstring;
Property changes on: trunk/bin/sh/nodes.c.pat
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/nodetypes
===================================================================
--- trunk/bin/sh/nodetypes 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/nodetypes 2018-06-02 21:06:59 UTC (rev 10240)
@@ -30,7 +30,7 @@
# SUCH DAMAGE.
#
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
-# $MidnightBSD$
+# $FreeBSD: stable/10/bin/sh/nodetypes 262951 2014-03-09 17:04:31Z jmmv $
# This file describes the nodes used in parse trees. Unindented lines
# contain a node type followed by a structure tag. Subsequent indented
@@ -118,8 +118,8 @@
NAPPEND nfile # fd>> fname
NCLOBBER nfile # fd>| fname
type int
+ fd int # file descriptor being redirected
next nodeptr # next redirection in list
- fd int # file descriptor being redirected
fname nodeptr # file name, in a NARG node
expfname temp char *expfname # actual file name
@@ -126,8 +126,8 @@
NTOFD ndup # fd<&dupfd
NFROMFD ndup # fd>&dupfd
type int
+ fd int # file descriptor being redirected
next nodeptr # next redirection in list
- fd int # file descriptor being redirected
dupfd int # file descriptor to duplicate
vname nodeptr # file name if fd>&$var
@@ -135,9 +135,10 @@
NHERE nhere # fd<<\!
NXHERE nhere # fd<<!
type int
+ fd int # file descriptor being redirected
next nodeptr # next redirection in list
- fd int # file descriptor being redirected
doc nodeptr # input to command (NARG node)
+ expdoc temp char *expdoc # actual document (for NXHERE)
NNOT nnot # ! command (actually pipeline)
type int
Property changes on: trunk/bin/sh/nodetypes
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/options.c
===================================================================
--- trunk/bin/sh/options.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/options.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/options.c 240247 2012-09-08 19:24:03Z jilles $");
#include <signal.h>
#include <unistd.h>
@@ -401,9 +402,10 @@
void
getoptsreset(const char *value)
{
- if (number(value) == 1) {
+ while (*value == '0')
+ value++;
+ if (strcmp(value, "1") == 0)
shellparam.reset = 1;
- }
}
/*
@@ -530,10 +532,6 @@
}
/*
- * XXX - should get rid of. have all builtins use getopt(3). the
- * library getopt must have the BSD extension static variable "optreset"
- * otherwise it can't be used within the shell safely.
- *
* Standard option processing (a la getopt) for builtin routines. The
* only argument that is passed to nextopt is the option string; the
* other arguments are unnecessary. It return the character, or '\0' on
Modified: trunk/bin/sh/options.h
===================================================================
--- trunk/bin/sh/options.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/options.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)options.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/options.h 223281 2011-06-18 23:43:28Z jilles $
*/
struct shparam {
Modified: trunk/bin/sh/output.c
===================================================================
--- trunk/bin/sh/output.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/output.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/output.c 253649 2013-07-25 13:09:17Z jilles $");
/*
* Shell output routines. We use our own output routines because:
@@ -75,25 +76,6 @@
struct output *out1 = &output;
struct output *out2 = &errout;
-
-
-#ifdef mkinit
-
-INCLUDE "output.h"
-INCLUDE "memalloc.h"
-
-RESET {
- out1 = &output;
- out2 = &errout;
- if (memout.buf != NULL) {
- ckfree(memout.buf);
- memout.buf = NULL;
- }
-}
-
-#endif
-
-
void
outcslow(int c, struct output *file)
{
@@ -239,7 +221,21 @@
}
+int
+outiserror(struct output *file)
+{
+ return (file->flags & OUTPUT_ERR);
+}
+
+
void
+outclearerror(struct output *file)
+{
+ file->flags &= ~OUTPUT_ERR;
+}
+
+
+void
outfmt(struct output *file, const char *fmt, ...)
{
va_list ap;
Modified: trunk/bin/sh/output.h
===================================================================
--- trunk/bin/sh/output.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/output.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)output.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/output.h 244162 2012-12-12 22:01:10Z jilles $
*/
#ifndef OUTPUT_INCL
@@ -66,6 +67,8 @@
void flushall(void);
void flushout(struct output *);
void freestdout(void);
+int outiserror(struct output *);
+void outclearerror(struct output *);
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
void out1fmt(const char *, ...) __printflike(1, 2);
void out2fmt_flush(const char *, ...) __printflike(1, 2);
Modified: trunk/bin/sh/parser.c
===================================================================
--- trunk/bin/sh/parser.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/parser.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -37,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/parser.c 301571 2016-06-08 01:17:22Z truckman $");
#include <stdlib.h>
#include <unistd.h>
@@ -97,9 +97,9 @@
static int doprompt; /* if set, prompt the user */
static int needprompt; /* true if interactive and at start of line */
static int lasttoken; /* last token read */
-MKINIT int tokpushback; /* last token pushed back */
+static int tokpushback; /* last token pushed back */
static char *wordtext; /* text of last word returned by readtoken */
-MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
+static int checkkwd;
static struct nodelist *backquotelist;
static union node *redirnode;
static struct heredoc *heredoc;
@@ -109,19 +109,21 @@
static struct parser_temp *parser_temp;
-static union node *list(int, int);
+static union node *list(int);
static union node *andor(void);
static union node *pipeline(void);
static union node *command(void);
static union node *simplecmd(union node **, union node *);
static union node *makename(void);
+static union node *makebinary(int type, union node *n1, union node *n2);
static void parsefname(void);
static void parseheredoc(void);
static int peektoken(void);
static int readtoken(void);
static int xxreadtoken(void);
-static int readtoken1(int, char const *, char *, int);
+static int readtoken1(int, const char *, const char *, int);
static int noexpand(char *);
+static void consumetoken(int);
static void synexpect(int) __dead2;
static void synerror(const char *) __dead2;
static void setprompt(int);
@@ -211,6 +213,7 @@
heredoclist = NULL;
tokpushback = 0;
+ checkkwd = 0;
doprompt = interact;
if (doprompt)
setprompt(1);
@@ -223,18 +226,51 @@
if (t == TNL)
return NULL;
tokpushback++;
- return list(1, 1);
+ return list(1);
}
+/*
+ * Read and parse words for wordexp.
+ * Returns a list of NARG nodes; NULL if there are no words.
+ */
+union node *
+parsewordexp(void)
+{
+ union node *n, *first = NULL, **pnext;
+ int t;
+
+ /* This assumes the parser is not re-entered,
+ * which could happen if we add command substitution on PS1/PS2.
+ */
+ parser_temp_free_all();
+ heredoclist = NULL;
+
+ tokpushback = 0;
+ checkkwd = 0;
+ doprompt = 0;
+ setprompt(0);
+ needprompt = 0;
+ pnext = &first;
+ while ((t = readtoken()) != TEOF) {
+ if (t != TWORD)
+ synexpect(TWORD);
+ n = makename();
+ *pnext = n;
+ pnext = &n->narg.next;
+ }
+ return first;
+}
+
+
static union node *
-list(int nlflag, int erflag)
+list(int nlflag)
{
union node *ntop, *n1, *n2, *n3;
int tok;
checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (!nlflag && !erflag && tokendlist[peektoken()])
+ if (!nlflag && tokendlist[peektoken()])
return NULL;
ntop = n1 = NULL;
for (;;) {
@@ -256,17 +292,11 @@
if (ntop == NULL)
ntop = n2;
else if (n1 == NULL) {
- n1 = (union node *)stalloc(sizeof (struct nbinary));
- n1->type = NSEMI;
- n1->nbinary.ch1 = ntop;
- n1->nbinary.ch2 = n2;
+ n1 = makebinary(NSEMI, ntop, n2);
ntop = n1;
}
else {
- n3 = (union node *)stalloc(sizeof (struct nbinary));
- n3->type = NSEMI;
- n3->nbinary.ch1 = n1->nbinary.ch2;
- n3->nbinary.ch2 = n2;
+ n3 = makebinary(NSEMI, n1->nbinary.ch2, n2);
n1->nbinary.ch2 = n3;
n1 = n3;
}
@@ -287,7 +317,7 @@
tokpushback++;
}
checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (!nlflag && !erflag && tokendlist[peektoken()])
+ if (!nlflag && tokendlist[peektoken()])
return ntop;
break;
case TEOF:
@@ -297,7 +327,7 @@
pungetc(); /* push back EOF on input */
return ntop;
default:
- if (nlflag || erflag)
+ if (nlflag)
synexpect(-1);
tokpushback++;
return ntop;
@@ -310,10 +340,10 @@
static union node *
andor(void)
{
- union node *n1, *n2, *n3;
+ union node *n;
int t;
- n1 = pipeline();
+ n = pipeline();
for (;;) {
if ((t = readtoken()) == TAND) {
t = NAND;
@@ -321,14 +351,9 @@
t = NOR;
} else {
tokpushback++;
- return n1;
+ return n;
}
- n2 = pipeline();
- n3 = (union node *)stalloc(sizeof (struct nbinary));
- n3->type = t;
- n3->nbinary.ch1 = n1;
- n3->nbinary.ch2 = n2;
- n1 = n3;
+ n = makebinary(t, n, pipeline());
}
}
@@ -410,49 +435,39 @@
case TIF:
n1 = (union node *)stalloc(sizeof (struct nif));
n1->type = NIF;
- if ((n1->nif.test = list(0, 0)) == NULL)
+ if ((n1->nif.test = list(0)) == NULL)
synexpect(-1);
- if (readtoken() != TTHEN)
- synexpect(TTHEN);
- n1->nif.ifpart = list(0, 0);
+ consumetoken(TTHEN);
+ n1->nif.ifpart = list(0);
n2 = n1;
while (readtoken() == TELIF) {
n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
n2 = n2->nif.elsepart;
n2->type = NIF;
- if ((n2->nif.test = list(0, 0)) == NULL)
+ if ((n2->nif.test = list(0)) == NULL)
synexpect(-1);
- if (readtoken() != TTHEN)
- synexpect(TTHEN);
- n2->nif.ifpart = list(0, 0);
+ consumetoken(TTHEN);
+ n2->nif.ifpart = list(0);
}
if (lasttoken == TELSE)
- n2->nif.elsepart = list(0, 0);
+ n2->nif.elsepart = list(0);
else {
n2->nif.elsepart = NULL;
tokpushback++;
}
- if (readtoken() != TFI)
- synexpect(TFI);
+ consumetoken(TFI);
checkkwd = CHKKWD | CHKALIAS;
break;
case TWHILE:
- case TUNTIL: {
- int got;
- n1 = (union node *)stalloc(sizeof (struct nbinary));
- n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
- if ((n1->nbinary.ch1 = list(0, 0)) == NULL)
+ case TUNTIL:
+ t = lasttoken;
+ if ((n1 = list(0)) == NULL)
synexpect(-1);
- if ((got=readtoken()) != TDO) {
-TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
- synexpect(TDO);
- }
- n1->nbinary.ch2 = list(0, 0);
- if (readtoken() != TDONE)
- synexpect(TDONE);
+ consumetoken(TDO);
+ n1 = makebinary((t == TWHILE)? NWHILE : NUNTIL, n1, list(0));
+ consumetoken(TDONE);
checkkwd = CHKKWD | CHKALIAS;
break;
- }
case TFOR:
if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
synerror("Bad for loop variable");
@@ -464,10 +479,7 @@
if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) {
app = ≈
while (readtoken() == TWORD) {
- n2 = (union node *)stalloc(sizeof (struct narg));
- n2->type = NARG;
- n2->narg.text = wordtext;
- n2->narg.backquote = backquotelist;
+ n2 = makename();
*app = n2;
app = &n2->narg.next;
}
@@ -499,21 +511,15 @@
t = TEND;
else
synexpect(-1);
- n1->nfor.body = list(0, 0);
- if (readtoken() != t)
- synexpect(t);
+ n1->nfor.body = list(0);
+ consumetoken(t);
checkkwd = CHKKWD | CHKALIAS;
break;
case TCASE:
n1 = (union node *)stalloc(sizeof (struct ncase));
n1->type = NCASE;
- if (readtoken() != TWORD)
- synexpect(TWORD);
- n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
- n2->type = NARG;
- n2->narg.text = wordtext;
- n2->narg.backquote = backquotelist;
- n2->narg.next = NULL;
+ consumetoken(TWORD);
+ n1->ncase.expr = makename();
while (readtoken() == TNL);
if (lasttoken != TWORD || ! equal(wordtext, "in"))
synerror("expecting \"in\"");
@@ -526,10 +532,7 @@
if (lasttoken == TLP)
readtoken();
for (;;) {
- *app = ap = (union node *)stalloc(sizeof (struct narg));
- ap->type = NARG;
- ap->narg.text = wordtext;
- ap->narg.backquote = backquotelist;
+ *app = ap = makename();
checkkwd = CHKNL | CHKKWD;
if (readtoken() != TPIPE)
break;
@@ -539,7 +542,7 @@
ap->narg.next = NULL;
if (lasttoken != TRP)
synexpect(TRP);
- cp->nclist.body = list(0, 0);
+ cp->nclist.body = list(0);
checkkwd = CHKNL | CHKKWD | CHKALIAS;
if ((t = readtoken()) != TESAC) {
@@ -559,34 +562,31 @@
case TLP:
n1 = (union node *)stalloc(sizeof (struct nredir));
n1->type = NSUBSHELL;
- n1->nredir.n = list(0, 0);
+ n1->nredir.n = list(0);
n1->nredir.redirect = NULL;
- if (readtoken() != TRP)
- synexpect(TRP);
+ consumetoken(TRP);
checkkwd = CHKKWD | CHKALIAS;
is_subshell = 1;
break;
case TBEGIN:
- n1 = list(0, 0);
- if (readtoken() != TEND)
- synexpect(TEND);
+ n1 = list(0);
+ consumetoken(TEND);
checkkwd = CHKKWD | CHKALIAS;
break;
- /* Handle an empty command like other simple commands. */
+ /* A simple command must have at least one redirection or word. */
case TBACKGND:
case TSEMI:
case TAND:
case TOR:
- /*
- * An empty command before a ; doesn't make much sense, and
- * should certainly be disallowed in the case of `if ;'.
- */
+ case TPIPE:
+ case TENDCASE:
+ case TFALLTHRU:
+ case TEOF:
+ case TNL:
+ case TRP:
if (!redir)
synexpect(-1);
- case TNL:
- case TEOF:
case TWORD:
- case TRP:
tokpushback++;
n1 = simplecmd(rpp, redir);
return n1;
@@ -644,10 +644,7 @@
for (;;) {
checkkwd = savecheckkwd;
if (readtoken() == TWORD) {
- n = (union node *)stalloc(sizeof (struct narg));
- n->type = NARG;
- n->narg.text = wordtext;
- n->narg.backquote = backquotelist;
+ n = makename();
*app = n;
app = &n->narg.next;
if (savecheckkwd != 0 && !isassignment(wordtext))
@@ -659,8 +656,7 @@
} else if (lasttoken == TLP && app == &args->narg.next
&& rpp == orig_rpp) {
/* We have a function */
- if (readtoken() != TRP)
- synexpect(TRP);
+ consumetoken(TRP);
funclinno = plinno;
/*
* - Require plain text.
@@ -708,7 +704,25 @@
return n;
}
+static union node *
+makebinary(int type, union node *n1, union node *n2)
+{
+ union node *n;
+
+ n = (union node *)stalloc(sizeof (struct nbinary));
+ n->type = type;
+ n->nbinary.ch1 = n1;
+ n->nbinary.ch2 = n2;
+ return (n);
+}
+
void
+forcealias(void)
+{
+ checkkwd |= CHKALIAS;
+}
+
+void
fixredir(union node *n, const char *text, int err)
{
TRACE(("Fix redir %s %d\n", text, err));
@@ -734,8 +748,7 @@
{
union node *n = redirnode;
- if (readtoken() != TWORD)
- synexpect(-1);
+ consumetoken(TWORD);
if (n->type == NHERE) {
struct heredoc *here = heredoc;
struct heredoc *p;
@@ -786,11 +799,7 @@
}
readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
here->eofmark, here->striptabs);
- n = (union node *)stalloc(sizeof (struct narg));
- n->narg.type = NARG;
- n->narg.next = NULL;
- n->narg.text = wordtext;
- n->narg.backquote = backquotelist;
+ n = makename();
here->here->nhere.doc = n;
}
}
@@ -983,7 +992,7 @@
char *volatile str;
struct jmploc jmploc;
struct jmploc *const savehandler = handler;
- int savelen;
+ size_t savelen;
int saveprompt;
const int bq_startlinno = plinno;
char *volatile ostr = NULL;
@@ -1090,14 +1099,14 @@
doprompt = 0;
}
- n = list(0, oldstyle);
+ n = list(0);
- if (oldstyle)
+ if (oldstyle) {
+ if (peektoken() != TEOF)
+ synexpect(-1);
doprompt = saveprompt;
- else {
- if (readtoken() != TRP)
- synexpect(TRP);
- }
+ } else
+ consumetoken(TRP);
(*nlpp)->n = n;
if (oldstyle) {
@@ -1300,7 +1309,8 @@
#define PARSEARITH() {goto parsearith; parsearith_return:;}
static int
-readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
+readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
+ int striptabs)
{
int c = firstc;
char *out;
@@ -1521,7 +1531,7 @@
}
if (c == *eofmark) {
if (pfgets(line, sizeof line) != NULL) {
- char *p, *q;
+ const char *p, *q;
p = line;
for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
@@ -1695,7 +1705,7 @@
pungetc();
else if (c == '\n' || c == PEOF)
synerror("Unexpected end of line in substitution");
- else
+ else if (BASESYNTAX[c] != CCTL)
USTPUTC(c, out);
}
if (subtype == 0) {
@@ -1711,7 +1721,8 @@
synerror("Unexpected end of line in substitution");
if (flags == VSNUL)
STPUTC(':', out);
- STPUTC(c, out);
+ if (BASESYNTAX[c] != CCTL)
+ STPUTC(c, out);
subtype = VSERROR;
} else
subtype = p - types + VSNORMAL;
@@ -1818,14 +1829,6 @@
} /* end of readtoken */
-
-#ifdef mkinit
-RESET {
- tokpushback = 0;
- checkkwd = 0;
-}
-#endif
-
/*
* Returns true if the text contains nothing to expand (no dollar signs
* or backquotes).
@@ -1887,6 +1890,14 @@
}
+static void
+consumetoken(int token)
+{
+ if (readtoken() != token)
+ synexpect(token);
+}
+
+
/*
* Called when an unexpected token is read during the parse. The argument
* is the token that is expected, or -1 if more than one type of token can
@@ -1964,7 +1975,7 @@
/*
* Format prompt string.
*/
- for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++)
+ for (i = 0; (i < PROMPTLEN - 1) && (*fmt != '\0'); i++, fmt++)
if (*fmt == '\\')
switch (*++fmt) {
@@ -1977,11 +1988,13 @@
case 'h':
case 'H':
ps[i] = '\0';
- gethostname(&ps[i], PROMPTLEN - i);
+ gethostname(&ps[i], PROMPTLEN - i - 1);
+ ps[PROMPTLEN - 1] = '\0';
/* Skip to end of hostname. */
trim = (*fmt == 'h') ? '.' : '\0';
- while ((ps[i+1] != '\0') && (ps[i+1] != trim))
+ while ((ps[i] != '\0') && (ps[i] != trim))
i++;
+ --i;
break;
/*
@@ -1993,7 +2006,7 @@
case 'W':
case 'w':
pwd = lookupvar("PWD");
- if (pwd == NULL)
+ if (pwd == NULL || *pwd == '\0')
pwd = "?";
if (*fmt == 'W' &&
*pwd == '/' && pwd[1] != '\0')
@@ -2026,8 +2039,9 @@
* Emit unrecognized formats verbatim.
*/
default:
- ps[i++] = '\\';
- ps[i] = *fmt;
+ ps[i] = '\\';
+ if (i < PROMPTLEN - 2)
+ ps[++i] = *fmt;
break;
}
else
@@ -2038,7 +2052,7 @@
const char *
-expandstr(char *ps)
+expandstr(const char *ps)
{
union node n;
struct jmploc jmploc;
Modified: trunk/bin/sh/parser.h
===================================================================
--- trunk/bin/sh/parser.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/parser.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)parser.h 8.3 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/parser.h 289938 2015-10-25 17:17:50Z jilles $
*/
/* control characters in argument strings */
@@ -69,18 +69,18 @@
/*
* NEOF is returned by parsecmd when it encounters an end of file. It
- * must be distinct from NULL, so we use the address of a variable that
- * happens to be handy.
+ * must be distinct from NULL.
*/
-extern int tokpushback;
-#define NEOF ((union node *)&tokpushback)
+#define NEOF ((union node *)-1)
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
extern const char *const parsekwd[];
union node *parsecmd(int);
+union node *parsewordexp(void);
+void forcealias(void);
void fixredir(union node *, const char *, int);
int goodname(const char *);
int isassignment(const char *);
char *getprompt(void *);
-const char *expandstr(char *);
+const char *expandstr(const char *);
Modified: trunk/bin/sh/redir.c
===================================================================
--- trunk/bin/sh/redir.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/redir.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/redir.c 287750 2015-09-13 13:43:08Z jilles $");
#include <sys/types.h>
#include <sys/stat.h>
@@ -64,17 +65,16 @@
#define EMPTY -2 /* marks an unused slot in redirtab */
#define CLOSED -1 /* fd was not open before redir */
-#define PIPESIZE 4096 /* amount of buffering in a pipe */
-MKINIT
struct redirtab {
struct redirtab *next;
int renamed[10];
+ int fd0_redirected;
};
-MKINIT struct redirtab *redirlist;
+static struct redirtab *redirlist;
/*
* We keep track of whether or not fd0 has been redirected. This is for
@@ -93,6 +93,13 @@
* undone by calling popredir. If the REDIR_BACKQ flag is set, then the
* standard output, and the standard error if it becomes a duplicate of
* stdout, is saved in memory.
+*
+ * We suppress interrupts so that we won't leave open file
+ * descriptors around. Because the signal handler remains
+ * installed and we do not use system call restart, interrupts
+ * will still abort blocking opens such as fifos (they will fail
+ * with EINTR). There is, however, a race condition if an interrupt
+ * arrives after INTOFF and before open blocks.
*/
void
@@ -104,6 +111,7 @@
int fd;
char memory[10]; /* file descriptors to write to memory */
+ INTOFF;
for (i = 10 ; --i >= 0 ; )
memory[i] = 0;
memory[1] = flags & REDIR_BACKQ;
@@ -111,11 +119,14 @@
sv = ckmalloc(sizeof (struct redirtab));
for (i = 0 ; i < 10 ; i++)
sv->renamed[i] = EMPTY;
+ sv->fd0_redirected = fd0_redirected;
sv->next = redirlist;
redirlist = sv;
}
for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd;
+ if (fd == 0)
+ fd0_redirected = 1;
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
n->ndup.dupfd == fd)
continue; /* redirect from/to same file descriptor */
@@ -122,7 +133,7 @@
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
INTOFF;
- if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
+ if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) {
switch (errno) {
case EBADF:
i = CLOSED;
@@ -132,19 +143,19 @@
error("%d: %s", fd, strerror(errno));
break;
}
- } else
- (void)fcntl(i, F_SETFD, FD_CLOEXEC);
+ }
sv->renamed[fd] = i;
INTON;
}
- if (fd == 0)
- fd0_redirected++;
openredirect(n, memory);
+ INTON;
+ INTOFF;
}
if (memory[1])
out1 = &memout;
if (memory[2])
out2 = &memout;
+ INTON;
}
@@ -153,19 +164,10 @@
{
struct stat sb;
int fd = redir->nfile.fd;
- char *fname;
+ const char *fname;
int f;
int e;
- /*
- * We suppress interrupts so that we won't leave open file
- * descriptors around. Because the signal handler remains
- * installed and we do not use system call restart, interrupts
- * will still abort blocking opens such as fifos (they will fail
- * with EINTR). There is, however, a race condition if an interrupt
- * arrives after INTOFF and before open blocks.
- */
- INTOFF;
memory[fd] = 0;
switch (redir->nfile.type) {
case NFROM:
@@ -172,21 +174,12 @@
fname = redir->nfile.expfname;
if ((f = open(fname, O_RDONLY)) < 0)
error("cannot open %s: %s", fname, strerror(errno));
-movefd:
- if (f != fd) {
- if (dup2(f, fd) == -1) {
- e = errno;
- close(f);
- error("%d: %s", fd, strerror(e));
- }
- close(f);
- }
break;
case NFROMTO:
fname = redir->nfile.expfname;
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
- goto movefd;
+ break;
case NTO:
if (Cflag) {
fname = redir->nfile.expfname;
@@ -204,7 +197,7 @@
} else
error("cannot create %s: %s", fname,
strerror(EEXIST));
- goto movefd;
+ break;
}
/* FALLTHROUGH */
case NCLOBBER:
@@ -211,12 +204,12 @@
fname = redir->nfile.expfname;
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
- goto movefd;
+ break;
case NAPPEND:
fname = redir->nfile.expfname;
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
- goto movefd;
+ break;
case NTOFD:
case NFROMFD:
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
@@ -230,15 +223,22 @@
} else {
close(fd);
}
- break;
+ return;
case NHERE:
case NXHERE:
f = openhere(redir);
- goto movefd;
+ break;
default:
abort();
}
- INTON;
+ if (f != fd) {
+ if (dup2(f, fd) == -1) {
+ e = errno;
+ close(f);
+ error("%d: %s", fd, strerror(e));
+ }
+ close(f);
+ }
}
@@ -251,18 +251,32 @@
static int
openhere(union node *redir)
{
+ const char *p;
int pip[2];
- int len = 0;
+ size_t len = 0;
+ int flags;
+ ssize_t written = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
- if (redir->type == NHERE) {
- len = strlen(redir->nhere.doc->narg.text);
- if (len <= PIPESIZE) {
- xwrite(pip[1], redir->nhere.doc->narg.text, len);
+
+ if (redir->type == NXHERE)
+ p = redir->nhere.expdoc;
+ else
+ p = redir->nhere.doc->narg.text;
+ len = strlen(p);
+ if (len == 0)
+ goto out;
+ flags = fcntl(pip[1], F_GETFL, 0);
+ if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) {
+ written = write(pip[1], p, len);
+ if (written < 0)
+ written = 0;
+ if ((size_t)written == len)
goto out;
- }
+ fcntl(pip[1], F_SETFL, flags);
}
+
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
close(pip[0]);
signal(SIGINT, SIG_IGN);
@@ -270,10 +284,7 @@
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGPIPE, SIG_DFL);
- if (redir->type == NHERE)
- xwrite(pip[1], redir->nhere.doc->narg.text, len);
- else
- expandhere(redir->nhere.doc, pip[1]);
+ xwrite(pip[1], p + written, len - written);
_exit(0);
}
out:
@@ -295,8 +306,6 @@
for (i = 0 ; i < 10 ; i++) {
if (rp->renamed[i] != EMPTY) {
- if (i == 0)
- fd0_redirected--;
if (rp->renamed[i] >= 0) {
dup2(rp->renamed[i], i);
close(rp->renamed[i]);
@@ -306,26 +315,12 @@
}
}
INTOFF;
+ fd0_redirected = rp->fd0_redirected;
redirlist = rp->next;
ckfree(rp);
INTON;
}
-/*
- * Undo all redirections. Called on error or interrupt.
- */
-
-#ifdef mkinit
-
-INCLUDE "redir.h"
-
-RESET {
- while (redirlist)
- popredir();
-}
-
-#endif
-
/* Return true if fd 0 has already been redirected at least once. */
int
fd0_redirected_p(void)
Modified: trunk/bin/sh/redir.h
===================================================================
--- trunk/bin/sh/redir.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/redir.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)redir.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/redir.h 254426 2013-08-16 20:24:41Z jilles $
*/
/* flags passed to redirect */
Modified: trunk/bin/sh/sh.1
===================================================================
--- trunk/bin/sh/sh.1 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/sh.1 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+.\" $MidnightBSD$
.\"-
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -30,10 +31,9 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
-.\" $FreeBSD: release/9.2.0/bin/sh/sh.1 252611 2013-07-03 21:31:13Z jilles $
-.\" $MidnightBSD$
+.\" $FreeBSD: stable/10/bin/sh/sh.1 302334 2016-07-04 14:23:36Z wblock $
.\"
-.Dd June 14, 2013
+.Dd May 30, 2016
.Dt SH 1
.Os
.Sh NAME
@@ -41,7 +41,7 @@
.Nd command interpreter (shell)
.Sh SYNOPSIS
.Nm
-.Op Fl /+abCEefIimnPpTuVvx
+.Op Fl /+abCEefhIimnPpTuVvx
.Op Fl /+o Ar longname
.Oo
.Ar script
@@ -48,7 +48,7 @@
.Op Ar arg ...
.Oc
.Nm
-.Op Fl /+abCEefIimnPpTuVvx
+.Op Fl /+abCEefhIimnPpTuVvx
.Op Fl /+o Ar longname
.Fl c Ar string
.Oo
@@ -56,7 +56,7 @@
.Op Ar arg ...
.Oc
.Nm
-.Op Fl /+abCEefIimnPpTuVvx
+.Op Fl /+abCEefhIimnPpTuVvx
.Op Fl /+o Ar longname
.Fl s
.Op Ar arg ...
@@ -139,10 +139,10 @@
.Pa .profile
in the home directory,
substituting for
-.Pa .shinit
+.Pa .shrc
the filename desired:
.Pp
-.Dl "ENV=$HOME/.shinit; export ENV"
+.Dl "ENV=$HOME/.shrc; export ENV"
.Pp
The first non-option argument specified on the command line
will be treated as the
@@ -236,10 +236,16 @@
.Dq Li ||
operator; or if the command is a pipeline preceded by the
.Ic !\&
-operator.
+keyword.
If a shell function is executed and its exit status is explicitly
tested, all commands of the function are considered to be tested as
well.
+.Pp
+It is recommended to check for failures explicitly
+instead of relying on
+.Fl e
+because it tends to behave in unexpected ways,
+particularly in larger scripts.
.It Fl f Li noglob
Disable pathname expansion.
.It Fl h Li trackall
@@ -376,13 +382,13 @@
.Bl -tag -width indent
.It Control operators:
.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact
-.It Li & Ta Li && Ta Li ( Ta Li ) Ta Li \en
-.It Li ;; Ta Li ;& Ta Li ; Ta Li | Ta Li ||
+.It Li & Ta Li && Ta Li \&( Ta Li \&) Ta Li \en
+.It Li ;; Ta Li ;& Ta Li \&; Ta Li \&| Ta Li ||
.El
.It Redirection operators:
.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact
.It Li < Ta Li > Ta Li << Ta Li >> Ta Li <>
-.It Li <& Ta Li >& Ta Li <<- Ta Li >|
+.It Li <& Ta Li >& Ta Li <<- Ta Li >| Ta \&
.El
.El
.Pp
@@ -488,8 +494,9 @@
The backslash inside double quotes is historically weird.
It remains literal unless it precedes the following characters,
which it serves to quote:
+.Pp
.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact
-.It Li $ Ta Li ` Ta Li \&" Ta Li \e\ Ta Li \en
+.It Li $ Ta Li ` Ta Li \&" Ta Li \e Ta Li \en
.El
.It Backslash
A backslash preserves the literal meaning of the following
@@ -527,6 +534,20 @@
.Pp
.Dl "ls -F foobar"
.Pp
+Aliases are also recognized after an alias
+whose value ends with a space or tab.
+For example, if there is also an alias called
+.Dq Li nohup
+with the value
+.Dq Li "nohup " ,
+then the input
+.Pp
+.Dl "nohup lf foobar"
+.Pp
+would become
+.Pp
+.Dl "nohup ls -F foobar"
+.Pp
Aliases provide a convenient way for naive users to
create shorthands for commands without having to learn how
to create functions with arguments.
@@ -564,7 +585,8 @@
Leading words of the form
.Dq Li name=value
are stripped off and assigned to the environment of
-the simple command.
+the simple command
+(they do not affect expansions).
Redirection operators and
their arguments (as described below) are stripped
off and saved for processing.
@@ -649,8 +671,8 @@
.Dq here-document .
.Bd -unfilled -offset indent
.Oo Ar n Oc Ns Li << Ar delimiter
-.D1 Ar here-doc-text
-.D1 ...
+.Ar here-doc-text
+.Ar ...
.Ar delimiter
.Ed
.Pp
@@ -1028,7 +1050,6 @@
.Pp
The first form executes the commands in a subshell environment.
A subshell environment has its own copy of:
-.Pp
.Bl -enum
.It
The current working directory as set by
@@ -1146,8 +1167,10 @@
.Pp
.D1 Ic return Op Ar exitstatus
.Pp
-It terminates the current executional scope, returning from the previous
-nested function, sourced script, or shell instance, in that order.
+It terminates the current executional scope, returning from the closest
+nested function or sourced script;
+if no function or sourced script is being executed,
+it exits the shell instance.
The
.Ic return
command is implemented as a special built-in command.
@@ -1172,6 +1195,20 @@
tilde expansion is also performed after the equals sign and after any colon
and usernames are also terminated by colons,
and field splitting and pathname expansion are not performed.
+.Pp
+This special expansion applies not only to assignments that form a simple
+command by themselves or precede a command word,
+but also to words passed to the
+.Ic export ,
+.Ic local
+or
+.Ic readonly
+built-in commands that have this form.
+For this, the builtin's name must be literal
+(not the result of an expansion)
+and may optionally be preceded by one or more literal instances of
+.Ic command
+without options.
.Ss Positional Parameters
A positional parameter is a parameter denoted by a number greater than zero.
The shell sets these initially to the values of its command line
@@ -1330,9 +1367,33 @@
.Dq Li "$ " ,
unless you are the superuser, in which case it defaults to
.Dq Li "# " .
+.Va PS1
+may include any of the following formatting sequences,
+which are replaced by the given information:
+.Bl -tag -width indent
+.It Li \eH
+This system's fully-qualified hostname (FQDN).
+.It Li \eh
+This system's hostname.
+.It Li \eW
+The final component of the current working directory.
+.It Li \ew
+The entire path of the current working directory.
+.It Li \e$
+Superuser status.
+.Dq Li "$ "
+for normal users and
+.Dq Li "# "
+for superusers.
+.It Li \e\e
+A literal backslash.
+.El
.It Va PS2
The secondary prompt string, which defaults to
.Dq Li "> " .
+.Va PS2
+may include any of the formatting sequences from
+.Va PS1 .
.It Va PS4
The prefix for the trace output (if
.Fl x
@@ -2222,10 +2283,6 @@
With no arguments whatsoever, the
.Ic hash
command prints out the contents of this table.
-Entries which have not been looked at since the last
-.Ic cd
-command are marked with an asterisk;
-it is possible for these entries to be invalid.
.Pp
With arguments, the
.Ic hash
@@ -2342,7 +2399,9 @@
elapses before a complete line of input is supplied,
the
.Ic read
-command will return an exit status of 1 without assigning any values.
+command will return an exit status as if terminated by
+.Dv SIGALRM
+without assigning any values.
The
.Ar timeout
value may optionally be followed by one of
@@ -2358,6 +2417,11 @@
The
.Fl e
option exists only for backward compatibility with older scripts.
+.Pp
+The exit status is 0 on success, 1 on end of file,
+between 2 and 128 if an error occurs
+and greater than 128 if a trapped signal interrupts
+.Ic read .
.It Ic readonly Oo Fl p Oc Op Ar name ...
Each specified
.Ar name
@@ -2453,7 +2517,8 @@
decreasing the value of
.Li $#
by one.
-If there are zero positional parameters, shifting does not do anything.
+For portability, shifting if there are zero positional parameters
+should be avoided, since the shell may abort.
.It Ic test
A built-in equivalent of
.Xr test 1 .
@@ -2605,12 +2670,17 @@
option is specified, the
.Ar name
arguments are treated as function names.
-.It Ic wait Op Ar job
-Wait for the specified
+.It Ic wait Op Ar job ...
+Wait for each specified
.Ar job
to complete and return the exit status of the last process in the
+last specified
.Ar job .
-If the argument is omitted, wait for all jobs to complete
+If any
+.Ar job
+specified is unknown to the shell, it is treated as if it
+were a known job that exited with exit status 127.
+If no operands are given, wait for all jobs to complete
and return an exit status of zero.
.El
.Ss Commandline Editing
@@ -2681,6 +2751,17 @@
at startup,
which may affect the shell as described under
.Sx Special Variables .
+.Sh FILES
+.Bl -tag -width "/etc/suid_profileXX" -compact
+.It Pa ~/.profile
+User's login profile.
+.It Pa /etc/profile
+System login profile.
+.It Pa /etc/shells
+Shell database.
+.It Pa /etc/suid_profile
+Privileged shell profile.
+.El
.Sh EXIT STATUS
Errors that are detected by the shell, such as a syntax error, will
cause the shell to exit with a non-zero exit status.
@@ -2706,7 +2787,8 @@
.Xr getrlimit 2 ,
.Xr umask 2 ,
.Xr wctype 3 ,
-.Xr editrc 5
+.Xr editrc 5 ,
+.Xr shells 5
.Sh HISTORY
A
.Nm
Property changes on: trunk/bin/sh/sh.1
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/bin/sh/shell.h
===================================================================
--- trunk/bin/sh/shell.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/shell.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)shell.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/shell.h 253658 2013-07-25 19:48:15Z jilles $
*/
#ifndef SHELL_H_
@@ -63,7 +64,6 @@
#define ARITH_MAX INTMAX_MAX
typedef void *pointer;
-#define MKINIT /* empty */
#include <sys/cdefs.h>
Modified: trunk/bin/sh/show.c
===================================================================
--- trunk/bin/sh/show.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/show.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/show.c 262951 2014-03-09 17:04:31Z jmmv $");
#include <fcntl.h>
#include <stdio.h>
@@ -390,11 +391,11 @@
else
p = "/tmp";
}
- scopy(p, s);
+ strcpy(s, p);
strcat(s, "/trace");
}
#else
- scopy("./trace", s);
+ strcpy(s, "./trace");
#endif /* not_this_way */
if ((tracefile = fopen(s, "a")) == NULL) {
fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
Modified: trunk/bin/sh/show.h
===================================================================
--- trunk/bin/sh/show.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/show.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
@@ -27,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)show.h 1.1 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/show.h 200956 2009-12-24 18:41:14Z jilles $
*/
void showtree(union node *);
Modified: trunk/bin/sh/trap.c
===================================================================
--- trunk/bin/sh/trap.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/trap.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/trap.c 297750 2016-04-09 14:24:17Z jilles $");
#include <signal.h>
#include <unistd.h>
@@ -72,14 +73,14 @@
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
-MKINIT char sigmode[NSIG]; /* current value of signal */
-int pendingsigs; /* indicates some signal received */
+static char sigmode[NSIG]; /* current value of signal */
+volatile sig_atomic_t pendingsig; /* indicates some signal received */
+volatile sig_atomic_t pendingsig_waitcmd; /* indicates SIGINT/SIGQUIT received */
int in_dotrap; /* do we execute in a trap handler? */
static char *volatile trap[NSIG]; /* trap handler commands */
static volatile sig_atomic_t gotsig[NSIG];
/* indicates specified signal received */
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
-volatile sig_atomic_t gotwinch;
static int last_trapsig;
static int exiting; /* exitshell() has been called */
@@ -150,7 +151,7 @@
* The trap builtin.
*/
int
-trapcmd(int argc, char **argv)
+trapcmd(int argc __unused, char **argv)
{
char *action;
int signo;
@@ -292,12 +293,6 @@
action = S_IGN;
break;
#endif
-#ifndef NO_HISTORY
- case SIGWINCH:
- if (rootshell && iflag)
- action = S_CATCH;
- break;
-#endif
}
}
@@ -361,13 +356,23 @@
ignoresig(int signo)
{
+ if (sigmode[signo] == 0)
+ setsignal(signo);
if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
signal(signo, SIG_IGN);
+ sigmode[signo] = S_IGN;
}
- sigmode[signo] = S_HARD_IGN;
}
+int
+issigchldtrapped(void)
+{
+
+ return (trap[SIGCHLD] != NULL && *trap[SIGCHLD] != '\0');
+}
+
+
/*
* Signal handler.
*/
@@ -380,27 +385,15 @@
return;
}
- if (signo != SIGCHLD || !ignore_sigchld)
- gotsig[signo] = 1;
- pendingsigs++;
-
/* If we are currently in a wait builtin, prepare to break it */
- if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
- breakwaitcmd = 1;
- /*
- * If a trap is set, not ignored and not the null command, we need
- * to make sure traps are executed even when a child blocks signals.
- */
- if (Tflag &&
- trap[signo] != NULL &&
- ! (trap[signo][0] == '\0') &&
- ! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
- breakwaitcmd = 1;
+ if (signo == SIGINT || signo == SIGQUIT)
+ pendingsig_waitcmd = signo;
-#ifndef NO_HISTORY
- if (signo == SIGWINCH)
- gotwinch = 1;
-#endif
+ if (trap[signo] != NULL && trap[signo][0] != '\0' &&
+ (signo != SIGCHLD || !ignore_sigchld)) {
+ gotsig[signo] = 1;
+ pendingsig = signo;
+ }
}
@@ -411,11 +404,14 @@
void
dotrap(void)
{
+ struct stackmark smark;
int i;
int savestatus, prev_evalskip, prev_skipcount;
in_dotrap++;
for (;;) {
+ pendingsig = 0;
+ pendingsig_waitcmd = 0;
for (i = 1; i < NSIG; i++) {
if (gotsig[i]) {
gotsig[i] = 0;
@@ -442,8 +438,9 @@
last_trapsig = i;
savestatus = exitstatus;
- evalstring(trap[i], 0);
- exitstatus = savestatus;
+ setstackmark(&smark);
+ evalstring(stsavestr(trap[i]), 0);
+ popstackmark(&smark);
/*
* If such a command was not
@@ -452,9 +449,11 @@
* trap action to have an effect
* outside of it.
*/
- if (prev_evalskip != 0) {
+ if (evalskip == 0 ||
+ prev_evalskip != 0) {
evalskip = prev_evalskip;
skipcount = prev_skipcount;
+ exitstatus = savestatus;
}
if (i == SIGCHLD)
@@ -467,7 +466,6 @@
break;
}
in_dotrap--;
- pendingsigs = 0;
}
@@ -484,9 +482,6 @@
setsignal(SIGINT);
setsignal(SIGQUIT);
setsignal(SIGTERM);
-#ifndef NO_HISTORY
- setsignal(SIGWINCH);
-#endif
is_interactive = on;
}
@@ -519,28 +514,25 @@
exiting_exitstatus = oexitstatus;
}
exitstatus = oexitstatus = exiting_exitstatus;
- if (setjmp(loc1.loc)) {
- goto l1;
+ if (!setjmp(loc1.loc)) {
+ handler = &loc1;
+ if ((p = trap[0]) != NULL && *p != '\0') {
+ /*
+ * Reset evalskip, or the trap on EXIT could be
+ * interrupted if the last command was a "return".
+ */
+ evalskip = 0;
+ trap[0] = NULL;
+ evalstring(p, 0);
+ }
}
- if (setjmp(loc2.loc)) {
- goto l2;
- }
- handler = &loc1;
- if ((p = trap[0]) != NULL && *p != '\0') {
- /*
- * Reset evalskip, or the trap on EXIT could be
- * interrupted if the last command was a "return".
- */
- evalskip = 0;
- trap[0] = NULL;
- evalstring(p, 0);
- }
-l1: handler = &loc2; /* probably unnecessary */
- flushall();
+ if (!setjmp(loc2.loc)) {
+ handler = &loc2; /* probably unnecessary */
+ flushall();
#if JOBS
- setjobctl(0);
+ setjobctl(0);
#endif
-l2:
+ }
if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN &&
sig != SIGTTOU) {
signal(sig, SIG_DFL);
Modified: trunk/bin/sh/trap.h
===================================================================
--- trunk/bin/sh/trap.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/trap.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,17 +31,18 @@
* SUCH DAMAGE.
*
* @(#)trap.h 8.3 (Berkeley) 6/5/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/trap.h 262951 2014-03-09 17:04:31Z jmmv $
*/
-extern int pendingsigs;
+extern volatile sig_atomic_t pendingsig;
+extern volatile sig_atomic_t pendingsig_waitcmd;
extern int in_dotrap;
-extern volatile sig_atomic_t gotwinch;
void clear_traps(void);
int have_traps(void);
void setsignal(int);
void ignoresig(int);
+int issigchldtrapped(void);
void onsig(int);
void dotrap(void);
void setinteractive(int);
Modified: trunk/bin/sh/var.c
===================================================================
--- trunk/bin/sh/var.c 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/var.c 2018-06-02 21:06:59 UTC (rev 10240)
@@ -37,7 +37,7 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/bin/sh/var.c 320531 2017-07-01 12:57:00Z jilles $");
#include <unistd.h>
#include <stdlib.h>
@@ -89,11 +89,9 @@
struct var vmail;
struct var vmpath;
struct var vpath;
-struct var vppid;
struct var vps1;
struct var vps2;
struct var vps4;
-struct var vvers;
static struct var voptind;
struct var vdisvfork;
@@ -112,8 +110,6 @@
NULL },
{ &vpath, 0, "PATH=" _PATH_DEFPATH,
changepath },
- { &vppid, VUNSET, "PPID=",
- NULL },
/*
* vps1 depends on uid
*/
@@ -147,29 +143,11 @@
static struct var *find_var(const char *, struct var ***, int *);
static int localevar(const char *);
-/*
- * Initialize the variable symbol tables and import the environment.
- */
+extern char **environ;
-#ifdef mkinit
-INCLUDE "var.h"
-MKINIT char **environ;
-INIT {
- char **envp;
-
- initvar();
- for (envp = environ ; *envp ; envp++) {
- if (strchr(*envp, '=')) {
- setvareq(*envp, VEXPORT|VTEXTFIXED);
- }
- }
-}
-#endif
-
-
/*
- * This routine initializes the builtin variables. It is called when the
- * shell is initialized.
+ * This routine initializes the builtin variables and imports the environment.
+ * It is called when the shell is initialized.
*/
void
@@ -179,6 +157,7 @@
const struct varinit *ip;
struct var *vp;
struct var **vpp;
+ char **envp;
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
@@ -198,10 +177,14 @@
vps1.text = __DECONST(char *, geteuid() ? "PS1=$ " : "PS1=# ");
vps1.flags = VSTRFIXED|VTEXTFIXED;
}
- if ((vppid.flags & VEXPORT) == 0) {
- fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
- setvarsafe("PPID", ppid, 0);
+ fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
+ setvarsafe("PPID", ppid, 0);
+ for (envp = environ ; *envp ; envp++) {
+ if (strchr(*envp, '=')) {
+ setvareq(*envp, VEXPORT|VTEXTFIXED);
+ }
}
+ setvareq("OPTIND=1", VTEXTFIXED);
}
/*
@@ -237,8 +220,9 @@
setvar(const char *name, const char *val, int flags)
{
const char *p;
- int len;
- int namelen;
+ size_t len;
+ size_t namelen;
+ size_t vallen;
char *nameeq;
int isbad;
@@ -257,21 +241,25 @@
}
namelen = p - name;
if (isbad)
- error("%.*s: bad variable name", namelen, name);
+ error("%.*s: bad variable name", (int)namelen, name);
len = namelen + 2; /* 2 is space for '=' and '\0' */
if (val == NULL) {
flags |= VUNSET;
+ vallen = 0;
} else {
- len += strlen(val);
+ vallen = strlen(val);
+ len += vallen;
}
+ INTOFF;
nameeq = ckmalloc(len);
memcpy(nameeq, name, namelen);
nameeq[namelen] = '=';
if (val)
- scopy(val, nameeq + namelen + 1);
+ memcpy(nameeq + namelen + 1, val, vallen + 1);
else
nameeq[namelen + 1] = '\0';
setvareq(nameeq, flags);
+ INTON;
}
static int
@@ -304,6 +292,7 @@
char *eqp;
char *ss;
+ INTOFF;
ss = savestr(s);
if ((eqp = strchr(ss, '=')) != NULL)
*eqp = '\0';
@@ -312,6 +301,7 @@
else
(void) unsetenv(ss);
ckfree(ss);
+ INTON;
return;
}
@@ -336,10 +326,16 @@
mklocal(s);
vp = find_var(s, &vpp, &nlen);
if (vp != NULL) {
- if (vp->flags & VREADONLY)
- error("%.*s: is read only", vp->name_len, s);
- if (flags & VNOSET)
+ if (vp->flags & VREADONLY) {
+ if ((flags & (VTEXTFIXED|VSTACK)) == 0)
+ ckfree(s);
+ error("%.*s: is read only", vp->name_len, vp->text);
+ }
+ if (flags & VNOSET) {
+ if ((flags & (VTEXTFIXED|VSTACK)) == 0)
+ ckfree(s);
return;
+ }
INTOFF;
if (vp->func && (flags & VNOFUNC) == 0)
@@ -357,7 +353,7 @@
* a regular variable function callback, but why bother?
*
* Note: this assumes iflag is not set to 1 initially.
- * As part of init(), this is called before arguments
+ * As part of initvar(), this is called before arguments
* are looked at.
*/
if ((vp == &vmpath || (vp == &vmail && ! mpathset())) &&
@@ -372,8 +368,12 @@
return;
}
/* not found */
- if (flags & VNOSET)
+ if (flags & VNOSET) {
+ if ((flags & (VTEXTFIXED|VSTACK)) == 0)
+ ckfree(s);
return;
+ }
+ INTOFF;
vp = ckmalloc(sizeof (*vp));
vp->flags = flags;
vp->text = s;
@@ -380,7 +380,6 @@
vp->name_len = nlen;
vp->next = *vpp;
vp->func = NULL;
- INTOFF;
*vpp = vp;
if ((vp->flags & VEXPORT) && localevar(s)) {
change_env(s, 1);
@@ -508,7 +507,7 @@
if (localevar(lp->text)) {
setlocale(LC_ALL, "");
updatecharset();
- return;
+ break;
}
}
INTON;
@@ -641,10 +640,11 @@
*/
int
-exportcmd(int argc, char **argv)
+exportcmd(int argc __unused, char **argv)
{
struct var **vpp;
struct var *vp;
+ char **ap;
char *name;
char *p;
char *cmdname;
@@ -652,26 +652,19 @@
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
cmdname = argv[0];
- optreset = optind = 1;
- opterr = 0;
values = 0;
- while ((ch = getopt(argc, argv, "p")) != -1) {
+ while ((ch = nextopt("p")) != '\0') {
switch (ch) {
case 'p':
values = 1;
break;
- case '?':
- default:
- error("unknown option: -%c", optopt);
}
}
- argc -= optind;
- argv += optind;
- if (values && argc != 0)
+ if (values && *argptr != NULL)
error("-p requires no arguments");
- if (argc != 0) {
- while ((name = *argv++) != NULL) {
+ if (*argptr != NULL) {
+ for (ap = argptr; (name = *ap) != NULL; ap++) {
if ((p = strchr(name, '=')) != NULL) {
p++;
} else {
@@ -729,6 +722,7 @@
{
char *name;
+ nextopt("");
if (! in_function())
error("Not in a function");
while ((name = *argptr++) != NULL) {
@@ -793,6 +787,7 @@
struct localvar *lvp;
struct var *vp;
+ INTOFF;
while ((lvp = localvars) != NULL) {
localvars = lvp->next;
vp = lvp->vp;
@@ -810,6 +805,7 @@
}
ckfree(lvp);
}
+ INTON;
}
@@ -848,6 +844,7 @@
if (flg_func == 0 && flg_var == 0)
flg_var = 1;
+ INTOFF;
for (ap = argptr; *ap ; ap++) {
if (flg_func)
ret |= unsetfunc(*ap);
@@ -854,6 +851,7 @@
if (flg_var)
ret |= unsetvar(*ap);
}
+ INTON;
return ret;
}
@@ -860,6 +858,7 @@
/*
* Unset the specified variable.
+ * Called with interrupts off.
*/
int
@@ -873,7 +872,6 @@
return (0);
if (vp->flags & VREADONLY)
return (1);
- INTOFF;
if (vp->text[vp->name_len + 1] != '\0')
setvar(s, nullstr, 0);
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
@@ -889,7 +887,6 @@
*vpp = vp->next;
ckfree(vp);
}
- INTON;
return (0);
}
@@ -896,7 +893,7 @@
/*
- * Returns true if the two strings specify the same varable. The first
+ * Returns true if the two strings specify the same variable. The first
* variable name is terminated by '='; the second may be terminated by
* either '=' or '\0'.
*/
@@ -917,7 +914,7 @@
* Search for a variable.
* 'name' may be terminated by '=' or a NUL.
* vppp is set to the pointer to vp, or the list head if vp isn't found
- * lenp is set to the number of charactets in 'name'
+ * lenp is set to the number of characters in 'name'
*/
static struct var *
Modified: trunk/bin/sh/var.h
===================================================================
--- trunk/bin/sh/var.h 2018-06-02 21:03:56 UTC (rev 10239)
+++ trunk/bin/sh/var.h 2018-06-02 21:06:59 UTC (rev 10240)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)var.h 8.2 (Berkeley) 5/4/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/bin/sh/var.h 262951 2014-03-09 17:04:31Z jmmv $
*/
/*
@@ -75,7 +76,6 @@
extern struct var vmail;
extern struct var vmpath;
extern struct var vpath;
-extern struct var vppid;
extern struct var vps1;
extern struct var vps2;
extern struct var vps4;
More information about the Midnightbsd-cvs
mailing list