diff options
author | Seemant Kulleen <seemant@gentoo.org> | 2003-02-11 11:18:13 +0000 |
---|---|---|
committer | Seemant Kulleen <seemant@gentoo.org> | 2003-02-11 11:18:13 +0000 |
commit | 9316d3911976e9a761cde4c50282d635da97b77d (patch) | |
tree | 610c36bd6435c46043ec30b277409c582ab72dc2 /app-shells/ash/files | |
parent | added a patch (diff) | |
download | gentoo-2-9316d3911976e9a761cde4c50282d635da97b77d.tar.gz gentoo-2-9316d3911976e9a761cde4c50282d635da97b77d.tar.bz2 gentoo-2-9316d3911976e9a761cde4c50282d635da97b77d.zip |
cleanup
Diffstat (limited to 'app-shells/ash/files')
-rw-r--r-- | app-shells/ash/files/dash-ash-hetio-yacc.diff | 17336 | ||||
-rw-r--r-- | app-shells/ash/files/digest-ash-1.6 | 1 |
2 files changed, 1 insertions, 17336 deletions
diff --git a/app-shells/ash/files/dash-ash-hetio-yacc.diff b/app-shells/ash/files/dash-ash-hetio-yacc.diff deleted file mode 100644 index f9513d835fc4..000000000000 --- a/app-shells/ash/files/dash-ash-hetio-yacc.diff +++ /dev/null @@ -1,17336 +0,0 @@ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/alias.c bin_NetBSD-1.6release/src/bin/sh/alias.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/alias.c 1998-05-20 12:07:30.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/alias.c 2003-02-08 14:35:42.000000000 +0000 -@@ -60,8 +60,9 @@ - struct alias *atab[ATABSIZE]; - - STATIC void setalias __P((char *, char *)); --STATIC int unalias __P((char *)); --STATIC struct alias **hashalias __P((char *)); -+STATIC struct alias **hashalias __P((const char *)); -+STATIC struct alias *freealias __P((struct alias *)); -+STATIC struct alias **__lookupalias __P((const char *)); - - STATIC - void -@@ -70,110 +71,58 @@ - { - struct alias *ap, **app; - -- app = hashalias(name); -- for (ap = *app; ap; ap = ap->next) { -- if (equal(name, ap->name)) { -+ app = __lookupalias(name); -+ ap = *app; - INTOFF; -+ if (ap) { -+ if (!(ap->flag & ALIASINUSE)) { - ckfree(ap->val); -- ap->val = savestr(val); -- INTON; -- return; -- } - } -+ ap->val = savestr(val); -+ ap->flag &= ~ALIASDEAD; -+ } else { - /* not found */ -- 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 markes 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 */ -- { -- int len = strlen(val); -- ap->val = ckmalloc(len + 2); -- memcpy(ap->val, val, len); -- ap->val[len] = ' '; /* fluff */ -- ap->val[len+1] = '\0'; -- } --#endif -- ap->next = *app; -+ ap->flag = 0; -+ ap->next = 0; - *app = ap; -+ } - INTON; - } - --STATIC int -+int - unalias(name) - char *name; - { -- struct alias *ap, **app; -+ struct alias **app; - -- app = hashalias(name); -+ app = __lookupalias(name); - -- for (ap = *app; ap; app = &(ap->next), ap = ap->next) { -- if (equal(name, ap->name)) { -- /* -- * if the alias is currently in use (i.e. its -- * buffer is being used by the input routine) we -- * just null out the name instead of freeing it. -- * We could clear it out later, but this situation -- * is so rare that it hardly seems worth it. -- */ -- if (ap->flag & ALIASINUSE) -- *ap->name = '\0'; -- else { -+ if (*app) { - INTOFF; -- *app = ap->next; -- ckfree(ap->name); -- ckfree(ap->val); -- ckfree(ap); -+ *app = freealias(*app); - INTON; -- } - return (0); - } -- } - - return (1); - } - --#ifdef mkinit --MKINIT void rmaliases __P((void)); -- --SHELLPROC { -- rmaliases(); --} --#endif -- - void - rmaliases() { -- struct alias *ap, *tmp; -+ struct alias *ap, **app; - int i; - - INTOFF; - for (i = 0; i < ATABSIZE; i++) { -- ap = atab[i]; -- atab[i] = NULL; -- while (ap) { -- ckfree(ap->name); -- ckfree(ap->val); -- tmp = ap; -- ap = ap->next; -- ckfree(tmp); -+ app = &atab[i]; -+ for (ap = *app; ap; ap = *app) { -+ *app = freealias(*app); -+ if (ap == *app) { -+ app = &ap->next; -+ } - } - } - INTON; -@@ -181,20 +130,14 @@ - - struct alias * - lookupalias(name, check) -- char *name; -+ const char *name; - int check; - { -- struct alias *ap = *hashalias(name); -+ struct alias *ap = *__lookupalias(name); - -- for (; ap; ap = ap->next) { -- if (equal(name, ap->name)) { -- if (check && (ap->flag & ALIASINUSE)) -+ if (check && ap && (ap->flag & ALIASINUSE)) - return (NULL); - return (ap); -- } -- } -- -- return (NULL); - } - - /* -@@ -214,18 +157,17 @@ - - for (i = 0; i < ATABSIZE; i++) - for (ap = atab[i]; ap; ap = ap->next) { -- if (*ap->name != '\0') -- out1fmt("alias %s=%s\n", ap->name, ap->val); -+ printalias(ap); - } - return (0); - } - while ((n = *++argv) != NULL) { - if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ -- if ((ap = lookupalias(n, 0)) == NULL) { -- outfmt(out2, "alias: %s not found\n", n); -+ if ((ap = *__lookupalias(n)) == NULL) { -+ outfmt(out2, "%s: %s not found\n", "alias", n); - ret = 1; - } else -- out1fmt("alias %s=%s\n", n, ap->val); -+ printalias(ap); - } - else { - *v++ = '\0'; -@@ -249,15 +191,19 @@ - return (0); - } - } -- for (i = 0; *argptr; argptr++) -- i = unalias(*argptr); -+ for (i = 0; *argptr; argptr++) { -+ if (unalias(*argptr)) { -+ outfmt(out2, "%s: %s not found\n", "unalias", *argptr); -+ i = 1; -+ } -+ } - - return (i); - } - - STATIC struct alias ** - hashalias(p) -- char *p; -+ const char *p; - { - unsigned int hashval; - -@@ -266,3 +212,37 @@ - hashval+= *p++; - return &atab[hashval % ATABSIZE]; - } -+ -+STATIC struct alias * -+freealias(struct alias *ap) { -+ struct alias *next; -+ -+ if (ap->flag & ALIASINUSE) { -+ ap->flag |= ALIASDEAD; -+ return ap; -+ } -+ -+ next = ap->next; -+ ckfree(ap->name); -+ ckfree(ap->val); -+ ckfree(ap); -+ return next; -+} -+ -+void -+printalias(const struct alias *ap) { -+ out1fmt("%s=%s\n", ap->name, single_quote(ap->val)); -+} -+ -+STATIC struct alias ** -+__lookupalias(const char *name) { -+ struct alias **app = hashalias(name); -+ -+ for (; *app; app = &(*app)->next) { -+ if (equal(name, (*app)->name)) { -+ break; -+ } -+ } -+ -+ return app; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/alias.h bin_NetBSD-1.6release/src/bin/sh/alias.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/alias.h 1995-10-14 00:43:54.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/alias.h 2003-02-08 14:35:42.000000000 +0000 -@@ -39,6 +39,7 @@ - */ - - #define ALIASINUSE 1 -+#define ALIASDEAD 2 - - struct alias { - struct alias *next; -@@ -47,7 +48,9 @@ - int flag; - }; - --struct alias *lookupalias __P((char *, int)); -+struct alias *lookupalias __P((const char *, int)); - int aliascmd __P((int, char **)); - int unaliascmd __P((int, char **)); - void rmaliases __P((void)); -+int unalias __P((char *)); -+void printalias __P((const struct alias *)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/arith_lex.l bin_NetBSD-1.6release/src/bin/sh/arith_lex.l ---- bin_NetBSD-1.6release.orig/src/bin/sh/arith_lex.l 1999-02-05 12:04:50.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/arith_lex.l 2003-02-08 14:35:42.000000000 +0000 -@@ -52,7 +52,7 @@ - #include "expand.h" - - extern int yylval; --extern char *arith_buf, *arith_startbuf; -+extern const char *arith_buf, *arith_startbuf; - #undef YY_INPUT - #define YY_INPUT(buf,result,max) \ - result = (*buf = *arith_buf++) ? 1 : YY_NULL; -@@ -84,7 +84,7 @@ - "-" { return(ARITH_SUB); } - "~" { return(ARITH_BNOT); } - "!" { return(ARITH_NOT); } --. { error("arith: syntax error: \"%s\"\n", arith_startbuf); } -+. { error("arith: syntax error: \"%s\"", arith_startbuf); } - %% - - void -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/arith.y bin_NetBSD-1.6release/src/bin/sh/arith.y ---- bin_NetBSD-1.6release.orig/src/bin/sh/arith.y 2001-02-05 11:15:29.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/arith.y 2003-02-08 14:35:42.000000000 +0000 -@@ -55,6 +55,7 @@ - - const char *arith_buf, *arith_startbuf; - -+int yyparse __P((void)); - void yyerror __P((const char *)); - #ifdef TESTARITH - int main __P((int , char *[])); -@@ -84,8 +85,8 @@ - - - expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; } -- | expr ARITH_OR expr = { $$ = $1 ? $1 : $3 ? $3 : 0; } -- | expr ARITH_AND expr = { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } -+ | expr ARITH_OR expr = { $$ = $1 || $3; } -+ | expr ARITH_AND expr = { $$ = $1 && $3; } - | expr ARITH_BOR expr = { $$ = $1 | $3; } - | expr ARITH_BXOR expr = { $$ = $1 ^ $3; } - | expr ARITH_BAND expr = { $$ = $1 & $3; } -@@ -166,7 +167,7 @@ - p = grabstackstr(concat); - } - } else -- p = ""; -+ p = nullstr; - - i = arith(p); - -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/arith_yylex.c bin_NetBSD-1.6release/src/bin/sh/arith_yylex.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/arith_yylex.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/arith_yylex.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,162 @@ -+/* $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ */ -+ -+/*- -+ * Copyright (c) 2002 -+ * Herbert Xu. -+ * Copyright (c) 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * This code is derived from software contributed to Berkeley by -+ * Kenneth Almquist. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+#include <stdlib.h> -+#include "arith.h" -+#include "expand.h" -+#include "error.h" -+ -+extern int yylval; -+extern const char *arith_buf, *arith_startbuf; -+ -+int -+yylex() -+{ -+ int value; -+ const char *buf = arith_buf; -+ -+ for (;;) { -+ switch (*buf) { -+ case ' ': -+ case '\t': -+ case '\n': -+ buf++; -+ continue; -+ default: -+err: -+ error("arith: syntax error: \"%s\"", arith_startbuf); -+ /* NOTREACHED */ -+ case '0': -+ case '1': -+ case '2': -+ case '3': -+ case '4': -+ case '5': -+ case '6': -+ case '7': -+ case '8': -+ case '9': -+ yylval = strtol(buf, (char **) &arith_buf, 0); -+ return ARITH_NUM; -+ case '=': -+ if (*++buf != '=') { -+ goto err; -+ } -+ value = ARITH_EQ; -+ break; -+ case '>': -+ switch (*++buf) { -+ case '=': -+ value = ARITH_GE; -+ break; -+ case '>': -+ value = ARITH_RSHIFT; -+ break; -+ default: -+ value = ARITH_GT; -+ goto out; -+ } -+ break; -+ case '<': -+ switch (*++buf) { -+ case '=': -+ value = ARITH_LE; -+ break; -+ case '<': -+ value = ARITH_LSHIFT; -+ break; -+ default: -+ value = ARITH_LT; -+ goto out; -+ } -+ break; -+ case '|': -+ if (*++buf != '|') { -+ value = ARITH_BOR; -+ goto out; -+ } -+ value = ARITH_OR; -+ break; -+ case '&': -+ if (*++buf != '&') { -+ value = ARITH_BAND; -+ goto out; -+ } -+ value = ARITH_AND; -+ break; -+ case '!': -+ if (*++buf != '=') { -+ value = ARITH_NOT; -+ goto out; -+ } -+ value = ARITH_NE; -+ break; -+ case 0: -+ value = 0; -+ goto out; -+ case '(': -+ value = ARITH_LPAREN; -+ break; -+ case ')': -+ value = ARITH_RPAREN; -+ break; -+ case '*': -+ value = ARITH_MUL; -+ break; -+ case '/': -+ value = ARITH_DIV; -+ break; -+ case '%': -+ value = ARITH_REM; -+ break; -+ case '+': -+ value = ARITH_ADD; -+ break; -+ case '-': -+ value = ARITH_SUB; -+ break; -+ case '~': -+ value = ARITH_BNOT; -+ break; -+ } -+ break; -+ } -+ -+ buf++; -+out: -+ arith_buf = buf; -+ return value; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/assignbltins.def bin_NetBSD-1.6release/src/bin/sh/assignbltins.def ---- bin_NetBSD-1.6release.orig/src/bin/sh/assignbltins.def 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/assignbltins.def 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,4 @@ -+alias -+export -+local -+readonly -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/bltin.h bin_NetBSD-1.6release/src/bin/sh/bltin/bltin.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/bltin.h 1997-07-05 12:12:37.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/bltin.h 2003-02-08 14:35:42.000000000 +0000 -@@ -47,7 +47,10 @@ - #include "../shell.h" - #include "../mystring.h" - #ifdef SHELL -+#include "../error.h" -+#include "../memalloc.h" - #include "../output.h" -+#ifndef USE_GLIBC_STDIO - #define stdout out1 - #define stderr out2 - #define printf out1fmt -@@ -56,12 +59,9 @@ - #define fprintf outfmt - #define fputs outstr - #define fflush flushout -+#define ferror outerr -+#endif - #define INITARGS(argv) --#define warnx(a, b, c) { \ -- char buf[64]; \ -- (void)snprintf(buf, sizeof(buf), a, b, c); \ -- error("%s", buf); \ --} - - #else - #undef NULL -@@ -70,8 +70,6 @@ - #define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else - #endif - --pointer stalloc __P((int)); --void error __P((char *, ...)); - int echocmd __P((int, char **)); - - -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/echo.c bin_NetBSD-1.6release/src/bin/sh/bltin/echo.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/echo.c 1996-11-03 12:06:22.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/echo.c 2003-02-08 14:35:42.000000000 +0000 -@@ -44,64 +44,48 @@ - - #define main echocmd - -+#ifdef USE_GLIBC_STDIO -+#include <stdio.h> -+ -+#include "../mystring.h" -+#else - #include "bltin.h" -+#endif - --/* #define eflag 1 */ -+int print_escape_str(const char *); - - int --main(argc, argv) char **argv; { -- register char **ap; -- register char *p; -- register char c; -- int count; -+main(int argc, char **argv) { - int nflag = 0; --#ifndef eflag -- int eflag = 0; --#endif -+ int c = ' '; - -- ap = argv; -- if (argc) -- ap++; -- if ((p = *ap) != NULL) { -- if (equal(p, "-n")) { -- nflag++; -- ap++; -- } else if (equal(p, "-e")) { --#ifndef eflag -- eflag++; --#endif -- ap++; -+ argv++; -+ if (*argv && equal(*argv, "-n")) { -+ argv++; -+ nflag = 1; - } -+ -+ if (!*argv) { -+ goto end; - } -- while ((p = *ap++) != NULL) { -- while ((c = *p++) != '\0') { -- if (c == '\\' && eflag) { -- switch (*p++) { -- case 'b': c = '\b'; break; -- case 'c': return 0; /* exit */ -- case 'f': c = '\f'; break; -- case 'n': c = '\n'; break; -- case 'r': c = '\r'; break; -- case 't': c = '\t'; break; -- case 'v': c = '\v'; break; -- case '\\': break; /* c = '\\' */ -- case '0': -- c = 0; -- count = 3; -- while (--count >= 0 && (unsigned)(*p - '0') < 8) -- c = (c << 3) + (*p++ - '0'); -+ -+ do { -+ if (print_escape_str(*argv)) { - break; -- default: -- p--; -+ } -+ if (!*++argv) { -+end: -+ if (nflag) { - break; - } -+ c = '\n'; - } - putchar(c); -- } -- if (*ap) -- putchar(' '); -- } -- if (! nflag) -- putchar('\n'); -+ } while (c == ' '); -+#ifdef SHELL - return 0; -+#else -+ fflush(stdout); -+ return ferror(stdout); -+#endif - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/printf.1 bin_NetBSD-1.6release/src/bin/sh/bltin/printf.1 ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/printf.1 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/printf.1 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,281 @@ -+.\" $NetBSD: printf.1,v 1.15 2002/02/08 01:36:31 ross Exp $ -+.\" -+.\" Copyright (c) 1989, 1990, 1993 -+.\" The Regents of the University of California. All rights reserved. -+.\" -+.\" This code is derived from software contributed to Berkeley by -+.\" the Institute of Electrical and Electronics Engineers, Inc. -+.\" -+.\" Redistribution and use in source and binary forms, with or without -+.\" modification, are permitted provided that the following conditions -+.\" are met: -+.\" 1. Redistributions of source code must retain the above copyright -+.\" notice, this list of conditions and the following disclaimer. -+.\" 2. Redistributions in binary form must reproduce the above copyright -+.\" notice, this list of conditions and the following disclaimer in the -+.\" documentation and/or other materials provided with the distribution. -+.\" 3. All advertising materials mentioning features or use of this software -+.\" must display the following acknowledgement: -+.\" This product includes software developed by the University of -+.\" California, Berkeley and its contributors. -+.\" 4. Neither the name of the University nor the names of its contributors -+.\" may be used to endorse or promote products derived from this software -+.\" without specific prior written permission. -+.\" -+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+.\" SUCH DAMAGE. -+.\" -+.\" from: @(#)printf.1 8.1 (Berkeley) 6/6/93 -+.\" -+.Dd November 5, 1993 -+.Dt PRINTF 1 -+.Os -+.Sh NAME -+.Nm printf -+.Nd formatted output -+.Sh SYNOPSIS -+.Nm -+.Ar format -+.Op Ar arguments ... -+.Sh DESCRIPTION -+.Nm -+formats and prints its arguments, after the first, under control -+of the -+.Ar format . -+The -+.Ar format -+is a character string which contains three types of objects: plain characters, -+which are simply copied to standard output, character escape sequences which -+are converted and copied to the standard output, and format specifications, -+each of which causes printing of the next successive -+.Ar argument . -+.Pp -+The -+.Ar arguments -+after the first are treated as strings if the corresponding format is -+either -+.Cm b , -+.Cm c -+or -+.Cm s ; -+otherwise it is evaluated as a C constant, with the following extensions: -+.Pp -+.Bl -bullet -offset indent -compact -+.It -+A leading plus or minus sign is allowed. -+.It -+If the leading character is a single or double quote, the value is the -+.Tn ASCII -+code of the next character. -+.El -+.Pp -+The format string is reused as often as necessary to satisfy the -+.Ar arguments . -+Any extra format specifications are evaluated with zero or the null -+string. -+.Pp -+Character escape sequences are in backslash notation as defined in -+.St -ansiC . -+The characters and their meanings -+are as follows: -+.Bl -tag -width Ds -offset indent -+.It Cm \ee -+Write an \*[Lt]escape\*[Gt] character. -+.It Cm \ea -+Write a \*[Lt]bell\*[Gt] character. -+.It Cm \eb -+Write a \*[Lt]backspace\*[Gt] character. -+.It Cm \ef -+Write a \*[Lt]form-feed\*[Gt] character. -+.It Cm \en -+Write a \*[Lt]new-line\*[Gt] character. -+.It Cm \er -+Write a \*[Lt]carriage return\*[Gt] character. -+.It Cm \et -+Write a \*[Lt]tab\*[Gt] character. -+.It Cm \ev -+Write a \*[Lt]vertical tab\*[Gt] character. -+.It Cm \e\' -+Write a \*[Lt]single quote\*[Gt] character. -+.It Cm \e\e -+Write a backslash character. -+.It Cm \e Ns Ar num -+Write an 8-bit character whose -+.Tn ASCII -+value is the 1-, 2-, or 3-digit -+octal number -+.Ar num . -+.El -+.Pp -+Each format specification is introduced by the percent character -+(``%''). -+The remainder of the format specification includes, -+in the following order: -+.Bl -tag -width Ds -+.It "Zero or more of the following flags:" -+.Bl -tag -width Ds -+.It Cm # -+A `#' character -+specifying that the value should be printed in an ``alternative form''. -+For -+.Cm c , -+.Cm d , -+and -+.Cm s , -+formats, this option has no effect. For the -+.Cm o -+formats the precision of the number is increased to force the first -+character of the output string to a zero. For the -+.Cm x -+.Pq Cm X -+format, a non-zero result has the string -+.Li 0x -+.Pq Li 0X -+prepended to it. For -+.Cm e , -+.Cm E , -+.Cm f , -+.Cm g , -+and -+.Cm G , -+formats, the result will always contain a decimal point, even if no -+digits follow the point (normally, a decimal point only appears in the -+results of those formats if a digit follows the decimal point). For -+.Cm g -+and -+.Cm G -+formats, trailing zeros are not removed from the result as they -+would otherwise be; -+.It Cm \&\- -+A minus sign `\-' which specifies -+.Em left adjustment -+of the output in the indicated field; -+.It Cm \&+ -+A `+' character specifying that there should always be -+a sign placed before the number when using signed formats. -+.It Sq \&\ \& -+A space specifying that a blank should be left before a positive number -+for a signed format. A `+' overrides a space if both are used; -+.It Cm \&0 -+A zero `0' character indicating that zero-padding should be used -+rather than blank-padding. A `\-' overrides a `0' if both are used; -+.El -+.It "Field Width:" -+An optional digit string specifying a -+.Em field width ; -+if the output string has fewer characters than the field width it will -+be blank-padded on the left (or right, if the left-adjustment indicator -+has been given) to make up the field width (note that a leading zero -+is a flag, but an embedded zero is part of a field width); -+.It Precision : -+An optional period, -+.Sq Cm \&.\& , -+followed by an optional digit string giving a -+.Em precision -+which specifies the number of digits to appear after the decimal point, -+for -+.Cm e -+and -+.Cm f -+formats, or the maximum number of characters to be printed -+from a string; if the digit string is missing, the precision is treated -+as zero; -+.It Format : -+A character which indicates the type of format to use (one of -+.Cm diouxXfwEgGbcs ) . -+.El -+.Pp -+A field width or precision may be -+.Sq Cm \&* -+instead of a digit string. -+In this case an -+.Ar argument -+supplies the field width or precision. -+.Pp -+The format characters and their meanings are: -+.Bl -tag -width Fl -+.It Cm diouXx -+The -+.Ar argument -+is printed as a signed decimal (d or i), unsigned octal, unsigned decimal, -+or unsigned hexadecimal (X or x), respectively. -+.It Cm f -+The -+.Ar argument -+is printed in the style -+.Sm off -+.Pf [\-]ddd Cm \&. No ddd -+.Sm on -+where the number of d's -+after the decimal point is equal to the precision specification for -+the argument. -+If the precision is missing, 6 digits are given; if the precision -+is explicitly 0, no digits and no decimal point are printed. -+.It Cm eE -+The -+.Ar argument -+is printed in the style -+.Sm off -+.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd -+.Sm on -+where there -+is one digit before the decimal point and the number after is equal to -+the precision specification for the argument; when the precision is -+missing, 6 digits are produced. -+An upper-case E is used for an `E' format. -+.It Cm gG -+The -+.Ar argument -+is printed in style -+.Cm f -+or in style -+.Cm e -+.Pq Cm E -+whichever gives full precision in minimum space. -+.It Cm b -+Characters from the string -+.Ar argument -+are printed with backslash-escape sequences expanded. -+.It Cm c -+The first character of -+.Ar argument -+is printed. -+.It Cm s -+Characters from the string -+.Ar argument -+are printed until the end is reached or until the number of characters -+indicated by the precision specification is reached; however if the -+precision is 0 or missing, all characters in the string are printed. -+.It Cm \&% -+Print a `%'; no argument is used. -+.El -+.Pp -+In no case does a non-existent or small field width cause truncation of -+a field; padding takes place only if the specified field width exceeds -+the actual width. -+.Sh EXIT STATUS -+.Nm -+exits 0 on success, 1 on failure. -+.Sh SEE ALSO -+.Xr echo 1 , -+.Xr printf 3 , -+.Xr printf 9 -+.Sh STANDARDS -+The -+.Nm -+utility conforms to -+.St -p1003.2-92 . -+.Sh BUGS -+Since the floating point numbers are translated from -+.Tn ASCII -+to floating-point and -+then back again, floating-point precision may be lost. -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/printf.c bin_NetBSD-1.6release/src/bin/sh/bltin/printf.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/printf.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/printf.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,532 @@ -+/* $NetBSD: printf.c,v 1.24 2002/06/14 11:32:15 tron Exp $ */ -+ -+/* -+ * Copyright (c) 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+#include <sys/cdefs.h> -+#ifndef lint -+#if !defined(BUILTIN) && !defined(SHELL) -+__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ -+ The Regents of the University of California. All rights reserved.\n"); -+#endif -+#endif -+ -+#ifndef lint -+#if 0 -+static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95"; -+#else -+__RCSID("$NetBSD: printf.c,v 1.24 2002/06/14 11:32:15 tron Exp $"); -+#endif -+#endif /* not lint */ -+ -+#include <sys/types.h> -+ -+#include <ctype.h> -+#include <err.h> -+#include <errno.h> -+#include <inttypes.h> -+#include <limits.h> -+#include <locale.h> -+#include <stdarg.h> -+#ifndef SHELL -+#include <stdio.h> -+#endif -+#include <stdlib.h> -+#include <string.h> -+#include <unistd.h> -+ -+int print_escape_str(const char *); -+static size_t print_escape(const char *); -+ -+static int getchr(void); -+static double getdouble(void); -+static intmax_t getintmax(void); -+static uintmax_t getuintmax __P ((void)); -+static char *getstr(void); -+static char *mklong(const char *, int); -+static void check_conversion(const char *, const char *); -+static void usage(void); -+ -+static int rval; -+static char **gargv; -+ -+#ifdef BUILTIN -+int progprintf(int, char **); -+#else -+int main(int, char **); -+#endif -+ -+#define isodigit(c) ((c) >= '0' && (c) <= '7') -+#define octtobin(c) ((c) - '0') -+#define hextobin(c) ((c) >= 'A' && (c) <= 'F' ? c - 'A' + 10 : (c) >= 'a' && (c) <= 'f' ? c - 'a' + 10 : c - '0') -+ -+#ifdef SHELL -+#define main printfcmd -+#include "bltin.h" -+#else -+#define nullstr "" -+#endif -+ -+#define PF(f, func) { \ -+ switch (param - array) { \ -+ case 0: \ -+ (void)printf(f, func); \ -+ break; \ -+ case 1: \ -+ (void)printf(f, array[0], func); \ -+ break; \ -+ default: \ -+ (void)printf(f, array[0], array[1], func); \ -+ break; \ -+ } \ -+} -+ -+int -+#ifdef BUILTIN -+progprintf(int argc, char **argv) -+#else -+main(int argc, char **argv) -+#endif -+{ -+ char *fmt; -+ char *format; -+ -+#if !defined(SHELL) && !defined(BUILTIN) -+ (void)setlocale (LC_ALL, ""); -+#endif -+ -+ if (--argc < 1) { -+ usage(); -+ return (1); -+ } -+ -+ format = *++argv; -+ gargv = ++argv; -+ -+#define SKIP1 "#-+ 0" -+#define SKIP2 "*0123456789" -+ do { -+ /* -+ * Basic algorithm is to scan the format string for conversion -+ * specifications -- once one is found, find out if the field -+ * width or precision is a '*'; if it is, gather up value. -+ * Note, format strings are reused as necessary to use up the -+ * provided arguments, arguments of zero/null string are -+ * provided to use up the format string. -+ */ -+ -+ /* find next format specification */ -+ for (fmt = format; *fmt; fmt++) { -+ switch (*fmt) { -+ case '%': { -+ char *start; -+ char convch, nextch; -+ int array[2]; -+ int *param; -+ -+ start = fmt++; -+ -+ if (*fmt == '%') { -+ (void)putchar('%'); -+ break; -+ } else if (*fmt == 'b') { -+ char *p = getstr(); -+ if (print_escape_str(p)) { -+ return (rval); -+ } -+ break; -+ } -+ -+ param = array; -+ -+ /* skip to field width */ -+ fmt += strspn(fmt, SKIP1); -+ if (*fmt == '*') -+ *param++ = getintmax(); -+ -+ /* skip to possible '.', get following precision */ -+ fmt += strspn(fmt, SKIP2); -+ if (*fmt == '.') -+ ++fmt; -+ if (*fmt == '*') -+ *param++ = getintmax(); -+ -+ fmt += strspn(fmt, SKIP2); -+ if (!*fmt) { -+ warnx ("missing format character"); -+ return(1); -+ } -+ -+ convch = *fmt; -+ nextch = *(fmt + 1); -+ *(fmt + 1) = '\0'; -+ switch(convch) { -+ case 'c': { -+ char p = getchr(); -+ PF(start, p); -+ break; -+ } -+ case 's': { -+ char *p = getstr(); -+ PF(start, p); -+ break; -+ } -+ case 'd': -+ case 'i': { -+ char *f = mklong(start, convch); -+ intmax_t p = getintmax(); -+ PF(f, p); -+ break; -+ } -+ case 'o': -+ case 'u': -+ case 'x': -+ case 'X': { -+ char *f = mklong(start, convch); -+ uintmax_t p = getuintmax(); -+ PF(f, p); -+ break; -+ } -+ case 'e': -+ case 'E': -+ case 'f': -+ case 'g': -+ case 'G': { -+ double p = getdouble(); -+ PF(start, p); -+ break; -+ } -+ default: -+ warnx ("%s: invalid directive", start); -+ return(1); -+ } -+ *(fmt + 1) = nextch; -+ break; -+ } -+ -+ case '\\': -+ fmt += print_escape(fmt); -+ break; -+ -+ default: -+ (void)putchar(*fmt); -+ break; -+ } -+ } -+ } while (gargv > argv && *gargv); -+ -+#ifdef SHELL -+ return (rval); -+#else -+ fflush(stdout); -+ return (rval ? rval : ferror(stdout)); -+#endif -+} -+ -+ -+/* -+ * Print SysV echo(1) style escape string -+ * Halts processing string and returns 1 if a \c escape is encountered. -+ */ -+int -+print_escape_str(const char *str) -+{ -+ char value; -+ char c; -+ -+ for (; (value = *str); str++) { -+ if (value == '\\') { -+ c = *++str; -+ /* -+ * %b string octal constants are not like those in C. -+ * They start with a \0, and are followed by 0, 1, 2, -+ * or 3 octal digits. -+ */ -+ if (c == '0') { -+ unsigned j; -+ unsigned char i; -+ i = 3; -+ j = 0; -+ do { -+ unsigned k = octtobin(*++str); -+ if (k > 7) { -+ str--; -+ break; -+ } -+ j <<= 3; -+ j += k; -+ } while (--i); -+ value = j; -+ } else if (c == 'c') { -+ return 1; -+ } else { -+ str--; -+ str += print_escape(str); -+ continue; -+ } -+ } -+ putchar(value); -+ } -+ -+ return 0; -+} -+ -+/* -+ * Print "standard" escape characters -+ */ -+static size_t -+print_escape(const char *str) -+{ -+ const char *start = str; -+ int value; -+ size_t c = 1; -+ -+ str++; -+ -+ switch (*str) { -+ case '0': case '1': case '2': case '3': -+ case '4': case '5': case '6': case '7': -+ for (c = 4, value = 0; --c && isodigit(*str); str++) { -+ value <<= 3; -+ value += octtobin(*str); -+ } -+ c = str - start - 1; -+ break; -+ -+#ifdef notrequired -+ case 'x': -+ str++; -+ for (value = 0; isxdigit((unsigned char)*str); str++) { -+ value <<= 4; -+ value += hextobin(*str); -+ } -+ if (value > UCHAR_MAX) { -+ warnx ("escape sequence out of range for character"); -+ rval = 1; -+ } -+ c = str - start - 1; -+ break; -+#endif -+ -+ case '\\': /* backslash */ -+ value = '\\'; -+ break; -+ -+#ifdef notrequired -+ case '\'': /* single quote */ -+ value = '\''; -+ break; -+ -+ case '"': /* double quote */ -+ value = '"'; -+ break; -+#endif -+ -+ case 'a': /* alert */ -+ value = '\a'; -+ break; -+ -+ case 'b': /* backspace */ -+ value = '\b'; -+ break; -+ -+#ifdef notrequired -+ case 'e': /* escape */ -+#ifdef __GNUC__ -+ value = '\e'; -+#else -+ value = 033; -+#endif -+ break; -+#endif -+ -+ case 'f': /* form-feed */ -+ value = '\f'; -+ break; -+ -+ case 'n': /* newline */ -+ value = '\n'; -+ break; -+ -+ case 'r': /* carriage-return */ -+ value = '\r'; -+ break; -+ -+ case 't': /* tab */ -+ value = '\t'; -+ break; -+ -+ case 'v': /* vertical-tab */ -+ value = '\v'; -+ break; -+ -+ default: -+#if 0 -+ value = *str; -+ warnx("unknown escape sequence `\\%c'", *str); -+ rval = 1; -+#else -+ value = '\\'; -+ c = 0; -+#endif -+ break; -+ } -+ -+ putchar(value); -+ return c; -+} -+ -+static char * -+mklong(const char *str, int ch) -+{ -+ static char copy[64]; -+ size_t len; -+ -+ len = strlen(str) + 2; -+ (void)memmove(copy, str, len - 3); -+ copy[len - 3] = 'j'; -+ copy[len - 2] = ch; -+ copy[len - 1] = '\0'; -+ return (copy); -+} -+ -+static int -+getchr(void) -+{ -+ int val = 0; -+ -+ if (*gargv) -+ val = **gargv++; -+ return val; -+} -+ -+static char * -+getstr(void) -+{ -+ char *val = nullstr; -+ -+ if (*gargv) -+ val = *gargv++; -+ return val; -+} -+ -+static intmax_t -+getintmax(void) -+{ -+ intmax_t val = 0; -+ char *ep; -+ const char *arg = *gargv; -+ -+ if (!arg) -+ goto out; -+ -+ gargv++; -+ -+ val = (unsigned char) arg[1]; -+ if (*arg == '\"' || *arg == '\'') -+ goto out; -+ -+ errno = 0; -+ val = strtoimax(arg, &ep, 0); -+ check_conversion(arg, ep); -+out: -+ return val; -+} -+ -+static uintmax_t -+getuintmax(void) -+{ -+ uintmax_t val = 0; -+ char *ep; -+ const char *arg = *gargv; -+ -+ if (!arg) -+ goto out; -+ -+ gargv++; -+ -+ val = (unsigned char) arg[1]; -+ if (*arg == '\"' || *arg == '\'') -+ goto out; -+ -+ errno = 0; -+ val = strtoumax(arg, &ep, 0); -+ check_conversion(arg, ep); -+out: -+ return val; -+} -+ -+static double -+getdouble(void) -+{ -+ double val = 0; -+ char *ep; -+ const char *arg = *gargv; -+ -+ if (!arg) -+ goto out; -+ -+ gargv++; -+ -+ if (*arg == '\"' || *arg == '\'') { -+ val = (unsigned char) arg[1]; -+ goto out; -+ } -+ -+ errno = 0; -+ val = strtod(arg, &ep); -+ check_conversion(arg, ep); -+out: -+ return val; -+} -+ -+static void -+check_conversion(const char *s, const char *ep) -+{ -+ if (*ep) { -+ if (ep == s) -+ warnx ("%s: expected numeric value", s); -+ else -+ warnx ("%s: not completely converted", s); -+ rval = 1; -+ } else if (errno == ERANGE) { -+ warnx ("%s: %s", s, strerror(ERANGE)); -+ rval = 1; -+ } -+} -+ -+static void -+usage(void) -+{ -+ (void)fprintf(stderr, "usage: printf format [arg ...]\n"); -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/test.1 bin_NetBSD-1.6release/src/bin/sh/bltin/test.1 ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/test.1 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/test.1 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,312 @@ -+.\" $NetBSD: test.1,v 1.17 2002/02/08 01:22:01 ross Exp $ -+.\" -+.\" Copyright (c) 1991, 1993 -+.\" The Regents of the University of California. All rights reserved. -+.\" -+.\" This code is derived from software contributed to Berkeley by -+.\" the Institute of Electrical and Electronics Engineers, Inc. -+.\" -+.\" Redistribution and use in source and binary forms, with or without -+.\" modification, are permitted provided that the following conditions -+.\" are met: -+.\" 1. Redistributions of source code must retain the above copyright -+.\" notice, this list of conditions and the following disclaimer. -+.\" 2. Redistributions in binary form must reproduce the above copyright -+.\" notice, this list of conditions and the following disclaimer in the -+.\" documentation and/or other materials provided with the distribution. -+.\" 3. All advertising materials mentioning features or use of this software -+.\" must display the following acknowledgement: -+.\" This product includes software developed by the University of -+.\" California, Berkeley and its contributors. -+.\" 4. Neither the name of the University nor the names of its contributors -+.\" may be used to endorse or promote products derived from this software -+.\" without specific prior written permission. -+.\" -+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+.\" SUCH DAMAGE. -+.\" -+.\" @(#)test.1 8.1 (Berkeley) 5/31/93 -+.\" -+.Dd May 31, 1993 -+.Dt TEST 1 -+.Os -+.Sh NAME -+.Nm test , -+.Nm \&[ -+.Nd condition evaluation utility -+.Sh SYNOPSIS -+.Nm test -+.Ar expression -+.Nm \&[ -+.Ar expression Cm ] -+.Sh DESCRIPTION -+The -+.Nm test -+utility evaluates the expression and, if it evaluates -+to true, returns a zero (true) exit status; otherwise -+it returns 1 (false). -+If there is no expression, test also -+returns 1 (false). -+.Pp -+All operators and flags are separate arguments to the -+.Nm test -+utility. -+.Pp -+The following primaries are used to construct expression: -+.Bl -tag -width Ar -+.It Fl b Ar file -+True if -+.Ar file -+exists and is a block special -+file. -+.It Fl c Ar file -+True if -+.Ar file -+exists and is a character -+special file. -+.It Fl d Ar file -+True if -+.Ar file -+exists and is a directory. -+.It Fl e Ar file -+True if -+.Ar file -+exists (regardless of type). -+.It Fl f Ar file -+True if -+.Ar file -+exists and is a regular file. -+.It Fl g Ar file -+True if -+.Ar file -+exists and its set group ID flag -+is set. -+.It Fl h Ar file -+True if -+.Ar file -+exists and is a symbolic link. -+.It Fl k Ar file -+True if -+.Ar file -+exists and its sticky bit is set. -+.It Fl n Ar string -+True if the length of -+.Ar string -+is nonzero. -+.It Fl p Ar file -+True if -+.Ar file -+is a named pipe -+.Po Tn FIFO Pc . -+.It Fl r Ar file -+True if -+.Ar file -+exists and is readable. -+.It Fl s Ar file -+True if -+.Ar file -+exists and has a size greater -+than zero. -+.It Fl t Ar file_descriptor -+True if the file whose file descriptor number -+is -+.Ar file_descriptor -+is open and is associated with a terminal. -+.It Fl u Ar file -+True if -+.Ar file -+exists and its set user ID flag -+is set. -+.It Fl w Ar file -+True if -+.Ar file -+exists and is writable. -+True -+indicates only that the write flag is on. -+The file is not writable on a read-only file -+system even if this test indicates true. -+.It Fl x Ar file -+True if -+.Ar file -+exists and is executable. -+True -+indicates only that the execute flag is on. -+If -+.Ar file -+is a directory, true indicates that -+.Ar file -+can be searched. -+.It Fl z Ar string -+True if the length of -+.Ar string -+is zero. -+.It Fl L Ar file -+True if -+.Ar file -+exists and is a symbolic link. -+This operator is retained for compatibility with previous versions of -+this program. Do not rely on its existence; use -+.Fl h -+instead. -+.It Fl O Ar file -+True if -+.Ar file -+exists and its owner matches the effective user id of this process. -+.It Fl G Ar file -+True if -+.Ar file -+exists and its group matches the effective group id of this process. -+.It Fl S Ar file -+True if -+.Ar file -+exists and is a socket. -+.It Ar file1 Fl nt Ar file2 -+True if -+.Ar file1 -+exists and is newer than -+.Ar file2 . -+.It Ar file1 Fl ot Ar file2 -+True if -+.Ar file1 -+exists and is older than -+.Ar file2 . -+.It Ar file1 Fl ef Ar file2 -+True if -+.Ar file1 -+and -+.Ar file2 -+exist and refer to the same file. -+.It Ar string -+True if -+.Ar string -+is not the null -+string. -+.It Ar \&s\&1 Cm \&= Ar \&s\&2 -+True if the strings -+.Ar \&s\&1 -+and -+.Ar \&s\&2 -+are identical. -+.It Ar \&s\&1 Cm \&!= Ar \&s\&2 -+True if the strings -+.Ar \&s\&1 -+and -+.Ar \&s\&2 -+are not identical. -+.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2 -+True if string -+.Ar \&s\&1 -+comes before -+.Ar \&s\&2 -+based on the ASCII value of their characters. -+.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2 -+True if string -+.Ar \&s\&1 -+comes after -+.Ar \&s\&2 -+based on the ASCII value of their characters. -+.It Ar \&n\&1 Fl \&eq Ar \&n\&2 -+True if the integers -+.Ar \&n\&1 -+and -+.Ar \&n\&2 -+are algebraically -+equal. -+.It Ar \&n\&1 Fl \&ne Ar \&n\&2 -+True if the integers -+.Ar \&n\&1 -+and -+.Ar \&n\&2 -+are not -+algebraically equal. -+.It Ar \&n\&1 Fl \> Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically -+greater than the integer -+.Ar \&n\&2 . -+.It Ar \&n\&1 Fl \&ge Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically -+greater than or equal to the integer -+.Ar \&n\&2 . -+.It Ar \&n\&1 Fl \< Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically less -+than the integer -+.Ar \&n\&2 . -+.It Ar \&n\&1 Fl \&le Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically less -+than or equal to the integer -+.Ar \&n\&2 . -+.El -+.Pp -+These primaries can be combined with the following operators: -+.Bl -tag -width Ar -+.It Cm \&! Ar expression -+True if -+.Ar expression -+is false. -+.It Ar expression1 Fl a Ar expression2 -+True if both -+.Ar expression1 -+and -+.Ar expression2 -+are true. -+.It Ar expression1 Fl o Ar expression2 -+True if either -+.Ar expression1 -+or -+.Ar expression2 -+are true. -+.It Cm \&( Ns Ar expression Ns Cm \&) -+True if expression is true. -+.El -+.Pp -+The -+.Fl a -+operator has higher precedence than the -+.Fl o -+operator. -+.Sh GRAMMAR AMBIGUITY -+The -+.Nm test -+grammar is inherently ambiguous. In order to assure a degree of consistency, -+the cases described in -+.St -p1003.2 -+section 4.62.4, -+are evaluated consistently according to the rules specified in the -+standards document. All other cases are subject to the ambiguity in the -+command semantics. -+.Sh EXIT STATUS -+The -+.Nm test -+utility exits with one of the following values: -+.Bl -tag -width Ds -+.It 0 -+expression evaluated to true. -+.It 1 -+expression evaluated to false or expression was -+missing. -+.It \*[Gt]1 -+An error occurred. -+.El -+.Sh STANDARDS -+The -+.Nm test -+utility implements a superset of the -+.St -p1003.2 -+specification. -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/test.c bin_NetBSD-1.6release/src/bin/sh/bltin/test.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/test.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/test.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,545 @@ -+/* $NetBSD: test.c,v 1.25 2002/05/25 23:12:16 wiz Exp $ */ -+ -+/* -+ * test(1); version 7-like -- author Erik Baalbergen -+ * modified by Eric Gisin to be used as built-in. -+ * modified by Arnold Robbins to add SVR3 compatibility -+ * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). -+ * modified by J.T. Conklin for NetBSD. -+ * -+ * This program is in the Public Domain. -+ */ -+ -+#include <sys/cdefs.h> -+#ifndef lint -+__RCSID("$NetBSD: test.c,v 1.25 2002/05/25 23:12:16 wiz Exp $"); -+#endif -+ -+#include <sys/stat.h> -+#include <sys/types.h> -+ -+#include <ctype.h> -+#include <err.h> -+#include <errno.h> -+#include <stdlib.h> -+#include <string.h> -+#include <unistd.h> -+#include <stdarg.h> -+#include "bltin.h" -+ -+/* test(1) accepts the following grammar: -+ oexpr ::= aexpr | aexpr "-o" oexpr ; -+ aexpr ::= nexpr | nexpr "-a" aexpr ; -+ nexpr ::= primary | "!" primary -+ primary ::= unary-operator operand -+ | operand binary-operator operand -+ | operand -+ | "(" oexpr ")" -+ ; -+ unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| -+ "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; -+ -+ binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| -+ "-nt"|"-ot"|"-ef"; -+ operand ::= <any legal UNIX file name> -+*/ -+ -+enum token { -+ EOI, -+ FILRD, -+ FILWR, -+ FILEX, -+ FILEXIST, -+ FILREG, -+ FILDIR, -+ FILCDEV, -+ FILBDEV, -+ FILFIFO, -+ FILSOCK, -+ FILSYM, -+ FILGZ, -+ FILTT, -+ FILSUID, -+ FILSGID, -+ FILSTCK, -+ FILNT, -+ FILOT, -+ FILEQ, -+ FILUID, -+ FILGID, -+ STREZ, -+ STRNZ, -+ STREQ, -+ STRNE, -+ STRLT, -+ STRGT, -+ INTEQ, -+ INTNE, -+ INTGE, -+ INTGT, -+ INTLE, -+ INTLT, -+ UNOT, -+ BAND, -+ BOR, -+ LPAREN, -+ RPAREN, -+ OPERAND -+}; -+ -+enum token_types { -+ UNOP, -+ BINOP, -+ BUNOP, -+ BBINOP, -+ PAREN -+}; -+ -+static struct t_op { -+ const char *op_text; -+ short op_num, op_type; -+} const ops [] = { -+ {"-r", FILRD, UNOP}, -+ {"-w", FILWR, UNOP}, -+ {"-x", FILEX, UNOP}, -+ {"-e", FILEXIST,UNOP}, -+ {"-f", FILREG, UNOP}, -+ {"-d", FILDIR, UNOP}, -+ {"-c", FILCDEV,UNOP}, -+ {"-b", FILBDEV,UNOP}, -+ {"-p", FILFIFO,UNOP}, -+ {"-u", FILSUID,UNOP}, -+ {"-g", FILSGID,UNOP}, -+ {"-k", FILSTCK,UNOP}, -+ {"-s", FILGZ, UNOP}, -+ {"-t", FILTT, UNOP}, -+ {"-z", STREZ, UNOP}, -+ {"-n", STRNZ, UNOP}, -+ {"-h", FILSYM, UNOP}, /* for backwards compat */ -+ {"-O", FILUID, UNOP}, -+ {"-G", FILGID, UNOP}, -+ {"-L", FILSYM, UNOP}, -+ {"-S", FILSOCK,UNOP}, -+ {"=", STREQ, BINOP}, -+ {"!=", STRNE, BINOP}, -+ {"<", STRLT, BINOP}, -+ {">", STRGT, BINOP}, -+ {"-eq", INTEQ, BINOP}, -+ {"-ne", INTNE, BINOP}, -+ {"-ge", INTGE, BINOP}, -+ {"-gt", INTGT, BINOP}, -+ {"-le", INTLE, BINOP}, -+ {"-lt", INTLT, BINOP}, -+ {"-nt", FILNT, BINOP}, -+ {"-ot", FILOT, BINOP}, -+ {"-ef", FILEQ, BINOP}, -+ {"!", UNOT, BUNOP}, -+ {"-a", BAND, BBINOP}, -+ {"-o", BOR, BBINOP}, -+ {"(", LPAREN, PAREN}, -+ {")", RPAREN, PAREN}, -+ {0, 0, 0} -+}; -+ -+static char **t_wp; -+static struct t_op const *t_wp_op; -+ -+static void syntax(const char *, const char *); -+static int oexpr(enum token); -+static int aexpr(enum token); -+static int nexpr(enum token); -+static int primary(enum token); -+static int binop(void); -+static int filstat(char *, enum token); -+static enum token t_lex(char *); -+static int isoperand(void); -+static int getn(const char *); -+static int newerf(const char *, const char *); -+static int olderf(const char *, const char *); -+static int equalf(const char *, const char *); -+static int test_eaccess(const char *, int); -+static int bash_group_member(gid_t); -+ -+#ifndef SHELL -+static void error(const char *, ...) __attribute__((__noreturn__)); -+ -+static void -+error(const char *msg, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, msg); -+ verrx(2, msg, ap); -+ /*NOTREACHED*/ -+ va_end(ap); -+} -+#endif -+ -+#ifdef SHELL -+int testcmd(int, char **); -+ -+int -+testcmd(int argc, char **argv) -+#else -+int main(int, char *[]); -+ -+int -+main(int argc, char *argv[]) -+#endif -+{ -+ int res; -+ -+#ifndef SHELL -+ setprogname(argv[0]); -+#endif -+ if (strcmp(argv[0], "[") == 0) { -+ if (strcmp(argv[--argc], "]")) -+ error("missing ]"); -+ argv[argc] = NULL; -+ } -+ -+ if (argc < 2) -+ return 1; -+ -+ t_wp = &argv[1]; -+ res = !oexpr(t_lex(*t_wp)); -+ -+ if (*t_wp != NULL && *++t_wp != NULL) -+ syntax(*t_wp, "unexpected operator"); -+ -+ return res; -+} -+ -+static void -+syntax(const char *op, const char *msg) -+{ -+ if (op && *op) -+ error("%s: %s", op, msg); -+ else -+ error("%s", msg); -+} -+ -+static int -+oexpr(enum token n) -+{ -+ int res; -+ -+ res = aexpr(n); -+ if (t_lex(*++t_wp) == BOR) -+ return oexpr(t_lex(*++t_wp)) || res; -+ t_wp--; -+ return res; -+} -+ -+static int -+aexpr(enum token n) -+{ -+ int res; -+ -+ res = nexpr(n); -+ if (t_lex(*++t_wp) == BAND) -+ return aexpr(t_lex(*++t_wp)) && res; -+ t_wp--; -+ return res; -+} -+ -+static int -+nexpr(enum token n) -+{ -+ if (n == UNOT) -+ return !nexpr(t_lex(*++t_wp)); -+ return primary(n); -+} -+ -+static int -+primary(enum token n) -+{ -+ enum token nn; -+ int res; -+ -+ if (n == EOI) -+ return 0; /* missing expression */ -+ if (n == LPAREN) { -+ if ((nn = t_lex(*++t_wp)) == RPAREN) -+ return 0; /* missing expression */ -+ res = oexpr(nn); -+ if (t_lex(*++t_wp) != RPAREN) -+ syntax(NULL, "closing paren expected"); -+ return res; -+ } -+ if (t_wp_op && t_wp_op->op_type == UNOP) { -+ /* unary expression */ -+ if (*++t_wp == NULL) -+ syntax(t_wp_op->op_text, "argument expected"); -+ switch (n) { -+ case STREZ: -+ return strlen(*t_wp) == 0; -+ case STRNZ: -+ return strlen(*t_wp) != 0; -+ case FILTT: -+ return isatty(getn(*t_wp)); -+ default: -+ return filstat(*t_wp, n); -+ } -+ } -+ -+ if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { -+ return binop(); -+ } -+ -+ return strlen(*t_wp) > 0; -+} -+ -+static int -+binop(void) -+{ -+ const char *opnd1, *opnd2; -+ struct t_op const *op; -+ -+ opnd1 = *t_wp; -+ (void) t_lex(*++t_wp); -+ op = t_wp_op; -+ -+ if ((opnd2 = *++t_wp) == (char *)0) -+ syntax(op->op_text, "argument expected"); -+ -+ switch (op->op_num) { -+ case STREQ: -+ return strcmp(opnd1, opnd2) == 0; -+ case STRNE: -+ return strcmp(opnd1, opnd2) != 0; -+ case STRLT: -+ return strcmp(opnd1, opnd2) < 0; -+ case STRGT: -+ return strcmp(opnd1, opnd2) > 0; -+ case INTEQ: -+ return getn(opnd1) == getn(opnd2); -+ case INTNE: -+ return getn(opnd1) != getn(opnd2); -+ case INTGE: -+ return getn(opnd1) >= getn(opnd2); -+ case INTGT: -+ return getn(opnd1) > getn(opnd2); -+ case INTLE: -+ return getn(opnd1) <= getn(opnd2); -+ case INTLT: -+ return getn(opnd1) < getn(opnd2); -+ case FILNT: -+ return newerf (opnd1, opnd2); -+ case FILOT: -+ return olderf (opnd1, opnd2); -+ case FILEQ: -+ return equalf (opnd1, opnd2); -+ default: -+ abort(); -+ /* NOTREACHED */ -+ } -+} -+ -+static int -+filstat(char *nm, enum token mode) -+{ -+ struct stat64 s; -+ -+ if (mode == FILSYM ? lstat64(nm, &s) : stat64(nm, &s)) -+ return 0; -+ -+ switch (mode) { -+ case FILRD: -+ return test_eaccess(nm, R_OK) == 0; -+ case FILWR: -+ return test_eaccess(nm, W_OK) == 0; -+ case FILEX: -+ return test_eaccess(nm, X_OK) == 0; -+ case FILEXIST: -+ return 1; -+ case FILREG: -+ return S_ISREG(s.st_mode); -+ case FILDIR: -+ return S_ISDIR(s.st_mode); -+ case FILCDEV: -+ return S_ISCHR(s.st_mode); -+ case FILBDEV: -+ return S_ISBLK(s.st_mode); -+ case FILFIFO: -+ return S_ISFIFO(s.st_mode); -+ case FILSOCK: -+ return S_ISSOCK(s.st_mode); -+ case FILSYM: -+ return S_ISLNK(s.st_mode); -+ case FILSUID: -+ return (s.st_mode & S_ISUID) != 0; -+ case FILSGID: -+ return (s.st_mode & S_ISGID) != 0; -+ case FILSTCK: -+ return (s.st_mode & S_ISVTX) != 0; -+ case FILGZ: -+ return s.st_size > (off_t)0; -+ case FILUID: -+ return s.st_uid == geteuid(); -+ case FILGID: -+ return s.st_gid == getegid(); -+ default: -+ return 1; -+ } -+} -+ -+static enum token -+t_lex(char *s) -+{ -+ struct t_op const *op; -+ -+ op = ops; -+ -+ if (s == 0) { -+ t_wp_op = (struct t_op *)0; -+ return EOI; -+ } -+ while (op->op_text) { -+ if (strcmp(s, op->op_text) == 0) { -+ if ((op->op_type == UNOP && isoperand()) || -+ (op->op_num == LPAREN && *(t_wp+1) == 0)) -+ break; -+ t_wp_op = op; -+ return op->op_num; -+ } -+ op++; -+ } -+ t_wp_op = (struct t_op *)0; -+ return OPERAND; -+} -+ -+static int -+isoperand(void) -+{ -+ struct t_op const *op; -+ char *s, *t; -+ -+ op = ops; -+ if ((s = *(t_wp+1)) == 0) -+ return 1; -+ if ((t = *(t_wp+2)) == 0) -+ return 0; -+ while (op->op_text) { -+ if (strcmp(s, op->op_text) == 0) -+ return op->op_type == BINOP && -+ (t[0] != ')' || t[1] != '\0'); -+ op++; -+ } -+ return 0; -+} -+ -+/* atoi with error detection */ -+static int -+getn(const char *s) -+{ -+ char *p; -+ long r; -+ -+ errno = 0; -+ r = strtol(s, &p, 10); -+ -+ if (errno != 0) -+ error("%s: out of range", s); -+ -+ while (isspace((unsigned char)*p)) -+ p++; -+ -+ if (*p) -+ error("%s: bad number", s); -+ -+ return (int) r; -+} -+ -+static int -+newerf (const char *f1, const char *f2) -+{ -+ struct stat b1, b2; -+ -+ return (stat (f1, &b1) == 0 && -+ stat (f2, &b2) == 0 && -+ b1.st_mtime > b2.st_mtime); -+} -+ -+static int -+olderf (const char *f1, const char *f2) -+{ -+ struct stat b1, b2; -+ -+ return (stat (f1, &b1) == 0 && -+ stat (f2, &b2) == 0 && -+ b1.st_mtime < b2.st_mtime); -+} -+ -+static int -+equalf (const char *f1, const char *f2) -+{ -+ struct stat b1, b2; -+ -+ return (stat (f1, &b1) == 0 && -+ stat (f2, &b2) == 0 && -+ b1.st_dev == b2.st_dev && -+ b1.st_ino == b2.st_ino); -+} -+ -+/* Do the same thing access(2) does, but use the effective uid and gid, -+ and don't make the mistake of telling root that any file is -+ executable. */ -+static int -+test_eaccess(const char *path, int mode) -+{ -+ struct stat64 st; -+ int euid = geteuid(); -+ -+ if (stat64(path, &st) < 0) -+ return (-1); -+ -+ if (euid == 0) { -+ /* Root can read or write any file. */ -+ if (mode != X_OK) -+ return (0); -+ -+ /* Root can execute any file that has any one of the execute -+ bits set. */ -+ if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) -+ return (0); -+ } -+ -+ if (st.st_uid == euid) /* owner */ -+ mode <<= 6; -+ else if (bash_group_member(st.st_gid)) -+ mode <<= 3; -+ -+ if (st.st_mode & mode) -+ return (0); -+ -+ return (-1); -+} -+ -+/* Return non-zero if GID is one that we have in our groups list. */ -+static int -+bash_group_member(gid_t gid) -+{ -+ register int i; -+ gid_t *group_array; -+ int ngroups; -+ -+ /* Short-circuit if possible, maybe saving a call to getgroups(). */ -+ if (gid == getgid() || gid == getegid()) -+ return (1); -+ -+ ngroups = getgroups(0, NULL); -+#ifdef SHELL -+ group_array = stalloc(ngroups * sizeof(gid_t)); -+#else -+ group_array = alloca(ngroups * sizeof(gid_t)); -+#endif -+ getgroups(ngroups, group_array); -+ -+ /* Search through the list looking for GID. */ -+ for (i = 0; i < ngroups; i++) -+ if (gid == group_array[i]) -+ return (1); -+ -+ return (0); -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/bltin/times.c bin_NetBSD-1.6release/src/bin/sh/bltin/times.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/bltin/times.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/bltin/times.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (c) 1999 Herbert Xu <herbert@debian.org> -+ * This file contains code for the times builtin. -+ * $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -+ */ -+ -+#include <sys/times.h> -+#include <unistd.h> -+#ifdef USE_GLIBC_STDIO -+#include <stdio.h> -+#else -+#include "bltin.h" -+#endif -+ -+#define main timescmd -+ -+int main() { -+ struct tms buf; -+ long int clk_tck = sysconf(_SC_CLK_TCK); -+ -+ times(&buf); -+ printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", -+ (int) (buf.tms_utime / clk_tck / 60), -+ ((double) buf.tms_utime) / clk_tck, -+ (int) (buf.tms_stime / clk_tck / 60), -+ ((double) buf.tms_stime) / clk_tck, -+ (int) (buf.tms_cutime / clk_tck / 60), -+ ((double) buf.tms_cutime) / clk_tck, -+ (int) (buf.tms_cstime / clk_tck / 60), -+ ((double) buf.tms_cstime) / clk_tck); -+ return 0; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/builtins.def bin_NetBSD-1.6release/src/bin/sh/builtins.def ---- bin_NetBSD-1.6release.orig/src/bin/sh/builtins.def 2000-04-10 12:02:58.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/builtins.def 2003-02-08 14:35:42.000000000 +0000 -@@ -49,12 +49,13 @@ - # - # NOTE: bltincmd must come first! - --bltincmd command -+bltincmd builtin - #alloccmd alloc - bgcmd -j bg - breakcmd break continue - #catfcmd catf - cdcmd cd chdir -+commandcmd command - dotcmd . - echocmd echo - evalcmd eval -@@ -68,12 +69,13 @@ - fgcmd -j fg - getoptscmd getopts - hashcmd hash --jobidcmd jobid -+#jobidcmd jobid - jobscmd jobs -+killcmd -j kill - #linecmd line - localcmd local - #nlechocmd nlecho --#printfcmd printf -+printfcmd printf - pwdcmd pwd - readcmd read - returncmd return -@@ -91,3 +93,4 @@ - aliascmd alias - ulimitcmd ulimit - testcmd test [ -+timescmd times -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/cd.c bin_NetBSD-1.6release/src/bin/sh/cd.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/cd.c 2001-11-15 11:08:17.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/cd.c 2003-02-08 14:35:42.000000000 +0000 -@@ -70,13 +70,33 @@ - #include "show.h" - #include "cd.h" - --STATIC int docd __P((char *, int)); --STATIC char *getcomponent __P((void)); --STATIC void updatepwd __P((char *)); -+#define CD_PHYSICAL 1 -+#define CD_PRINT 2 - --char *curdir = NULL; /* current working directory */ --char *prevdir; /* previous working directory */ --STATIC char *cdcomppath; -+STATIC int docd __P((const char *, int)); -+STATIC const char *updatepwd __P((const char *)); -+STATIC char *getpwd __P((void)); -+STATIC int cdopt __P((void)); -+ -+STATIC char *curdir = nullstr; /* current working directory */ -+STATIC char *physdir = nullstr; /* physical working directory */ -+ -+STATIC int -+cdopt() -+{ -+ int flags = 0; -+ int i, j; -+ -+ j = 'L'; -+ while ((i = nextopt("LP"))) { -+ if (i != j) { -+ flags ^= CD_PHYSICAL; -+ j = i; -+ } -+ } -+ -+ return flags; -+} - - int - cdcmd(argc, argv) -@@ -85,296 +105,218 @@ - { - const char *dest; - const char *path; -- char *p; -+ const char *p; -+ char c; - struct stat statb; -- int print = 0; -+ int flags; - -- nextopt(nullstr); -- if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL) -- error("HOME not set"); -- if (*dest == '\0') -- dest = "."; -- if (dest[0] == '-' && dest[1] == '\0') { -- dest = prevdir ? prevdir : curdir; -- print = 1; -- if (dest) -- print = 1; -- else -- dest = "."; -+ flags = cdopt(); -+ dest = *argptr; -+ if (!dest) -+ dest = bltinlookup(homestr); -+ else if (dest[0] == '-' && dest[1] == '\0') { -+ dest = bltinlookup("OLDPWD"); -+ flags |= CD_PRINT; -+ goto step7; - } -- if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL) -- path = nullstr; -- while ((p = padvance(&path, dest)) != NULL) { -- if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { -- if (!print) { -- /* -- * XXX - rethink -- */ -- if (p[0] == '.' && p[1] == '/' && p[2] != '\0') -- p += 2; -- print = strcmp(p, dest); -+ if (!dest) -+ dest = nullstr; -+ if (*dest == '/') -+ goto step7; -+ if (*dest == '.') { -+ c = dest[1]; -+dotdot: -+ switch (c) { -+ case '\0': -+ case '/': -+ goto step6; -+ case '.': -+ c = dest[2]; -+ if (c != '.') -+ goto dotdot; - } -- if (docd(p, print) >= 0) -- return 0; -- - } -+ if (!*dest) -+ dest = "."; -+ if (!(path = bltinlookup("CDPATH"))) { -+step6: -+step7: -+ p = dest; -+ goto docd; -+ } -+ do { -+ c = *path; -+ p = padvance(&path, dest); -+ if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { -+ if (c && c != ':') -+ flags |= CD_PRINT; -+docd: -+ if (!docd(p, flags)) -+ goto out; -+ break; - } -+ } while (path); - error("can't cd to %s", dest); - /* NOTREACHED */ -+out: -+ if (flags & CD_PRINT) -+ out1fmt(snlfmt, curdir); -+ return 0; - } - - - /* -- * Actually do the chdir. In an interactive shell, print the -- * directory name if "print" is nonzero. -+ * Actually do the chdir. We also call hashcd to let the routines in exec.c -+ * know that the current directory has changed. - */ - - STATIC int --docd(dest, print) -- char *dest; -- int print; -+docd(const char *dest, int flags) - { -- char *p; -- char *q; -- char *component; -- struct stat statb; -- int first; -- int badstat; -- -- TRACE(("docd(\"%s\", %d) called\n", dest, print)); -+ const char *dir = 0; -+ int err; - -- /* -- * Check each component of the path. If we find a symlink or -- * something we can't stat, clear curdir to force a getcwd() -- * next time we get the value of the current directory. -- */ -- badstat = 0; -- cdcomppath = stalloc(strlen(dest) + 1); -- scopy(dest, cdcomppath); -- STARTSTACKSTR(p); -- if (*dest == '/') { -- STPUTC('/', p); -- cdcomppath++; -- } -- first = 1; -- while ((q = getcomponent()) != NULL) { -- if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) -- continue; -- if (! first) -- STPUTC('/', p); -- first = 0; -- component = q; -- while (*q) -- STPUTC(*q++, p); -- if (equal(component, "..")) -- continue; -- STACKSTRNUL(p); -- if ((lstat(stackblock(), &statb) < 0) -- || (S_ISLNK(statb.st_mode))) { -- /* print = 1; */ -- badstat = 1; -- break; -- } -- } -+ TRACE(("docd(\"%s\", %d) called\n", dest, flags)); - - INTOFF; -- if (chdir(dest) < 0) { -- INTON; -- return -1; -+ if (!(flags & CD_PHYSICAL)) { -+ dir = updatepwd(dest); -+ if (dir) -+ dest = dir; - } -- updatepwd(badstat ? NULL : dest); -+ err = chdir(dest); -+ if (err) -+ goto out; -+ setpwd(dir, 1); -+ hashcd(); -+out: - INTON; -- if (print && iflag && curdir) -- out1fmt("%s\n", curdir); -- return 0; --} -- -- --/* -- * Get the next component of the path name pointed to by cdcomppath. -- * This routine overwrites the string pointed to by cdcomppath. -- */ -- --STATIC char * --getcomponent() { -- char *p; -- char *start; -- -- if ((p = cdcomppath) == NULL) -- return NULL; -- start = cdcomppath; -- while (*p != '/' && *p != '\0') -- p++; -- if (*p == '\0') { -- cdcomppath = NULL; -- } else { -- *p++ = '\0'; -- cdcomppath = p; -- } -- return start; -+ return err; - } - - -- - /* - * Update curdir (the name of the current directory) in response to a -- * cd command. We also call hashcd to let the routines in exec.c know -- * that the current directory has changed. -+ * cd command. - */ - --STATIC void --updatepwd(dir) -- char *dir; -- { -+STATIC const char * -+updatepwd(const char *dir) -+{ - char *new; - char *p; -+ char *cdcomppath; -+ const char *lim; - -- hashcd(); /* update command hash table */ -- -- /* -- * If our argument is NULL, we don't know the current directory -- * any more because we traversed a symbolic link or something -- * we couldn't stat(). -- */ -- if (dir == NULL || curdir == NULL) { -- if (prevdir) -- ckfree(prevdir); -- INTOFF; -- prevdir = curdir; -- curdir = NULL; -- getpwd(); -- setvar("PWD", curdir, VEXPORT); -- INTON; -- return; -- } -- cdcomppath = stalloc(strlen(dir) + 1); -- scopy(dir, cdcomppath); -+ cdcomppath = sstrdup(dir); - STARTSTACKSTR(new); - if (*dir != '/') { -- p = curdir; -- while (*p) -- STPUTC(*p++, new); -- if (p[-1] == '/') -+ if (curdir == nullstr) -+ return 0; -+ new = stputs(curdir, new); -+ } -+ new = makestrspace(strlen(dir) + 2, new); -+ lim = stackblock() + 1; -+ if (*dir != '/') { -+ if (new[-1] != '/') -+ USTPUTC('/', new); -+ if (new > lim && *lim == '/') -+ lim++; -+ } else { -+ USTPUTC('/', new); -+ cdcomppath++; -+ if (dir[1] == '/' && dir[2] != '/') { -+ USTPUTC('/', new); -+ cdcomppath++; -+ lim++; -+ } -+ } -+ p = strtok(cdcomppath, "/"); -+ while (p) { -+ switch(*p) { -+ case '.': -+ if (p[1] == '.' && p[2] == '\0') { -+ while (new > lim) { - STUNPUTC(new); -+ if (new[-1] == '/') -+ break; - } -- while ((p = getcomponent()) != NULL) { -- if (equal(p, "..")) { -- while (new > stackblock() && (STUNPUTC(new), *new) != '/'); -- } else if (*p != '\0' && ! equal(p, ".")) { -- STPUTC('/', new); -- while (*p) -- STPUTC(*p++, new); -+ break; -+ } else if (p[1] == '\0') -+ break; -+ /* fall through */ -+ default: -+ new = stputs(p, new); -+ USTPUTC('/', new); - } -+ p = strtok(0, "/"); - } -- if (new == stackblock()) -- STPUTC('/', new); -- STACKSTRNUL(new); -- INTOFF; -- if (prevdir) -- ckfree(prevdir); -- prevdir = curdir; -- curdir = savestr(stackblock()); -- setvar("PWD", curdir, VEXPORT); -- INTON; -+ if (new > lim) -+ STUNPUTC(new); -+ *new = 0; -+ return stackblock(); - } - - -+#define MAXPWD 256 -+ -+/* -+ * Find out what the current directory is. If we already know the current -+ * directory, this routine returns immediately. -+ */ -+inline -+STATIC char * -+getpwd() -+{ -+ char *dir = getcwd(0, 0); -+ return dir ? dir : nullstr; -+} - - int - pwdcmd(argc, argv) - int argc; - char **argv; - { -- getpwd(); -- out1str(curdir); -- out1c('\n'); -+ int flags; -+ const char *dir = curdir; -+ -+ flags = cdopt(); -+ if (flags) { -+ if (physdir == nullstr) -+ setpwd(dir, 0); -+ dir = physdir; -+ } -+ out1fmt(snlfmt, dir); - return 0; - } - -- -- -- --#define MAXPWD 256 -- --/* -- * Find out what the current directory is. If we already know the current -- * directory, this routine returns immediately. -- */ - void --getpwd() -+setpwd(const char *val, int setold) - { -- char buf[MAXPWD]; -- -- if (curdir) -- return; -- /* -- * Things are a bit complicated here; we could have just used -- * getcwd, but traditionally getcwd is implemented using popen -- * to /bin/pwd. This creates a problem for us, since we cannot -- * keep track of the job if it is being ran behind our backs. -- * So we re-implement getcwd(), and we suppress interrupts -- * throughout the process. This is not completely safe, since -- * the user can still break out of it by killing the pwd program. -- * We still try to use getcwd for systems that we know have a -- * c implementation of getcwd, that does not open a pipe to -- * /bin/pwd. -- */ --#if defined(__NetBSD__) || defined(__SVR4) -+ char *oldcur, *dir; - -- if (getcwd(buf, sizeof(buf)) == NULL) { -- char *pwd = getenv("PWD"); -- struct stat stdot, stpwd; -+ oldcur = dir = curdir; - -- if (pwd && *pwd == '/' && stat(".", &stdot) != -1 && -- stat(pwd, &stpwd) != -1 && -- stdot.st_dev == stpwd.st_dev && -- stdot.st_ino == stpwd.st_ino) { -- curdir = savestr(pwd); -- return; -- } -- error("getcwd() failed: %s", strerror(errno)); -+ if (setold) { -+ setvar("OLDPWD", oldcur, VEXPORT); - } -- curdir = savestr(buf); --#else -- { -- char *p; -- int i; -- int status; -- struct job *jp; -- int pip[2]; -- - INTOFF; -- if (pipe(pip) < 0) -- error("Pipe call failed"); -- jp = makejob((union node *)NULL, 1); -- if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) { -- (void) close(pip[0]); -- if (pip[1] != 1) { -- close(1); -- copyfd(pip[1], 1); -- close(pip[1]); -- } -- (void) execl("/bin/pwd", "pwd", (char *)0); -- error("Cannot exec /bin/pwd"); -- } -- (void) close(pip[1]); -- pip[1] = -1; -- p = buf; -- while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0 -- || (i == -1 && errno == EINTR)) { -- if (i > 0) -- p += i; -+ if (physdir != nullstr) { -+ if (physdir != oldcur) -+ free(physdir); -+ physdir = nullstr; - } -- (void) close(pip[0]); -- pip[0] = -1; -- status = waitforjob(jp); -- if (status != 0) -- error((char *)0); -- if (i < 0 || p == buf || p[-1] != '\n') -- error("pwd command failed"); -- p[-1] = '\0'; -+ if (oldcur == val || !val) { -+ char *s = getpwd(); -+ physdir = s; -+ if (!val) -+ dir = s; -+ } else -+ dir = savestr(val); -+ if (oldcur != dir && oldcur != nullstr) { -+ free(oldcur); - } -- curdir = savestr(buf); -+ curdir = dir; - INTON; --#endif -+ setvar("PWD", dir, VEXPORT); - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/cd.h bin_NetBSD-1.6release/src/bin/sh/cd.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/cd.h 1997-07-05 12:12:27.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/cd.h 2003-02-08 14:35:42.000000000 +0000 -@@ -34,6 +34,6 @@ - * - */ - --void getpwd __P((void)); - int cdcmd __P((int, char **)); - int pwdcmd __P((int, char **)); -+void setpwd __P((const char *, int)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/ash.dirs bin_NetBSD-1.6release/src/bin/sh/debian/ash.dirs ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/ash.dirs 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/ash.dirs 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,2 @@ -+bin -+usr/share/man/man1 -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/ash.postinst bin_NetBSD-1.6release/src/bin/sh/debian/ash.postinst ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/ash.postinst 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/ash.postinst 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,54 @@ -+#!/bin/sh -+# -+# post-install script for the Debian GNU/Linux ash package -+# -+# $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -+ -+set -e -+ -+check_divert() { -+ div=$(dpkg-divert --list $1) -+ distrib=${3:-$1.distrib} -+ case $div in -+ '' | *by\ dash) -+ ;; -+ *by\ ash) -+ dst=${div% by ash} -+ dst=${dst##* to } -+ -+ # Work around dpkg-divert bug. -+ if [ -e "$dst" ]; then -+ mv "$dst" "$dst.ash-tmp" -+ fi -+ dpkg-divert --remove $1 -+ if [ -e "$dst.ash-tmp" ]; then -+ mv "$dst.ash-tmp" "$dst" -+ fi -+ -+ dpkg-divert --package dash --divert $distrib --add $1 -+ if [ "$dst" != $distrib ] && [ -e "$dst" ]; then -+ mv "$dst" $distrib -+ fi -+ ln -sf $2 $1 -+ ;; -+ *) -+ d=${1%/*} -+ if -+ [ -h $1 ] && [ -f $1 ] && [ -f $d/$4 ] && -+ cmp $1 $d/$4 -+ then -+ ln -sf $2 $1 -+ fi -+ ;; -+ esac -+} -+ -+dcv='dpkg --compare-versions' -+ -+if [ "$1" = configure ] && [ -n "$2" ] && $dcv "$2" lt 0.4.3; then -+ check_divert /bin/sh dash '' ash -+ check_divert /usr/share/man/man1/sh.1.gz dash.1.gz \ -+ /usr/share/man/man1/sh.distrib.1.gz ash.1.gz -+fi -+ -+#DEBHELPER# -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/bsdyacc bin_NetBSD-1.6release/src/bin/sh/debian/bsdyacc ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/bsdyacc 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/bsdyacc 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,20 @@ -+#!/bin/sh -e -+ -+if echo "$@" | grep -q -- -o; then -+ OUTPUT=$(echo "$@" | -+ sed 's/.*-o[[:blank:]]\+\([^[:blank:]]\+\)\.c.*/\1/') -+ OPTIONS=$(echo "$@" | -+ sed 's/\(.*\)-o[[:blank:]]\+[^[:blank:]]\+\(.*\)/\1\2/') -+ NEW=1 -+else -+ OUTPUT=$(echo "$@" | -+ sed -e 's/.*[[:blank:]]\+\([^[:blank:]]\+\)\.y.*/\1/') -+ OPTIONS="$@" -+ NEW=0 -+fi -+ -+byacc $OPTIONS -+if [ $NEW = 1 ]; then -+ mv y.tab.c $OUTPUT.c -+fi -+mv y.tab.h $OUTPUT.h -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/changelog bin_NetBSD-1.6release/src/bin/sh/debian/changelog ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/changelog 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/changelog 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,868 @@ -+dash (0.4.10) unstable; urgency=low -+ -+ * Fixed redirection fd leak when execing. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 19 Jan 2003 13:25:41 +1100 -+ -+dash (0.4.9) unstable; urgency=low -+ -+ * Reset exitstatus in evalsubshell if backgnd is true. -+ * Fixed glibc glob syntax error in expand.c. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 11 Jan 2003 16:04:02 +1100 -+ -+dash (0.4.8) unstable; urgency=low -+ -+ * Removed backgnd flag from ncmd due to previous redirection change. -+ * Set lim after the stack stablises in updatepwd (closes: #173884). -+ * Do not clobber the exitstatus after redirection. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 23 Dec 2002 19:50:06 +1100 -+ -+dash (0.4.7) unstable; urgency=low -+ -+ * Merged clearredir with reset code in redir.c. -+ * Redirect before command search in evalcommand (closes: #168862). -+ * Build binary-all packages in binary-indep (closes: #173191). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 21 Dec 2002 13:52:37 +1100 -+ -+dash (0.4.6) unstable; urgency=low -+ -+ * Restored code for leaving job control. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 8 Dec 2002 15:21:58 +1100 -+ -+dash (0.4.5) unstable; urgency=low -+ -+ * Optimised doformat so that vsnprintf is usually called only once. -+ * Reset redirlist in clearredir so that popredir can work (closes: #170247). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 23 Nov 2002 22:09:59 +1100 -+ -+dash (0.4.4) unstable; urgency=low -+ -+ * Fixed duplicate define warnings in init.c. -+ * Set debhelper compat to 4. -+ * Vanishing mail boxes no longer elicit "you have mail" messages. -+ * Function redirection errors no longer abort the shell. -+ * Fixed potential memory leak in redirect. -+ * Only allocate memory if necessary in redirect. -+ * Reap dead here documents. -+ * Do not strdup default values of static shell variables. -+ * Removed unnecessary setprompt(0) calls. -+ * Read in BUFSIZ chunks rather than BUFSIZ - 1. -+ * Documented undefined escape behaviour for echo(1) (closes: #167893). -+ * Do va_copy when we use a va_list twice (closes: #169503). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 20 Nov 2002 19:48:31 +1100 -+ -+dash (0.4.3) unstable; urgency=low -+ -+ * Added manual entry for PPID. -+ * Exporting an unset variable no longer causes it to be set. -+ * Fixed fd0 redirection in asynchronous lists. -+ * Only stat if necessary in cdcmd (see #42880). -+ * Removed extra newline in error message in arith lexer. -+ * Set heredoclist to 0 ASAP in parseheredoc. -+ * Removed BSD advertising clause from copyright file. -+ * Check non-ash diversions as well in dash.postinst. -+ * Duplicated diversion checking in ash.postinst (closes: #166441). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 26 Oct 2002 21:28:33 +1000 -+ -+dash (0.4.2) unstable; urgency=low -+ -+ * Give benefits of dash in templates (closes: #161527). -+ * Fixed signed/unsigned on result of xwrite (closes: #161606). -+ * Removed support for SIG prefixes in kill and trap. -+ * Added -- processing in trap. -+ * Dropped use of unset in postinst (closes: 161868). -+ * Fixed printf(1) %* processing on bad integers and zero. -+ * Use stat64 in test(1). -+ * Allocate group_array with stalloc in test(1). -+ * Disabled alias checking after a pattern in a case statement. -+ * Wait now returns 128 + last trapped signal. -+ * Printf now keeps going after errors. -+ * Empty non-trivial parameter expansions are now removed correctly. -+ * Call reset() before exitshell() is called. This fixes the bug where -+ returning an error from a function running under set -e caused the exit -+ trap to be taken with evalskip set. -+ * Fixed quoting of empty strings in single_quote(). -+ * Show line numbers on all errors. -+ * Function names must be valid identifiers. -+ * Removed unused dependency on groff. -+ * Fixed race condition before entering a function. -+ * Fixed getopts initialisation for functions. -+ * Added memory barriers in INT macros. -+ * Banned empty compound lists in most places. -+ * Keep usage counters on functions (closes: #164234). -+ * Updated copyright file. -+ * Check evalskip in evalstring (closes: #165056). -+ * Merged changes from NetBSD 1.6: -+ . Added intmax support in printf(1). -+ . Implemented set -u. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 19 Oct 2002 14:23:11 +1000 -+ -+dash (0.4.1) unstable; urgency=low -+ -+ * Removed extra new line in command -v output for aliases. -+ * Removed alais prefix in the output of alias. -+ * Recognise octal and hex numbers in arith expansion (closes: #151449). -+ * Added sh(1) entries for echo, printf and test (closes: #156446). -+ * Renamed to dash --- the Debian Almquist Shell. -+ * Cleaned up rules file (Matej Vela). -+ * Check mtime instead of size in chkmail per POSIX. -+ * Added support for LFS (closes: #157884). -+ * Added SuS options to cd and pwd (closes: #145828). -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 13 Sep 2002 20:35:06 +1000 -+ -+ash (0.3.8-38) unstable; urgency=low -+ -+ * Turned pre-dependency to dependency in udeb since the former is not allowed -+ (closes: #143749). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 28 Apr 2002 11:59:05 +1000 -+ -+ash (0.3.8-37) unstable; urgency=low -+ -+ * Added Japanese debconf translation (Tomohiro KUBOTA, closes: #137431). -+ * Added missing escapes in manual page (Aaron Schrab, closes: #137966). -+ * Added Russian debconf translation (Ilgiz Kalmetev, closes: #137618). -+ * Fixed trap(1) documentation (closes: #140973). -+ * Do not abort if getcwd fails. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 3 Apr 2002 20:58:09 +1000 -+ -+ash (0.3.8-36) unstable; urgency=low -+ -+ * Added library dependency for ash-udeb. -+ * Handle null case statements correctly. -+ * Fixed alias expansions in case statements (NetBSD). -+ * Disabled unused jobid command. -+ * Corrected documentation about shifting too much. -+ * Added French debconf translation (Denis Barbier, closes: #134625). -+ * Updated Spanish debconf translation (Carlos Valdivia, closes: #136366). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 2 Mar 2002 18:31:22 +1100 -+ -+ash (0.3.8-35) unstable; urgency=low -+ -+ * Moved PWD initialisation into var.c (closes: #124032). -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 24 Dec 2001 09:34:55 +1100 -+ -+ash (0.3.8-34) unstable; urgency=low -+ -+ * NSEMI must be NOR + 1. -+ * Set exitstatus to zero before evaluating cases (closes: #124066). -+ * Explicitly set default answer of the ash/sh question to false so that -+ people whose debconf priority is set to low and who keeps banging on their -+ keyboards don't accidently end up with ash as /bin/sh. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 21 Dec 2001 20:30:49 +1100 -+ -+ash (0.3.8-33) unstable; urgency=low -+ -+ * Added missing inclusion of bltin.h in bltin/times.c. -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 13 Dec 2001 18:46:07 +1100 -+ -+ash (0.3.8-32) unstable; urgency=low -+ -+ * Back slashes in expansions are now escaped (closes: #121516). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 28 Nov 2001 20:15:01 +1100 -+ -+ash (0.3.8-31) unstable; urgency=low -+ -+ * Made sure all back slashes are escaped. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 26 Nov 2001 19:10:27 +1100 -+ -+ash (0.3.8-30) unstable; urgency=low -+ -+ * Restored fnmatch(3) code. -+ * Treat escaped slashes correctly while globbing. -+ * Restored missing EV_EXIT check in evalcommand (closes: #120364). -+ * Fixed stack corruption in _rmescapes. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 25 Nov 2001 17:51:19 +1100 -+ -+ash (0.3.8-29) unstable; urgency=low -+ -+ * Added missing va_end in fmtstr (NetBSD). -+ * Removed shellproc crap. -+ * Updated Swedish debconf translation (Mikael Hedin, closes: #116097). -+ * Updated German debconf translation (Andreas Metzler, closes: #117160). -+ * Break now treats illegal numbers according to SuS. -+ * Errors in special builtins now rise to the top. -+ * Normal redirection errors no longer abort the shell. -+ * Functions now have the same variable assignment properties as special -+ builtins. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 3 Nov 2001 11:36:36 +1100 -+ -+ash (0.3.8-28) unstable; urgency=low -+ -+ * Local variables are now unset properly in shprocvar() (closes: #114917). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 13 Oct 2001 14:07:21 +1000 -+ -+ash (0.3.8-27) unstable; urgency=low -+ -+ * Kill no longer aborts if it fails to kill someone. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 30 Sep 2001 22:20:36 +1000 -+ -+ash (0.3.8-26) unstable; urgency=low -+ -+ * The sh.1.gz diversion now agrees with reality (closes: #113831). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 29 Sep 2001 08:43:27 +1000 -+ -+ash (0.3.8-25) unstable; urgency=low -+ -+ * Only read ENV if the shell is interactive (closes: #110421). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 29 Aug 2001 19:18:53 +1000 -+ -+ash (0.3.8-24) unstable; urgency=low -+ -+ * Handle SIGINT when waiting even if there is no trap (closes: #107699). -+ * Protect all makejob/forkshell/waitforjobs sequences from SIGINT. -+ * Work around gcc bug that generates bad ..ng references (closes: #107994). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 8 Aug 2001 20:28:28 +1000 -+ -+ash (0.3.8-23) unstable; urgency=low -+ -+ * Fixed fence post error in scanleft (closes: #107229). -+ * Removed stunalloc in expname as it interferes with addfname. -+ * Fixed CTLESC skipping in scanright. -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 2 Aug 2001 20:06:00 +1000 -+ -+ash (0.3.8-22) unstable; urgency=low -+ -+ * Fixed trailing back slash bug in echo/printf (closes: #106693). -+ * Some quoted's are meant to be quotes. -+ * Added Brazilian translation (Andre Luis Lopes, closes: #107041). -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 30 Jul 2001 20:21:52 +1000 -+ -+ash (0.3.8-21) unstable; urgency=low -+ -+ * Fixed EV_EXIT/redirection bugs that caused core dumps. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 28 Jul 2001 17:03:28 +1000 -+ -+ash (0.3.8-20) unstable; urgency=low -+ -+ * Don't save fd2 if job control is turned off. -+ * Don't push redirections when EV_EXIT is set. -+ * Fixed assignment recognition in the presence of back ticks. -+ * Combined checkkwd and checkalias. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 27 Jul 2001 22:29:41 +1000 -+ -+ash (0.3.8-19) unstable; urgency=low -+ -+ * Recompute strings after growing in subevalvar (closes: #106050). -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 23 Jul 2001 21:16:50 +1000 -+ -+ash (0.3.8-18) unstable; urgency=low -+ -+ * Added more space optimisations for udeb on i386. -+ * Set stack mark in patmatch (closes: #106050). -+ * Fixed theoretical bug in expari. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 21 Jul 2001 20:08:15 +1000 -+ -+ash (0.3.8-17) unstable; urgency=low -+ -+ * Don't complain about unknown escape codes in echo and printf -+ (closes: #105659). -+ * Updated build-time dependency on groff-base (closes: #105612). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 18 Jul 2001 19:33:20 +1000 -+ -+ash (0.3.8-16) unstable; urgency=low -+ -+ * Fixed backslash bug in new pattern matching code. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 16 Jul 2001 21:47:39 +1000 -+ -+ash (0.3.8-15) unstable; urgency=low -+ -+ * Added Swedish translation of templates (Martin Sjögren, closes: #103158). -+ * Restored escape code support in echo. -+ * Removed assignment builtins since it is at best undefined by the SuS and -+ also can't be implemented consistently. -+ * Removed extraneous volatile modifier (closes: #104518). -+ * General overhaul of word expansion (closes: #96588). -+ * Redirection prefixes no longer stop assignments from being recognised. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 15 Jul 2001 17:27:03 +1000 -+ -+ash (0.3.8-14) unstable; urgency=low -+ -+ * Divert sh.1.gz to sh.distrib.1.gz (closes: #102251). -+ * Added HETIO support for ^D and ^U (Aaron Lehmann, closes: #102215). -+ * Added Spaniash translation of debconf templates (Carlos Valdivia Yagüe, -+ closes: #103040). -+ * Added versioned build-time dependency on groff. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 2 Jul 2001 19:32:03 +1000 -+ -+ash (0.3.8-13) unstable; urgency=low -+ -+ * Fixed a bug where errors in pipelines which are part of andor lists were -+ not ignored when -e is in effect. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 25 Jun 2001 19:40:27 +1000 -+ -+ash (0.3.8-12) unstable; urgency=low -+ -+ * Rewrote arith_lex.l in C (Aaron Lehmann, closes: #101741). -+ * && and || in arithmetic expansions now return either 0 or 1. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 24 Jun 2001 20:14:29 +1000 -+ -+ash (0.3.8-11) unstable; urgency=low -+ -+ * Check for NULL argument in evaltree() (closes: #98865, #98867). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 27 May 2001 17:53:14 +1000 -+ -+ash (0.3.8-10) unstable; urgency=low -+ -+ * Use /bin/ash in postinst to sidestep bugs in other shells (closes: #98739). -+ * Exit status is now tested on non-negated pipelines (closes: #98736). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 26 May 2001 23:56:07 +1000 -+ -+ash (0.3.8-9) unstable; urgency=medium -+ -+ * IFS is now fetched using bltinlookup() again in read (closes: #98343). -+ * Divert sh(1) man page as well as /bin/sh (closes: #98525). -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 25 May 2001 20:30:06 +1000 -+ -+ash (0.3.8-8) unstable; urgency=low -+ -+ * Fixed diversion removal in prerm (duh, closes: #98031). -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 21 May 2001 20:52:48 +1000 -+ -+ash (0.3.8-7) unstable; urgency=low -+ -+ * Fixed diversion test in prerm (closes: #98031). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 20 May 2001 12:30:53 +1000 -+ -+ash (0.3.8-6) unstable; urgency=low -+ -+ * Make sure that fd2 is closed when clearing redirects (closes: #96619). -+ * Fixed memory corruption in stunalloc(). -+ * The output of export/readonly/set is now correctly quoted. -+ * Fixed newline eating bug in expbackq(). -+ * Set OLDPWD. -+ * Removed ash-medium as neither bf or di uses it. -+ * Wait now waits for all its argument rather than the first one. -+ * Wait will exit with 129 when interrupted by a signal for a which a trap has -+ been set. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 18 May 2001 21:51:41 +1000 -+ -+ash (0.3.8-5) unstable; urgency=low -+ -+ * Added German translation to template file (Sebastian Feltel, -+ closes: #96203). -+ * Added missing initialisation in setalias() (closes: #95433). -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 4 May 2001 20:54:31 +1000 -+ -+ash (0.3.8-4) unstable; urgency=low -+ -+ * Disabled fnmatch code as fnmatch(3) in glibc is broken. -+ * Fixed echo example in man page (Kalle Olavi Niemitalo, closes: #96014). -+ * Fixed trailing semicolon bug with eval (NetBSD). -+ * Fixed globbing inconsistency with broken symlinks (NetBSD). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 2 May 2001 22:57:16 +1000 -+ -+ash (0.3.8-3) unstable; urgency=low -+ -+ * Work around broken autoconf scripts (closes: #95430). -+ -+ -- Herbert Xu <herbert@debian.org> Tue, 1 May 2001 18:27:50 +1000 -+ -+ash (0.3.8-2) unstable; urgency=low -+ -+ * Save checkalias before calling xxreadtoken() (closes: #95628). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 29 Apr 2001 17:36:01 +1000 -+ -+ash (0.3.8-1) unstable; urgency=low -+ -+ * NetBSD-current version as of 20010316. -+ * Removed code that sets IFS. -+ * Fixed memory leak with PWD. -+ * Set PPID. -+ * Fixed inconsistencies in alias expansion. -+ * Restored original output code. -+ * Enabled fnmatch code again. -+ * Added builtin printf. -+ * Offer to divert /bin/sh (closes: #70462). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 25 Apr 2001 22:32:39 +1000 -+ -+ash (0.3.7-16) unstable; urgency=low -+ -+ * Fixed incorrect default IFS in readcmd (closes: #88950). -+ * Added missing return in hashcmd. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 9 Mar 2001 20:44:40 +1100 -+ -+ash (0.3.7-15) unstable; urgency=low -+ -+ * Unknown escape codes are now prnted literally by echo (closes: #82869). -+ * Made hetio_read_input() fail if fd is not stdin. -+ * Some uses of VSQUOTE were really meant to be quotes (closes: #88777). -+ * Build different ashes in different subdirectories. -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 8 Mar 2001 21:32:28 +1100 -+ -+ash (0.3.7-14) unstable; urgency=low -+ -+ * Removed predependency from udeb (closes: #81995). -+ * Added /bin/sh symlink to udeb (closes: #81967). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 13 Jan 2001 15:23:21 +1100 -+ -+ash (0.3.7-13) unstable; urgency=low -+ -+ * Renamed the udeb to ash-udeb. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 20 Dec 2000 19:32:34 +1100 -+ -+ash (0.3.7-12) unstable; urgency=low -+ -+ * Added support for udebs (Randolph Chung, closes: #79237). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 16 Dec 2000 13:53:28 +1100 -+ -+ash (0.3.7-11) unstable; urgency=low -+ -+ * Preserve the previous exit status upon entering a function -+ (closes: #78374). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 3 Dec 2000 13:34:27 +1100 -+ -+ash (0.3.7-10) unstable; urgency=low -+ -+ * Merged changes for GNU from Igor Khavkine. -+ * Minimise the number of sigactions. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 3 Nov 2000 20:31:52 +1100 -+ -+ash (0.3.7-9) unstable; urgency=low -+ -+ * Predepend on the libraries. -+ * Always save fd 2 when it is redirected (closes: #75302). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 22 Oct 2000 08:40:40 +1100 -+ -+ash (0.3.7-8) unstable; urgency=high -+ -+ * More redirection fixes (closes: #73613). -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 5 Oct 2000 18:22:17 +1100 -+ -+ash (0.3.7-7) unstable; urgency=high -+ -+ * Added missing break in redirection code (closes: #72956). -+ -+ -- Herbert Xu <herbert@debian.org> Tue, 3 Oct 2000 07:58:04 +1100 -+ -+ash (0.3.7-6) unstable; urgency=low -+ -+ * command -[vV] no longer displays an error message on stdout. -+ * Redirecting to /proc/self/fd/* now works (closes: #72852). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 1 Oct 2000 12:56:39 +1100 -+ -+ash (0.3.7-5) unstable; urgency=low -+ -+ * Implemented set -a. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 30 Sep 2000 16:00:33 +1100 -+ -+ash (0.3.7-4) unstable; urgency=low -+ -+ * Added build-time dependency on debhelper (closes: #69920). -+ * Extended maximum length of arithmetic expansions to match 32-bit integers. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 20 Sep 2000 14:28:16 +1100 -+ -+ash (0.3.7-3) unstable; urgency=low -+ -+ * Switch to the old globbing code since glob(3) is hopelessly broken -+ (closes: #69455). -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 21 Aug 2000 20:37:15 +1000 -+ -+ash (0.3.7-2) unstable; urgency=low -+ -+ * Call glob(3) with GLOB_NOMAGIC (ouch). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 6 Aug 2000 17:47:08 +1000 -+ -+ash (0.3.7-1) unstable; urgency=low -+ -+ * NetBSD-current version as of 20000729. -+ * Use fnmatch(3) and glob(3). -+ * Fixed the use of backslashes in the pattern in parameter substitutions, -+ hopefully for the last time. -+ * Applied HETIO patch and built ash.medium (closes: #50788). Will do ash.big -+ when readline is fixed so that it doesn't leak anymore. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 4 Aug 2000 21:36:44 +1000 -+ -+ash (0.3.6-5) unstable; urgency=low -+ -+ * Fixed manpage entry for read with patch from Kevin Ryde (closes: #62500). -+ * Fixed a file descriptor leak for pipelines. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 19 Apr 2000 18:56:20 +1000 -+ -+ash (0.3.6-4) unstable; urgency=low -+ -+ * Fixed the case of an empty command with redirections. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 7 Apr 2000 12:07:18 +1000 -+ -+ash (0.3.6-3) unstable; urgency=low -+ -+ * ! is now recognised correctly. -+ * Ash is now more strict on the syntax, e.g., a lone ! is no longer accepted -+ as an alternative to ! true. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 7 Apr 2000 10:46:06 +1000 -+ -+ash (0.3.6-2) unstable; urgency=low -+ -+ * Fixed a problem with fmtstr() which broke getopts. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 2 Apr 2000 10:49:26 +1000 -+ -+ash (0.3.6-1) unstable; urgency=low -+ -+ * NetBSD-current version as of 20000326. -+ * Added a Build-Depends on groff (closes: #61041). -+ * Implemented noclobber (closes: #59028). -+ * Rewrote output.c to use stream IO. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 1 Apr 2000 19:24:31 +1000 -+ -+ash (0.3.5-10) frozen unstable; urgency=low -+ -+ * Don't stat mail boxes in non-interactive mode (closes: #59213). -+ * Added an fflush(stdout) to the times builtin (closes: #59027). -+ * Documented the times builtin. -+ * Added source depends. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 18 Mar 2000 18:58:44 +1100 -+ -+ash (0.3.5-9) unstable; urgency=low -+ -+ * Double quotes inside paramater substitutions inside double quotes are now -+ ignored as in bash (the originial behaviour was POSIX compliant too but -+ IMHO this one makes a little bit more sense). -+ This one broke mwm (but it was actually mwm's fault). -+ * Corrected backslash/CTLESC treatment for patterns in parameter -+ substitutions. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 6 Nov 1999 18:13:19 +1100 -+ -+ash (0.3.5-8) unstable; urgency=low -+ -+ * Replaced use of echo -n in manual page with escape codes. -+ * Made FHS compliant (closes: #47978). -+ * Restored echo's option processing ability. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 22 Oct 1999 10:20:58 +1000 -+ -+ash (0.3.5-7) unstable; urgency=low -+ -+ * echo no longer supports options. -+ * Don't quote patterns inside parameter substitutions enclosed by double -+ quotes (closes: #47842). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 20 Oct 1999 20:28:14 +1000 -+ -+ash (0.3.5-6) unstable; urgency=low -+ -+ * Use getcwd() instead of /bin/pwd -- Zack Weinberg (closes: #46981). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 10 Oct 1999 16:31:49 +1000 -+ -+ash (0.3.5-5) unstable; urgency=low -+ -+ * Only test for -e on simple commands (fixes #44559). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 8 Sep 1999 22:18:27 +1000 -+ -+ash (0.3.5-4) unstable; urgency=low -+ -+ * Don't wait for stopped children if job control is disabled (fixes #42814). -+ * Allow an option '(' in a case statement (fixes #42364). -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 12 Aug 1999 23:30:30 +1000 -+ -+ash (0.3.5-3) unstable; urgency=low -+ -+ * OK, the fix to the esoteric problem in 0.3.5-1 actually breaks VSASSIGN -+ and VSQUESTION, they should work properly now (fixes #41327). -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 15 Jul 1999 22:47:13 +1000 -+ -+ash (0.3.5-2) unstable; urgency=low -+ -+ * PATH search and execution is now correct. -+ * hash no longer shows builtins. -+ * Added kill builtin. -+ * New description from James R. van Zandt reformatted by Josip Rodin. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 12 Jul 1999 18:51:42 +1000 -+ -+ash (0.3.5-1) unstable; urgency=low -+ -+ * New upstream release. -+ * Adapted to new pmake (fixes #38737). -+ * Fixed behvaiour of backslashes preceding a closing brace for a parameter -+ substituion inside double quotes (even bash messes this one up :). -+ * Fixed command (fixes #34639). -+ * Fixed a pipe bug where stdin may be wrongly closed (fixes #35452). -+ * Revamped getopts (fixes #39694). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 4 Jul 1999 12:19:01 +1000 -+ -+ash (0.3.4-7) unstable; urgency=low -+ -+ * Fixed a glibc 2.1 compatitibility problem. -+ * Fixed a PWD inconsistency that stuffed up the kernel compilation. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 17 May 1999 23:14:57 +1000 -+ -+ash (0.3.4-6) unstable; urgency=low -+ -+ * Fixed incorrect -e test due to the last bug fix (fixes #26509). -+ -+ -- Herbert Xu <herbert@debian.org> Tue, 8 Sep 1998 10:02:46 +1000 -+ -+ash (0.3.4-5) unstable; urgency=low -+ -+ * Use test_eaccess from bash instead of access(2) (fixes #26110). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 26 Aug 1998 21:22:49 +1000 -+ -+ash (0.3.4-4) unstable; urgency=low -+ -+ * Only upload to unstable. -+ -+ -- Herbert Xu <herbert@debian.org> Tue, 5 May 1998 18:01:02 +1000 -+ -+ash (0.3.4-3) frozen unstable; urgency=low -+ -+ * Applied sparc patch (fixes #21562). -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 1 May 1998 19:48:13 +1000 -+ -+ash (0.3.4-2) frozen unstable; urgency=low -+ -+ * Fixed the incorrect trap fixes (fixes #20363). -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 16 Apr 1998 21:07:10 +1000 -+ -+ash (0.3.4-1) unstable; urgency=low -+ -+ * New upstream release. -+ * Reverted word splitting change in 0.3.2-1 since the fix was broken and -+ major work (the quote removal is done too quickly at the moment) is needed -+ to fix it properly. -+ * Fixed more trap noncompliance. -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 19 Mar 1998 22:59:12 +1100 -+ -+ash (0.3.2-5) unstable; urgency=low -+ -+ * Fixed a bug when doing pattern matching in parameter expansions. -+ -+ -- Herbert Xu <herbert@debian.org> Tue, 10 Mar 1998 21:25:40 +1100 -+ -+ash (0.3.2-4) unstable; urgency=low -+ -+ * Allow ] to be quoted in bracket expressions (fixes #17533). -+ * Move dh_fixperms to second last spot (fixes #18267). -+ * Don't do field splitting in evalfor. -+ -+ -- Herbert Xu <herbert@debian.org> Tue, 17 Feb 1998 13:32:09 +1100 -+ -+ash (0.3.2-3) unstable; urgency=low -+ -+ * Fixed stupid core dump. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 11 Feb 1998 21:33:55 +1100 -+ -+ash (0.3.2-2) unstable; urgency=low -+ -+ * Hack for special builtins (fixes #18055). -+ * Hack for command. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 11 Feb 1998 21:19:46 +1100 -+ -+ash (0.3.2-1) unstable; urgency=low -+ -+ * NetBSD-current version as of 19980209. -+ * Fixed a word splitting problem after parameter expansion thanks to Alexey -+ Marinichev. -+ * Converted to debhelper (fixes #14612, #15005). -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 9 Feb 1998 16:53:48 +1100 -+ -+ash (0.3.1-20) unstable; urgency=low -+ -+ * Fixed -e problem with eval. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 7 Dec 1997 20:19:00 +1100 -+ -+ash (0.3.1-19) unstable; urgency=low -+ -+ * Fixed -e problem with command substitution. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 7 Dec 1997 19:44:49 +1100 -+ -+ash (0.3.1-18) unstable; urgency=low -+ -+ * Do not link with ncurses (#15485). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 30 Nov 1997 12:00:11 +1100 -+ -+ash (0.3.1-17) unstable; urgency=low -+ -+ * Set PATH like bash (#15238). -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 26 Nov 1997 16:17:27 +1100 -+ -+ash (0.3.1-16) unstable; urgency=low -+ -+ * Fixed incorrect assignment builtin code. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 24 Nov 1997 16:19:10 +1100 -+ -+ash (0.3.1-15) unstable; urgency=low -+ -+ * hash now returns error codes (needed by the Linux kernel). -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 23 Nov 1997 21:37:08 +1100 -+ -+ash (0.3.1-14) unstable; urgency=low -+ -+ * Disabled word-splitting for assignment builtins. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 23 Nov 1997 12:45:15 +1100 -+ -+ash (0.3.1-13) unstable; urgency=low -+ -+ * ! is now recognised even after &&/||. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 21 Nov 1997 22:09:05 +1100 -+ -+ash (0.3.1-12) unstable; urgency=low -+ -+ * More fixes to the handling of SIGINT when forking. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 14 Nov 1997 15:14:32 +1100 -+ -+ash (0.3.1-11) unstable; urgency=low -+ -+ * Ignore SIGINT when forking non-interactively. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 3 Nov 1997 12:00:02 +1100 -+ -+ash (0.3.1-10) unstable; urgency=low -+ -+ * echo now handles options correctly. -+ * echo nolonger returns 0 if erorrs occured while writing to stdout. -+ * New code from GNU echo merged. -+ * Error messages from test now work. -+ -+ -- Herbert Xu <herbert@debian.org> Wed, 8 Oct 1997 21:47:13 +1000 -+ -+ash (0.3.1-9) unstable; urgency=low -+ -+ * ! is recognised at pipeline level like bash. -+ -+ -- Herbert Xu <herbert@debian.org> Mon, 15 Sep 1997 23:13:45 +1000 -+ -+ash (0.3.1-8) unstable; urgency=medium -+ -+ * Old patch regarding SIGCHLD in again. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 31 Aug 1997 11:20:27 +1000 -+ -+ash (0.3.1-7) unstable; urgency=low -+ -+ * /bin/sh -e is behaving even better now (for loops within conditionals). -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 23 Aug 1997 22:08:19 +1000 -+ -+ash (0.3.1-6) unstable; urgency=low -+ -+ * /bin/sh -e is behaving better now. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 23 Aug 1997 13:16:26 +1000 -+ -+ash (0.3.1-5) unstable; urgency=low -+ -+ * hash -v /dir/command doesn't coredump anymore. -+ * type /dir/command now works correctly. -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 1 Aug 1997 20:48:19 +1000 -+ -+ash (0.3.1-4) unstable; urgency=low -+ -+ * trap now understands symbolic signal names. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 26 Jul 1997 14:04:46 +1000 -+ -+ash (0.3.1-3) unstable; urgency=low -+ -+ * Added the builtin test command. -+ -+ -- Herbert Xu <herbert@debian.org> Sun, 20 Jul 1997 15:00:14 +1000 -+ -+ash (0.3.1-2) unstable; urgency=medium -+ -+ * Fixed a coredump involving $*. -+ -+ -- Herbert Xu <herbert@debian.org> Sat, 19 Jul 1997 12:03:02 +1000 -+ -+ash (0.3.1-1) unstable; urgency=medium -+ -+ * NetBSD-current version as of 19970715. -+ * Fixed a "use after free" bug (#11294). -+ -+ -- Herbert Xu <herbert@debian.org> Fri, 18 Jul 1997 13:48:09 +1000 -+ -+ash (0.3-1) unstable; urgency=low -+ -+ * Initial Release. -+ -+ -- Herbert Xu <herbert@debian.org> Thu, 19 Jun 1997 19:29:16 +1000 -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/compat bin_NetBSD-1.6release/src/bin/sh/debian/compat ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/compat 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/compat 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1 @@ -+4 -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/control bin_NetBSD-1.6release/src/bin/sh/debian/control ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/control 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/control 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,53 @@ -+Source: dash -+Section: shells -+Priority: optional -+Maintainer: Herbert Xu <herbert@debian.org> -+Build-Depends: byacc, debhelper (>= 4), pmake -+Standards-Version: 3.5.8 -+ -+Package: dash -+Architecture: any -+Pre-Depends: ${shlibs:Depends} -+Description: The Debian Almquist Shell -+ "dash" is a POSIX compliant shell that is much smaller than "bash". -+ We take advantage of that by making it the shell on the installation -+ root floppy, where space is at a premium. -+ . -+ It can be usefully installed as /bin/sh (because it executes scripts -+ somewhat faster than "bash"), or as the default shell either of root -+ or of a second user with a userid of 0 (because it depends on fewer -+ libraries, and is therefore less likely to be affected by an upgrade -+ problem or a disk failure). It is also useful for checking that a -+ script uses only POSIX syntax. -+ . -+ "bash" is a better shell for most users, since it has some nice -+ features absent from "dash", and is a required part of the system. -+ -+Package: dash-udeb -+Architecture: any -+Depends: ${shlibs:Depends} -+Section: debian-installer -+Priority: standard -+Description: The Debian Almquist Shell for boot floppies -+ "dash" is a POSIX compliant shell that is much smaller than "bash". -+ We take advantage of that by making it the shell on the installation -+ root floppy, where space is at a premium. -+ . -+ It can be usefully installed as /bin/sh (because it executes scripts -+ somewhat faster than "bash"), or as the default shell either of root -+ or of a second user with a userid of 0 (because it depends on fewer -+ libraries, and is therefore less likely to be affected by an upgrade -+ problem or a disk failure). It is also useful for checking that a -+ script uses only POSIX syntax. -+ . -+ "bash" is a better shell for most users, since it has some nice -+ features absent from "dash", and is a required part of the system. -+ -+Package: ash -+Architecture: all -+Pre-Depends: dash -+Description: Compatibility package for the Debian Almquist Shell -+ This package exists so that users of the "ash" package can upgrade to the -+ "dash" package which replaces the former. It includes the /bin/ash symlink. -+ You can remove this package if you do not use /bin/ash explicitly. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/copyright bin_NetBSD-1.6release/src/bin/sh/debian/copyright ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/copyright 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/copyright 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,44 @@ -+This package was debianized by Mark W. Eichin eichin@kitten.gen.ma.us on -+Mon, 24 Feb 1997 16:00:16 -0500. -+ -+This package was re-ported from NetBSD and debianized by -+Herbert Xu herbert@debian.org on Thu, 19 Jun 1997 19:29:16 +1000. -+ -+It was downloaded from ftp.netbsd.org. -+ -+Copyright: -+ -+Copyright (c) 1989-1994 -+ The Regents of the University of California. All rights reserved. -+Copyright (c) 1997-2002 -+ Herbert Xu <herbert@debian.org> -+ -+This code is derived from software contributed to Berkeley by Kenneth Almquist. -+ -+Please refer to /usr/share/common-licenses/BSD for details. -+ -+mksignames.c: -+ -+This file is not directly linked with dash. However, its output is. -+ -+Copyright (C) 1992 Free Software Foundation, Inc. -+ -+This file is part of GNU Bash, the Bourne Again SHell. -+ -+Bash is free software; you can redistribute it and/or modify it under -+the terms of the GNU General Public License as published by the Free -+Software Foundation; either version 2, or (at your option) any later -+version. -+ -+Bash is distributed in the hope that it will be useful, but WITHOUT ANY -+WARRANTY; without even the implied warranty of MERCHANTABILITY or -+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+for more details. -+ -+You should have received a copy of the GNU General Public License with -+your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with the -+Debian GNU/Linux hello source package as the file COPYING. If not, -+write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, -+Boston, MA 02111 USA. -+ -+$Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.config bin_NetBSD-1.6release/src/bin/sh/debian/dash.config ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.config 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.config 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,39 @@ -+#!/bin/sh -+# -+# debconf script for the Debian GNU/Linux ash package -+# -+# $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -+ -+set -e -+ -+. /usr/share/debconf/confmodule -+ -+db_version 2.0 -+ -+if [ "$1" = configure ] && [ -z "$2" ]; then -+ set +e -+ db_fget ash/sh seen -+ err=$? -+ set -e -+ -+ case $err in -+ 0) -+ if [ "$RET" = true ]; then -+ db_fset dash/sh seen true -+ db_get ash/sh -+ db_set dash/sh "$RET" -+ exit -+ fi -+ ;; -+ 10) -+ # ash/sh does not exist -+ ;; -+ *) -+ echo "db_fget exited with $err" >&2 -+ exit $err -+ ;; -+ esac -+fi -+ -+db_input low dash/sh || true -+db_go -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.dirs bin_NetBSD-1.6release/src/bin/sh/debian/dash.dirs ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.dirs 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.dirs 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,2 @@ -+bin -+usr/share/man/man1 -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.postinst bin_NetBSD-1.6release/src/bin/sh/debian/dash.postinst ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.postinst 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.postinst 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,81 @@ -+#!/bin/sh -+# -+# post-install script for the Debian GNU/Linux dash package -+# -+# $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -+ -+set -e -+ -+check_divert() { -+ div=$(dpkg-divert --list $2) -+ distrib=${4:-$2.distrib} -+ case "$1" in -+ true) -+ if [ -z "$div" ]; then -+ dpkg-divert --package dash --divert $distrib --add $2 -+ cp -dp $2 $distrib -+ ln -sf $3 $2 -+ fi -+ ;; -+ false) -+ if [ -n "$div" ] && [ -z "${div%%*by dash}" ]; then -+ mv $distrib $2 -+ dpkg-divert --remove $2 -+ fi -+ ;; -+ ash) -+ case $div in -+ '') -+ ;; -+ *by\ ash) -+ dst=${div% by ash} -+ dst=${dst##* to } -+ -+ # Work around dpkg-divert bug. -+ if [ -e "$dst" ]; then -+ mv "$dst" "$dst.dash-tmp" -+ fi -+ dpkg-divert --remove $2 -+ if [ -e "$dst.dash-tmp" ]; then -+ mv "$dst.dash-tmp" "$dst" -+ fi -+ -+ dpkg-divert --package dash --divert $distrib --add $2 -+ if [ "$dst" != $distrib ] && [ -e "$dst" ]; then -+ mv "$dst" $distrib -+ fi -+ ln -sf $3 $2 -+ ;; -+ *) -+ d=${2%/*} -+ if -+ [ -h $2 ] && [ -f $2 ] && [ -f $d/$5 ] && -+ cmp $2 $d/$5 -+ then -+ ln -sf $3 $2 -+ fi -+ ;; -+ esac -+ esac -+} -+ -+debconf= -+if [ -f /usr/share/debconf/confmodule ]; then -+ . /usr/share/debconf/confmodule -+ debconf=yes -+fi -+ -+if [ "$1" = configure ] && [ -z "$2" ]; then -+ check_divert ash /bin/sh dash '' ash -+ check_divert ash /usr/share/man/man1/sh.1.gz dash.1.gz \ -+ /usr/share/man/man1/sh.distrib.1.gz ash.1.gz -+fi -+ -+if [ $debconf ]; then -+ db_get dash/sh -+ check_divert "$RET" /bin/sh dash -+ check_divert "$RET" /usr/share/man/man1/sh.1.gz dash.1.gz \ -+ /usr/share/man/man1/sh.distrib.1.gz -+fi -+ -+#DEBHELPER# -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.prerm bin_NetBSD-1.6release/src/bin/sh/debian/dash.prerm ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.prerm 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.prerm 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,24 @@ -+#!/bin/sh -+# -+# pre-removal script for the Debian GNU/Linux ash package -+# -+# $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -+ -+set -e -+ -+remove_divert() { -+ div=$(dpkg-divert --list $1) -+ if [ -n "$div" ] && [ -z "${div%%*by dash}" ]; then -+ distrib=${div% by dash} -+ distrib=${distrib##* to } -+ mv $distrib $1 -+ dpkg-divert --remove $1 -+ fi -+} -+ -+if [ "$1" = remove ] || [ "$1" = deconfigure ]; then -+ remove_divert /bin/sh -+ remove_divert /usr/share/man/man1/sh.1.gz -+fi -+ -+#DEBHELPER# -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,10 @@ -+Template: dash/sh -+Type: boolean -+Default: false -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. You may wish to do this because dash is faster -+ and smaller than bash. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.de bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.de ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.de 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.de 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,13 @@ -+Template: dash/sh -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-de: dash als /bin/sh installieren? -+ Bash ist die Standard-Shell (/bin/sh) auf einem Debian-System. Da die -+ Debian-Policy von allen Shellscripts, die /bin/sh benutzen, -+ POSIX-Kompatibilität verlangt, kann für /bin/sh jede POSIX-kompatible Shell -+ benutzt werden. Dash ist POSIX-kompatibel und kann daher als /bin/sh verwendet -+ werden. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.es bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.es ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.es 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.es 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,13 @@ -+Template: dash/sh -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-es: ¿Instalar dash como /bin/sh? -+ Bash es el intérprte de comandos /bin/sh por defecto de los sistemas Debian. -+ Sin embargo, dado que nuestras normas obligan a que todos los scripts para el -+ intérprete de comandos se atengan a las normas POSIX, cualquier intérprete -+ compatible con POSIX puede servir como /bin/sh. Puesto que dash lo es, puede -+ usarse como /bin/sh. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.fr bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.fr ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.fr 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.fr 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,12 @@ -+Template: dash/sh -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-fr: Mettre un lien de /bin/sh vers dash ? -+ Sur un système Debian, /bin/sh est bash par défaut. Cependant, comme notre -+ charte impose que tous les scripts shells utilisant /bin/sh soient conformes -+ à la norme POSIX, /bin/sh peut être n'importe quel shell conforme à cette -+ norme. Et comme dash l'est, il peut servir de /bin/sh. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.ja bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.ja ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.ja 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.ja 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,13 @@ -+Template: dash/sh -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-ja: dash ¤ò /bin/sh ¤È¤·¤Æ¥¤¥ó¥¹¥È¡¼¥ë¤·¤Þ¤¹¤«? -+ Debian ¥·¥¹¥Æ¥à¤Ç¤Ï bash ¤¬¥Ç¥Õ¥©¥ë¥È¤Î /bin/sh ¤Ç¤¹¡£¤·¤«¤·¡¢Debian -+ ¤Î¥Ý¥ê¥·¡¼¤Ë¤è¤Ã¤Æ¡¢/bin/sh ¤òÍѤ¤¤ëÁ´¤Æ¤Î¥·¥§¥ë¥¹¥¯¥ê¥×¥È¤Ï POSIX -+ ½àµò¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤¿¤á¡¢POSIX ¤òËþ¤¿¤¹¥·¥§¥ë¤Ï¤É¤ì¤Ç¤â /bin/sh -+ ¤È¤Ê¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£dash ¤Ï POSIX ½àµò¤Ç¤¹¤Î¤Ç¡¢/bin/sh ¤È¤·¤Æ»È¤¦ -+ ¤³¤È¤¬¤Ç¤¤Þ¤¹¡£ -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.pt_BR bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.pt_BR ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.pt_BR 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.pt_BR 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,12 @@ -+Template: dash/sh -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-pt_BR: Instalar dash como /bin/sh ? -+ Bash é o /bin/sh padrão em um sistema Debian. Porém, uma vez que nossa -+ política requer que todos os shell scripts usando /bin/sh sejam compatíveis -+ POSIX, qualquer shell que esteja em conformidade POSIX pode servir como -+ /bin/sh. Uma vez que dash é compatível POSIX, pode ser usado como /bin/sh. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.ru bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.ru ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.ru 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.ru 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,13 @@ -+Template: dash/sh -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-ru: õÓÔÁÎÏ×ÉÔØ dash ËÁË /bin/sh? -+ Bash - ÜÔÏ /bin/sh ÐÏ ÕÍÏÌÞÁÎÉÀ × ÓÉÓÔÅÍÅ Debian. ïÄÎÁËÏ, ÔÁË ËÁË ÎÁÛÁ -+ ÐÏÌÉÔÉËÁ ÔÒÅÂÕÅÔ, ÞÔÏÂÙ ×ÓÅ ÓÃÅÎÁÒÉÉ ÏÂÏÌÏÞËÉ, ÉÓÐÏÌØÚÕÀÝÉÅ /bin/sh, -+ ÂÙÌÉ ÓÏ×ÍÅÓÔÉÍÙÍÉ Ó POSIX, ÔÏ ÒÁÂÏÔÁÔØ ËÁË /bin/sh ÍÏÖÅÔ ÌÀÂÁÑ -+ ÏÂÏÌÏÞËÁ, ÓÏ×ÍÅÓÔÉÍÁÑ Ó POSIX. ôÁË ËÁË dash ÓÏ×ÍÅÓÔÉÍ Ó POSIX, ÔÏ ÏÎ -+ ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØÓÑ ËÁË /bin/sh. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.sv bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.sv ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.sv 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash.templates.sv 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,13 @@ -+Template: dash/sh -+Type: boolean -+Description: Install dash as /bin/sh? -+ Bash is the default /bin/sh on a Debian system. However, since our policy -+ requires all shell scripts using /bin/sh to be POSIX compliant, any shell -+ that conforms to POSIX can serve as /bin/sh. Since dash is POSIX compliant, -+ it can be used as /bin/sh. -+Description-sv: Installera dash som /bin/sh? -+ Bash är standardinställningen för /bin/sh på Debiansystem. Eftersom vår -+ policy kräver att alla script som använder /bin/sh måste vara -+ POSIX-kompatibla, kan vilket POSIX-kompatibelt skal som helst vara /bi/sh. Då -+ dash är POSIX-kompatibelt kan det användas som /bin/sh. -+ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash-udeb.dirs bin_NetBSD-1.6release/src/bin/sh/debian/dash-udeb.dirs ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash-udeb.dirs 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/dash-udeb.dirs 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1 @@ -+bin -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/debian/rules bin_NetBSD-1.6release/src/bin/sh/debian/rules ---- bin_NetBSD-1.6release.orig/src/bin/sh/debian/rules 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/debian/rules 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,101 @@ -+#!/usr/bin/make -f -+# $Id: dash-ash-hetio-yacc.diff,v 1.1 2003/02/09 09:36:31 satai Exp $ -+ -+# Uncomment this to turn on verbose mode. -+#export DH_VERBOSE=1 -+ -+# This has to be exported to make some magic below work. -+export DH_OPTIONS -+ -+DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) -+ -+CDEF := \ -+ -Wall -DBSD=1 -DSMALL -D_GNU_SOURCE -DGLOB_BROKEN -DHAVE_VASPRINTF=1 \ -+ -DIFS_BROKEN -DGCC_BROKEN_NG \ -+ -D__COPYRIGHT\(x\)= -D__RCSID\(x\)= -D_DIAGASSERT\(x\)= -+ -+OPT := -g -O2 -fstrict-aliasing -+OPTSM := -g -Os -fstrict-aliasing -fomit-frame-pointer -DREALLY_SMALL -+ -+ifeq ($(DEB_HOST_ARCH),i386) -+OPTSM += \ -+ -malign-loops=0 -malign-jumps=0 -malign-functions=0 \ -+ -mpreferred-stack-boundary=2 -DUSE_NORETURN -+endif -+ -+setup: setup-stamp -+setup-stamp: -+ rm -rf obj obj-udeb -+ mkdir obj obj-udeb -+ chmod u+x debian/bsdyacc -+ touch setup-stamp -+ -+build: setup-stamp -+ dh_testdir -+ -+ pmake CFLAGS:='$(CDEF) $(OPT)' \ -+ YACC:='$${.CURDIR}/debian/bsdyacc' -+ MAKEOBJDIR=obj-udeb pmake CFLAGS:='$(CDEF) $(OPTSM)' \ -+ YACC:='$${.CURDIR}/debian/bsdyacc' -+ -+clean: -+ dh_testdir -+ dh_testroot -+ rm -f setup-stamp -+ -+ rm -rf obj obj-udeb -+ -+ dh_clean -+ -+install: build -+ dh_testdir -+ dh_testroot -+ dh_clean -k -+ dh_installdirs -+ -+ install obj/sh debian/dash/bin/dash -+ install -m 644 sh.1 debian/dash/usr/share/man/man1/dash.1 -+ install obj-udeb/sh debian/dash-udeb/bin/dash -+ ln -s dash debian/dash-udeb/bin/sh -+ ln -s dash debian/ash/bin/ash -+ ln -s dash.1.gz debian/ash/usr/share/man/man1/ash.1.gz -+ -+# This single target is used to build all the packages, all at once, or -+# one at a time. So keep in mind: any options passed to commands here will -+# affect _all_ packages. Anything you want to only affect one package -+# should be put in another target, such as the install target. -+binary-common: -+ dh_testdir -+ dh_testroot -+ dh_installdebconf -+ dh_installdocs -Ndash-udeb -+ dh_installexamples -+ dh_installmenu -+ dh_installcron -+ dh_installchangelogs -Ndash-udeb -+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) -+ dh_strip -+endif -+ dh_compress -+ dh_fixperms -+ dh_installdeb -Ndash-udeb -+ dh_shlibdeps -+ dh_gencontrol -+ dh_md5sums -+ dh_builddeb -+ -+# Build architecture-independent files here. -+binary-indep: install -+ $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common -+ -+# Build architecture-dependent files here. -+binary-arch: install -+ $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common -+ -+ for i in ../dash-udeb_*.deb; do mv $$i $${i%deb}udeb; done -+ sed '/^[^ ]*\.udeb/d; s/^\(dash-udeb_[^ ]*\.\)deb/\1udeb/' \ -+ debian/files > debian/files.new -+ mv debian/files.new debian/files -+ -+binary: binary-indep binary-arch -+.PHONY: build clean binary-indep binary-arch binary binary-common install setup -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/error.c bin_NetBSD-1.6release/src/bin/sh/error.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/error.c 2002-05-16 11:41:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/error.c 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: error.c,v 1.24 2002/05/15 16:33:35 christos Exp $ */ -+/* $NetBSD: error.c,v 1.25 2002/05/25 23:09:06 wiz Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -41,7 +41,7 @@ - #if 0 - static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; - #else --__RCSID("$NetBSD: error.c,v 1.24 2002/05/15 16:33:35 christos Exp $"); -+__RCSID("$NetBSD: error.c,v 1.25 2002/05/25 23:09:06 wiz Exp $"); - #endif - #endif /* not lint */ - -@@ -51,6 +51,7 @@ - - #include <signal.h> - #include <stdlib.h> -+#include <string.h> - #include <unistd.h> - #include <errno.h> - -@@ -60,6 +61,8 @@ - #include "output.h" - #include "error.h" - #include "show.h" -+#include "eval.h" -+#include "parser.h" - - - /* -@@ -68,13 +71,12 @@ - - struct jmploc *handler; - int exception; --volatile int suppressint; --volatile int intpending; --char *commandname; -+int suppressint; -+volatile sig_atomic_t intpending; - - --static void exverror __P((int, const char *, va_list)) -- __attribute__((__noreturn__)); -+static void exverror(int, const char *, va_list) __attribute__((__noreturn__)); -+static void vwarn(const char *, va_list); - - /* - * Called to raise an exception. Since C doesn't include exceptions, we -@@ -86,8 +88,12 @@ - exraise(e) - int e; - { -+#ifdef DEBUG - if (handler == NULL) - abort(); -+#endif -+ INTOFF; -+ - exception = e; - longjmp(handler->loc, 1); - } -@@ -97,29 +103,18 @@ - * Called from trap.c when a SIGINT is received. (If the user specifies - * that SIGINT is to be trapped or ignored using the trap builtin, then - * this routine is not called.) Suppressint is nonzero when interrupts -- * are held using the INTOFF macro. The call to _exit is necessary because -- * there is a short period after a fork before the signal handlers are -- * set to the appropriate value for the child. (The test for iflag is -- * just defensive programming.) -+ * are held using the INTOFF macro. (The test for iflag is just -+ * defensive programming.) - */ - - void - onint() { -- sigset_t sigset; -- -- if (suppressint) { -- intpending++; -- return; -- } - intpending = 0; -- sigemptyset(&sigset); -- sigprocmask(SIG_SETMASK, &sigset, NULL); -- if (rootshell && iflag) -- exraise(EXINT); -- else { -+ if (!(rootshell && iflag)) { - signal(SIGINT, SIG_DFL); - raise(SIGINT); - } -+ exraise(EXINT); - /* NOTREACHED */ - } - -@@ -135,73 +130,37 @@ - const char *msg; - va_list ap; - { -- CLEAR_PENDING_INT; -- INTOFF; -- - #ifdef DEBUG - if (msg) - TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); - else - TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); - #endif -- if (msg) { -- if (commandname) -- outfmt(&errout, "%s: ", commandname); -- doformat(&errout, msg, ap); -- out2c('\n'); -- } -+ vwarn(msg, ap); - flushall(); - exraise(cond); - /* NOTREACHED */ - } - - --#ifdef __STDC__ - void - error(const char *msg, ...) --#else --void --error(va_alist) -- va_dcl --#endif - { --#ifndef __STDC__ -- const char *msg; --#endif - va_list ap; --#ifdef __STDC__ -+ - va_start(ap, msg); --#else -- va_start(ap); -- msg = va_arg(ap, const char *); --#endif - exverror(EXERROR, msg, ap); - /* NOTREACHED */ - va_end(ap); - } - - --#ifdef __STDC__ - void - exerror(int cond, const char *msg, ...) --#else --void --exerror(va_alist) -- va_dcl --#endif - { --#ifndef __STDC__ -- int cond; -- const char *msg; --#endif - va_list ap; --#ifdef __STDC__ -+ - va_start(ap, msg); --#else -- va_start(ap); -- cond = va_arg(ap, int); -- msg = va_arg(ap, const char *); --#endif - exverror(cond, msg, ap); - /* NOTREACHED */ - va_end(ap); -@@ -223,56 +182,14 @@ - #define ALL (E_OPEN|E_CREAT|E_EXEC) - - STATIC const struct errname errormsg[] = { -- { EINTR, ALL, "interrupted" }, -- { EACCES, ALL, "permission denied" }, -- { EIO, ALL, "I/O error" }, -- { EEXIST, ALL, "file exists" }, -- { ENOENT, E_OPEN, "no such file" }, -- { ENOENT, E_CREAT,"directory nonexistent" }, -+ { ENOENT, E_OPEN, "No such file" }, -+ { ENOENT, E_CREAT,"Directory nonexistent" }, - { ENOENT, E_EXEC, "not found" }, -- { ENOTDIR, E_OPEN, "no such file" }, -- { ENOTDIR, E_CREAT,"directory nonexistent" }, -+ { ENOTDIR, E_OPEN, "No such file" }, -+ { ENOTDIR, E_CREAT,"Directory nonexistent" }, - { ENOTDIR, E_EXEC, "not found" }, -- { EISDIR, ALL, "is a directory" }, --#ifdef notdef -- { EMFILE, ALL, "too many open files" }, --#endif -- { ENFILE, ALL, "file table overflow" }, -- { ENOSPC, ALL, "file system full" }, --#ifdef EDQUOT -- { EDQUOT, ALL, "disk quota exceeded" }, --#endif --#ifdef ENOSR -- { ENOSR, ALL, "no streams resources" }, --#endif -- { ENXIO, ALL, "no such device or address" }, -- { EROFS, ALL, "read-only file system" }, -- { ETXTBSY, ALL, "text busy" }, - #ifdef SYSV -- { EAGAIN, E_EXEC, "not enough memory" }, --#endif -- { ENOMEM, ALL, "not enough memory" }, --#ifdef ENOLINK -- { ENOLINK, ALL, "remote access failed" }, --#endif --#ifdef EMULTIHOP -- { EMULTIHOP, ALL, "remote access failed" }, --#endif --#ifdef ECOMM -- { ECOMM, ALL, "remote access failed" }, --#endif --#ifdef ESTALE -- { ESTALE, ALL, "remote access failed" }, --#endif --#ifdef ETIMEDOUT -- { ETIMEDOUT, ALL, "remote access failed" }, --#endif --#ifdef ELOOP -- { ELOOP, ALL, "symbolic link loop" }, --#endif -- { E2BIG, E_EXEC, "argument list too long" }, --#ifdef ELIBACC -- { ELIBACC, E_EXEC, "shared library missing" }, -+ { EAGAIN, E_EXEC, "Not enough memory" }, - #endif - { 0, 0, NULL }, - }; -@@ -290,12 +207,55 @@ - int action; - { - struct errname const *ep; -- static char buf[12]; - - for (ep = errormsg ; ep->errcode ; ep++) { - if (ep->errcode == e && (ep->action & action) != 0) - return ep->msg; - } -- fmtstr(buf, sizeof buf, "error %d", e); -- return buf; -+ return strerror(e); -+} -+ -+ -+#ifdef REALLY_SMALL -+void -+__inton() { -+ if (--suppressint == 0 && intpending) { -+ onint(); -+ } -+} -+#endif -+ -+ -+ -+/* -+ * Print an error message for the current command. -+ */ -+static void vwarn(const char *const msg, va_list ap) { -+ struct output *errs; -+ const char *name; -+ const char *fmt; -+ -+ errs = out2; -+ name = arg0; -+ fmt = "%s: "; -+ if (commandname) { -+ name = commandname; -+ fmt = "%s: %d: "; -+ } -+ outfmt(errs, fmt, name, startlinno); -+ doformat(errs, msg, ap); -+#if FLUSHERR -+ outc('\n', errs); -+#else -+ outcslow('\n', errs); -+#endif -+} -+ -+ -+void warnx(const char *msg, ...) { -+ va_list ap; -+ -+ va_start(ap, msg); -+ vwarn(msg, ap); -+ va_end(ap); - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/error.h bin_NetBSD-1.6release/src/bin/sh/error.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/error.h 2001-02-05 11:15:29.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/error.h 2003-02-08 14:35:42.000000000 +0000 -@@ -38,6 +38,9 @@ - * @(#)error.h 8.2 (Berkeley) 5/4/95 - */ - -+#include <setjmp.h> -+#include <signal.h> -+ - /* - * Types of operations (passed to the errmsg routine). - */ -@@ -57,8 +60,6 @@ - * inner scope, and restore handler on exit from the scope. - */ - --#include <setjmp.h> -- - struct jmploc { - jmp_buf loc; - }; -@@ -71,6 +72,7 @@ - #define EXERROR 1 /* a generic error */ - #define EXSHELLPROC 2 /* execute a shell procedure */ - #define EXEXEC 3 /* command execution failed */ -+#define EXEXIT 4 /* exit the shell */ - - - /* -@@ -80,20 +82,53 @@ - * more fun than worrying about efficiency and portability. :-)) - */ - --extern volatile int suppressint; --extern volatile int intpending; -+extern int suppressint; -+extern volatile sig_atomic_t intpending; - --#define INTOFF suppressint++ --#define INTON { if (--suppressint == 0 && intpending) onint(); } --#define FORCEINTON {suppressint = 0; if (intpending) onint();} -+#define barrier() ({ __asm__ __volatile__ ("": : :"memory"); }) -+#define INTOFF \ -+ ({ \ -+ suppressint++; \ -+ barrier(); \ -+ 0; \ -+ }) -+#ifdef REALLY_SMALL -+void __inton __P((void)); -+#define INTON __inton() -+#else -+#define INTON \ -+ ({ \ -+ barrier(); \ -+ if (--suppressint == 0 && intpending) onint(); \ -+ 0; \ -+ }) -+#endif -+#define FORCEINTON \ -+ ({ \ -+ barrier(); \ -+ suppressint = 0; \ -+ if (intpending) onint(); \ -+ 0; \ -+ }) -+#define SAVEINT(v) ((v) = suppressint) -+#define RESTOREINT(v) \ -+ ({ \ -+ barrier(); \ -+ if ((suppressint = (v)) == 0 && intpending) onint(); \ -+ }) - #define CLEAR_PENDING_INT intpending = 0 - #define int_pending() intpending - - void exraise __P((int)) __attribute__((__noreturn__)); -+#ifdef USE_NORETURN -+void onint __P((void)) __attribute__((__noreturn__)); -+#else - void onint __P((void)); -+#endif - void error __P((const char *, ...)) __attribute__((__noreturn__)); - void exerror __P((int, const char *, ...)) __attribute__((__noreturn__)); - const char *errmsg __P((int, int)); -+void warnx __P((const char *, ...)); - - - /* -@@ -101,7 +136,7 @@ - * so we use _setjmp instead. - */ - --#if defined(BSD) && !defined(__SVR4) -+#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__) - #define setjmp(jmploc) _setjmp(jmploc) - #define longjmp(jmploc, val) _longjmp(jmploc, val) - #endif -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/eval.c bin_NetBSD-1.6release/src/bin/sh/eval.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/eval.c 2002-05-16 11:41:20.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/eval.c 2003-02-08 14:35:42.000000000 +0000 -@@ -45,8 +45,11 @@ - #endif - #endif /* not lint */ - -+#include <sys/types.h> - #include <signal.h> -+#include <malloc.h> - #include <unistd.h> -+#include <errno.h> - - /* - * Evaluate a command. -@@ -98,9 +101,18 @@ - STATIC void evalcase __P((union node *, int)); - STATIC void evalsubshell __P((union node *, int)); - STATIC void expredir __P((union node *)); --STATIC void evalpipe __P((union node *)); -+STATIC void evalpipe __P((union node *, int)); -+#ifdef notyet - STATIC void evalcommand __P((union node *, int, struct backcmd *)); -+#else -+STATIC void evalcommand __P((union node *, int)); -+#endif - STATIC void prehash __P((union node *)); -+STATIC void eprintlist __P((struct strlist *)); -+#if !defined(__alpha__) || !defined(GCC_BROKEN_NG) -+STATIC -+#endif -+void evaltreenr __P((union node *, int)) __attribute__ ((noreturn)); - - - /* -@@ -115,10 +127,6 @@ - loopnest = 0; - funcnest = 0; - } -- --SHELLPROC { -- exitstatus = 0; --} - #endif - - -@@ -142,8 +150,7 @@ - STARTSTACKSTR(concat); - ap = argv + 2; - for (;;) { -- while (*p) -- STPUTC(*p++, concat); -+ concat = stputs(p, concat); - if ((p = *ap++) == NULL) - break; - STPUTC(' ', concat); -@@ -170,10 +177,12 @@ - struct stackmark smark; - - setstackmark(&smark); -- setinputstring(s, 1); -+ setinputstring(s); - while ((n = parsecmd(0)) != NEOF) { - evaltree(n, flag); - popstackmark(&smark); -+ if (evalskip) -+ break; - } - popfile(); - popstackmark(&smark); -@@ -191,9 +200,12 @@ - union node *n; - int flags; - { -+ int checkexit = 0; -+ void (*evalfn)(union node *, int); -+ unsigned isor; -+ int status; - if (n == NULL) { - TRACE(("evaltree(NULL) called\n")); -- exitstatus = 0; - goto out; - } - #ifndef SMALL -@@ -201,89 +213,122 @@ - #endif - TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type)); - switch (n->type) { -- case NSEMI: -- evaltree(n->nbinary.ch1, flags & EV_TESTED); -- if (evalskip) -- goto out; -- evaltree(n->nbinary.ch2, flags); -- break; -- case NAND: -- evaltree(n->nbinary.ch1, EV_TESTED); -- if (evalskip || exitstatus != 0) { -- /* don't bomb out on "set -e; false && true" */ -- flags |= EV_TESTED; -- goto out; -- } -- evaltree(n->nbinary.ch2, flags | EV_TESTED); -- break; -- case NOR: -- evaltree(n->nbinary.ch1, EV_TESTED); -- if (evalskip || exitstatus == 0) -- goto out; -- evaltree(n->nbinary.ch2, flags | EV_TESTED); -+ default: -+#ifdef DEBUG -+ out1fmt("Node type = %d\n", n->type); -+#ifndef USE_GLIBC_STDIO -+ flushout(out1); -+#endif - break; -+#endif -+ case NNOT: -+ evaltree(n->nnot.com, EV_TESTED); -+ status = !exitstatus; -+ goto setstatus; - case NREDIR: - expredir(n->nredir.redirect); -- redirect(n->nredir.redirect, REDIR_PUSH); -- evaltree(n->nredir.n, flags); -- popredir(); -+ status = redirectsafe(n->nredir.redirect, REDIR_PUSH); -+ if (!status) { -+ evaltree(n->nredir.n, flags & EV_TESTED); -+ status = exitstatus; -+ } -+ popredir(0); -+ goto setstatus; -+ case NCMD: -+#ifdef notyet -+ if (eflag && !(flags & EV_TESTED)) -+ checkexit = ~0; -+ evalcommand(n, flags, (struct backcmd *)NULL); - break; -+#else -+ evalfn = evalcommand; -+checkexit: -+ if (eflag && !(flags & EV_TESTED)) -+ checkexit = ~0; -+ goto calleval; -+#endif -+ case NFOR: -+ evalfn = evalfor; -+ goto calleval; -+ case NWHILE: -+ case NUNTIL: -+ evalfn = evalloop; -+ goto calleval; - case NSUBSHELL: -- evalsubshell(n, flags); -- break; - case NBACKGND: -- evalsubshell(n, flags); -+ evalfn = evalsubshell; -+ goto calleval; -+ case NPIPE: -+ evalfn = evalpipe; -+#ifdef notyet -+ if (eflag && !(flags & EV_TESTED)) -+ checkexit = ~0; -+ goto calleval; -+#else -+ goto checkexit; -+#endif -+ case NCASE: -+ evalfn = evalcase; -+ goto calleval; -+ case NAND: -+ case NOR: -+ case NSEMI: -+#if NAND + 1 != NOR -+#error NAND + 1 != NOR -+#endif -+#if NOR + 1 != NSEMI -+#error NOR + 1 != NSEMI -+#endif -+ isor = n->type - NAND; -+ evaltree( -+ n->nbinary.ch1, -+ (flags | ((isor >> 1) - 1)) & EV_TESTED -+ ); -+ if (!exitstatus == isor) - break; -- case NIF: { -- evaltree(n->nif.test, EV_TESTED); -- if (evalskip) -- goto out; -- if (exitstatus == 0) -- evaltree(n->nif.ifpart, flags); -- else if (n->nif.elsepart) -- evaltree(n->nif.elsepart, flags); -- else -- exitstatus = 0; -+ if (!evalskip) { -+ n = n->nbinary.ch2; -+evaln: -+ evalfn = evaltree; -+calleval: -+ evalfn(n, flags); - break; - } -- case NWHILE: -- case NUNTIL: -- evalloop(n, flags); - break; -- case NFOR: -- evalfor(n, flags); -- break; -- case NCASE: -- evalcase(n, flags); -+ case NIF: -+ evaltree(n->nif.test, EV_TESTED); -+ if (evalskip) - break; -+ if (exitstatus == 0) { -+ n = n->nif.ifpart; -+ goto evaln; -+ } else if (n->nif.elsepart) { -+ n = n->nif.elsepart; -+ goto evaln; -+ } -+ goto success; - case NDEFUN: - defun(n->narg.text, n->narg.next); -- exitstatus = 0; -- break; -- case NNOT: -- evaltree(n->nnot.com, EV_TESTED); -- exitstatus = !exitstatus; -- break; -- -- case NPIPE: -- evalpipe(n); -- break; -- case NCMD: -- evalcommand(n, flags, (struct backcmd *)NULL); -- break; -- default: -- out1fmt("Node type = %d\n", n->type); -- flushout(&output); -+success: -+ status = 0; -+setstatus: -+ exitstatus = status; - break; - } - out: - if (pendingsigs) - dotrap(); -- if ((flags & EV_EXIT) != 0) -- exitshell(exitstatus); -+ if (flags & EV_EXIT || checkexit & exitstatus) -+ exraise(EXEXIT); - } - - -+#if !defined(__alpha__) || !defined(GCC_BROKEN_NG) -+STATIC -+#endif -+void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"))); -+ -+ - STATIC void - evalloop(n, flags) - union node *n; -@@ -293,6 +338,7 @@ - - loopnest++; - status = 0; -+ flags &= EV_TESTED; - for (;;) { - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip) { -@@ -311,7 +357,7 @@ - if (exitstatus == 0) - break; - } -- evaltree(n->nbinary.ch2, flags & EV_TESTED); -+ evaltree(n->nbinary.ch2, flags); - status = exitstatus; - if (evalskip) - goto skipping; -@@ -344,9 +390,10 @@ - - exitstatus = 0; - loopnest++; -+ flags &= EV_TESTED; - for (sp = arglist.list ; sp ; sp = sp->next) { - setvar(n->nfor.var, sp->text, 0); -- evaltree(n->nfor.body, flags & EV_TESTED); -+ evaltree(n->nfor.body, flags); - if (evalskip) { - if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = 0; -@@ -377,6 +424,7 @@ - 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 (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { -@@ -405,20 +453,28 @@ - { - struct job *jp; - int backgnd = (n->type == NBACKGND); -+ int status; - - expredir(n->nredir.redirect); -+ if (!backgnd && flags & EV_EXIT && !trap[0]) -+ goto nofork; -+ INTOFF; - jp = makejob(n, 1); - if (forkshell(jp, n, backgnd) == 0) { -+ INTON; -+ flags |= EV_EXIT; - if (backgnd) - flags &=~ EV_TESTED; -+nofork: - redirect(n->nredir.redirect, 0); -- evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ -+ evaltreenr(n->nredir.n, flags); -+ /* never returns */ - } -- if (! backgnd) { -- INTOFF; -- exitstatus = waitforjob(jp); -+ status = 0; -+ if (!backgnd) -+ status = waitforjob(jp); -+ exitstatus = status; - INTON; -- } - } - - -@@ -467,8 +523,9 @@ - */ - - STATIC void --evalpipe(n) -+evalpipe(n, flags) - union node *n; -+ int flags; - { - struct job *jp; - struct nodelist *lp; -@@ -480,6 +537,7 @@ - pipelen = 0; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) - pipelen++; -+ flags |= EV_EXIT; - INTOFF; - jp = makejob(n, pipelen); - prevfd = -1; -@@ -494,33 +552,29 @@ - } - if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { - INTON; -+ if (pip[1] >= 0) { -+ close(pip[0]); -+ } - if (prevfd > 0) { -- close(0); -- copyfd(prevfd, 0); -+ dup2(prevfd, 0); - close(prevfd); - } -- if (pip[1] >= 0) { -- close(pip[0]); -- if (pip[1] != 1) { -- close(1); -- copyfd(pip[1], 1); -+ if (pip[1] > 1) { -+ dup2(pip[1], 1); - close(pip[1]); - } -- } -- evaltree(lp->n, EV_EXIT); -+ evaltree(lp->n, flags); - } - if (prevfd >= 0) - close(prevfd); - prevfd = pip[0]; - close(pip[1]); - } -- INTON; - if (n->npipe.backgnd == 0) { -- INTOFF; - exitstatus = waitforjob(jp); - TRACE(("evalpipe: job done exit status %d\n", exitstatus)); -- INTON; - } -+ INTON; - } - - -@@ -595,10 +649,16 @@ - */ - - STATIC void -+#ifdef notyet - evalcommand(cmd, flags, backcmd) - union node *cmd; - int flags; - struct backcmd *backcmd; -+#else -+evalcommand(cmd, flags) -+ union node *cmd; -+ int flags; -+#endif - { - struct stackmark smark; - union node *argp; -@@ -607,25 +667,30 @@ - char **argv; - int argc; - char **envp; -- int varflag; - struct strlist *sp; - int mode; -+#ifdef notyet - int pip[2]; -+#endif - struct cmdentry cmdentry; - struct job *jp; -- struct jmploc jmploc; -- struct jmploc *volatile savehandler; - char *volatile savecmdname; - volatile struct shparam saveparam; - struct localvar *volatile savelocalvars; -- volatile int e; - char *lastarg; -+ const char *path; -+ int spclbltin; -+ int redir; -+ struct jmploc *volatile savehandler; -+ struct jmploc jmploc; - #if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &argv; - (void) &argc; - (void) &lastarg; - (void) &flags; -+ (void) &spclbltin; -+ (void) &redir; - #endif - - /* First expand the arguments. */ -@@ -633,22 +698,15 @@ - setstackmark(&smark); - arglist.lastp = &arglist.list; - varlist.lastp = &varlist.list; -- varflag = 1; -+ arglist.list = 0; - oexitstatus = exitstatus; - exitstatus = 0; -- for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { -- char *p = argp->narg.text; -- if (varflag && is_name(*p)) { -- do { -- p++; -- } while (is_in_name(*p)); -- if (*p == '=') { -+ path = pathval(); -+ for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { - expandarg(argp, &varlist, EXP_VARTILDE); -- continue; -- } - } -+ for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) { - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); -- varflag = 0; - } - *arglist.lastp = NULL; - *varlist.lastp = NULL; -@@ -670,77 +728,140 @@ - - /* Print the command if xflag is set. */ - if (xflag) { -+#ifdef FLUSHERR - outc('+', &errout); -- for (sp = varlist.list ; sp ; sp = sp->next) { -- outc(' ', &errout); -- out2str(sp->text); -- } -- for (sp = arglist.list ; sp ; sp = sp->next) { -- outc(' ', &errout); -- out2str(sp->text); -- } -+#else -+ outcslow('+', &errout); -+#endif -+ eprintlist(varlist.list); -+ eprintlist(arglist.list); -+#ifdef FLUSHERR - outc('\n', &errout); - flushout(&errout); -+#else -+ outcslow('\n', &errout); -+#endif - } - -+ redir = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH); -+ - /* Now locate the command. */ - if (argc == 0) { - cmdentry.cmdtype = CMDBUILTIN; -- cmdentry.u.index = BLTINCMD; -+ cmdentry.u.cmd = BLTINCMD; -+ spclbltin = 1; - } else { -- static const char PATH[] = "PATH="; -- const char *path = pathval(); -+ const char *oldpath; -+ int findflag = DO_ERR; -+ int oldfindflag; - - /* - * Modify the command lookup path, if a PATH= assignment - * is present - */ - for (sp = varlist.list ; sp ; sp = sp->next) -- if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) -- path = sp->text + sizeof(PATH) - 1; -- -- find_command(argv[0], &cmdentry, DO_ERR, path); -+ if (varequal(sp->text, defpathvar)) { -+ path = sp->text + 5; -+ findflag |= DO_BRUTE; -+ } -+ oldpath = path; -+ oldfindflag = findflag; -+ spclbltin = -1; -+ for(;;) { -+ find_command(argv[0], &cmdentry, findflag, path); - if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ -- exitstatus = 127; -- flushout(&errout); -- return; -+ goto notfound; - } -- /* implement the bltin builtin here */ -- if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) { -- for (;;) { -+ /* implement bltin and command here */ -+ if (cmdentry.cmdtype != CMDBUILTIN) { -+ break; -+ } -+ if (spclbltin < 0) { -+ spclbltin = -+ !!( -+ cmdentry.u.cmd->flags & -+ BUILTIN_SPECIAL -+ ) * 2 -+ ; -+ } -+ if (cmdentry.u.cmd == BLTINCMD) { -+ for(;;) { -+ struct builtincmd *bcmd; -+ - argv++; - if (--argc == 0) -- break; -- if ((cmdentry.u.index = find_builtin(*argv)) < 0) { -+ goto found; -+ if (!(bcmd = find_builtin(*argv))) { - outfmt(&errout, "%s: not found\n", *argv); -+notfound: - exitstatus = 127; -+#ifdef FLUSHERR - flushout(&errout); -- return; -+#endif -+ goto out; - } -- if (cmdentry.u.index != BLTINCMD) -+ cmdentry.u.cmd = bcmd; -+ if (bcmd != BLTINCMD) - break; - } - } -+ if (cmdentry.u.cmd == COMMANDCMD) { -+ argv++; -+ if (--argc == 0) { -+ goto found; -+ } -+ if (*argv[0] == '-') { -+ if (!equal(argv[0], "-p")) { -+ argv--; -+ argc++; -+ break; -+ } -+ argv++; -+ if (--argc == 0) { -+ goto found; -+ } -+ path = defpath; -+ findflag |= DO_BRUTE; -+ } else { -+ path = oldpath; -+ findflag = oldfindflag; -+ } -+ findflag |= DO_NOFUN; -+ continue; -+ } -+found: -+ break; -+ } - } - - /* Fork off a child process if necessary. */ -- if (cmd->ncmd.backgnd -- || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) -+ if ( -+ ( -+ cmdentry.cmdtype == CMDNORMAL && -+ (!(flags & EV_EXIT) || trap[0]) -+ ) -+#ifdef notyet - || ((flags & EV_BACKCMD) != 0 - && (cmdentry.cmdtype != CMDBUILTIN -- || cmdentry.u.index == DOTCMD -- || cmdentry.u.index == EVALCMD))) { -+ || cmdentry.u.bcmd == DOTCMD -+ || cmdentry.u.bcmd == EVALCMD)) -+#endif -+ ) { -+ INTOFF; - jp = makejob(cmd, 1); -- mode = cmd->ncmd.backgnd; -+ mode = FORK_FG; -+#ifdef notyet - if (flags & EV_BACKCMD) { - mode = FORK_NOJOB; - if (pipe(pip) < 0) - error("Pipe call failed"); - } -+#endif - if (forkshell(jp, cmd, mode) != 0) - goto parent; /* at end of routine */ -- if (flags & EV_BACKCMD) { - FORCEINTON; -+#ifdef notyet -+ if (flags & EV_BACKCMD) { - close(pip[0]); - if (pip[1] != 1) { - close(1); -@@ -748,148 +869,168 @@ - close(pip[1]); - } - } -+#endif - flags |= EV_EXIT; -+ } else { -+ flags &= ~EV_EXIT; - } - - /* This is the child process if a fork occurred. */ - /* Execute the command. */ -- if (cmdentry.cmdtype == CMDFUNCTION) { -+ if (redir) { -+ /* We have a redirection error. */ -+ exitstatus = redir; -+ if (spclbltin == 2) -+ exraise(EXERROR); -+ } else if (cmdentry.cmdtype == CMDFUNCTION) { - #ifdef DEBUG - trputs("Shell function: "); trargs(argv); - #endif -- redirect(cmd->ncmd.redirect, REDIR_PUSH); -+ exitstatus = oexitstatus; - saveparam = shellparam; -- shellparam.malloc = 0; -- shellparam.reset = 1; -- shellparam.nparam = argc - 1; -- shellparam.p = argv + 1; -- shellparam.optnext = NULL; -- INTOFF; - savelocalvars = localvars; -- localvars = NULL; -- INTON; -+ exception = -1; - if (setjmp(jmploc.loc)) { -- if (exception == EXSHELLPROC) { -- freeparam((volatile struct shparam *) -- &saveparam); -- } else { -- freeparam(&shellparam); -- shellparam = saveparam; -- } -- poplocalvars(); -- localvars = savelocalvars; -- handler = savehandler; -- longjmp(handler->loc, 1); -+ goto funcdone; - } -+ INTOFF; - savehandler = handler; - handler = &jmploc; -- for (sp = varlist.list ; sp ; sp = sp->next) -- mklocal(sp->text); -+ localvars = NULL; -+ shellparam.malloc = 0; -+ cmdentry.u.func->count++; -+ INTON; -+ shellparam.nparam = argc - 1; -+ shellparam.p = argv + 1; -+ shellparam.optind = 1; -+ shellparam.optoff = -1; -+ listsetvar(varlist.list, 0); - funcnest++; -- evaltree(cmdentry.u.func, flags & EV_TESTED); -+ evaltree(&cmdentry.u.func->n, flags & EV_TESTED); - funcnest--; -+funcdone: - INTOFF; -+ freefunc(cmdentry.u.func); - poplocalvars(); - localvars = savelocalvars; - freeparam(&shellparam); - shellparam = saveparam; - handler = savehandler; -- popredir(); - INTON; -+ if (exception >= 0) { -+ longjmp(handler->loc, 1); -+ } - if (evalskip == SKIPFUNC) { - evalskip = 0; - skipcount = 0; - } -- if (flags & EV_EXIT) -- exitshell(exitstatus); - } else if (cmdentry.cmdtype == CMDBUILTIN) { - #ifdef DEBUG - trputs("builtin command: "); trargs(argv); - #endif -- mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; -- if (flags == EV_BACKCMD) { -- memout.nleft = 0; -- memout.nextc = memout.buf; -- memout.bufsize = 64; -- mode |= REDIR_BACKQ; -+ if (spclbltin) { -+ int f = 0; -+ if (cmdentry.u.cmd == EXECCMD) { -+ redir++; -+ if (argc > 1) -+ f = VEXPORT; -+ } -+ listsetvar(varlist.list, f); - } -- redirect(cmd->ncmd.redirect, mode); - savecmdname = commandname; - cmdenviron = varlist.list; -- e = -1; -+ exception = -1; - if (setjmp(jmploc.loc)) { -- e = exception; -- exitstatus = (e == EXINT)? SIGINT+128 : 2; - goto cmddone; - } - savehandler = handler; - handler = &jmploc; -+#ifdef notyet -+ if (flags == EV_BACKCMD) { -+#ifdef USE_GLIBC_STDIO -+ openmemout(); -+#else -+ memout.nleft = 0; -+ memout.nextc = memout.buf; -+ memout.bufsize = 64; -+#endif -+ } -+#endif - commandname = argv[0]; - argptr = argv + 1; - optptr = NULL; /* initialize nextopt */ -- exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); -+ exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv); - flushall(); - cmddone: -+ exitstatus |= outerr(out1); -+#ifdef notyet - out1 = &output; - out2 = &errout; -+#endif - freestdout(); - cmdenviron = NULL; -- if (e != EXSHELLPROC) { - commandname = savecmdname; -- if (flags & EV_EXIT) -- exitshell(exitstatus); -- } - handler = savehandler; -- if (e != -1) { -- if ((e != EXERROR && e != EXEXEC) -- || cmdentry.u.index == BLTINCMD -- || cmdentry.u.index == DOTCMD -- || cmdentry.u.index == EVALCMD --#ifndef SMALL -- || cmdentry.u.index == HISTCMD --#endif -- || cmdentry.u.index == EXECCMD) -- exraise(e); -+ if (exception >= 0) { -+ int f = exception; -+ if (f != EXEXIT) { -+ int status = (f == EXINT) ? SIGINT + 128 : 2; -+ exitstatus = status; -+ } -+ if (f == EXINT || spclbltin & 2) { -+ exraise(f); -+ } - FORCEINTON; - } -- if (cmdentry.u.index != EXECCMD) -- popredir(); -+#ifdef notyet - if (flags == EV_BACKCMD) { -+#ifdef USE_GLIBC_STDIO -+ if (__closememout()) { -+ error( -+ "__closememout() failed: %s", -+ strerror(errno) -+ ); -+ } -+#endif - backcmd->buf = memout.buf; -+#ifdef USE_GLIBC_STDIO -+ backcmd->nleft = memout.bufsize; -+#else - backcmd->nleft = memout.nextc - memout.buf; -+#endif - memout.buf = NULL; - } -+#endif - } else { - #ifdef DEBUG - trputs("normal command: "); trargs(argv); - #endif -- clearredir(); -- redirect(cmd->ncmd.redirect, 0); - for (sp = varlist.list ; sp ; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); - envp = environment(); -- shellexec(argv, envp, pathval(), cmdentry.u.index); -+ shellexec(argv, envp, path, cmdentry.u.index); - } -+ if (flags & EV_EXIT) -+ exraise(EXEXIT); - goto out; - - parent: /* parent process gets here (if we forked) */ -- if (mode == 0) { /* argument to fork */ -- INTOFF; -+ if (mode == FORK_FG) { /* argument to fork */ - exitstatus = waitforjob(jp); -- INTON; -- } else if (mode == 2) { -+#ifdef notyet -+ } else if (mode == FORK_NOJOB) { - backcmd->fd = pip[0]; - close(pip[1]); - backcmd->jp = jp; -+#endif - } -+ INTON; - - out: -+ popredir(redir); - if (lastarg) - setvar("_", lastarg, 0); - popstackmark(&smark); -- -- if (eflag && exitstatus && !(flags & EV_TESTED)) -- exitshell(exitstatus); - } - - -@@ -897,8 +1038,7 @@ - /* - * Search for a command. This is called before we fork so that the - * location of the command will be available in the parent as well as -- * the child. The check for "goodname" is an overly conservative -- * check that the name will not be subject to expansion. -+ * the child. - */ - - STATIC void -@@ -908,9 +1048,7 @@ - struct cmdentry entry; - - if (n->type == NCMD && n->ncmd.args) -- if (goodname(n->ncmd.args->narg.text)) -- find_command(n->ncmd.args->narg.text, &entry, 0, -- pathval()); -+ find_command(n->ncmd.args->narg.text, &entry, 0, pathval()); - } - - -@@ -930,7 +1068,6 @@ - int argc; - char **argv; - { -- listsetvar(cmdenviron); - /* - * Preserve exitstatus of a previous possible redirection - * as POSIX mandates -@@ -957,6 +1094,8 @@ - { - int n = argc > 1 ? number(argv[1]) : 1; - -+ if (n <= 0) -+ error(illnum, argv[1]); - if (n > loopnest) - n = loopnest; - if (n > 0) { -@@ -1016,14 +1155,18 @@ - char **argv; - { - if (argc > 1) { -- struct strlist *sp; -- - iflag = 0; /* exit on error */ - mflag = 0; - optschanged(); -- for (sp = cmdenviron; sp ; sp = sp->next) -- setvareq(sp->text, VEXPORT|VSTACK); - shellexec(argv + 1, environment(), pathval(), 0); - } - return 0; - } -+ -+STATIC void -+eprintlist(struct strlist *sp) -+{ -+ for (; sp; sp = sp->next) { -+ outfmt(&errout, " %s",sp->text); -+ } -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/exec.c bin_NetBSD-1.6release/src/bin/sh/exec.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/exec.c 2001-02-05 11:15:30.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/exec.c 2003-02-08 14:35:42.000000000 +0000 -@@ -51,6 +51,9 @@ - #include <fcntl.h> - #include <errno.h> - #include <stdlib.h> -+#include <sysexits.h> -+#include <stdbool.h> -+#include <paths.h> - - /* - * When commands are first encountered, they are entered in a hash table. -@@ -99,19 +102,21 @@ - - STATIC struct tblentry *cmdtable[CMDTABLESIZE]; - STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */ --int exerrno = 0; /* Last exec error */ -+int exerrno; /* Last exec error */ - - - STATIC void tryexec __P((char *, char **, char **)); -+#if !defined(BSD) && !defined(linux) - STATIC void execinterp __P((char **, char **)); -+#endif - STATIC void printentry __P((struct tblentry *, int)); - STATIC void clearcmdentry __P((int)); - STATIC struct tblentry *cmdlookup __P((char *, int)); - STATIC void delete_cmd_entry __P((void)); -+STATIC int describe_command __P((struct output *, char *, int)); -+STATIC int path_change __P((const char *, int *)); - - --extern char *const parsekwd[]; -- - /* - * Exec a program. Never returns. If you change this routine, you may - * have to change the find_command routine as well. -@@ -126,6 +131,7 @@ - char *cmdname; - int e; - -+ clearredir(1); - if (strchr(argv[0], '/') != NULL) { - tryexec(argv[0], argv, envp); - e = errno; -@@ -164,11 +170,12 @@ - char **argv; - char **envp; - { -- int e; --#ifndef BSD -+ int repeated = 0; -+#if !defined(BSD) && !defined(linux) - char *p; - #endif - -+repeat: - #ifdef SYSV - do { - execve(cmd, argv, envp); -@@ -176,103 +183,22 @@ - #else - execve(cmd, argv, envp); - #endif -- e = errno; -- if (e == ENOEXEC) { -- initshellproc(); -- setinputfile(cmd, 0); -- commandname = arg0 = savestr(argv[0]); --#ifndef BSD -- pgetc(); pungetc(); /* fill up input buffer */ -- p = parsenextc; -- if (parsenleft > 2 && p[0] == '#' && p[1] == '!') { -- argv[0] = cmd; -- execinterp(argv, envp); -- } --#endif -- setparam(argv + 1); -- exraise(EXSHELLPROC); -- } -- errno = e; --} -- -- --#ifndef BSD --/* -- * Execute an interpreter introduced by "#!", for systems where this -- * feature has not been built into the kernel. If the interpreter is -- * the shell, return (effectively ignoring the "#!"). If the execution -- * of the interpreter fails, exit. -- * -- * This code peeks inside the input buffer in order to avoid actually -- * reading any input. It would benefit from a rewrite. -- */ -- --#define NEWARGS 5 -- --STATIC void --execinterp(argv, envp) -- char **argv, **envp; -- { -- int n; -- char *inp; -- char *outp; -- char c; -- char *p; -+ if (repeated++) { -+ ckfree(argv); -+ } else if (errno == ENOEXEC) { - char **ap; -- char *newargs[NEWARGS]; -- int i; -- char **ap2; - char **new; - -- n = parsenleft - 2; -- inp = parsenextc + 2; -- ap = newargs; -- for (;;) { -- while (--n >= 0 && (*inp == ' ' || *inp == '\t')) -- inp++; -- if (n < 0) -- goto bad; -- if ((c = *inp++) == '\n') -- break; -- if (ap == &newargs[NEWARGS]) --bad: error("Bad #! line"); -- STARTSTACKSTR(outp); -- do { -- STPUTC(c, outp); -- } while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n'); -- STPUTC('\0', outp); -- n++, inp--; -- *ap++ = grabstackstr(outp); -- } -- if (ap == newargs + 1) { /* if no args, maybe no exec is needed */ -- p = newargs[0]; -- for (;;) { -- if (equal(p, "sh") || equal(p, "ash")) { -- return; -- } -- while (*p != '/') { -- if (*p == '\0') -- goto break2; -- p++; -- } -- p++; -- } --break2:; -+ for (ap = argv; *ap; ap++) -+ ; -+ ap = new = ckmalloc((ap - argv + 2) * sizeof(char *)); -+ *ap++ = cmd = _PATH_BSHELL; -+ while ((*ap++ = *argv++)) -+ ; -+ argv = new; -+ goto repeat; - } -- i = (char *)ap - (char *)newargs; /* size in bytes */ -- if (i == 0) -- error("Bad #! line"); -- for (ap2 = argv ; *ap2++ != NULL ; ); -- new = ckmalloc(i + ((char *)ap2 - (char *)argv)); -- ap = newargs, ap2 = new; -- while ((i -= sizeof (char **)) >= 0) -- *ap2++ = *ap++; -- ap = argv; -- while (*ap2++ = *ap++); -- shellexec(new, envp, pathval(), 0); -- /* NOTREACHED */ - } --#endif - - - -@@ -296,7 +222,7 @@ - const char *p; - char *q; - const char *start; -- int len; -+ size_t len; - - if (*path == NULL) - return NULL; -@@ -345,6 +271,7 @@ - while ((c = nextopt("rv")) != '\0') { - if (c == 'r') { - clearcmdentry(0); -+ return 0; - } else if (c == 'v') { - verbose++; - } -@@ -352,27 +279,29 @@ - if (*argptr == NULL) { - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { -+ if (cmdp->cmdtype != CMDBUILTIN) { - printentry(cmdp, verbose); - } - } -+ } - return 0; - } -+ c = 0; - while ((name = *argptr) != NULL) { - if ((cmdp = cmdlookup(name, 0)) != NULL - && (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))) - delete_cmd_entry(); - find_command(name, &entry, DO_ERR, pathval()); -- if (verbose) { -- if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */ -+ if (entry.cmdtype == CMDUNKNOWN) c = 1; -+ else if (verbose) { - cmdp = cmdlookup(name, 0); -- printentry(cmdp, verbose); -- } -+ if (cmdp) printentry(cmdp, verbose); - flushall(); - } - argptr++; - } -- return 0; -+ return c; - } - - -@@ -399,9 +328,8 @@ - out1fmt("function %s", cmdp->cmdname); - if (verbose) { - INTOFF; -- name = commandtext(cmdp->param.func); -- out1c(' '); -- out1str(name); -+ name = commandtext(&cmdp->param.func->n); -+ out1fmt(" %s", name); - ckfree(name); - INTON; - } -@@ -410,9 +338,7 @@ - error("internal error: cmdtype %d", cmdp->cmdtype); - #endif - } -- if (cmdp->rehash) -- out1c('*'); -- out1c('\n'); -+ out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr); - } - - -@@ -433,14 +359,18 @@ - int idx; - int prev; - char *fullname; -- struct stat statb; -+ struct stat64 statb; - int e; -- int i; -+ int bltin; -+ int firstchange; -+ int updatetbl; -+ bool regular; -+ struct builtincmd *bcmd; - - /* If name contains a slash, don't use the hash table */ - if (strchr(name, '/') != NULL) { - if (act & DO_ABS) { -- while (stat(name, &statb) < 0) { -+ while (stat64(name, &statb) < 0) { - #ifdef SYSV - if (errno == EINTR) - continue; -@@ -460,23 +390,69 @@ - return; - } - -+ updatetbl = 1; -+ if (act & DO_BRUTE) { -+ firstchange = path_change(path, &bltin); -+ } else { -+ bltin = builtinloc; -+ firstchange = 9999; -+ } -+ - /* 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 && cmdp->rehash == 0) { -+ if (cmdp->cmdtype == CMDFUNCTION) { -+ if (act & DO_NOFUN) { -+ updatetbl = 0; -+ } else { -+ goto success; -+ } -+ } else if (act & DO_BRUTE) { -+ if ((cmdp->cmdtype == CMDNORMAL && -+ cmdp->param.index >= firstchange) || -+ (cmdp->cmdtype == CMDBUILTIN && -+ ((builtinloc < 0 && bltin >= 0) ? -+ bltin : builtinloc) >= firstchange)) { -+ /* need to recompute the entry */ -+ } else { -+ goto success; -+ } -+ } else { -+ goto success; -+ } -+ } -+ -+ bcmd = find_builtin(name); -+ regular = bcmd && bcmd->flags & BUILTIN_REGULAR; -+ -+ if (regular) { -+ if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) { - goto success; -+ } -+ } else if (act & DO_BRUTE) { -+ if (firstchange == 0) { -+ updatetbl = 0; -+ } -+ } - - /* If %builtin not in path, check for builtin next */ -- if (builtinloc < 0 && (i = find_builtin(name)) >= 0) { -+ if (regular || (bltin < 0 && bcmd)) { -+builtin: -+ if (!updatetbl) { -+ entry->cmdtype = CMDBUILTIN; -+ entry->u.cmd = bcmd; -+ return; -+ } - INTOFF; - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDBUILTIN; -- cmdp->param.index = i; -+ cmdp->param.cmd = bcmd; - INTON; - goto success; - } - - /* We have to search path. */ - prev = -1; /* where to start */ -- if (cmdp) { /* doing a rehash */ -+ if (cmdp && cmdp->rehash) { /* doing a rehash */ - if (cmdp->cmdtype == CMDBUILTIN) - prev = builtinloc; - else -@@ -489,30 +465,31 @@ - while ((fullname = padvance(&path, name)) != NULL) { - stunalloc(fullname); - idx++; -+ if (idx >= firstchange) { -+ updatetbl = 0; -+ } - if (pathopt) { - if (prefix("builtin", pathopt)) { -- if ((i = find_builtin(name)) < 0) -- goto loop; -- INTOFF; -- cmdp = cmdlookup(name, 1); -- cmdp->cmdtype = CMDBUILTIN; -- cmdp->param.index = i; -- INTON; -- goto success; -- } else if (prefix("func", pathopt)) { -+ if ((bcmd = find_builtin(name))) { -+ goto builtin; -+ } -+ continue; -+ } else if (!(act & DO_NOFUN) && -+ prefix("func", pathopt)) { - /* handled below */ - } else { -- goto loop; /* ignore unimplemented options */ -+ continue; /* ignore unimplemented options */ - } - } - /* if rehash, don't redo absolute path names */ -- if (fullname[0] == '/' && idx <= prev) { -+ if (fullname[0] == '/' && idx <= prev && -+ idx < firstchange) { - if (idx < prev) -- goto loop; -+ continue; - TRACE(("searchexec \"%s\": no change\n", name)); - goto success; - } -- while (stat(fullname, &statb) < 0) { -+ while (stat64(fullname, &statb) < 0) { - #ifdef SYSV - if (errno == EINTR) - continue; -@@ -523,7 +500,7 @@ - } - e = EACCES; /* if we fail, this will be the error */ - if (!S_ISREG(statb.st_mode)) -- goto loop; -+ continue; - if (pathopt) { /* this is a %func directory */ - stalloc(strlen(fullname) + 1); - readcmdfile(fullname); -@@ -545,6 +522,13 @@ - } - #endif - TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); -+ /* If we aren't called with DO_BRUTE and cmdp is set, it must -+ be a function and we're being called with DO_NOFUN */ -+ if (!updatetbl) { -+ entry->cmdtype = CMDNORMAL; -+ entry->u.index = idx; -+ return; -+ } - INTOFF; - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDNORMAL; -@@ -554,10 +538,10 @@ - } - - /* We failed. If there was an entry for this command, delete it */ -- if (cmdp) -+ if (cmdp && updatetbl) - delete_cmd_entry(); - if (act & DO_ERR) -- outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC)); -+ warnx("%s: %s", name, errmsg(e, E_EXEC)); - entry->cmdtype = CMDUNKNOWN; - return; - -@@ -573,17 +557,16 @@ - * Search the table of builtin commands. - */ - --int --find_builtin(name) -- char *name; -+struct builtincmd * -+find_builtin(const char *name) - { -- const struct builtincmd *bp; -+ struct builtincmd *bp; - -- for (bp = builtincmd ; bp->name ; bp++) { -- if (*bp->name == *name && equal(bp->name, name)) -- return bp->code; -- } -- return -1; -+ bp = bsearch( -+ &name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd), -+ pstrcmp -+ ); -+ return bp; - } - - -@@ -619,37 +602,12 @@ - changepath(newval) - const char *newval; - { -- const char *old, *new; -- int idx; - int firstchange; - int bltin; - -- old = pathval(); -- new = newval; -- firstchange = 9999; /* assume no change */ -- idx = 0; -- bltin = -1; -- for (;;) { -- if (*old != *new) { -- firstchange = idx; -- if ((*old == '\0' && *new == ':') -- || (*old == ':' && *new == '\0')) -- firstchange++; -- old = new; /* ignore subsequent differences */ -- } -- if (*new == '\0') -- break; -- if (*new == '%' && bltin < 0 && prefix("builtin", new + 1)) -- bltin = idx; -- if (*new == ':') { -- idx++; -- } -- new++, old++; -- } -+ firstchange = path_change(newval, &bltin); - if (builtinloc < 0 && bltin >= 0) - builtinloc = bltin; /* zap builtins */ -- if (builtinloc >= 0 && bltin < 0) -- firstchange = 0; - clearcmdentry(firstchange); - builtinloc = bltin; - } -@@ -687,41 +645,6 @@ - } - - --/* -- * Delete all functions. -- */ -- --#ifdef mkinit --MKINIT void deletefuncs __P((void)); -- --SHELLPROC { -- deletefuncs(); --} --#endif -- --void --deletefuncs() { -- struct tblentry **tblp; -- struct tblentry **pp; -- struct tblentry *cmdp; -- -- INTOFF; -- for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { -- pp = tblp; -- while ((cmdp = *pp) != NULL) { -- if (cmdp->cmdtype == CMDFUNCTION) { -- *pp = cmdp->next; -- freefunc(cmdp->param.func); -- ckfree(cmdp); -- } else { -- pp = &cmdp->next; -- } -- } -- } -- INTON; --} -- -- - - /* - * Locate a command in the command hash table. If "add" is nonzero, -@@ -780,6 +703,8 @@ - INTOFF; - cmdp = *lastcmdentry; - *lastcmdentry = cmdp->next; -+ if (cmdp->cmdtype == CMDFUNCTION) -+ freefunc(cmdp->param.func); - ckfree(cmdp); - INTON; - } -@@ -851,18 +776,14 @@ - * Delete a function if it exists. - */ - --int -+void - unsetfunc(name) - char *name; - { - struct tblentry *cmdp; - -- if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { -- freefunc(cmdp->param.func); -+ if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) - delete_cmd_entry(); -- return (0); -- } -- return (1); - } - - /* -@@ -874,74 +795,187 @@ - int argc; - char **argv; - { -- struct cmdentry entry; -- struct tblentry *cmdp; -- char * const *pp; -- struct alias *ap; - int i; - int err = 0; - - for (i = 1; i < argc; i++) { -- out1str(argv[i]); -- /* First look at the keywords */ -- for (pp = parsekwd; *pp; pp++) -- if (**pp == *argv[i] && equal(*pp, argv[i])) -- break; -+ err |= describe_command(out1, argv[i], 1); -+ } -+ return err; -+} - -- if (*pp) { -- out1str(" is a shell keyword\n"); -- continue; -+STATIC int -+describe_command(out, command, verbose) -+ struct output *out; -+ char *command; -+ int verbose; -+{ -+ struct cmdentry entry; -+ struct tblentry *cmdp; -+ const struct alias *ap; -+ const char *path = pathval(); -+ -+ if (verbose) { -+ outstr(command, out); -+ } -+ -+ /* First look at the keywords */ -+ if (findkwd(command)) { -+ outstr(verbose ? " is a shell keyword" : command, out); -+ goto out; - } - - /* Then look at the aliases */ -- if ((ap = lookupalias(argv[i], 1)) != NULL) { -- out1fmt(" is an alias for %s\n", ap->val); -- continue; -+ if ((ap = lookupalias(command, 0)) != NULL) { -+ if (verbose) { -+ outfmt(out, " is an alias for %s", ap->val); -+ } else { -+ outstr("alias ", out); -+ printalias(ap); -+ return 0; -+ } -+ goto out; - } - - /* Then check if it is a tracked alias */ -- if ((cmdp = cmdlookup(argv[i], 0)) != NULL) { -+ if ((cmdp = cmdlookup(command, 0)) != NULL) { - entry.cmdtype = cmdp->cmdtype; - entry.u = cmdp->param; -- } -- else { -+ } else { - /* Finally use brute force */ -- find_command(argv[i], &entry, DO_ABS, pathval()); -+ find_command(command, &entry, DO_ABS, path); - } - - switch (entry.cmdtype) { - case CMDNORMAL: { -- if (strchr(argv[i], '/') == NULL) { -- const char *path = pathval(); -- char *name; - int j = entry.u.index; -+ char *p; -+ if (j == -1) { -+ p = command; -+ } else { - do { -- name = padvance(&path, argv[i]); -- stunalloc(name); -+ p = padvance(&path, command); -+ stunalloc(p); - } while (--j >= 0); -- out1fmt(" is%s %s\n", -- cmdp ? " a tracked alias for" : "", name); -+ } -+ if (verbose) { -+ outfmt( -+ out, " is%s %s", -+ cmdp ? " a tracked alias for" : nullstr, p -+ ); - } else { -- if (access(argv[i], X_OK) == 0) -- out1fmt(" is %s\n", argv[i]); -- else -- out1fmt(": %s\n", strerror(errno)); -+ outstr(p, out); - } - break; - } -+ - case CMDFUNCTION: -- out1str(" is a shell function\n"); -+ if (verbose) { -+ outstr(" is a shell function", out); -+ } else { -+ outstr(command, out); -+ } - break; - - case CMDBUILTIN: -- out1str(" is a shell builtin\n"); -+ if (verbose) { -+ outfmt( -+ out, " is a %sshell builtin", -+ entry.u.cmd->flags & BUILTIN_SPECIAL ? -+ "special " : nullstr -+ ); -+ } else { -+ outstr(command, out); -+ } - break; - - default: -- out1str(": not found\n"); -- err |= 127; -+ if (verbose) { -+ outstr(": not found\n", out); -+ } -+ return 127; -+ } -+ -+out: -+ outc('\n', out); -+ return 0; -+} -+ -+int -+commandcmd(argc, argv) -+ int argc; -+ char **argv; -+{ -+ int c; -+ int default_path = 0; -+ int verify_only = 0; -+ int verbose_verify_only = 0; -+ -+ while ((c = nextopt("pvV")) != '\0') -+ switch (c) { -+ case 'p': -+ default_path = 1; - break; -+ case 'v': -+ verify_only = 1; -+ break; -+ case 'V': -+ verbose_verify_only = 1; -+ break; -+ default: -+ outfmt(out2, -+"command: nextopt returned character code 0%o\n", c); -+ return EX_SOFTWARE; - } -+ -+ if (default_path + verify_only + verbose_verify_only > 1 || -+ !*argptr) { -+ outfmt(out2, -+"command [-p] command [arg ...]\n"); -+ outfmt(out2, -+"command {-v|-V} command\n"); -+ return EX_USAGE; - } -- return err; -+ -+ if (verify_only || verbose_verify_only) { -+ return describe_command(out1, *argptr, verbose_verify_only); -+ } -+ -+ return 0; -+} -+ -+STATIC int -+path_change(newval, bltin) -+ const char *newval; -+ int *bltin; -+{ -+ const char *old, *new; -+ int idx; -+ int firstchange; -+ -+ old = pathval(); -+ new = newval; -+ firstchange = 9999; /* assume no change */ -+ idx = 0; -+ *bltin = -1; -+ for (;;) { -+ if (*old != *new) { -+ firstchange = idx; -+ if ((*old == '\0' && *new == ':') -+ || (*old == ':' && *new == '\0')) -+ firstchange++; -+ old = new; /* ignore subsequent differences */ -+ } -+ if (*new == '\0') -+ break; -+ if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1)) -+ *bltin = idx; -+ if (*new == ':') { -+ idx++; -+ } -+ new++, old++; -+ } -+ if (builtinloc >= 0 && *bltin < 0) -+ firstchange = 0; -+ return firstchange; - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/exec.h bin_NetBSD-1.6release/src/bin/sh/exec.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/exec.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/exec.h 2003-02-08 14:35:42.000000000 +0000 -@@ -49,13 +49,16 @@ - int cmdtype; - union param { - int index; -- union node *func; -+ struct funcnode *func; -+ const struct builtincmd *cmd; - } u; - }; - - - #define DO_ERR 1 /* find_command prints errors */ - #define DO_ABS 2 /* find_command checks absolute paths */ -+#define DO_NOFUN 4 /* find_command ignores functions */ -+#define DO_BRUTE 8 /* find_command ignores hash table */ - - extern const char *pathopt; /* set by padvance */ - extern int exerrno; /* last exec error */ -@@ -65,12 +68,12 @@ - char *padvance __P((const char **, const char *)); - int hashcmd __P((int, char **)); - void find_command __P((char *, struct cmdentry *, int, const char *)); --int find_builtin __P((char *)); -+struct builtincmd *find_builtin __P((const char *)); - void hashcd __P((void)); - void changepath __P((const char *)); --void deletefuncs __P((void)); - void getcmdentry __P((char *, struct cmdentry *)); - void addcmdentry __P((char *, struct cmdentry *)); - void defun __P((char *, union node *)); --int unsetfunc __P((char *)); -+void unsetfunc __P((char *)); - int typecmd __P((int, char **)); -+int commandcmd __P((int, char **)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/expand.c bin_NetBSD-1.6release/src/bin/sh/expand.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/expand.c 2002-05-16 11:41:20.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/expand.c 2003-02-08 14:35:42.000000000 +0000 -@@ -54,6 +54,15 @@ - #include <pwd.h> - #include <stdlib.h> - #include <stdio.h> -+#include <limits.h> -+#if defined(__GLIBC__) -+#if !defined(FNMATCH_BROKEN) -+#include <fnmatch.h> -+#if !defined(GLOB_BROKEN) -+#include <glob.h> -+#endif -+#endif -+#endif - - /* - * Routines to expand arguments to commands. We have to deal with -@@ -78,6 +87,15 @@ - #include "show.h" - - /* -+ * _rmescape() flags -+ */ -+#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ -+#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ -+#define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */ -+#define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ -+#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ -+ -+/* - * Structure specifying which parts of the string should be searched - * for IFS characters. - */ -@@ -89,34 +107,84 @@ - int nulonly; /* search for nul bytes only */ - }; - -- --char *expdest; /* output of current string */ --struct nodelist *argbackq; /* list of back quote expressions */ --struct ifsregion ifsfirst; /* first struct in list of ifs regions */ --struct ifsregion *ifslastp; /* last struct in list */ --struct arglist exparg; /* holds expanded arg list */ -+/* output of current string */ -+static char *expdest; -+/* list of back quote expressions */ -+static struct nodelist *argbackq; -+/* first struct in list of ifs regions */ -+static struct ifsregion ifsfirst; -+/* last struct in list */ -+static struct ifsregion *ifslastp; -+/* holds expanded arg list */ -+static struct arglist exparg; - - STATIC void argstr __P((char *, int)); - STATIC char *exptilde __P((char *, int)); - STATIC void expbackq __P((union node *, int, int)); --STATIC int subevalvar __P((char *, char *, int, int, int, int)); -+STATIC const char *subevalvar __P((char *, char *, int, int, int, int, int)); - STATIC char *evalvar __P((char *, int)); - STATIC int varisset __P((char *, int)); -+STATIC void strtodest __P((const char *, const char *, int)); -+STATIC void memtodest __P((const char *, size_t, const char *, int)); - STATIC void varvalue __P((char *, int, int)); - STATIC void recordregion __P((int, int, int)); - STATIC void removerecordregions __P((int)); - STATIC void ifsbreakup __P((char *, struct arglist *)); - STATIC void ifsfree __P((void)); - STATIC void expandmeta __P((struct strlist *, int)); -+#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) -+STATIC void addglob __P((const glob_t *)); -+#else - STATIC void expmeta __P((char *, char *)); -+#endif - STATIC void addfname __P((char *)); -+#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) - STATIC struct strlist *expsort __P((struct strlist *)); - STATIC struct strlist *msort __P((struct strlist *, int)); --STATIC int pmatch __P((char *, char *, int)); --STATIC char *cvtnum __P((int, char *)); -+#endif -+STATIC int patmatch __P((char *, const char *)); -+#if !defined(__GLIBC__) || defined(FNMATCH_BROKEN) -+STATIC int pmatch __P((const char *, const char *)); -+#else -+#define pmatch(a, b) !fnmatch((a), (b), 0) -+#endif -+STATIC int cvtnum __P((long)); -+STATIC size_t esclen __P((const char *, const char *)); -+STATIC char *scanleft __P((char *, char *, char *, char *, int, int)); -+STATIC char *scanright __P((char *, char *, char *, char *, int, int)); -+static void varunset(const char *, const char *, const char *, int) -+ __attribute__((__noreturn__)); - - extern int oexitstatus; - -+ -+/* -+ * Prepare a pattern for a glob(3) call. -+ * -+ * Returns an stalloced string. -+ */ -+ -+STATIC inline char * -+preglob(const char *pattern, int quoted, int flag) { -+ flag |= RMESCAPE_GLOB; -+ if (quoted) { -+ flag |= RMESCAPE_QUOTED; -+ } -+ return _rmescapes((char *)pattern, flag); -+} -+ -+ -+STATIC size_t -+esclen(const char *start, const char *p) { -+ size_t esc = 0; -+ -+ while (p > start && *--p == CTLESC) { -+ esc++; -+ } -+ return esc; -+} -+ -+ - /* - * Expand shell variables and backquotes inside a here document. - */ -@@ -196,64 +264,126 @@ - char *p; - int flag; - { -- char c; -+ static const char spclchars[] = { -+ '=', -+ ':', -+ CTLQUOTEMARK, -+ CTLENDVAR, -+ CTLESC, -+ CTLVAR, -+ CTLBACKQ, -+ CTLBACKQ | CTLQUOTE, -+ CTLENDARI, -+ 0 -+ }; -+ const char *reject = spclchars; -+ int c; - int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ -- int firsteq = 1; -+ int breakall = flag & EXP_WORD; -+ int inquotes; -+ size_t length; -+ int startloc; - -- if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) -+ if (!(flag & EXP_VARTILDE)) { -+ reject += 2; -+ } else if (flag & EXP_VARTILDE2) { -+ reject++; -+ } -+ inquotes = 0; -+ length = 0; -+ if (flag & EXP_TILDE) { -+ flag &= ~EXP_TILDE; -+tilde: - p = exptilde(p, flag); -+ } -+start: -+ startloc = expdest - stackblock(); - for (;;) { -- switch (c = *p++) { -+ length += strcspn(p + length, reject); -+ c = p[length]; -+ if ((c && !(c & 0x80)) || c == CTLENDARI) { -+ /* c == '=' || c == ':' || c == CTLENDARI */ -+ length++; -+ } -+ if (length > 0) { -+ int newloc; -+ expdest = stnputs(p, length, expdest); -+ newloc = expdest - stackblock(); -+ if (breakall && !inquotes && newloc > startloc) { -+ recordregion(startloc, newloc, 0); -+ } -+ startloc = newloc; -+ } -+ p += length + 1; -+ length = 0; -+ -+ switch (c) { - case '\0': -+ goto breakloop; -+ case '=': -+ if (flag & EXP_VARTILDE2) { -+ p--; -+ continue; -+ } -+ flag |= EXP_VARTILDE2; -+ reject++; -+ /* fall through */ -+ case ':': -+ /* -+ * sort of a hack - expand tildes in variable -+ * assignments (after the first '=' and after ':'s). -+ */ -+ if (*--p == '~') { -+ goto tilde; -+ } -+ continue; -+ } -+ -+ switch (c) { - case CTLENDVAR: /* ??? */ - goto breakloop; - case CTLQUOTEMARK: - /* "$@" syntax adherence hack */ -- if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=') -- break; -- if ((flag & EXP_FULL) != 0) -- STPUTC(c, expdest); -+ if ( -+ !inquotes && -+ !memcmp(p, dolatstr, DOLATSTRLEN) && -+ (p[4] == CTLQUOTEMARK || ( -+ p[4] == CTLENDVAR && -+ p[5] == CTLQUOTEMARK -+ )) -+ ) { -+ p = evalvar(p + 1, flag) + 1; -+ goto start; -+ } -+ inquotes = !inquotes; -+addquote: -+ if (quotes) { -+ p--; -+ length++; -+ startloc++; -+ } - break; - case CTLESC: -- if (quotes) -- STPUTC(c, expdest); -- c = *p++; -- STPUTC(c, expdest); -- break; -+ startloc++; -+ length++; -+ goto addquote; - case CTLVAR: - p = evalvar(p, flag); -- break; -+ goto start; - case CTLBACKQ: -+ c = 0; - case CTLBACKQ|CTLQUOTE: -- expbackq(argbackq->n, c & CTLQUOTE, flag); -+ expbackq(argbackq->n, c, quotes); - argbackq = argbackq->next; -- break; -+ goto start; - case CTLENDARI: -- expari(flag); -- break; -- case ':': -- case '=': -- /* -- * sort of a hack - expand tildes in variable -- * assignments (after the first '=' and after ':'s). -- */ -- STPUTC(c, expdest); -- if (flag & EXP_VARTILDE && *p == '~') { -- if (c == '=') { -- if (firsteq) -- firsteq = 0; -- else -- break; -- } -- p = exptilde(p, flag); -- } -- break; -- default: -- STPUTC(c, expdest); -+ p--; -+ expari(quotes); -+ goto start; - } - } --breakloop:; -- return; -+breakloop: -+ ; - } - - STATIC char * -@@ -262,11 +392,21 @@ - int flag; - { - char c, *startp = p; -+ char *name; - struct passwd *pw; - const char *home; - int quotes = flag & (EXP_FULL | EXP_CASE); -+ int startloc; - -- while ((c = *p) != '\0') { -+ if (*p == CTLESC && (flag & EXP_QWORD)) { -+ p++; -+ } -+ if (*p != '~') { -+ return startp; -+ } -+ name = p + 1; -+ -+ while ((c = *++p) != '\0') { - switch(c) { - case CTLESC: - return (startp); -@@ -277,28 +417,26 @@ - goto done; - break; - case '/': -+ case CTLENDVAR: - goto done; - } -- p++; - } - done: - *p = '\0'; -- if (*(startp+1) == '\0') { -- if ((home = lookupvar("HOME")) == NULL) -+ if (*name == '\0') { -+ if ((home = lookupvar(homestr)) == NULL) - goto lose; - } else { -- if ((pw = getpwnam(startp+1)) == NULL) -+ if ((pw = getpwnam(name)) == NULL) - goto lose; - home = pw->pw_dir; - } - if (*home == '\0') - goto lose; - *p = c; -- while ((c = *home++) != '\0') { -- if (quotes && SQSYNTAX[(int)c] == CCTL) -- STPUTC(CTLESC, expdest); -- STPUTC(c, expdest); -- } -+ startloc = expdest - stackblock(); -+ strtodest(home, SQSYNTAX, quotes); -+ recordregion(startloc, expdest - stackblock(), 0); - return (p); - lose: - *p = c; -@@ -352,61 +490,60 @@ - * evaluate, place result in (backed up) result, adjust string position. - */ - void --expari(flag) -- int flag; -+expari(quotes) -+ int quotes; - { - char *p, *start; -- int result; - int begoff; -- int quotes = flag & (EXP_FULL | EXP_CASE); -- int quoted; -+ int flag; -+ int len; - - /* ifsfree(); */ - - /* - * 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 if we add exponentation. 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. -+ * efficiency. Next we scan backwards looking for the -+ * start of arithmetic. - */ --#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10 --#error "integers with more than 10 digits are not supported" --#endif -- CHECKSTRSPACE(12 - 2, expdest); -- USTPUTC('\0', expdest); - start = stackblock(); - p = expdest - 1; -- while (*p != CTLARI && p >= start) -- --p; -- if (*p != CTLARI) -+ *p = '\0'; -+ p--; -+ do { -+ int esc; -+ -+ while (*p != CTLARI) { -+ p--; -+#ifdef DEBUG -+ if (p < start) { - error("missing CTLARI (shouldn't happen)"); -- if (p > start && *(p-1) == CTLESC) -- for (p = start; *p != CTLARI; p++) -- if (*p == CTLESC) -- p++; -+ } -+#endif -+ } -+ -+ esc = esclen(start, p); -+ if (!(esc % 2)) { -+ break; -+ } -+ -+ p -= esc + 1; -+ } while (1); - -- if (p[1] == '"') -- quoted=1; -- else -- quoted=0; - begoff = p - start; -+ - removerecordregions(begoff); -+ -+ flag = p[1]; -+ -+ expdest = p; -+ - if (quotes) -- rmescapes(p+2); -- result = arith(p+2); -- fmtstr(p, 12, "%d", result); -+ rmescapes(p + 2); - -- while (*p++) -- ; -+ len = cvtnum(arith(p + 2)); - -- if (quoted == 0) -- recordregion(begoff, p - 1 - start, 0); -- result = expdest - p + 1; -- STADJUST(-result, expdest); -+ if (flag != '"') -+ recordregion(begoff, begoff + len, 0); - } - - -@@ -415,42 +552,47 @@ - */ - - STATIC void --expbackq(cmd, quoted, flag) -+expbackq(cmd, quoted, quotes) - union node *cmd; - int quoted; -- int flag; -+ int quotes; - { - struct backcmd in; - int i; - char buf[128]; - char *p; - char *dest = expdest; -- struct ifsregion saveifs, *savelastp; -+ struct ifsregion saveifs; -+ struct ifsregion *savelastp; - struct nodelist *saveargbackq; -- char lastc; - int startloc = dest - stackblock(); - char const *syntax = quoted? DQSYNTAX : BASESYNTAX; - int saveherefd; -- int quotes = flag & (EXP_FULL | EXP_CASE); - -- INTOFF; -+ in.fd = -1; -+ in.buf = 0; -+ in.jp = 0; -+ - saveifs = ifsfirst; - savelastp = ifslastp; - saveargbackq = argbackq; - saveherefd = herefd; - herefd = -1; -- p = grabstackstr(dest); -- evalbackcmd(cmd, &in); -- ungrabstackstr(p, dest); -+ -+ INTOFF; -+ evalbackcmd(cmd, (struct backcmd *) &in); - ifsfirst = saveifs; - ifslastp = savelastp; - argbackq = saveargbackq; - herefd = saveherefd; - - p = in.buf; -- lastc = '\0'; -+ i = in.nleft; -+ if (i == 0) -+ goto read; - for (;;) { -- if (--in.nleft < 0) { -+ memtodest(p, i, syntax, quotes); -+read: - if (in.fd < 0) - break; - while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); -@@ -458,18 +600,12 @@ - if (i <= 0) - break; - p = buf; -- in.nleft = i - 1; -- } -- lastc = *p++; -- if (lastc != '\0') { -- if (quotes && syntax[(int)lastc] == CCTL) -- STPUTC(CTLESC, dest); -- STPUTC(lastc, dest); -- } - } - -+ dest = expdest; -+ - /* Eat all trailing newlines */ -- for (p--; lastc == '\n'; lastc = *--p) -+ for (; dest > stackblock() && dest[-1] == '\n';) - STUNPUTC(dest); - - if (in.fd >= 0) -@@ -478,6 +614,7 @@ - ckfree(in.buf); - if (in.jp) - exitstatus = waitforjob(in.jp); -+ INTON; - if (quoted == 0) - recordregion(startloc, dest - stackblock(), 0); - TRACE(("evalbackq: size=%d: \"%.*s\"\n", -@@ -485,131 +622,149 @@ - (dest - stackblock()) - startloc, - stackblock() + startloc)); - expdest = dest; -- INTON; - } - - -+STATIC char * -+scanleft( -+ char *startp, char *rmesc, char *rmescend, char *str, int quotes, -+ int zero -+) { -+ char *loc; -+ char *loc2; -+ char c; -+ -+ loc = startp; -+ loc2 = rmesc; -+ do { -+ int match; -+ const char *s = loc2; -+ c = *loc2; -+ if (zero) { -+ *loc2 = '\0'; -+ s = rmesc; -+ } -+ match = pmatch(str, s); -+ *loc2 = c; -+ if (match) -+ return loc; -+ if (quotes && *loc == CTLESC) -+ loc++; -+ loc++; -+ loc2++; -+ } while (c); -+ return 0; -+} -+ -+ -+STATIC char * -+scanright( -+ char *startp, char *rmesc, char *rmescend, char *str, int quotes, -+ int zero -+) { -+ int esc = 0; -+ char *loc; -+ char *loc2; - --STATIC int --subevalvar(p, str, strloc, subtype, startloc, varflags) -+ for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) { -+ int match; -+ char c = *loc2; -+ const char *s = loc2; -+ if (zero) { -+ *loc2 = '\0'; -+ s = rmesc; -+ } -+ match = pmatch(str, s); -+ *loc2 = c; -+ if (match) -+ return loc; -+ loc--; -+ if (quotes) { -+ if (--esc < 0) { -+ esc = esclen(startp, loc); -+ } -+ if (esc % 2) { -+ esc--; -+ loc--; -+ } -+ } -+ } -+ return 0; -+} -+ -+STATIC const char * -+subevalvar(p, str, strloc, subtype, startloc, varflags, quotes) - char *p; - char *str; - int strloc; - int subtype; - int startloc; - int varflags; -+ int quotes; - { - char *startp; -- char *loc = NULL; -- char *q; -- int c = 0; -+ char *loc; - int saveherefd = herefd; - struct nodelist *saveargbackq = argbackq; - int amount; -+ char *rmesc, *rmescend; -+ int zero; -+ char *(*scan)(char *, char *, char *, char *, int , int); - - herefd = -1; -- argstr(p, 0); -- STACKSTRNUL(expdest); -+ argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0); -+ STPUTC('\0', expdest); - herefd = saveherefd; - argbackq = saveargbackq; - startp = stackblock() + startloc; -- if (str == NULL) -- str = stackblock() + strloc; - - switch (subtype) { - case VSASSIGN: - setvar(str, startp, 0); - amount = startp - expdest; - STADJUST(amount, expdest); -- varflags &= ~VSNUL; -- if (c != 0) -- *loc = c; -- return 1; -+ return startp; - - case VSQUESTION: -- if (*p != CTLENDVAR) { -- outfmt(&errout, "%s\n", startp); -- error((char *)NULL); -- } -- error("%.*s: parameter %snot set", p - str - 1, -- str, (varflags & VSNUL) ? "null or " -- : nullstr); -+ varunset(p, str, startp, varflags); - /* NOTREACHED */ -- -- case VSTRIMLEFT: -- for (loc = startp; loc < str; loc++) { -- c = *loc; -- *loc = '\0'; -- if (patmatch(str, startp, varflags & VSQUOTE)) -- goto recordleft; -- *loc = c; -- if ((varflags & VSQUOTE) && *loc == CTLESC) -- loc++; - } -- return 0; - -- case VSTRIMLEFTMAX: -- for (loc = str - 1; loc >= startp;) { -- c = *loc; -- *loc = '\0'; -- if (patmatch(str, startp, varflags & VSQUOTE)) -- goto recordleft; -- *loc = c; -- loc--; -- if ((varflags & VSQUOTE) && loc > startp && -- *(loc - 1) == CTLESC) { -- for (q = startp; q < loc; q++) -- if (*q == CTLESC) -- q++; -- if (q > loc) -- loc--; -- } -- } -- return 0; -+ subtype -= VSTRIMRIGHT; -+#ifdef DEBUG -+ if (subtype < 0 || subtype > 3) -+ abort(); -+#endif - -- case VSTRIMRIGHT: -- for (loc = str - 1; loc >= startp;) { -- if (patmatch(str, loc, varflags & VSQUOTE)) -- goto recordright; -- loc--; -- if ((varflags & VSQUOTE) && loc > startp && -- *(loc - 1) == CTLESC) { -- for (q = startp; q < loc; q++) -- if (*q == CTLESC) -- q++; -- if (q > loc) -- loc--; -+ rmesc = startp; -+ rmescend = stackblock() + strloc; -+ if (quotes) { -+ rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); -+ if (rmesc != startp) { -+ rmescend = expdest; -+ startp = stackblock() + startloc; - } - } -- return 0; -+ rmescend--; -+ str = stackblock() + strloc; -+ preglob(str, varflags & VSQUOTE, 0); - -- case VSTRIMRIGHTMAX: -- for (loc = startp; loc < str - 1; loc++) { -- if (patmatch(str, loc, varflags & VSQUOTE)) -- goto recordright; -- if ((varflags & VSQUOTE) && *loc == CTLESC) -- loc++; -- } -- return 0; -+ /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */ -+ zero = subtype >> 1; -+ /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */ -+ scan = (subtype & 1) ^ zero ? scanleft : scanright; - -- default: -- abort(); -+ loc = scan(startp, rmesc, rmescend, str, quotes, zero); -+ if (loc) { -+ if (zero) { -+ memmove(startp, loc, str - loc); -+ loc = startp + (str - loc) - 1; - } -- --recordleft: -- *loc = c; -- amount = ((str - 1) - (loc - startp)) - expdest; -- STADJUST(amount, expdest); -- while (loc != str - 1) -- *startp++ = *loc++; -- return 1; -- --recordright: -+ *loc = '\0'; - amount = loc - expdest; - STADJUST(amount, expdest); -- STPUTC('\0', expdest); -- STADJUST(-1, expdest); -- return 1; -+ } -+ return loc; - } - - -@@ -617,120 +772,129 @@ - * Expand a variable, and return a pointer to the next character in the - * input string. - */ -- - STATIC char * - evalvar(p, flag) - char *p; -- int flag; -+ const int flag; - { - int subtype; - int varflags; - char *var; -- char *val; - int patloc; - int c; - int set; -- int special; - int startloc; -- int varlen; -+ size_t varlen; - int easy; -- int quotes = flag & (EXP_FULL | EXP_CASE); -+ int quotes; -+ int quoted; - -+ quotes = flag & (EXP_FULL | EXP_CASE); - varflags = *p++; - subtype = varflags & VSTYPE; -+ quoted = varflags & VSQUOTE; - var = p; -- special = 0; -- if (! is_name(*p)) -- special = 1; -- p = strchr(p, '=') + 1; --again: /* jump here after setting a variable with ${var=text} */ -- if (special) { -- set = varisset(var, varflags & VSNUL); -- val = NULL; -- } else { -- val = lookupvar(var); -- if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { -- val = NULL; -- set = 0; -- } else -- set = 1; -- } -+ easy = (!quoted || (*var == '@' && shellparam.nparam)); - varlen = 0; - startloc = expdest - stackblock(); -- if (!set && uflag) -- switch (subtype) { -- case VSNORMAL: -- case VSTRIMLEFT: -- case VSTRIMLEFTMAX: -- case VSTRIMRIGHT: -- case VSTRIMRIGHTMAX: -- case VSLENGTH: -- error("%.*s: parameter not set", p - var - 1, var); -- /* NOTREACHED */ -- } -- if (set && subtype != VSPLUS) { -- /* insert the value of the variable */ -- if (special) { -- varvalue(var, varflags & VSQUOTE, flag & EXP_FULL); -+ p = strchr(p, '=') + 1; -+ -+ if (!is_name(*var)) { -+ set = varisset(var, varflags & VSNUL); -+ set--; -+ if (subtype == VSPLUS) -+ goto vsplus; -+ if (++set) { -+ varvalue(var, quoted, flag); - if (subtype == VSLENGTH) { - varlen = expdest - stackblock() - startloc; - STADJUST(-varlen, expdest); -+ goto vslen; -+ } - } - } else { -- char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX -- : BASESYNTAX; -+ const char *val; -+again: -+ /* jump here after setting a variable with ${var=text} */ -+ val = lookupvar(var); -+ set = !val || ((varflags & VSNUL) && !*val); -+ if (subtype == VSPLUS) -+ goto vsplus; -+ if (--set) { -+ varlen = strlen(val); -+ if (subtype == VSLENGTH) -+ goto vslen; -+ memtodest( -+ val, varlen, quoted ? DQSYNTAX : BASESYNTAX, -+ quotes -+ ); -+ } -+ } - -- if (subtype == VSLENGTH) { -- for (;*val; val++) -- varlen++; -+ -+ if (subtype == VSMINUS) { -+vsplus: -+ if (!set) { -+ argstr( -+ p, flag | EXP_TILDE | -+ (quoted ? EXP_QWORD : EXP_WORD) -+ ); -+ goto end; - } -- else { -- while (*val) { -- if (quotes && syntax[(int)*val] == CCTL) -- STPUTC(CTLESC, expdest); -- STPUTC(*val++, expdest); -+ if (easy) -+ goto record; -+ goto end; - } - -+ if (subtype == VSASSIGN || subtype == VSQUESTION) { -+ if (!set) { -+ if (subevalvar(p, var, 0, subtype, startloc, -+ varflags, 0)) { -+ varflags &= ~VSNUL; -+ /* -+ * Remove any recorded regions beyond -+ * start of variable -+ */ -+ removerecordregions(startloc); -+ goto again; - } -+ goto end; - } -+ if (easy) -+ goto record; -+ goto end; - } - -- if (subtype == VSPLUS) -- set = ! set; -- -- easy = ((varflags & VSQUOTE) == 0 || -- (*var == '@' && shellparam.nparam != 1)); -- -+ if (!set && uflag) -+ varunset(p, var, 0, 0); - -- switch (subtype) { -- case VSLENGTH: -- expdest = cvtnum(varlen, expdest); -+ if (subtype == VSLENGTH) { -+vslen: -+ cvtnum(varlen); - goto record; -+ } - -- case VSNORMAL: -+ if (subtype == VSNORMAL) { - if (!easy) -- break; -+ goto end; - record: -- recordregion(startloc, expdest - stackblock(), -- varflags & VSQUOTE); -- break; -- -- case VSPLUS: -- case VSMINUS: -- if (!set) { -- argstr(p, flag); -- break; -+ recordregion(startloc, expdest - stackblock(), quoted); -+ goto end; - } -- if (easy) -- goto record; -- break; - -+#ifdef DEBUG -+ switch (subtype) { - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: -- if (!set) - break; -+ default: -+ abort(); -+ } -+#endif -+ -+ if (set) { - /* - * Terminate the string and start recording the pattern - * right after it -@@ -738,37 +902,16 @@ - STPUTC('\0', expdest); - patloc = expdest - stackblock(); - if (subevalvar(p, NULL, patloc, subtype, -- startloc, varflags) == 0) { -- int amount = (expdest - stackblock() - patloc) + 1; -+ startloc, varflags, quotes) == 0) { -+ int amount = expdest - (stackblock() + patloc - 1); - STADJUST(-amount, expdest); - } - /* Remove any recorded regions beyond start of variable */ - removerecordregions(startloc); - goto record; -- -- case VSASSIGN: -- case VSQUESTION: -- if (!set) { -- if (subevalvar(p, var, 0, subtype, startloc, -- varflags)) { -- varflags &= ~VSNUL; -- /* -- * Remove any recorded regions beyond -- * start of variable -- */ -- removerecordregions(startloc); -- goto again; -- } -- break; -- } -- if (easy) -- goto record; -- break; -- -- default: -- abort(); - } - -+end: - if (subtype != VSNORMAL) { /* skip to end of alternative */ - int nesting = 1; - for (;;) { -@@ -801,7 +944,7 @@ - int nulok; - { - if (*name == '!') -- return backgndpid != -1; -+ return backgndpid != 0; - else if (*name == '@' || *name == '*') { - if (*shellparam.p == NULL) - return 0; -@@ -835,37 +978,60 @@ - - - /* -+ * Put a string on the stack. -+ */ -+ -+STATIC void -+memtodest(const char *p, size_t len, const char *syntax, int quotes) { -+ char *q = expdest; -+ -+ q = makestrspace(len * 2, q); -+ -+ while (len--) { -+ int c = *p++; -+ if (!c) -+ continue; -+ if (quotes && (syntax[c] == CCTL || syntax[c] == CBACK)) -+ USTPUTC(CTLESC, q); -+ USTPUTC(c, q); -+ } -+ -+ expdest = q; -+} -+ -+ -+STATIC void -+strtodest(p, syntax, quotes) -+ const char *p; -+ const char *syntax; -+ int quotes; -+{ -+ memtodest(p, strlen(p), syntax, quotes); -+} -+ -+ -+ -+/* - * Add the value of a specialized variable to the stack string. - */ - - STATIC void --varvalue(name, quoted, allow_split) -+varvalue(name, quoted, flags) - char *name; - int quoted; -- int allow_split; -+ int flags; - { - int num; - char *p; - int i; -- char sep; -+ int sep; -+ int sepq = 0; - char **ap; - char const *syntax; -+ int allow_split = flags & EXP_FULL; -+ int quotes = flags & (EXP_FULL | EXP_CASE); - --#define STRTODEST(p) \ -- do {\ -- if (allow_split) { \ -- syntax = quoted? DQSYNTAX : BASESYNTAX; \ -- while (*p) { \ -- if (syntax[(int)*p] == CCTL) \ -- STPUTC(CTLESC, expdest); \ -- STPUTC(*p++, expdest); \ -- } \ -- } else \ -- while (*p) \ -- STPUTC(*p++, expdest); \ -- } while (0) -- -- -+ syntax = quoted ? DQSYNTAX : BASESYNTAX; - switch (*name) { - case '$': - num = rootpid; -@@ -879,46 +1045,44 @@ - case '!': - num = backgndpid; - numvar: -- expdest = cvtnum(num, expdest); -+ cvtnum(num); - break; - case '-': - for (i = 0 ; i < NOPTS ; i++) { -- if (optlist[i].val) -- STPUTC(optlist[i].letter, expdest); -+ if (optlist[i]) -+ STPUTC(optletters[i], expdest); - } - break; - case '@': - if (allow_split && quoted) { -- for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { -- STRTODEST(p); -- if (*ap) -- STPUTC('\0', expdest); -- } -- break; -+ sep = 1 << CHAR_BIT; -+ goto param; - } - /* fall through */ - case '*': -- if (ifsset() != 0) -- sep = ifsval()[0]; -- else -- sep = ' '; -+ sep = ifsset() ? ifsval()[0] : ' '; -+ if (quotes) { -+ sepq = (syntax[sep] == CCTL) || (syntax[sep] == CBACK); -+ } -+param: - for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { -- STRTODEST(p); -- if (*ap && sep) -- STPUTC(sep, expdest); -+ strtodest(p, syntax, quotes); -+ if (*ap && sep) { -+ p = expdest; -+ if (sepq) -+ STPUTC(CTLESC, p); -+ STPUTC(sep, p); -+ expdest = p; -+ } - } - break; - case '0': -- p = arg0; -- STRTODEST(p); -+ strtodest(arg0, syntax, quotes); - break; - default: -- if (is_digit(*name)) { - num = atoi(name); - if (num > 0 && num <= shellparam.nparam) { -- p = shellparam.p[num - 1]; -- STRTODEST(p); -- } -+ strtodest(shellparam.p[num - 1], syntax, quotes); - } - break; - } -@@ -942,11 +1106,13 @@ - if (ifslastp == NULL) { - ifsp = &ifsfirst; - } else { -+ INTOFF; - ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); -+ ifsp->next = NULL; - ifslastp->next = ifsp; -+ INTON; - } - ifslastp = ifsp; -- ifslastp->next = NULL; - ifslastp->begoff = start; - ifslastp->endoff = end; - ifslastp->nulonly = nulonly; -@@ -969,7 +1135,7 @@ - char *start; - char *p; - char *q; -- const char *ifs; -+ const char *ifs, *realifs; - int ifsspc; - int nulonly; - -@@ -977,13 +1143,13 @@ - start = string; - ifsspc = 0; - nulonly = 0; -+ realifs = ifsset() ? ifsval() : defifs; - if (ifslastp != NULL) { - ifsp = &ifsfirst; - do { - p = string + ifsp->begoff; - nulonly = ifsp->nulonly; -- ifs = nulonly ? nullstr : -- ( ifsset() ? ifsval() : " \t\n" ); -+ ifs = nulonly ? nullstr : realifs; - ifsspc = 0; - while (p < string + ifsp->endoff) { - q = p; -@@ -991,7 +1157,7 @@ - p++; - if (strchr(ifs, *p)) { - if (!nulonly) -- ifsspc = (strchr(" \t\n", *p) != NULL); -+ ifsspc = (strchr(defifs, *p) != NULL); - /* Ignore IFS whitespace at start */ - if (q == start && ifsspc) { - p++; -@@ -1015,7 +1181,7 @@ - if (strchr(ifs, *p) == NULL ) { - p = q; - break; -- } else if (strchr(" \t\n",*p) == NULL) { -+ } else if (strchr(defifs, *p) == NULL) { - if (ifsspc) { - p++; - ifsspc = 0; -@@ -1032,19 +1198,18 @@ - p++; - } - } while ((ifsp = ifsp->next) != NULL); -- if (*start || (!ifsspc && start > string && -- (nulonly || 1))) { -- sp = (struct strlist *)stalloc(sizeof *sp); -- sp->text = start; -- *arglist->lastp = sp; -- arglist->lastp = &sp->next; -+ if (nulonly) -+ goto add; - } -- } else { -+ -+ if (!*start) -+ return; -+ -+add: - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; -- } - } - - STATIC void -@@ -1069,7 +1234,69 @@ - * should be escapes. The results are stored in the list exparg. - */ - --char *expdir; -+#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) -+STATIC void -+expandmeta(str, flag) -+ struct strlist *str; -+ int flag; -+{ -+ /* TODO - EXP_REDIR */ -+ -+ while (str) { -+ const char *p; -+ glob_t pglob; -+ int i; -+ -+ if (fflag) -+ goto nometa; -+ INTOFF; -+ p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP); -+ i = glob(p, GLOB_NOMAGIC, 0, &pglob); -+ if (p != str->text) -+ ckfree(p); -+ switch (i) { -+ case 0: -+ if (!(pglob.gl_flags & GLOB_MAGCHAR)) -+ goto nometa2; -+ addglob(&pglob); -+ globfree(&pglob); -+ INTON; -+ break; -+ case GLOB_NOMATCH: -+nometa2: -+ globfree(&pglob); -+ INTON; -+nometa: -+ *exparg.lastp = str; -+ rmescapes(str->text); -+ exparg.lastp = &str->next; -+ break; -+ default: /* GLOB_NOSPACE */ -+ error("Out of space"); -+ } -+ str = str->next; -+ } -+} -+ -+ -+/* -+ * Add the result of glob(3) to the list. -+ */ -+ -+STATIC void -+addglob(pglob) -+ const glob_t *pglob; -+{ -+ char **p = pglob->gl_pathv; -+ -+ do { -+ addfname(*p); -+ } while (*++p); -+} -+ -+ -+#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ -+STATIC char *expdir; - - - STATIC void -@@ -1077,32 +1304,33 @@ - struct strlist *str; - int flag; - { -- char *p; -- struct strlist **savelastp; -- struct strlist *sp; -- char c; -+ static const char metachars[] = { -+ '*', '?', '[', 0 -+ }; - /* TODO - EXP_REDIR */ - - while (str) { -+ struct strlist **savelastp; -+ struct strlist *sp; -+ char *p; -+ - if (fflag) - goto nometa; -- p = str->text; -- for (;;) { /* fast check for meta chars */ -- if ((c = *p++) == '\0') -+ if (!strpbrk(str->text, metachars)) - goto nometa; -- if (c == '*' || c == '?' || c == '[' || c == '!') -- break; -- } - savelastp = exparg.lastp; -+ - INTOFF; -- if (expdir == NULL) { -+ p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP); -+ { - int i = strlen(str->text); - expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ - } - -- expmeta(expdir, str->text); -+ expmeta(expdir, p); - ckfree(expdir); -- expdir = NULL; -+ if (p != str->text) -+ ckfree(p); - INTON; - if (exparg.lastp == savelastp) { - /* -@@ -1135,11 +1363,10 @@ - { - char *p; - const char *cp; -- char *q; - char *start; - char *endname; - int metaflag; -- struct stat statb; -+ struct stat64 statb; - DIR *dirp; - struct dirent *dp; - int atend; -@@ -1147,17 +1374,15 @@ - - metaflag = 0; - start = name; -- for (p = name ; ; p++) { -+ for (p = name; *p; p++) { - if (*p == '*' || *p == '?') - metaflag = 1; - else if (*p == '[') { -- q = p + 1; -+ char *q = p + 1; - if (*q == '!') - q++; - for (;;) { -- while (*q == CTLQUOTEMARK) -- q++; -- if (*q == CTLESC) -+ if (*q == '\\') - q++; - if (*q == '/' || *q == '\0') - break; -@@ -1166,46 +1391,36 @@ - break; - } - } -- } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { -- metaflag = 1; -- } else if (*p == '\0') -- break; -- else if (*p == CTLQUOTEMARK) -- continue; -- else if (*p == CTLESC) -+ } else if (*p == '\\') - p++; -- if (*p == '/') { -+ else if (*p == '/') { - if (metaflag) -- break; -+ goto out; - start = p + 1; - } - } -+out: - if (metaflag == 0) { /* we've reached the end of the file name */ - if (enddir != expdir) - metaflag++; -- for (p = name ; ; p++) { -- if (*p == CTLQUOTEMARK) -- continue; -- if (*p == CTLESC) -+ p = name; -+ do { -+ if (*p == '\\') - p++; - *enddir++ = *p; -- if (*p == '\0') -- break; -- } -- if (metaflag == 0 || lstat(expdir, &statb) >= 0) -+ } while (*p++); -+ if (metaflag == 0 || lstat64(expdir, &statb) >= 0) - addfname(expdir); - return; - } - endname = p; -- if (start != name) { -+ if (name < start) { - p = name; -- while (p < start) { -- while (*p == CTLQUOTEMARK) -- p++; -- if (*p == CTLESC) -+ do { -+ if (*p == '\\') - p++; - *enddir++ = *p++; -- } -+ } while (p < start); - } - if (enddir == expdir) { - cp = "."; -@@ -1227,16 +1442,14 @@ - } - matchdot = 0; - p = start; -- while (*p == CTLQUOTEMARK) -- p++; -- if (*p == CTLESC) -+ if (*p == '\\') - p++; - if (*p == '.') - matchdot++; - while (! int_pending() && (dp = readdir(dirp)) != NULL) { - if (dp->d_name[0] == '.' && ! matchdot) - continue; -- if (patmatch(start, dp->d_name, 0)) { -+ if (pmatch(start, dp->d_name)) { - if (atend) { - scopy(dp->d_name, enddir); - addfname(expdir); -@@ -1253,6 +1466,7 @@ - if (! atend) - endname[-1] = '/'; - } -+#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ - - - /* -@@ -1263,18 +1477,16 @@ - addfname(name) - char *name; - { -- char *p; - struct strlist *sp; - -- p = stalloc(strlen(name) + 1); -- scopy(name, p); - sp = (struct strlist *)stalloc(sizeof *sp); -- sp->text = p; -+ sp->text = sstrdup(name); - *exparg.lastp = sp; - exparg.lastp = &sp->next; - } - - -+#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) - /* - * Sort the results of file name expansion. It calculates the number of - * strings to sort and then calls msort (short for merge sort) to do the -@@ -1336,35 +1548,29 @@ - } - return list; - } -- -+#endif - - - /* - * Returns true if the pattern matches the string. - */ - --int --patmatch(pattern, string, squoted) -+STATIC inline int -+patmatch(pattern, string) - char *pattern; -- char *string; -- int squoted; /* string might have quote chars */ -+ const char *string; - { --#ifdef notdef -- if (pattern[0] == '!' && pattern[1] == '!') -- return 1 - pmatch(pattern + 2, string); -- else --#endif -- return pmatch(pattern, string, squoted); -+ return pmatch(preglob(pattern, 0, 0), string); - } - - -+#if !defined(__GLIBC__) || defined(FNMATCH_BROKEN) - STATIC int --pmatch(pattern, string, squoted) -- char *pattern; -- char *string; -- int squoted; -+pmatch(pattern, string) -+ const char *pattern; -+ const char *string; - { -- char *p, *q; -+ const char *p, *q; - char c; - - p = pattern; -@@ -1373,46 +1579,33 @@ - switch (c = *p++) { - case '\0': - goto breakloop; -- case CTLESC: -- if (squoted && *q == CTLESC) -- q++; -- if (*q++ != *p++) -- return 0; -- break; -- case CTLQUOTEMARK: -- continue; -+ case '\\': -+ if (*p) { -+ c = *p++; -+ } -+ goto dft; - case '?': -- if (squoted && *q == CTLESC) -- q++; - if (*q++ == '\0') - return 0; - break; - case '*': - c = *p; -- while (c == CTLQUOTEMARK || c == '*') -+ while (c == '*') - c = *++p; -- if (c != CTLESC && c != CTLQUOTEMARK && -- c != '?' && c != '*' && c != '[') { -+ if (c != '\\' && c != '?' && c != '*' && c != '[') { - while (*q != c) { -- if (squoted && *q == CTLESC && -- q[1] == c) -- break; - if (*q == '\0') - return 0; -- if (squoted && *q == CTLESC) -- q++; - q++; - } - } - do { -- if (pmatch(p, q, squoted)) -+ if (pmatch(p, q)) - return 1; -- if (squoted && *q == CTLESC) -- q++; - } while (*q++ != '\0'); - return 0; - case '[': { -- char *endp; -+ const char *endp; - int invert, found; - char chr; - -@@ -1420,11 +1613,9 @@ - if (*endp == '!') - endp++; - for (;;) { -- while (*endp == CTLQUOTEMARK) -- endp++; - if (*endp == '\0') - goto dft; /* no matching ] */ -- if (*endp == CTLESC) -+ if (*endp == '\\') - endp++; - if (*++endp == ']') - break; -@@ -1436,21 +1627,15 @@ - } - found = 0; - chr = *q++; -- if (squoted && chr == CTLESC) -- chr = *q++; - if (chr == '\0') - return 0; - c = *p++; - do { -- if (c == CTLQUOTEMARK) -- continue; -- if (c == CTLESC) -+ if (c == '\\') - c = *p++; - if (*p == '-' && p[1] != ']') { - p++; -- while (*p == CTLQUOTEMARK) -- p++; -- if (*p == CTLESC) -+ if (*p == '\\') - p++; - if (chr >= c && chr <= *p) - found = 1; -@@ -1465,8 +1650,6 @@ - break; - } - dft: default: -- if (squoted && *q == CTLESC) -- q++; - if (*q++ != c) - return 0; - break; -@@ -1477,6 +1660,7 @@ - return 0; - return 1; - } -+#endif - - - -@@ -1484,28 +1668,75 @@ - * Remove any CTLESC characters from a string. - */ - --void --rmescapes(str) -+char * -+_rmescapes(str, flag) - char *str; -+ int flag; - { -- char *p, *q; -+ char *p, *q, *r; -+ static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; -+ unsigned inquotes; -+ int notescaped; -+ int globbing; - -- p = str; -- while (*p != CTLESC && *p != CTLQUOTEMARK) { -- if (*p++ == '\0') -- return; -+ p = strpbrk(str, qchars); -+ if (!p) { -+ return str; - } - q = p; -+ r = str; -+ if (flag & RMESCAPE_ALLOC) { -+ size_t len = p - str; -+ size_t fulllen = len + strlen(p) + 1; -+ -+ if (flag & RMESCAPE_GROW) { -+ r = makestrspace(fulllen, expdest); -+ } else if (flag & RMESCAPE_HEAP) { -+ r = ckmalloc(fulllen); -+ } else { -+ r = stalloc(fulllen); -+ } -+ q = r; -+ if (len > 0) { -+#ifdef _GNU_SOURCE -+ q = mempcpy(q, str, len); -+#else -+ memcpy(q, str, len); -+ q += len; -+#endif -+ } -+ } -+ inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED; -+ globbing = flag & RMESCAPE_GLOB; -+ notescaped = globbing; - while (*p) { - if (*p == CTLQUOTEMARK) { -+ inquotes = ~inquotes; - p++; -+ notescaped = globbing; - continue; - } -- if (*p == CTLESC) -+ if (*p == '\\') { -+ /* naked back slash */ -+ notescaped = 0; -+ goto copy; -+ } -+ if (*p == CTLESC) { - p++; -+ if (notescaped && inquotes && *p != '/') { -+ *q++ = '\\'; -+ } -+ } -+ notescaped = globbing; -+copy: - *q++ = *p++; - } - *q = '\0'; -+ if (flag & RMESCAPE_GROW) { -+ expdest = r; -+ STADJUST(q - r + 1, expdest); -+ } -+ return r; - } - - -@@ -1521,16 +1752,14 @@ - { - struct stackmark smark; - int result; -- char *p; - - setstackmark(&smark); - argbackq = pattern->narg.backquote; - STARTSTACKSTR(expdest); - ifslastp = NULL; - argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); -- STPUTC('\0', expdest); -- p = grabstackstr(expdest); -- result = patmatch(p, val, 0); -+ STACKSTRNUL(expdest); -+ result = patmatch(stackblock(), val); - popstackmark(&smark); - return result; - } -@@ -1539,25 +1768,30 @@ - * Our own itoa(). - */ - --STATIC char * --cvtnum(num, buf) -- int num; -- char *buf; -- { -- char temp[32]; -- int neg = num < 0; -- char *p = temp + 31; -- -- temp[31] = '\0'; -+STATIC int -+cvtnum(long num) { -+ int len; - -- do { -- *--p = num % 10 + '0'; -- } while ((num /= 10) != 0); -+ expdest = makestrspace(32, expdest); -+ len = fmtstr(expdest, 32, "%ld", num); -+ STADJUST(len, expdest); -+ return len; -+} - -- if (neg) -- *--p = '-'; -+static void -+varunset(const char *end, const char *var, const char *umsg, int varflags) -+{ -+ const char *msg; -+ const char *tail; - -- while (*p) -- STPUTC(*p++, buf); -- return buf; -+ tail = nullstr; -+ msg = "parameter not set"; -+ if (umsg) { -+ if (*end == CTLENDVAR) { -+ if (varflags & VSNUL) -+ tail = " or null"; -+ } else -+ msg = umsg; -+ } -+ error("%.*s: %s%s", end - var - 1, var, msg, tail); - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/expand.h bin_NetBSD-1.6release/src/bin/sh/expand.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/expand.h 1999-07-09 12:02:06.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/expand.h 2003-02-08 14:35:42.000000000 +0000 -@@ -58,18 +58,25 @@ - #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ - #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ - #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */ -+#define EXP_VARTILDE2 0x40 /* expand tildes after colons only */ -+#define EXP_WORD 0x80 /* expand word in parameter expansion */ -+#define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ - - - union node; - void expandhere __P((union node *, int)); - void expandarg __P((union node *, struct arglist *, int)); - void expari __P((int)); --int patmatch __P((char *, char *, int)); --void rmescapes __P((char *)); -+#define rmescapes(p) _rmescapes((p), 0) -+char *_rmescapes __P((char *, int)); - int casematch __P((union node *, char *)); - - /* From arith.y */ - int arith __P((const char *)); - int expcmd __P((int , char **)); -+#ifdef USE_LEX - void arith_lex_reset __P((void)); -+#else -+#define arith_lex_reset() -+#endif - int yylex __P((void)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/hetio.c bin_NetBSD-1.6release/src/bin/sh/hetio.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/hetio.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/hetio.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,397 @@ -+/* -+ * Termios command line History and Editting for NetBSD sh (ash) -+ * Copyright (c) 1999 -+ * Main code: Adam Rogoyski <rogoyski@cs.utexas.edu> -+ * Etc: Dave Cinege <dcinege@psychosis.com> -+ * -+ * You may use this code as you wish, so long as the original author(s) -+ * are attributed in any redistributions of the source code. -+ * This code is 'as is' with no warranty. -+ * This code may safely be consumed by a BSD or GPL license. -+ * -+ * v 0.5 19990328 Initial release -+ * -+ * Future plans: Simple file and path name completion. (like BASH) -+ * -+ */ -+ -+/* -+Usage and Known bugs: -+ Terminal key codes are not extensive, and more will probably -+ need to be added. This version was created on Debian GNU/Linux 2.x. -+ Delete, Backspace, Home, End, and the arrow keys were tested -+ to work in an Xterm and console. Ctrl-A also works as Home. -+ Ctrl-E also works as End. Ctrl-D and Ctrl-U perform their respective -+ functions. The binary size increase is <3K. -+ -+ Editting will not display correctly for lines greater then the -+ terminal width. (more then one line.) However, history will. -+*/ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <string.h> -+#include <termios.h> -+#include <ctype.h> -+#include <sys/ioctl.h> -+ -+#include "input.h" -+#include "output.h" -+ -+#include "hetio.h" -+ -+ -+#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */ -+ -+#define ESC 27 -+#define DEL 127 -+ -+static struct history *his_front = NULL; /* First element in command line list */ -+static struct history *his_end = NULL; /* Last element in command line list */ -+static struct termios old_term, new_term; /* Current termio and the previous termio before starting ash */ -+ -+static int history_counter = 0; /* Number of commands in history list */ -+static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */ -+static int hetio_inter = 0; -+ -+struct history -+{ -+ char *s; -+ struct history *p; -+ struct history *n; -+}; -+ -+ -+void input_delete (int); -+void input_home (int *); -+void input_end (int *, int); -+void input_backspace (int *, int *); -+ -+ -+ -+void hetio_init(void) -+{ -+ hetio_inter = 1; -+} -+ -+ -+void hetio_reset_term(void) -+{ -+ if (reset_term) -+ tcsetattr(1, TCSANOW, &old_term); -+} -+ -+ -+void setIO(struct termios *new, struct termios *old) /* Set terminal IO to canonical mode, and save old term settings. */ -+{ -+ tcgetattr(0, old); -+ memcpy(new, old, sizeof(*new)); -+ new->c_cc[VMIN] = 1; -+ new->c_cc[VTIME] = 0; -+ new->c_lflag &= ~ICANON; /* unbuffered input */ -+ new->c_lflag &= ~ECHO; -+ tcsetattr(0, TCSANOW, new); -+} -+ -+void input_home(int *cursor) /* Command line input routines */ -+{ -+ while (*cursor > 0) { -+ out1c('\b'); -+ --*cursor; -+ } -+ flushout(out1); -+} -+ -+ -+void input_delete(int cursor) -+{ -+ int j = 0; -+ -+ memmove(parsenextc + cursor, parsenextc + cursor + 1, -+ BUFSIZ - cursor - 1); -+ for (j = cursor; j < (BUFSIZ - 1); j++) { -+ if (!*(parsenextc + j)) -+ break; -+ else -+ out1c(*(parsenextc + j)); -+ } -+ -+ out1str(" \b"); -+ -+ while (j-- > cursor) -+ out1c('\b'); -+ flushout(out1); -+} -+ -+ -+void input_end(int *cursor, int len) -+{ -+ while (*cursor < len) { -+ out1str("\033[C"); -+ ++*cursor; -+ } -+ flushout(out1); -+} -+ -+ -+void -+input_backspace(int *cursor, int *len) -+{ -+ int j = 0; -+ -+ if (*cursor > 0) { -+ out1str("\b \b"); -+ --*cursor; -+ memmove(parsenextc + *cursor, parsenextc + *cursor + 1, -+ BUFSIZ - *cursor + 1); -+ -+ for (j = *cursor; j < (BUFSIZ - 1); j++) { -+ if (!*(parsenextc + j)) -+ break; -+ else -+ out1c(*(parsenextc + j)); -+ } -+ -+ out1str(" \b"); -+ -+ while (j-- > *cursor) -+ out1c('\b'); -+ -+ --*len; -+ flushout(out1); -+ } -+} -+ -+int hetio_read_input(int fd) -+{ -+ int nr = 0; -+ -+ /* Are we an interactive shell? */ -+ if (!hetio_inter || fd) { -+ return -255; -+ } else { -+ int len = 0; -+ int j = 0; -+ int cursor = 0; -+ int break_out = 0; -+ int ret = 0; -+ char c = 0; -+ struct history *hp = his_end; -+ -+ if (!reset_term) { -+ setIO(&new_term, &old_term); -+ reset_term = 1; -+ } else { -+ tcsetattr(0, TCSANOW, &new_term); -+ } -+ -+ memset(parsenextc, 0, BUFSIZ); -+ -+ while (1) { -+ if ((ret = read(fd, &c, 1)) < 1) -+ return ret; -+ -+ switch (c) { -+ case 1: /* Control-A Beginning of line */ -+ input_home(&cursor); -+ break; -+ case 5: /* Control-E EOL */ -+ input_end(&cursor, len); -+ break; -+ case 4: /* Control-D */ -+ if (!len) -+ exitshell(0); -+ break; -+ case 21: /* Control-U */ -+ /* Return to begining of line. */ -+ for (; cursor > 0; cursor--) -+ out1c('\b'); -+ /* Erase old command. */ -+ for (j = 0; j < len; j++) { -+ /* -+ * Clear buffer while we're at -+ * it. -+ */ -+ parsenextc[j] = 0; -+ out1c(' '); -+ } -+ /* return to begining of line */ -+ for (; len > 0; len--) -+ out1c('\b'); -+ flushout(out1); -+ break; -+ case '\b': /* Backspace */ -+ case DEL: -+ input_backspace(&cursor, &len); -+ break; -+ case '\n': /* Enter */ -+ *(parsenextc + len++ + 1) = c; -+ out1c(c); -+ flushout(out1); -+ break_out = 1; -+ break; -+ case ESC: /* escape sequence follows */ -+ if ((ret = read(fd, &c, 1)) < 1) -+ return ret; -+ -+ if (c == '[' ) { /* 91 */ -+ if ((ret = read(fd, &c, 1)) < 1) -+ return ret; -+ -+ switch (c) { -+ case 'A': -+ if (hp && hp->p) { /* Up */ -+ hp = hp->p; -+ goto hop; -+ } -+ break; -+ case 'B': -+ if (hp && hp->n && hp->n->s) { /* Down */ -+ hp = hp->n; -+ goto hop; -+ } -+ break; -+ -+hop: /* hop */ -+ len = strlen(parsenextc); -+ -+ for (; cursor > 0; cursor--) /* return to begining of line */ -+ out1c('\b'); -+ -+ for (j = 0; j < len; j++) /* erase old command */ -+ out1c(' '); -+ -+ for (; j > 0; j--) /* return to begining of line */ -+ out1c('\b'); -+ -+ strcpy (parsenextc, hp->s); /* write new command */ -+ len = strlen (hp->s); -+ out1str(parsenextc); -+ flushout(out1); -+ cursor = len; -+ break; -+ case 'C': /* Right */ -+ if (cursor < len) { -+ out1str("\033[C"); -+ cursor++; -+ flushout(out1); -+ } -+ break; -+ case 'D': /* Left */ -+ if (cursor > 0) { -+ out1str("\033[D"); -+ cursor--; -+ flushout(out1); -+ } -+ break; -+ case '3': /* Delete */ -+ if (cursor != len) { -+ input_delete(cursor); -+ len--; -+ } -+ break; -+ case '1': /* Home (Ctrl-A) */ -+ input_home(&cursor); -+ break; -+ case '4': /* End (Ctrl-E) */ -+ input_end(&cursor, len); -+ break; -+ } -+ if (c == '1' || c == '3' || c == '4') -+ if ((ret = read(fd, &c, 1)) < 1) -+ return ret; /* read 126 (~) */ -+ } -+ -+ if (c == 'O') { /* 79 */ -+ if ((ret = read(fd, &c, 1)) < 1) -+ return ret; -+ switch (c) { -+ case 'H': /* Home (xterm) */ -+ input_home(&cursor); -+ break; -+ case 'F': /* End (xterm_ */ -+ input_end(&cursor, len); -+ break; -+ } -+ } -+ -+ c = 0; -+ break; -+ -+ default: /* If it's regular input, do the normal thing */ -+ if (!isprint(c)) /* Skip non-printable characters */ -+ break; -+ -+ if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ -+ break; -+ -+ len++; -+ -+ if (cursor == (len - 1)) { /* Append if at the end of the line */ -+ *(parsenextc + cursor) = c; -+ } else { /* Insert otherwise */ -+ memmove(parsenextc + cursor + 1, parsenextc + cursor, -+ len - cursor - 1); -+ -+ *(parsenextc + cursor) = c; -+ -+ for (j = cursor; j < len; j++) -+ out1c(*(parsenextc + j)); -+ for (; j > cursor; j--) -+ out1str("\033[D"); -+ } -+ -+ cursor++; -+ out1c(c); -+ flushout(out1); -+ break; -+ } -+ -+ if (break_out) /* Enter is the command terminator, no more input. */ -+ break; -+ } -+ -+ nr = len + 1; -+ tcsetattr(0, TCSANOW, &old_term); -+ -+ if (*(parsenextc)) { /* Handle command history log */ -+ struct history *h = his_end; -+ -+ if (!h) { /* No previous history */ -+ h = his_front = malloc(sizeof (struct history)); -+ h->n = malloc(sizeof (struct history)); -+ h->p = NULL; -+ h->s = strdup(parsenextc); -+ -+ h->n->p = h; -+ h->n->n = NULL; -+ h->n->s = NULL; -+ his_end = h->n; -+ history_counter++; -+ } else { /* Add a new history command */ -+ -+ h->n = malloc(sizeof (struct history)); -+ -+ h->n->p = h; -+ h->n->n = NULL; -+ h->n->s = NULL; -+ h->s = strdup(parsenextc); -+ his_end = h->n; -+ -+ if (history_counter >= MAX_HISTORY) { /* After max history, remove the last known command */ -+ struct history *p = his_front->n; -+ -+ p->p = NULL; -+ free(his_front->s); -+ free(his_front); -+ his_front = p; -+ } else { -+ history_counter++; -+ } -+ } -+ } -+ } -+ -+ return nr; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/hetio.h bin_NetBSD-1.6release/src/bin/sh/hetio.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/hetio.h 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/hetio.h 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,22 @@ -+/* -+ * Termios command line History and Editting for NetBSD sh (ash) -+ * Copyright (c) 1999 -+ * Main code: Adam Rogoyski <rogoyski@cs.utexas.edu> -+ * Etc: Dave Cinege <dcinege@psychosis.com> -+ * -+ * You may use this code as you wish, so long as the original author(s) -+ * are attributed in any redistributions of the source code. -+ * This code is 'as is' with no warranty. -+ * This code may safely be consumed by a BSD or GPL license. -+ * -+ * v 0.5 19990328 Initial release -+ * -+ * Future plans: Simple file and path name completion. (like BASH) -+ * -+ */ -+ -+void hetio_init(void); -+int hetio_read_input(int fd); -+void hetio_reset_term(void); -+ -+extern int hetio_inter; -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/histedit.c bin_NetBSD-1.6release/src/bin/sh/histedit.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/histedit.c 2002-03-12 11:22:09.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/histedit.c 2003-02-08 14:35:42.000000000 +0000 -@@ -60,9 +60,9 @@ - #include "main.h" - #include "output.h" - #include "mystring.h" --#include "myhistedit.h" - #include "error.h" - #ifndef SMALL -+#include "myhistedit.h" - #include "eval.h" - #include "memalloc.h" - -@@ -219,7 +219,11 @@ - if (argc == 1) - error("missing history argument"); - -+#ifdef __GLIBC__ -+ optind = 0; -+#else - optreset = 1; optind = 1; /* initialize getopt */ -+#endif - while (not_fcnumber(argv[optind]) && - (ch = getopt(argc, argv, ":e:lnrs")) != -1) - switch ((char)ch) { -@@ -277,8 +281,8 @@ - */ - if (sflg == 0) { - if (editor == NULL && -- (editor = bltinlookup("FCEDIT", 1)) == NULL && -- (editor = bltinlookup("EDITOR", 1)) == NULL) -+ (editor = bltinlookup("FCEDIT")) == NULL && -+ (editor = bltinlookup("EDITOR")) == NULL) - editor = DEFEDITOR; - if (editor[0] == '-' && editor[1] == '\0') { - sflg = 1; /* no edit */ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/input.c bin_NetBSD-1.6release/src/bin/sh/input.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/input.c 2001-02-05 11:15:30.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/input.c 2003-02-08 14:35:42.000000000 +0000 -@@ -66,17 +66,24 @@ - #include "error.h" - #include "alias.h" - #include "parser.h" -+#ifndef SMALL - #include "myhistedit.h" -+#endif -+ -+#ifdef HETIO -+#include "hetio.h" -+#endif - - #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ -+#define IBUFSIZ (BUFSIZ + 1) - - MKINIT - struct strpush { - struct strpush *prev; /* preceding string on stack */ - char *prevstring; - int prevnleft; -- int prevlleft; - struct alias *ap; /* if push was associated with an alias */ -+ char *string; /* remember the string since it may change */ - }; - - /* -@@ -103,12 +110,13 @@ - MKINIT int parselleft; /* copy of parsefile->lleft */ - char *parsenextc; /* copy of parsefile->nextc */ - MKINIT struct parsefile basepf; /* top level input file */ --MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */ -+MKINIT char basebuf[IBUFSIZ]; /* buffer for top level input file */ - struct parsefile *parsefile = &basepf; /* current input file */ --int init_editline = 0; /* editline library initialized? */ - int whichprompt; /* 1 == PS1, 2 == PS2 */ - -+#ifndef SMALL - EditLine *el; /* cookie for editline package */ -+#endif - - STATIC void pushfile __P((void)); - static int preadfd __P((void)); -@@ -123,14 +131,9 @@ - } - - RESET { -- if (exception != EXSHELLPROC) - parselleft = parsenleft = 0; /* clear input buffer */ - popallfiles(); - } -- --SHELLPROC { -- popallfiles(); --} - #endif - - -@@ -148,7 +151,7 @@ - int c; - - while (--nleft > 0) { -- c = pgetc_macro(); -+ c = pgetc2(); - if (c == PEOF) { - if (p == line) - return NULL; -@@ -163,7 +166,6 @@ - } - - -- - /* - * Read a character from the script, returning PEOF on end of file. - * Nul characters in the input are silently discarded. -@@ -176,6 +178,21 @@ - } - - -+/* -+ * Same as pgetc(), but ignores PEOA. -+ */ -+ -+int -+pgetc2() -+{ -+ int c; -+ do { -+ c = pgetc_macro(); -+ } while (c == PEOA); -+ return c; -+} -+ -+ - static int - preadfd() - { -@@ -197,10 +214,14 @@ - } - } else - #endif -- nr = read(parsefile->fd, buf, BUFSIZ - 1); -+ -+#ifdef HETIO -+ nr = hetio_read_input(parsefile->fd); -+ if (nr == -255) -+#endif -+ nr = read(parsefile->fd, buf, IBUFSIZ - 1); - - -- if (nr <= 0) { - if (nr < 0) { - if (errno == EINTR) - goto retry; -@@ -215,8 +236,6 @@ - } - } - } -- nr = -1; -- } - return nr; - } - -@@ -235,10 +254,18 @@ - { - char *p, *q; - int more; -+#ifndef SMALL - int something; -+#endif - char savec; - -- if (parsefile->strpush) { -+ while (parsefile->strpush) { -+ if ( -+ parsenleft == -1 && parsefile->strpush->ap && -+ parsenextc[-1] != ' ' && parsenextc[-1] != '\t' -+ ) { -+ return PEOA; -+ } - popstring(); - if (--parsenleft >= 0) - return (*parsenextc++); -@@ -246,11 +273,13 @@ - if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) - return PEOF; - flushout(&output); -+#ifdef FLUSHERR - flushout(&errout); -+#endif - - again: - if (parselleft <= 0) { -- if ((parselleft = preadfd()) == -1) { -+ if ((parselleft = preadfd()) <= 0) { - parselleft = parsenleft = EOF_NLEFT; - return PEOF; - } -@@ -259,34 +288,39 @@ - q = p = parsenextc; - - /* delete nul characters */ -+#ifndef SMALL - something = 0; -+#endif - for (more = 1; more;) { - switch (*p) { - case '\0': - p++; /* Skip nul */ - goto check; - -+#ifndef SMALL - case '\t': - case ' ': - break; -+#endif - - case '\n': - parsenleft = q - parsenextc; - more = 0; /* Stop processing here */ - break; - -+#ifndef SMALL - default: - something = 1; - break; -+#endif - } - - *q++ = *p++; - check: -- if (--parselleft <= 0) { -+ if (--parselleft <= 0 && more) { - parsenleft = q - parsenextc - 1; - if (parsenleft < 0) - goto again; -- *q = '\0'; - more = 0; - } - } -@@ -306,7 +340,9 @@ - - if (vflag) { - out2str(parsenextc); -+#ifdef FLUSHERR - flushout(out2); -+#endif - } - - *q = savec; -@@ -330,13 +366,14 @@ - * We handle aliases this way. - */ - void --pushstring(s, len, ap) -+pushstring(s, ap) - char *s; -- int len; - void *ap; - { - struct strpush *sp; -+ size_t len; - -+ len = strlen(s); - INTOFF; - /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ - if (parsefile->strpush) { -@@ -347,10 +384,11 @@ - sp = parsefile->strpush = &(parsefile->basestrpush); - sp->prevstring = parsenextc; - sp->prevnleft = parsenleft; -- sp->prevlleft = parselleft; - sp->ap = (struct alias *)ap; -- if (ap) -+ if (ap) { - ((struct alias *)ap)->flag |= ALIASINUSE; -+ sp->string = s; -+ } - parsenextc = s; - parsenleft = len; - INTON; -@@ -362,12 +400,21 @@ - struct strpush *sp = parsefile->strpush; - - INTOFF; -+ if (sp->ap) { -+ if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') { -+ checkkwd |= CHKALIAS; -+ } -+ if (sp->string != sp->ap->val) { -+ ckfree(sp->string); -+ } -+ sp->ap->flag &= ~ALIASINUSE; -+ if (sp->ap->flag & ALIASDEAD) { -+ unalias(sp->ap->name); -+ } -+ } - parsenextc = sp->prevstring; - parsenleft = sp->prevnleft; -- parselleft = sp->prevlleft; - /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ -- if (sp->ap) -- sp->ap->flag &= ~ALIASINUSE; - parsefile->strpush = sp->prev; - if (sp != &(parsefile->basestrpush)) - ckfree(sp); -@@ -414,13 +461,15 @@ - (void) fcntl(fd, F_SETFD, FD_CLOEXEC); - if (push) { - pushfile(); -- parsefile->buf = ckmalloc(BUFSIZ); -+ parsefile->buf = 0; -+ } else { -+ closescript(); -+ while (parsefile->strpush) -+ popstring(); - } -- if (parsefile->fd > 0) -- close(parsefile->fd); - parsefile->fd = fd; - if (parsefile->buf == NULL) -- parsefile->buf = ckmalloc(BUFSIZ); -+ parsefile->buf = ckmalloc(IBUFSIZ); - parselleft = parsenleft = 0; - plinno = 1; - } -@@ -431,15 +480,13 @@ - */ - - void --setinputstring(string, push) -+setinputstring(string) - char *string; -- int push; - { - INTOFF; -- if (push) - pushfile(); - parsenextc = string; -- parselleft = parsenleft = strlen(string); -+ parsenleft = strlen(string); - parsefile->buf = NULL; - plinno = 1; - INTON; -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/input.h bin_NetBSD-1.6release/src/bin/sh/input.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/input.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/input.h 2003-02-08 14:35:42.000000000 +0000 -@@ -48,17 +48,17 @@ - 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 */ - - char *pfgets __P((char *, int)); - int pgetc __P((void)); -+int pgetc2 __P((void)); - int preadbuffer __P((void)); - void pungetc __P((void)); --void pushstring __P((char *, int, void *)); -+void pushstring __P((char *, void *)); - void popstring __P((void)); - void setinputfile __P((const char *, int)); - void setinputfd __P((int, int)); --void setinputstring __P((char *, int)); -+void setinputstring __P((char *)); - void popfile __P((void)); - void popallfiles __P((void)); - void closescript __P((void)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/jobs.c bin_NetBSD-1.6release/src/bin/sh/jobs.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/jobs.c 2002-05-16 11:41:20.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/jobs.c 2003-02-08 14:35:42.000000000 +0000 -@@ -85,21 +85,30 @@ - #include "mystring.h" - - --struct job *jobtab; /* array of jobs */ --int njobs; /* size of array */ --MKINIT short backgndpid = -1; /* pid of last background process */ -+/* array of jobs */ -+STATIC struct job *jobtab; -+/* size of array */ -+STATIC int njobs; -+/* pid of last background process */ -+MKINIT pid_t backgndpid; - #if JOBS --int initialpgrp; /* pgrp of shell on invocation */ --short curjob; /* current job */ -+/* pgrp of shell on invocation */ -+STATIC int initialpgrp; -+/* current job */ -+STATIC struct job *curjob; - #endif --static int ttyfd = -1; -+STATIC int ttyfd = -1; -+/* number of presumed living untracked jobs */ -+STATIC int jobless; - - STATIC void restartjob __P((struct job *)); - STATIC void freejob __P((struct job *)); - STATIC struct job *getjob __P((char *)); - STATIC int dowait __P((int, struct job *)); -+#ifdef SYSV - STATIC int onsigchild __P((void)); --STATIC int waitproc __P((int, struct job *, int *)); -+#endif -+STATIC int waitproc __P((int, int *)); - STATIC void cmdtxt __P((union node *)); - STATIC void cmdputs __P((const char *)); - -@@ -127,12 +136,15 @@ - } - #endif - -+#if JOBS - /* - * Turn job control on and off. - * - * Note: This code assumes that the third arg to ioctl is a character - * pointer, which is true on Berkeley systems but not System V. Since - * System V doesn't have job control yet, this isn't a problem now. -+ * -+ * Called with interrupts off. - */ - - MKINIT int jobctl; -@@ -144,93 +156,185 @@ - #ifdef OLD_TTY_DRIVER - int ldisc; - #endif -+ int fd; -+ int pgrp; - - if (on == jobctl || rootshell == 0) - return; - if (on) { - #if defined(FIOCLEX) || defined(FD_CLOEXEC) -- int err; -- if (ttyfd != -1) -- close(ttyfd); -- if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) { -- int i; -- for (i = 0; i < 3; i++) { -- if (isatty(i) && (ttyfd = dup(i)) != -1) -- break; -+ int ofd; -+ ofd = fd = open(_PATH_TTY, O_RDWR); -+ if (fd < 0) { -+ fd += 3; -+ while (!isatty(fd) && --fd >= 0) -+ ; - } -- if (i == 3) -+ fd = fcntl(fd, F_DUPFD, 10); -+ close(ofd); -+ if (fd < 0) - goto out; -- } --#ifdef FIOCLEX -- err = ioctl(ttyfd, FIOCLEX, 0); --#elif FD_CLOEXEC -- err = fcntl(ttyfd, FD_CLOEXEC, 1); -+#ifdef linux -+ fcntl(fd, F_SETFD, FD_CLOEXEC); -+#elif defined(FIOCLEX) -+ ioctl(fd, FIOCLEX, 0); -+#elif defined(FD_CLOEXEC) -+ fcntl(fd, FD_CLOEXEC, 1); - #endif -- if (err == -1) { -- close(ttyfd); -- ttyfd = -1; -- goto out; -- } - #else -- out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control"); -- goto out; -+ warnx("Need FIOCLEX or FD_CLOEXEC to support job control"); -+ mflag = 0; -+ return; - #endif - do { /* while we are in the background */ -- if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) { -+ if ((pgrp = tcgetpgrp(fd)) < 0) { - out: -- out2str("sh: can't access tty; job control turned off\n"); -- mflag = 0; -- return; -+ warnx("can't access tty; job control turned off"); -+ mflag = on = 0; -+ goto close; - } -- if (initialpgrp == -1) -- initialpgrp = getpgrp(); -- else if (initialpgrp != getpgrp()) { -+ if (pgrp == getpgrp()) -+ break; - killpg(0, SIGTTIN); -- continue; -- } -- } while (0); -+ } while (1); -+ initialpgrp = pgrp; - - #ifdef OLD_TTY_DRIVER -- if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0 -+ if (ioctl(fd, TIOCGETD, (char *)&ldisc) < 0 - || ldisc != NTTYDISC) { -- out2str("sh: need new tty driver to run job control; job control turned off\n"); -- mflag = 0; -- return; -+ warnx("need new tty driver to run job control; job control turned off"); -+ mflag = on = 0; -+ goto close; - } - #endif - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); -- setpgid(0, rootpid); -- tcsetpgrp(ttyfd, rootpid); -- } else { /* turning job control off */ -- setpgid(0, initialpgrp); -- tcsetpgrp(ttyfd, initialpgrp); -- close(ttyfd); -- ttyfd = -1; -+ pgrp = rootpid; -+ setpgid(0, pgrp); -+ tcsetpgrp(fd, pgrp); -+ } else { -+ /* turning job control off */ -+ fd = ttyfd; -+ pgrp = initialpgrp; -+ tcsetpgrp(fd, pgrp); -+ setpgid(0, pgrp); - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); -+close: -+ close(fd); -+ fd = -1; - } -+ ttyfd = fd; - jobctl = on; - } -+#endif - - --#ifdef mkinit --INCLUDE <stdlib.h> - --SHELLPROC { -- backgndpid = -1; - #if JOBS -- jobctl = 0; --#endif --} -+int -+killcmd(argc, argv) -+ int argc; -+ char **argv; -+{ -+ extern char *signal_names[]; -+ int signo = -1; -+ int list = 0; -+ int i; -+ pid_t pid; -+ struct job *jp; -+ -+ if (argc <= 1) { -+usage: -+ error( -+"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n" -+"kill -l [exitstatus]" -+ ); -+ } -+ -+ if (*argv[1] == '-') { -+ signo = decode_signal(argv[1] + 1, 1); -+ if (signo < 0) { -+ int c; - -+ while ((c = nextopt("ls:")) != '\0') -+ switch (c) { -+ case 'l': -+ list = 1; -+ break; -+ case 's': -+ signo = decode_signal(optionarg, 1); -+ if (signo < 0) { -+ error( -+ "invalid signal number or name: %s", -+ optionarg -+ ); -+ } -+ break; -+#ifdef DEBUG -+ default: -+ error( -+ "nextopt returned character code 0%o", c); - #endif -+ } -+ } else -+ argptr++; -+ } - -+ if (!list && signo < 0) -+ signo = SIGTERM; - -+ if ((signo < 0 || !*argptr) ^ list) { -+ goto usage; -+ } -+ -+ if (list) { -+ if (!*argptr) { -+ out1str("0\n"); -+ for (i = 1; i < NSIG; i++) { -+ out1fmt(snlfmt, signal_names[i]); -+ } -+ return 0; -+ } -+ signo = atoi(*argptr); -+ if (signo > 128) -+ signo -= 128; -+ if (0 < signo && signo < NSIG) -+ out1fmt(snlfmt, signal_names[signo]); -+ else -+ error("invalid signal number or exit status: %s", -+ *argptr); -+ return 0; -+ } -+ -+ i = 0; -+ do { -+ if (**argptr == '%') { -+ jp = getjob(*argptr); -+ if (jp->jobctl == 0) { -+ outfmt( -+ out2, -+ "job %s not created " -+ "under job control\n", -+ *argptr -+ ); -+ i = 1; -+ continue; -+ } -+ pid = -jp->ps[0].pid; -+ } else -+ pid = atoi(*argptr); -+ if (kill(pid, signo) != 0) { -+ outfmt(out2, "%s: %s\n", *argptr, strerror(errno)); -+ i = 1; -+ } -+ } while (*++argptr); -+ -+ return i; -+} - --#if JOBS - int - fgcmd(argc, argv) - int argc; -@@ -246,9 +350,7 @@ - pgrp = jp->ps[0].pid; - tcsetpgrp(ttyfd, pgrp); - restartjob(jp); -- INTOFF; - status = waitforjob(jp); -- INTON; - return status; - } - -@@ -366,12 +468,10 @@ - } - out1str(s); - col += strlen(s); -- do { -- out1c(' '); -- col++; -- } while (col < 30); -- out1str(ps->cmd); -- out1c('\n'); -+ out1fmt( -+ "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ', -+ ps->cmd -+ ); - if (--procno <= 0) - break; - } -@@ -399,14 +499,11 @@ - if (ps->cmd != nullstr) - ckfree(ps->cmd); - } -- if (jp->ps != &jp->ps0) { -+ if (jp->ps != &jp->ps0) - ckfree(jp->ps); -- jp->ps = &jp->ps0; -- } -- jp->nprocs = 0; - jp->used = 0; - #if JOBS -- if (curjob == jp - jobtab + 1) -+ if (curjob == jp) - curjob = 0; - #endif - INTON; -@@ -423,8 +520,9 @@ - int status, retval; - struct job *jp; - -- if (argc > 1) { -- job = getjob(argv[1]); -+ if (--argc > 0) { -+start: -+ job = getjob(*++argv); - } else { - job = NULL; - } -@@ -432,6 +530,11 @@ - if (job != NULL) { - if (job->state) { - status = job->ps[job->nprocs - 1].status; -+ if (! iflag) -+ freejob(job); -+ if (--argc) { -+ goto start; -+ } - if (WIFEXITED(status)) - retval = WEXITSTATUS(status); - #if JOBS -@@ -442,26 +545,28 @@ - /* XXX: limits number of signals */ - retval = WTERMSIG(status) + 128; - } -- if (! iflag) -- freejob(job); - return retval; - } - } else { -+ struct job *end = jobtab + njobs; - for (jp = jobtab ; ; jp++) { -- if (jp >= jobtab + njobs) { /* no running procs */ -+ if (jp >= end) { -+ /* no running procs */ - return 0; - } - if (jp->used && jp->state == 0) - break; - } - } -- if (dowait(1, (struct job *)NULL) == -1) -- return 128 + SIGINT; -+ dowait(2, 0); -+ if (pendingsigs) -+ return 128 + pendingsigs; - } - } - - - -+#if 0 - int - jobidcmd(argc, argv) - int argc; -@@ -472,11 +577,14 @@ - - jp = getjob(argv[1]); - for (i = 0 ; i < jp->nprocs ; ) { -- out1fmt("%ld", (long)jp->ps[i].pid); -- out1c(++i < jp->nprocs? ' ' : '\n'); -+ out1fmt( -+ "%ld%c", (long)jp->ps[i].pid, -+ ++i < jp->nprocs? ' ' : '\n' -+ ); - } - return 0; - } -+#endif - - - -@@ -496,9 +604,9 @@ - if (name == NULL) { - #if JOBS - currentjob: -- if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0) -+ if (!curjob || !curjob->used) - error("No current job"); -- return &jobtab[jobno - 1]; -+ return curjob; - #else - error("No current job"); - #endif -@@ -575,13 +683,13 @@ - break; - } - INTOFF; -- jp->state = 0; -- jp->used = 1; -- jp->changed = 0; - jp->nprocs = 0; -+ jp->state = 0; - #if JOBS - jp->jobctl = jobctl; - #endif -+ jp->changed = 0; -+ jp->used = 1; - if (nprocs > 1) { - jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); - } else { -@@ -636,23 +744,17 @@ - TRACE(("Child shell %d\n", getpid())); - wasroot = rootshell; - rootshell = 0; -- for (i = njobs, p = jobtab ; --i >= 0 ; p++) { -- if (p == jp) -- continue; /* don't free current job */ -- if (p->used) -- freejob(p); -- } - closescript(); - INTON; - clear_traps(); - #if JOBS -- jobctl = 0; /* do job control only in root shell */ -+ jobctl = pid; /* do job control only in root shell */ - if (wasroot && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = getpid(); - else - pgrp = jp->ps[0].pid; -- setpgid(0, pgrp); -+ setpgid(pid, pgrp); - if (mode == FORK_FG) { - /*** this causes superfluous TIOCSPGRPS ***/ - if (tcsetpgrp(ttyfd, pgrp) < 0) -@@ -661,32 +763,26 @@ - setsignal(SIGTSTP); - setsignal(SIGTTOU); - } else if (mode == FORK_BG) { -- ignoresig(SIGINT); -- ignoresig(SIGQUIT); -- if ((jp == NULL || jp->nprocs == 0) && -- ! fd0_redirected_p ()) { -- close(0); -- if (open(devnull, O_RDONLY) != 0) -- error(nullerr, devnull); -- } -- } - #else - if (mode == FORK_BG) { -+#endif - ignoresig(SIGINT); - ignoresig(SIGQUIT); -- if ((jp == NULL || jp->nprocs == 0) && -- ! fd0_redirected_p ()) { -- close(0); -+ if ((jp == NULL || jp->nprocs == 0)) { -+ close(pid); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } --#endif -+ for (i = njobs, p = jobtab ; --i >= 0 ; p++) -+ if (p->used) -+ freejob(p); - if (wasroot && iflag) { - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); - } -+ jobless = pid; - return pid; - } - if (rootshell && mode != FORK_NOJOB && mflag) { -@@ -705,6 +801,9 @@ - ps->cmd = nullstr; - if (iflag && rootshell && n) - ps->cmd = commandtext(n); -+ } else { -+ while (jobless && dowait(0, 0) > 0); -+ jobless++; - } - INTON; - TRACE(("In parent shell: child = %d\n", pid)); -@@ -753,7 +852,7 @@ - error("tcsetpgrp failed, errno=%d\n", errno); - } - if (jp->state == JOBSTOPPED) -- curjob = jp - jobtab + 1; -+ curjob = jp; - #endif - status = jp->ps[jp->nprocs - 1].status; - /* convert to 8 bits */ -@@ -798,29 +897,31 @@ - { - int pid; - int status; -- struct procstat *sp; - struct job *jp; -+ struct job *end; - struct job *thisjob; -- int done; -- int stopped; - int core; - int sig; -- extern volatile char gotsig[]; -+ int state; - - TRACE(("dowait(%d) called\n", block)); - do { -- pid = waitproc(block, job, &status); -+ pid = waitproc(block, &status); - TRACE(("wait returns %d, status=%d\n", pid, status)); -- } while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0); -+ } while (!(block & 2) && pid == -1 && errno == EINTR); - if (pid <= 0) - return pid; - INTOFF; - thisjob = NULL; -- for (jp = jobtab ; jp < jobtab + njobs ; jp++) { -- if (jp->used) { -- done = 1; -- stopped = 1; -- for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { -+ end = jobtab + njobs; -+ for (jp = jobtab; jp < end; jp++) { -+ struct procstat *sp; -+ struct procstat *spend; -+ if (!jp->used) -+ continue; -+ state = JOBDONE; -+ spend = jp->ps + jp->nprocs; -+ for (sp = jp->ps; sp < spend; sp++) { - if (sp->pid == -1) - continue; - if (sp->pid == pid) { -@@ -829,23 +930,30 @@ - thisjob = jp; - } - if (sp->status == -1) -- stopped = 0; -+ state = 0; - else if (WIFSTOPPED(sp->status)) -- done = 0; -+ state = JOBSTOPPED; - } -- if (stopped) { /* stopped or done */ -- int state = done? JOBDONE : JOBSTOPPED; -- if (jp->state != state) { -- TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); -- jp->state = state; -+ if (!thisjob) -+ continue; -+ if (state) { -+ /* stopped or done */ -+ if (thisjob->state != state) { -+ TRACE(("Job %d: changing state from %d to %d\n", thisjob - jobtab + 1, thisjob->state, state)); -+ thisjob->state = state; - #if JOBS -- if (done && curjob == jp - jobtab + 1) -- curjob = 0; /* no current job */ --#endif -+ if (state == JOBDONE && curjob == thisjob) { -+ /* no current job */ -+ curjob = 0; - } -+#endif - } - } -+ goto gotjob; - } -+ if (!WIFSTOPPED(status)) -+ jobless--; -+gotjob: - INTON; - if (! rootshell || ! iflag || (job && thisjob == job)) { - core = WCOREDUMP(status); -@@ -871,7 +979,9 @@ - if (core) - out2str(" - core dumped"); - out2c('\n'); -+#ifdef FLUSHERR - flushout(&errout); -+#endif - } else { - TRACE(("Not printing status: status=%d, sig=%d\n", - status, sig)); -@@ -925,16 +1035,15 @@ - - - STATIC int --waitproc(block, jp, status) -+waitproc(block, status) - int block; -- struct job *jp; - int *status; - { - #ifdef BSD - int flags = 0; - - #if JOBS -- if (jp != NULL && jp->jobctl) -+ if (jobctl) - flags |= WUNTRACED; - #endif - if (block == 0) -@@ -963,7 +1072,7 @@ - /* - * return 1 if there are stopped jobs, otherwise 0 - */ --int job_warning = 0; -+int job_warning; - int - stoppedjobs() - { -@@ -1088,10 +1197,10 @@ - for (np = n->ncmd.args ; np ; np = np->narg.next) { - cmdtxt(np); - if (np->narg.next) -- cmdputs(" "); -+ cmdputs(spcstr); - } - for (np = n->ncmd.redirect ; np ; np = np->nfile.next) { -- cmdputs(" "); -+ cmdputs(spcstr); - cmdtxt(np); - } - break; -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/jobs.h bin_NetBSD-1.6release/src/bin/sh/jobs.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/jobs.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/jobs.h 2003-02-08 14:35:42.000000000 +0000 -@@ -38,6 +38,9 @@ - * @(#)jobs.h 8.2 (Berkeley) 5/4/95 - */ - -+#include <stdint.h> -+#include <sys/types.h> -+ - /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ - #define FORK_FG 0 - #define FORK_BG 1 -@@ -66,20 +69,22 @@ - struct job { - struct procstat ps0; /* status of process */ - struct procstat *ps; /* status or processes when more than one */ -- short nprocs; /* number of processes */ -- short pgrp; /* process group of this job */ -- char state; /* true if job is finished */ -- char used; /* true if this entry is in used */ -- char changed; /* true if status has changed */ -+ pid_t pgrp; /* process group of this job */ -+ uint32_t -+ nprocs: 16, /* number of processes */ -+ state: 8, /* true if job is finished */ - #if JOBS -- char jobctl; /* job running under job control */ -+ jobctl: 1, /* job running under job control */ - #endif -+ used: 1, /* true if this entry is in used */ -+ changed: 1; /* true if status has changed */ - }; - --extern short backgndpid; /* pid of last background process */ -+extern pid_t backgndpid; /* pid of last background process */ - extern int job_warning; /* user was warned about stopped jobs */ - - void setjobctl __P((int)); -+int killcmd __P((int, char **)); - int fgcmd __P((int, char **)); - int bgcmd __P((int, char **)); - int jobscmd __P((int, char **)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mail.c bin_NetBSD-1.6release/src/bin/sh/mail.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/mail.c 2001-01-12 16:50:36.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/mail.c 2003-02-08 14:35:42.000000000 +0000 -@@ -53,73 +53,73 @@ - #include <stdlib.h> - - #include "shell.h" -+#include "nodes.h" - #include "exec.h" /* defines padvance() */ - #include "var.h" - #include "output.h" - #include "memalloc.h" - #include "error.h" - #include "mail.h" -+#include "mystring.h" - - - #define MAXMBOXES 10 - -- --STATIC int nmboxes; /* number of mailboxes */ --STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */ -+/* times of mailboxes */ -+static time_t mailtime[MAXMBOXES]; -+/* Set if MAIL or MAILPATH is changed. */ -+static int changed; - - - - /* -- * Print appropriate message(s) if mail has arrived. If the argument is -- * nozero, then the value of MAIL has changed, so we just update the -- * values. -+ * Print appropriate message(s) if mail has arrived. If changed is set, -+ * then the value of MAIL has changed, so we just update the values. - */ - - void --chkmail(silent) -- int silent; -+chkmail() - { -- int i; - const char *mpath; - char *p; - char *q; -+ time_t *mtp; - struct stackmark smark; -- struct stat statb; -+ struct stat64 statb; - -- if (silent) -- nmboxes = 10; -- if (nmboxes == 0) -- return; - setstackmark(&smark); - mpath = mpathset()? mpathval() : mailval(); -- for (i = 0 ; i < nmboxes ; i++) { -+ for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) { - p = padvance(&mpath, nullstr); - if (p == NULL) - break; - if (*p == '\0') - continue; - for (q = p ; *q ; q++); -+#ifdef DEBUG - if (q[-1] != '/') - abort(); -+#endif - q[-1] = '\0'; /* delete trailing '/' */ --#ifdef notdef /* this is what the System V shell claims to do (it lies) */ -- if (stat(p, &statb) < 0) -- statb.st_mtime = 0; -- if (statb.st_mtime > mailtime[i] && ! silent) { -- out2str(pathopt? pathopt : "you have mail"); -- out2c('\n'); -+ if (stat64(p, &statb) < 0) { -+ *mtp = 0; -+ continue; - } -- mailtime[i] = statb.st_mtime; --#else /* this is what it should do */ -- if (stat(p, &statb) < 0) -- statb.st_size = 0; -- if (statb.st_size > mailtime[i] && ! silent) { -- out2str(pathopt? pathopt : "you have mail"); -- out2c('\n'); -+ if (!changed && statb.st_mtime != *mtp) { -+ outfmt( -+ &errout, snlfmt, -+ pathopt? pathopt : "you have mail" -+ ); - } -- mailtime[i] = statb.st_size; --#endif -+ *mtp = statb.st_mtime; - } -- nmboxes = i; -+ changed = 0; - popstackmark(&smark); - } -+ -+ -+void -+changemail(const char *val) -+{ -+ changed++; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mail.h bin_NetBSD-1.6release/src/bin/sh/mail.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/mail.h 1995-10-14 00:44:08.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mail.h 2003-02-08 14:35:42.000000000 +0000 -@@ -38,4 +38,5 @@ - * @(#)mail.h 8.2 (Berkeley) 5/4/95 - */ - --void chkmail __P((int)); -+void chkmail __P((void)); -+void changemail __P((const char *)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/main.c bin_NetBSD-1.6release/src/bin/sh/main.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/main.c 2001-06-13 11:08:37.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/main.c 2003-02-08 14:35:42.000000000 +0000 -@@ -79,12 +79,14 @@ - #include "exec.h" - #include "cd.h" - -+#ifdef HETIO -+#include "hetio.h" -+#endif -+ - #define PROFILE 0 - - int rootpid; - int rootshell; --STATIC union node *curcmd; --STATIC union node *prevcmd; - #if PROFILE - short profile_buf[16384]; - extern int etext(); -@@ -108,53 +110,49 @@ - int argc; - char **argv; - { -+ char *shinit; -+ volatile int state; - struct jmploc jmploc; - struct stackmark smark; -- volatile int state; -- char *shinit; - - #if PROFILE - monitor(4, etext, profile_buf, sizeof profile_buf, 50); - #endif - state = 0; - if (setjmp(jmploc.loc)) { -- /* -- * When a shell procedure is executed, we raise the -- * exception EXSHELLPROC to clean up before executing -- * the shell procedure. -- */ -- switch (exception) { -- case EXSHELLPROC: -- rootpid = getpid(); -- rootshell = 1; -- minusc = NULL; -- state = 3; -- break; -+ int status; -+ int e; - -+ reset(); -+ -+ e = exception; -+ switch (exception) { - case EXEXEC: -- exitstatus = exerrno; -+ status = exerrno; - break; - - case EXERROR: -- exitstatus = 2; -+ status = 2; - break; - - default: -+ status = exitstatus; - break; - } -+ exitstatus = status; - -- if (exception != EXSHELLPROC) { -- if (state == 0 || iflag == 0 || ! rootshell) -- exitshell(exitstatus); -- } -- reset(); -- if (exception == EXINT -+ if (e == EXEXIT || state == 0 || iflag == 0 || ! rootshell) -+ exitshell(); -+ -+ if (e == EXINT - #if ATTY - && (! attyset() || equal(termval(), "emacs")) - #endif - ) { - out2c('\n'); -- flushout(&errout); -+#ifdef FLUSHERR -+ flushout(out2); -+#endif - } - popstackmark(&smark); - FORCEINTON; /* enable interrupts */ -@@ -186,29 +184,18 @@ - } - state2: - state = 3; -- if (getuid() == geteuid() && getgid() == getegid()) { -+ if ( -+#ifndef linux -+ getuid() == geteuid() && getgid() == getegid() && -+#endif -+ iflag -+ ) { - if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { -- state = 3; - read_profile(shinit); - } - } - state3: - state = 4; -- if (sflag == 0 || minusc) { -- static int sigs[] = { -- SIGINT, SIGQUIT, SIGHUP, --#ifdef SIGTSTP -- SIGTSTP, --#endif -- SIGPIPE -- }; --#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) -- int i; -- -- for (i = 0; i < SIGSSIZE; i++) -- setsignal(sigs[i]); -- } -- - if (minusc) - evalstring(minusc, 0); - -@@ -219,7 +206,7 @@ - #if PROFILE - monitor(0); - #endif -- exitshell(exitstatus); -+ exitshell(); - /* NOTREACHED */ - } - -@@ -240,6 +227,10 @@ - - TRACE(("cmdloop(%d) called\n", top)); - setstackmark(&smark); -+#ifdef HETIO -+ if(iflag && top) -+ hetio_init(); -+#endif - for (;;) { - if (pendingsigs) - dotrap(); -@@ -247,7 +238,7 @@ - if (iflag && top) { - inter++; - showjobs(1); -- chkmail(0); -+ chkmail(); - flushout(&output); - } - n = parsecmd(inter); -@@ -376,12 +367,8 @@ - int argc; - char **argv; - { -- struct strlist *sp; - exitstatus = 0; - -- for (sp = cmdenviron; sp ; sp = sp->next) -- setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED); -- - if (argc >= 2) { /* That's what SVR2 does */ - char *fullname; - struct stackmark smark; -@@ -403,12 +390,14 @@ - int argc; - char **argv; - { -+ int status; -+ - if (stoppedjobs()) - return 0; -+ status = oexitstatus; - if (argc > 1) -- exitstatus = number(argv[1]); -- else -- exitstatus = oexitstatus; -- exitshell(exitstatus); -+ status = number(argv[1]); -+ exitstatus = status; -+ exraise(EXEXIT); - /* NOTREACHED */ - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/Makefile bin_NetBSD-1.6release/src/bin/sh/Makefile ---- bin_NetBSD-1.6release.orig/src/bin/sh/Makefile 2002-12-07 08:17:35.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/Makefile 2003-02-08 14:39:28.000000000 +0000 -@@ -1,40 +1,35 @@ --# $NetBSD: Makefile,v 1.57.2.2 2002/12/06 23:29:26 he Exp $ -+# $NetBSD: Makefile,v 1.59 2002/09/15 00:19:22 thorpej Exp $ - # @(#)Makefile 8.4 (Berkeley) 5/5/95 - - .include <bsd.own.mk> - - YHEADER=1 - PROG= sh --SHSRCS= alias.c cd.c echo.c error.c eval.c exec.c expand.c \ -+SHSRCS= alias.c arith_yylex.c cd.c echo.c error.c eval.c exec.c expand.c \ - histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ -- mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \ -- test.c --GENSRCS=arith.c arith.h arith_lex.c builtins.c builtins.h init.c nodes.c \ -- nodes.h syntax.c syntax.h token.h -+ mystring.c options.c parser.c printf.c redir.c show.c trap.c output.c \ -+ var.c test.c setmode.c times.c hetio.c -+GENSRCS=arith.c arith.h builtins.c builtins.h init.c nodes.c \ -+ nodes.h signames.c syntax.c syntax.h token.h - SRCS= ${SHSRCS} ${GENSRCS} - --LDADD+= -ll -ledit -ltermcap --DPADD+= ${LIBL} ${LIBEDIT} ${LIBTERMCAP} -- --LFLAGS= -8 # 8-bit lex scanner for arithmetic - YFLAGS= -d - - CPPFLAGS+=-DSHELL -I. -I${.CURDIR} -+CPPFLAGS+=-DSMALL -DHETIO - --.ifdef SMALLPROG --CPPFLAGS+=-DSMALL --.endif -- --.PATH: ${.CURDIR}/bltin ${.CURDIR}/../test -+.PATH: ${.CURDIR}/bltin ${NETBSDSRCDIR}/bin/test - - CLEANFILES+= mkinit mknodes mksyntax - CLEANFILES+= ${GENSRCS} y.tab.h - -+BLTINDEFS=specialbltins.def regularbltins.def assignbltins.def -+ - token.h: mktokens - sh ${.ALLSRC} - --builtins.c builtins.h: mkbuiltins shell.h builtins.def -- sh ${.ALLSRC} ${.OBJDIR} -+builtins.c builtins.h: mkbuiltins shell.h builtins.def ${BLTINDEFS} -+ sh ${.ALLSRC} ${.OBJDIR} '${CFLAGS}' - - init.c: mkinit ${SHSRCS} - ./${.ALLSRC} -@@ -45,22 +40,18 @@ - syntax.c syntax.h: mksyntax - ./${.ALLSRC} - -+signames.c: mksignames -+ ./${.ALLSRC} -+ - mkinit: mkinit.c - ${HOST_LINK.c} -o mkinit ${.IMPSRC} - - mknodes: mknodes.c - ${HOST_LINK.c} -o mknodes ${.IMPSRC} - --.if (${MACHINE_ARCH} == "powerpc") || \ -- (${MACHINE_CPU} == "arm") --TARGET_CHARFLAG= -DTARGET_CHAR="unsigned char" --.else --TARGET_CHARFLAG= -DTARGET_CHAR="signed char" --.endif -- - mksyntax: mksyntax.c - ${HOST_LINK.c} ${TARGET_CHARFLAG} -o mksyntax ${.IMPSRC} - - .include <bsd.prog.mk> - --${OBJS}: builtins.h nodes.h syntax.h token.h -+${OBJS}: arith.h builtins.h nodes.h syntax.h token.h -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/memalloc.c bin_NetBSD-1.6release/src/bin/sh/memalloc.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/memalloc.c 2001-01-12 16:50:36.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/memalloc.c 2003-02-08 14:35:42.000000000 +0000 -@@ -60,15 +60,11 @@ - */ - - pointer --ckmalloc(nbytes) -- int nbytes; -+ckmalloc(size_t nbytes) - { - pointer p; - -- INTOFF; -- p = malloc(nbytes); -- INTON; -- if (p == NULL) -+ if ((p = malloc(nbytes)) == NULL) - error("Out of space"); - return p; - } -@@ -79,9 +75,7 @@ - */ - - pointer --ckrealloc(p, nbytes) -- pointer p; -- int nbytes; -+ckrealloc(pointer p, size_t nbytes) - { - - if ((p = realloc(p, nbytes)) == NULL) -@@ -96,12 +90,11 @@ - - char * - savestr(s) -- char *s; -+ const char *s; - { -- char *p; -- -- p = ckmalloc(strlen(s) + 1); -- scopy(s, p); -+ char *p = strdup(s); -+ if (!p) -+ error("Out of space"); - return p; - } - -@@ -115,7 +108,7 @@ - * well. - */ - --#define MINSIZE 504 /* minimum size of a block */ -+#define MINSIZE ALIGN(504) /* minimum size of a block */ - - - struct stack_block { -@@ -127,37 +120,42 @@ - struct stack_block *stackp = &stackbase; - struct stackmark *markp; - char *stacknxt = stackbase.space; --int stacknleft = MINSIZE; --int sstrnleft; -+size_t stacknleft = MINSIZE; -+char *sstrend = stackbase.space + MINSIZE; - int herefd = -1; - - - - pointer --stalloc(nbytes) -- int nbytes; -+stalloc(size_t nbytes) - { - char *p; -+ size_t aligned; - -- nbytes = ALIGN(nbytes); -+ aligned = ALIGN(nbytes); - if (nbytes > stacknleft) { -- int blocksize; -+ size_t len; -+ size_t blocksize; - struct stack_block *sp; - -- blocksize = nbytes; -+ blocksize = aligned; - if (blocksize < MINSIZE) - blocksize = MINSIZE; -+ len = sizeof(struct stack_block) - MINSIZE + blocksize; -+ if (len < blocksize) -+ error("Out of space"); - INTOFF; -- sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize); -+ sp = ckmalloc(len); - sp->prev = stackp; - stacknxt = sp->space; - stacknleft = blocksize; -+ sstrend = stacknxt + blocksize; - stackp = sp; - INTON; - } - p = stacknxt; -- stacknxt += nbytes; -- stacknleft -= nbytes; -+ stacknxt += aligned; -+ stacknleft -= aligned; - return p; - } - -@@ -166,10 +164,12 @@ - stunalloc(p) - pointer p; - { -- if (p == NULL) { /*DEBUG */ -+#ifdef DEBUG -+ if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) { - write(2, "stunalloc\n", 10); - abort(); - } -+#endif - stacknleft += stacknxt - (char *)p; - stacknxt = p; - } -@@ -203,6 +203,7 @@ - } - stacknxt = mark->stacknxt; - stacknleft = mark->stacknleft; -+ sstrend = mark->stacknxt + mark->stacknleft; - INTON; - } - -@@ -220,22 +221,31 @@ - void - growstackblock() { - char *p; -- int newlen = ALIGN(stacknleft * 2 + 100); -+ size_t newlen, grosslen; - char *oldspace = stacknxt; -- int oldlen = stacknleft; -+ size_t oldlen = stacknleft; - struct stack_block *sp; - struct stack_block *oldstackp; -+ struct stack_block *prevstackp; -+ -+ grosslen = stacknleft * 2; -+ if (grosslen < stacknleft) -+ error("Out of space"); -+ if (grosslen < 128) -+ grosslen += 128 + sizeof(struct stack_block) - MINSIZE; -+ newlen = grosslen - (sizeof(struct stack_block) - MINSIZE); - - if (stacknxt == stackp->space && stackp != &stackbase) { - INTOFF; - oldstackp = stackp; - sp = stackp; -- stackp = sp->prev; -- sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen); -- sp->prev = stackp; -+ prevstackp = sp->prev; -+ sp = ckrealloc((pointer)sp, grosslen); -+ sp->prev = prevstackp; - stackp = sp; - stacknxt = sp->space; - stacknleft = newlen; -+ sstrend = sp->space + newlen; - { - /* Stack marks pointing to the start of the old block - * must be relocated to point to the new block -@@ -252,17 +262,16 @@ - INTON; - } else { - p = stalloc(newlen); -- memcpy(p, oldspace, oldlen); -- stacknxt = p; /* free the space */ -- stacknleft += newlen; /* we just allocated */ -+ /* free the space we just allocated */ -+ stacknxt = memcpy(p, oldspace, oldlen); -+ stacknleft += newlen; - } - } - - - - void --grabstackblock(len) -- int len; -+grabstackblock(size_t len) - { - len = ALIGN(len); - stacknxt += len; -@@ -290,16 +299,14 @@ - */ - - --char * -+void * - growstackstr() { -- int len = stackblocksize(); -+ size_t len = stackblocksize(); - if (herefd >= 0 && len >= 1024) { - xwrite(herefd, stackblock(), len); -- sstrnleft = len - 1; - return stackblock(); - } - growstackblock(); -- sstrnleft = stackblocksize() - len - 1; - return stackblock() + len; - } - -@@ -309,21 +316,33 @@ - */ - - char * --makestrspace() { -- int len = stackblocksize() - sstrnleft; -+makestrspace(size_t newlen, char *p) { -+ size_t len = p - stackblock(); -+ size_t size = stackblocksize(); -+ -+ for (;;) { -+ size_t nleft; -+ -+ size = stackblocksize(); -+ nleft = size - len; -+ if (nleft >= newlen) -+ break; - growstackblock(); -- sstrnleft = stackblocksize() - len; -+ } - return stackblock() + len; - } - - - --void --ungrabstackstr(s, p) -- char *s; -- char *p; -- { -- stacknleft += stacknxt - s; -- stacknxt = s; -- sstrnleft = stacknleft - (p - s); -+char * -+stnputs(const char *s, size_t n, char *p) { -+ p = makestrspace(n, p); -+ p = mempcpy(p, s, n); -+ return p; -+} -+ -+ -+char * -+stputs(const char *s, char *p) { -+ return stnputs(s, strlen(s), p); - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/memalloc.h bin_NetBSD-1.6release/src/bin/sh/memalloc.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/memalloc.h 2001-01-12 16:50:37.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/memalloc.h 2003-02-08 14:35:42.000000000 +0000 -@@ -38,44 +38,62 @@ - * @(#)memalloc.h 8.2 (Berkeley) 5/4/95 - */ - -+#include <stddef.h> -+ - struct stackmark { - struct stack_block *stackp; - char *stacknxt; -- int stacknleft; -+ size_t stacknleft; - struct stackmark *marknext; - }; - - - extern char *stacknxt; --extern int stacknleft; --extern int sstrnleft; -+extern size_t stacknleft; -+extern char *sstrend; - extern int herefd; - --pointer ckmalloc __P((int)); --pointer ckrealloc __P((pointer, int)); --char *savestr __P((char *)); --pointer stalloc __P((int)); -+pointer ckmalloc __P((size_t)); -+pointer ckrealloc __P((pointer, size_t)); -+char *savestr __P((const char *)); -+pointer stalloc __P((size_t)); - void stunalloc __P((pointer)); - void setstackmark __P((struct stackmark *)); - void popstackmark __P((struct stackmark *)); - void growstackblock __P((void)); --void grabstackblock __P((int)); --char *growstackstr __P((void)); --char *makestrspace __P((void)); --void ungrabstackstr __P((char *, char *)); -+void grabstackblock __P((size_t)); -+void *growstackstr __P((void)); -+char *makestrspace __P((size_t, char *)); -+char *stnputs __P((const char *, size_t, char *)); -+char *stputs __P((const char *, char *)); - - -+static inline char *_STPUTC(char c, char *p) { -+ if (p == sstrend) -+ p = growstackstr(); -+ *p++ = c; -+ return p; -+} - - #define stackblock() stacknxt - #define stackblocksize() stacknleft --#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize() --#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c))) --#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); } --#define USTPUTC(c, p) (--sstrnleft, *p++ = (c)) --#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0')) --#define STUNPUTC(p) (++sstrnleft, --p) -+#define STARTSTACKSTR(p) (p) = ((void *) stackblock()) -+#define STPUTC(c, p) (p) = _STPUTC(c, p) -+#define CHECKSTRSPACE(n, p) \ -+ ({ \ -+ char *q = (p); \ -+ size_t l = (n); \ -+ size_t m = sstrend - q; \ -+ if (l > m) \ -+ (p) = makestrspace(l, q); \ -+ 0; \ -+ }) -+#define USTPUTC(c, p) (*p++ = (c)) -+#define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0')) -+#define STUNPUTC(p) (--p) - #define STTOPC(p) p[-1] --#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount)) --#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) -+#define STADJUST(amount, p) (p += (amount)) -+#define grabstackstr(p) stalloc(((char *) (p)) - stackblock()) -+#define ungrabstackstr(s, p) stunalloc((s)) - - #define ckfree(p) free((pointer)(p)) -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/miscbltin.c bin_NetBSD-1.6release/src/bin/sh/miscbltin.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/miscbltin.c 2001-02-05 11:15:31.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/miscbltin.c 2003-02-08 14:35:42.000000000 +0000 -@@ -70,6 +70,15 @@ - - #undef rflag - -+#ifdef __GLIBC__ -+mode_t getmode(const void *, mode_t); -+void *setmode(const char *); -+ -+#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1 -+typedef enum __rlimit_resource rlim_t; -+#endif -+#endif -+ - - - /* -@@ -89,7 +98,7 @@ - char c; - int rflag; - char *prompt; -- char *ifs; -+ const char *ifs; - char *p; - int startword; - int status; -@@ -105,12 +114,14 @@ - } - if (prompt && isatty(0)) { - out2str(prompt); -+#ifdef FLUSHERR - flushall(); -+#endif - } - if (*(ap = argptr) == NULL) - error("arg count"); -- if ((ifs = bltinlookup("IFS", 1)) == NULL) -- ifs = nullstr; -+ if ((ifs = bltinlookup("IFS")) == NULL) -+ ifs = defifs; - status = 0; - startword = 1; - backslash = 0; -@@ -125,7 +136,7 @@ - if (backslash) { - backslash = 0; - if (c != '\n') -- STPUTC(c, p); -+ goto put; - continue; - } - if (!rflag && c == '\\') { -@@ -138,19 +149,14 @@ - continue; - } - startword = 0; -- if (backslash && c == '\\') { -- if (read(0, &c, 1) != 1) { -- status = 1; -- break; -- } -- STPUTC(c, p); -- } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { -+ if (ap[1] != NULL && strchr(ifs, c) != NULL) { - STACKSTRNUL(p); - setvar(*ap, stackblock(), 0); - ap++; - startword = 1; - STARTSTACKSTR(p); - } else { -+put: - STPUTC(c, p); - } - } -@@ -225,7 +231,7 @@ - mask = 0; - do { - if (*ap >= '8' || *ap < '0') -- error("Illegal number: %s", argv[1]); -+ error(illnum, argv[1]); - mask = (mask << 3) + (*ap - '0'); - } while (*++ap != '\0'); - umask(mask); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mkbuiltins bin_NetBSD-1.6release/src/bin/sh/mkbuiltins ---- bin_NetBSD-1.6release.orig/src/bin/sh/mkbuiltins 1999-07-09 12:02:07.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mkbuiltins 2003-02-08 14:35:42.000000000 +0000 -@@ -37,21 +37,25 @@ - # - # @(#)mkbuiltins 8.2 (Berkeley) 5/4/95 - --temp=/tmp/ka$$ -+trap 'rm -f $temp $temp2' EXIT -+temp=$(tempfile) -+temp2=$(tempfile) -+ -+shell=$1 -+builtins=$2 -+specialbltins=$3 -+regularbltins=$4 -+assignbltins=$5 -+objdir=$6 - - havehist=1 --if [ "X$1" = "X-h" ]; then -+if [ -z "${7##*-DSMALL*}" ]; then - havehist=0 -- shift - fi --shell=$1 --builtins=$2 --objdir=$3 - --havejobs=0 --if grep '^#define JOBS[ ]*1' ${shell} > /dev/null --then -- havejobs=1 -+havejobs=1 -+if [ -z "${7##*-DJOBS=0*}" ]; then -+ havejobs=0 - fi - - exec > ${objdir}/builtins.c -@@ -65,19 +69,19 @@ - - ! - awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \ -- print $0}' ${builtins} | sed 's/-j//' > $temp -+ print $0}' ${builtins} | sed 's/-[hj]//' > $temp - awk '{ printf "int %s __P((int, char **));\n", $1}' $temp - echo ' --int (*const builtinfunc[]) __P((int, char **)) = {' --awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp --echo '}; -- - const struct builtincmd builtincmd[] = {' - awk '{ for (i = 2 ; i <= NF ; i++) { -- printf "\t{ \"%s\", %d },\n", $i, NR-1 -- }}' $temp --echo ' { NULL, 0 } --};' -+ print $i "\t" $1 -+ }}' $temp | sort -k 1,1 | tee $temp2 | -+ join -a 1 -e 0 -o 1.1,1.2,2.1 - $specialbltins | -+ join -a 1 -e 0 -o 1.1,1.2,1.3,2.1 - $regularbltins | -+ join -a 1 -e 0 -o 1.1,1.2,1.3,1.4,2.1 - $assignbltins | -+ awk '{ printf "\t{ \"%s\", %s, %d },\n", $1, $2, -+ !!$3 + (!!$4 * 2) + (!!$5 * 4)}' -+echo '};' - - exec > ${objdir}/builtins.h - cat <<\! -@@ -87,14 +91,19 @@ - - #include <sys/cdefs.h> - ! --tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp | -- awk '{ printf "#define %s %d\n", $1, NR-1}' -+nl -v 0 $temp2 | sort -u -k 3,3 | -+tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | -+ awk '{ printf "#define %s (builtincmd + %d)\n", $3, $1}' -+printf '\n#define NUMBUILTINS %d\n' $(wc -l < $temp2) - echo ' -+#define BUILTIN_SPECIAL 0x1 -+#define BUILTIN_REGULAR 0x2 -+#define BUILTIN_ASSIGN 0x4 -+ - struct builtincmd { - const char *name; -- int code; -+ int (*const builtinfunc) __P((int, char **)); -+ unsigned flags; - }; - --extern int (*const builtinfunc[]) __P((int, char **)); - extern const struct builtincmd builtincmd[];' --rm -f $temp -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mkinit.c bin_NetBSD-1.6release/src/bin/sh/mkinit.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/mkinit.c 2001-01-12 16:50:37.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/mkinit.c 2003-02-08 14:35:42.000000000 +0000 -@@ -131,16 +131,10 @@ - * interactive shell and control is returned to the main command loop.\n\ - */\n"; - --char shellproc[] = "\ --/*\n\ -- * This routine is called to initialize the shell to run a shell procedure.\n\ -- */\n"; -- - - struct event event[] = { - {"INIT", "init", init}, - {"RESET", "reset", reset}, -- {"SHELLPROC", "initshellproc", shellproc}, - {NULL, NULL} - }; - -@@ -218,8 +212,6 @@ - doinclude(line); - if (line[0] == 'M' && match("MKINIT", line)) - dodecl(line, fp); -- if (line[0] == '#' && gooddefine(line)) -- addstr(line, &defines); - if (line[0] == '#' && gooddefine(line)) { - char *cp; - char line2[1024]; -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mknodes.c bin_NetBSD-1.6release/src/bin/sh/mknodes.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/mknodes.c 2001-01-12 16:50:38.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/mknodes.c 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $ */ -+/* $NetBSD: mknodes.c,v 1.19 2002/05/25 23:09:06 wiz Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -47,7 +47,7 @@ - static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95"; - #else - static const char rcsid[] = -- "$NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $"; -+ "$NetBSD: mknodes.c,v 1.19 2002/05/25 23:09:06 wiz Exp $"; - #endif - #endif /* not lint */ - -@@ -59,12 +59,7 @@ - #include <stdio.h> - #include <stdlib.h> - #include <string.h> --#ifdef __STDC__ - #include <stdarg.h> --#else --#include <varargs.h> --#endif -- - - #define MAXTYPES 50 /* max number of node types */ - #define MAXFIELDS 20 /* max fields in a structure */ -@@ -270,13 +265,12 @@ - fputs("\tstruct nodelist *next;\n", hfile); - fputs("\tunion node *n;\n", hfile); - fputs("};\n\n\n", hfile); -- fputs("#ifdef __STDC__\n", hfile); -- fputs("union node *copyfunc(union node *);\n", hfile); -- fputs("void freefunc(union node *);\n", hfile); -- fputs("#else\n", hfile); -- fputs("union node *copyfunc();\n", hfile); -- fputs("void freefunc();\n", hfile); -- fputs("#endif\n", hfile); -+ fputs("struct funcnode {\n", hfile); -+ fputs("\tint count;\n", hfile); -+ fputs("\tunion node n;\n", hfile); -+ fputs("};\n\n\n", hfile); -+ fputs("struct funcnode *copyfunc(union node *);\n", hfile); -+ fputs("void freefunc(struct funcnode *);\n", hfile); - - fputs(writer, cfile); - while (fgets(line, sizeof line, patfile) != NULL) { -@@ -451,21 +445,11 @@ - - - static void --#ifdef __STDC__ - error(const char *msg, ...) --#else --error(va_alist) -- va_dcl --#endif - { - va_list va; --#ifdef __STDC__ -+ - va_start(va, msg); --#else -- char *msg; -- va_start(va); -- msg = va_arg(va, char *); --#endif - - (void) fprintf(stderr, "line %d: ", linno); - (void) vfprintf(stderr, msg, va); -Files bin_NetBSD-1.6release.orig/src/bin/sh/mksignames and bin_NetBSD-1.6release/src/bin/sh/mksignames differ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mksignames.c bin_NetBSD-1.6release/src/bin/sh/mksignames.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/mksignames.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mksignames.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,419 @@ -+/* signames.c -- Create and write `signames.c', which contains an array of -+ signal names. */ -+ -+/* Copyright (C) 1992 Free Software Foundation, Inc. -+ -+ This file is part of GNU Bash, the Bourne Again SHell. -+ -+ Bash is free software; you can redistribute it and/or modify it under -+ the terms of the GNU General Public License as published by the Free -+ Software Foundation; either version 2, or (at your option) any later -+ version. -+ -+ Bash is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ for more details. -+ -+ You should have received a copy of the GNU General Public License along -+ with Bash; see the file COPYING. If not, write to the Free Software -+ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -+ -+#include <stdio.h> -+#include <sys/types.h> -+#include <signal.h> -+#include <stdlib.h> -+ -+#if !defined (NSIG) -+# define NSIG 64 -+#endif -+ -+/* -+ * Special traps: -+ * EXIT == 0 -+ */ -+#define LASTSIG NSIG-1 -+ -+char *signal_names[2 * NSIG + 3]; -+ -+#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0])) -+ -+char *progname; -+ -+/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively. -+ I don't want to allocate so much unused space for the intervening signal -+ numbers, so we just punt if SIGRTMAX is past the bounds of the -+ signal_names array (handled in configure). */ -+#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS) -+# undef SIGRTMAX -+# undef SIGRTMIN -+#endif -+ -+#if defined (SIGRTMAX) || defined (SIGRTMIN) -+# define RTLEN 14 -+# define RTLIM 256 -+#endif -+ -+void -+initialize_signames () -+{ -+ register int i; -+#if defined (SIGRTMAX) || defined (SIGRTMIN) -+ int rtmin, rtmax, rtcnt; -+#endif -+ -+ for (i = 1; i < signal_names_size; i++) -+ signal_names[i] = (char *)NULL; -+ -+ /* `signal' 0 is what we do on exit. */ -+ signal_names[0] = "EXIT"; -+ -+ /* Place signal names which can be aliases for more common signal -+ names first. This allows (for example) SIGABRT to overwrite SIGLOST. */ -+ -+ /* POSIX 1003.1b-1993 real time signals, but take care of incomplete -+ implementations. Acoording to the standard, both, SIGRTMIN and -+ SIGRTMAX must be defined, SIGRTMIN must be stricly less than -+ SIGRTMAX, and the difference must be at least 7, that is, there -+ must be at least eight distinct real time signals. */ -+ -+ /* The generated signal names are SIGRTMIN, SIGRTMIN+1, ..., -+ SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number -+ of RT signals is odd, there is an extra SIGRTMIN+(x+1). -+ These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */ -+ -+#if defined (SIGRTMIN) -+ rtmin = SIGRTMIN; -+ signal_names[rtmin] = "RTMIN"; -+#endif -+ -+#if defined (SIGRTMAX) -+ rtmax = SIGRTMAX; -+ signal_names[rtmax] = "RTMAX"; -+#endif -+ -+#if defined (SIGRTMAX) && defined (SIGRTMIN) -+ if (rtmax > rtmin) -+ { -+ rtcnt = (rtmax - rtmin - 1) / 2; -+ /* croak if there are too many RT signals */ -+ if (rtcnt >= RTLIM/2) -+ { -+ rtcnt = RTLIM/2-1; -+ fprintf(stderr, "%s: error: more than %i real time signals, fix `%s'\n", -+ progname, RTLIM, progname); -+ } -+ -+ for (i = 1; i <= rtcnt; i++) -+ { -+ signal_names[rtmin+i] = (char *)malloc(RTLEN); -+ if (signal_names[rtmin+i]) -+ sprintf (signal_names[rtmin+i], "RTMIN+%d", i); -+ signal_names[rtmax-i] = (char *)malloc(RTLEN); -+ if (signal_names[rtmax-i]) -+ sprintf (signal_names[rtmax-i], "RTMAX-%d", i); -+ } -+ -+ if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2) -+ { -+ /* Need an extra RTMIN signal */ -+ signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN); -+ if (signal_names[rtmin+rtcnt+1]) -+ sprintf (signal_names[rtmin+rtcnt+1], "RTMIN+%d", rtcnt+1); -+ } -+ } -+#endif /* SIGRTMIN && SIGRTMAX */ -+ -+/* AIX */ -+#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */ -+ signal_names[SIGLOST] = "LOST"; -+#endif -+ -+#if defined (SIGMSG) /* HFT input data pending */ -+ signal_names[SIGMSG] = "MSG"; -+#endif -+ -+#if defined (SIGDANGER) /* system crash imminent */ -+ signal_names[SIGDANGER] = "DANGER"; -+#endif -+ -+#if defined (SIGMIGRATE) /* migrate process to another CPU */ -+ signal_names[SIGMIGRATE] = "MIGRATE"; -+#endif -+ -+#if defined (SIGPRE) /* programming error */ -+ signal_names[SIGPRE] = "PRE"; -+#endif -+ -+#if defined (SIGVIRT) /* AIX virtual time alarm */ -+ signal_names[SIGVIRT] = "VIRT"; -+#endif -+ -+#if defined (SIGALRM1) /* m:n condition variables */ -+ signal_names[SIGALRM1] = "ALRM1"; -+#endif -+ -+#if defined (SIGWAITING) /* m:n scheduling */ -+ signal_names[SIGWAITING] = "WAITING"; -+#endif -+ -+#if defined (SIGGRANT) /* HFT monitor mode granted */ -+ signal_names[SIGGRANT] = "GRANT"; -+#endif -+ -+#if defined (SIGKAP) /* keep alive poll from native keyboard */ -+ signal_names[SIGKAP] = "KAP"; -+#endif -+ -+#if defined (SIGRETRACT) /* HFT monitor mode retracted */ -+ signal_names[SIGRETRACT] = "RETRACT"; -+#endif -+ -+#if defined (SIGSOUND) /* HFT sound sequence has completed */ -+ signal_names[SIGSOUND] = "SOUND"; -+#endif -+ -+#if defined (SIGSAK) /* Secure Attention Key */ -+ signal_names[SIGSAK] = "SAK"; -+#endif -+ -+/* SunOS5 */ -+#if defined (SIGLWP) /* special signal used by thread library */ -+ signal_names[SIGLWP] = "LWP"; -+#endif -+ -+#if defined (SIGFREEZE) /* special signal used by CPR */ -+ signal_names[SIGFREEZE] = "FREEZE"; -+#endif -+ -+#if defined (SIGTHAW) /* special signal used by CPR */ -+ signal_names[SIGTHAW] = "THAW"; -+#endif -+ -+#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */ -+ signal_names[SIGCANCEL] = "CANCEL"; -+#endif -+ -+/* HP-UX */ -+#if defined (SIGDIL) /* DIL signal (?) */ -+ signal_names[SIGDIL] = "DIL"; -+#endif -+ -+/* System V */ -+#if defined (SIGCLD) /* Like SIGCHLD. */ -+ signal_names[SIGCLD] = "CLD"; -+#endif -+ -+#if defined (SIGPWR) /* power state indication */ -+ signal_names[SIGPWR] = "PWR"; -+#endif -+ -+#if defined (SIGPOLL) /* Pollable event (for streams) */ -+ signal_names[SIGPOLL] = "POLL"; -+#endif -+ -+/* Unknown */ -+#if defined (SIGWINDOW) -+ signal_names[SIGWINDOW] = "WINDOW"; -+#endif -+ -+/* Common */ -+#if defined (SIGHUP) /* hangup */ -+ signal_names[SIGHUP] = "HUP"; -+#endif -+ -+#if defined (SIGINT) /* interrupt */ -+ signal_names[SIGINT] = "INT"; -+#endif -+ -+#if defined (SIGQUIT) /* quit */ -+ signal_names[SIGQUIT] = "QUIT"; -+#endif -+ -+#if defined (SIGILL) /* illegal instruction (not reset when caught) */ -+ signal_names[SIGILL] = "ILL"; -+#endif -+ -+#if defined (SIGTRAP) /* trace trap (not reset when caught) */ -+ signal_names[SIGTRAP] = "TRAP"; -+#endif -+ -+#if defined (SIGIOT) /* IOT instruction */ -+ signal_names[SIGIOT] = "IOT"; -+#endif -+ -+#if defined (SIGABRT) /* Cause current process to dump core. */ -+ signal_names[SIGABRT] = "ABRT"; -+#endif -+ -+#if defined (SIGEMT) /* EMT instruction */ -+ signal_names[SIGEMT] = "EMT"; -+#endif -+ -+#if defined (SIGFPE) /* floating point exception */ -+ signal_names[SIGFPE] = "FPE"; -+#endif -+ -+#if defined (SIGKILL) /* kill (cannot be caught or ignored) */ -+ signal_names[SIGKILL] = "KILL"; -+#endif -+ -+#if defined (SIGBUS) /* bus error */ -+ signal_names[SIGBUS] = "BUS"; -+#endif -+ -+#if defined (SIGSEGV) /* segmentation violation */ -+ signal_names[SIGSEGV] = "SEGV"; -+#endif -+ -+#if defined (SIGSYS) /* bad argument to system call */ -+ signal_names[SIGSYS] = "SYS"; -+#endif -+ -+#if defined (SIGPIPE) /* write on a pipe with no one to read it */ -+ signal_names[SIGPIPE] = "PIPE"; -+#endif -+ -+#if defined (SIGALRM) /* alarm clock */ -+ signal_names[SIGALRM] = "ALRM"; -+#endif -+ -+#if defined (SIGTERM) /* software termination signal from kill */ -+ signal_names[SIGTERM] = "TERM"; -+#endif -+ -+#if defined (SIGURG) /* urgent condition on IO channel */ -+ signal_names[SIGURG] = "URG"; -+#endif -+ -+#if defined (SIGSTOP) /* sendable stop signal not from tty */ -+ signal_names[SIGSTOP] = "STOP"; -+#endif -+ -+#if defined (SIGTSTP) /* stop signal from tty */ -+ signal_names[SIGTSTP] = "TSTP"; -+#endif -+ -+#if defined (SIGCONT) /* continue a stopped process */ -+ signal_names[SIGCONT] = "CONT"; -+#endif -+ -+#if defined (SIGCHLD) /* to parent on child stop or exit */ -+ signal_names[SIGCHLD] = "CHLD"; -+#endif -+ -+#if defined (SIGTTIN) /* to readers pgrp upon background tty read */ -+ signal_names[SIGTTIN] = "TTIN"; -+#endif -+ -+#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local<OSTOP) */ -+ signal_names[SIGTTOU] = "TTOU"; -+#endif -+ -+#if defined (SIGIO) /* input/output possible signal */ -+ signal_names[SIGIO] = "IO"; -+#endif -+ -+#if defined (SIGXCPU) /* exceeded CPU time limit */ -+ signal_names[SIGXCPU] = "XCPU"; -+#endif -+ -+#if defined (SIGXFSZ) /* exceeded file size limit */ -+ signal_names[SIGXFSZ] = "XFSZ"; -+#endif -+ -+#if defined (SIGVTALRM) /* virtual time alarm */ -+ signal_names[SIGVTALRM] = "VTALRM"; -+#endif -+ -+#if defined (SIGPROF) /* profiling time alarm */ -+ signal_names[SIGPROF] = "PROF"; -+#endif -+ -+#if defined (SIGWINCH) /* window changed */ -+ signal_names[SIGWINCH] = "WINCH"; -+#endif -+ -+/* 4.4 BSD */ -+#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */ -+ signal_names[SIGINFO] = "INFO"; -+#endif -+ -+#if defined (SIGUSR1) /* user defined signal 1 */ -+ signal_names[SIGUSR1] = "USR1"; -+#endif -+ -+#if defined (SIGUSR2) /* user defined signal 2 */ -+ signal_names[SIGUSR2] = "USR2"; -+#endif -+ -+#if defined (SIGKILLTHR) /* BeOS: Kill Thread */ -+ signal_names[SIGKILLTHR] = "KILLTHR"; -+#endif -+ -+ for (i = 0; i < NSIG; i++) -+ if (signal_names[i] == (char *)NULL) -+ { -+ signal_names[i] = (char *)malloc (18); -+ if (signal_names[i]) -+ sprintf (signal_names[i], "%d", i); -+ } -+} -+ -+void -+write_signames (stream) -+ FILE *stream; -+{ -+ register int i; -+ -+ fprintf (stream, "/* This file was automatically created by %s.\n", -+ progname); -+ fprintf (stream, " Do not edit. Edit support/mksignames.c instead. */\n\n"); -+ fprintf (stream, "#include <signal.h>\n\n"); -+ fprintf (stream, -+ "/* A translation list so we can be polite to our users. */\n"); -+ fprintf (stream, "const char *const signal_names[NSIG + 1] = {\n"); -+ -+ for (i = 0; i <= LASTSIG; i++) -+ fprintf (stream, " \"%s\",\n", signal_names[i]); -+ -+ fprintf (stream, " (char *)0x0\n"); -+ fprintf (stream, "};\n"); -+} -+ -+int -+main (argc, argv) -+ int argc; -+ char **argv; -+{ -+ char *stream_name; -+ FILE *stream; -+ -+ progname = argv[0]; -+ -+ if (argc == 1) -+ { -+ stream_name = "signames.c"; -+ } -+ else if (argc == 2) -+ { -+ stream_name = argv[1]; -+ } -+ else -+ { -+ fprintf (stderr, "Usage: %s [output-file]\n", progname); -+ exit (1); -+ } -+ -+ stream = fopen (stream_name, "w"); -+ if (!stream) -+ { -+ fprintf (stderr, "%s: %s: cannot open for writing\n", -+ progname, stream_name); -+ exit (2); -+ } -+ -+ initialize_signames (); -+ write_signames (stream); -+ exit (0); -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mksyntax.c bin_NetBSD-1.6release/src/bin/sh/mksyntax.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/mksyntax.c 2002-06-02 02:11:43.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mksyntax.c 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: mksyntax.c,v 1.24.4.1 2002/05/31 16:42:05 tv Exp $ */ -+/* $NetBSD: mksyntax.c,v 1.25 2002/05/31 16:18:48 christos Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -47,7 +47,7 @@ - static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95"; - #else - static const char rcsid[] = -- "$NetBSD: mksyntax.c,v 1.24.4.1 2002/05/31 16:42:05 tv Exp $"; -+ "$NetBSD: mksyntax.c,v 1.25 2002/05/31 16:18:48 christos Exp $"; - #endif - #endif /* not lint */ - -@@ -73,6 +73,7 @@ - { "CBACK", "a backslash character" }, - { "CSQUOTE", "single quote" }, - { "CDQUOTE", "double quote" }, -+ { "CENDQUOTE", "a terminating quote" }, - { "CBQUOTE", "backwards single quote" }, - { "CVAR", "a dollar sign" }, - { "CENDVAR", "a '}' character" }, -@@ -81,6 +82,7 @@ - { "CEOF", "end of file" }, - { "CCTL", "like CWORD, except it must be escaped" }, - { "CSPCL", "these terminate a word" }, -+ { "CIGN", "character should be ignored" }, - { NULL, NULL } - }; - -@@ -168,7 +170,7 @@ - exit(2); - } - size = (1 << nbits) + 1; -- base = 1; -+ base = 2; - if (sign) - base += 1 << (nbits - 1); - digit_contig = 1; -@@ -179,6 +181,11 @@ - - fputs("#include <sys/cdefs.h>\n", hfile); - fputs("#include <ctype.h>\n", hfile); -+ fputs("\n", hfile); -+ fputs("#ifdef CEOF\n", hfile); -+ fputs("#undef CEOF\n", hfile); -+ fputs("#endif\n", hfile); -+ fputs("\n", hfile); - - /* Generate the #define statements in the header file */ - fputs("/* Syntax classes */\n", hfile); -@@ -201,10 +208,7 @@ - putc('\n', hfile); - fprintf(hfile, "#define SYNBASE %d\n", base); - fprintf(hfile, "#define PEOF %d\n\n", -base); -- if (sign) -- fprintf(hfile, "#define UPEOF ((char)%d)\n\n", -base); -- else -- fprintf(hfile, "#define UPEOF ((unsigned char)%d)\n\n", -base); -+ fprintf(hfile, "#define PEOA %d\n\n", -base + 1); - putc('\n', hfile); - fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); - fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); -@@ -227,32 +231,31 @@ - add("$", "CVAR"); - add("}", "CENDVAR"); - add("<>();&| \t", "CSPCL"); -+ syntax[1] = "CSPCL"; - print("basesyntax"); - init(); - fputs("\n/* syntax table used when in double quotes */\n", cfile); - add("\n", "CNL"); - add("\\", "CBACK"); -- add("\"", "CDQUOTE"); -+ add("\"", "CENDQUOTE"); - add("`", "CBQUOTE"); - add("$", "CVAR"); - add("}", "CENDVAR"); - /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ -- add("!*?[=~:/-", "CCTL"); -+ add("!*?[=~:/-]", "CCTL"); - print("dqsyntax"); - init(); - fputs("\n/* syntax table used when in single quotes */\n", cfile); - add("\n", "CNL"); -- add("'", "CSQUOTE"); -+ add("'", "CENDQUOTE"); - /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ -- add("!*?[=~:/-", "CCTL"); -+ add("!*?[=~:/-]\\", "CCTL"); - print("sqsyntax"); - init(); - fputs("\n/* syntax table used when in arithmetic */\n", cfile); - add("\n", "CNL"); - add("\\", "CBACK"); - add("`", "CBQUOTE"); -- add("'", "CSQUOTE"); -- add("\"", "CDQUOTE"); - add("$", "CVAR"); - add("}", "CENDVAR"); - add("(", "CLP"); -@@ -298,6 +301,7 @@ - { - filltable("CWORD"); - syntax[0] = "CEOF"; -+ syntax[1] = "CIGN"; - #ifdef TARGET_CHAR - syntax[base + (TARGET_CHAR)CTLESC] = "CCTL"; - syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL"; -@@ -374,9 +378,9 @@ - - static char *macro[] = { - "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)", -- "#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))", -- "#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))", -- "#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))", -+ "#define is_alpha(c)\t(((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))", -+ "#define is_name(c)\t(((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))", -+ "#define is_in_name(c)\t(((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))", - "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))", - NULL - }; -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mktokens bin_NetBSD-1.6release/src/bin/sh/mktokens ---- bin_NetBSD-1.6release.orig/src/bin/sh/mktokens 1999-07-09 12:02:07.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mktokens 2003-02-08 14:35:42.000000000 +0000 -@@ -55,21 +55,22 @@ - TENDBQUOTE 1 "`" - TREDIR 0 redirection - TWORD 0 word --TIF 0 "if" --TTHEN 1 "then" --TELSE 1 "else" -+TNOT 0 "!" -+TCASE 0 "case" -+TDO 1 "do" -+TDONE 1 "done" - TELIF 1 "elif" -+TELSE 1 "else" -+TESAC 1 "esac" - TFI 1 "fi" --TWHILE 0 "while" --TUNTIL 0 "until" - TFOR 0 "for" --TDO 1 "do" --TDONE 1 "done" -+TIF 0 "if" -+TIN 0 "in" -+TTHEN 1 "then" -+TUNTIL 0 "until" -+TWHILE 0 "while" - TBEGIN 0 "{" - TEND 1 "}" --TCASE 0 "case" --TESAC 1 "esac" --TNOT 0 "!" - ! - nl=`wc -l /tmp/ka$$` - exec > token.h -@@ -87,10 +88,9 @@ - echo '}; - ' - sed 's/"//g' /tmp/ka$$ | awk ' --/TIF/{print "#define KWDOFFSET " NR-1; print ""; -- print "const char *const parsekwd[] = {"} --/TIF/,/neverfound/{print " \"" $3 "\","}' --echo ' 0 --};' -+/TNOT/{print "#define KWDOFFSET " NR-1; print ""; -+ print "STATIC const char *const parsekwd[] = {"} -+/TNOT/,/neverfound/{if (last) print " \"" last "\","; last = $3} -+END{print " \"" last "\"\n};"}' - - rm /tmp/ka$$ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mystring.c bin_NetBSD-1.6release/src/bin/sh/mystring.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/mystring.c 1999-07-09 12:02:07.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mystring.c 2003-02-08 14:35:42.000000000 +0000 -@@ -60,9 +60,16 @@ - #include "syntax.h" - #include "error.h" - #include "mystring.h" -+#include "memalloc.h" -+#include "parser.h" - - - char nullstr[1]; /* zero length string */ -+const char spcstr[] = " "; -+const char snlfmt[] = "%s\n"; -+const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' }; -+const char illnum[] = "Illegal number: %s"; -+const char homestr[] = "HOME"; - - /* - * equal - #defined in mystring.h -@@ -73,6 +80,7 @@ - */ - - -+#if 0 - /* - * scopyn - copy a string from "from" to "to", truncating the string - * if necessary. "To" is always nul terminated, even if -@@ -92,6 +100,7 @@ - } - *to = '\0'; - } -+#endif - - - /* -@@ -122,7 +131,7 @@ - { - - if (! is_number(s)) -- error("Illegal number: %s", s); -+ error(illnum, s); - return atoi(s); - } - -@@ -142,3 +151,78 @@ - } while (*++p != '\0'); - return 1; - } -+ -+ -+/* -+ * Produce a possibly single quoted string suitable as input to the shell. -+ * The return string is allocated on the stack. -+ */ -+ -+char * -+single_quote(const char *s) { -+ char *p; -+ -+ STARTSTACKSTR(p); -+ -+ do { -+ char *q; -+ size_t len; -+ -+ len = strchrnul(s, '\'') - s; -+ -+ q = p = makestrspace(len + 3, p); -+ -+ *q++ = '\''; -+ q = mempcpy(q, s, len); -+ *q++ = '\''; -+ s += len; -+ -+ STADJUST(q - p, p); -+ -+ len = strspn(s, "'"); -+ if (!len) -+ break; -+ -+ q = p = makestrspace(len + 3, p); -+ -+ *q++ = '"'; -+ q = mempcpy(q, s, len); -+ *q++ = '"'; -+ s += len; -+ -+ STADJUST(q - p, p); -+ } while (*s); -+ -+ USTPUTC(0, p); -+ -+ return stackblock(); -+} -+ -+/* -+ * Like strdup but works with the ash stack. -+ */ -+ -+char * -+sstrdup(const char *p) -+{ -+ size_t len = strlen(p) + 1; -+ return memcpy(stalloc(len), p, len); -+} -+ -+/* -+ * Wrapper around strcmp for qsort/bsearch/... -+ */ -+int -+pstrcmp(const void *a, const void *b) -+{ -+ return strcmp(*(const char *const *) a, *(const char *const *) b); -+} -+ -+/* -+ * Find a string is in a sorted array. -+ */ -+const char *const * -+findstring(const char *s, const char *const *array, size_t nmemb) -+{ -+ return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp); -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/mystring.h bin_NetBSD-1.6release/src/bin/sh/mystring.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/mystring.h 1995-10-14 00:44:16.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/mystring.h 2003-02-08 14:35:42.000000000 +0000 -@@ -40,10 +40,23 @@ - - #include <string.h> - -+extern const char snlfmt[]; -+extern const char spcstr[]; -+extern const char dolatstr[]; -+#define DOLATSTRLEN 4 -+extern const char illnum[]; -+extern const char homestr[]; -+ -+#if 0 - void scopyn __P((const char *, char *, int)); -+#endif - int prefix __P((const char *, const char *)); - int number __P((const char *)); - int is_number __P((const char *)); -+char *single_quote __P((const char *)); -+char *sstrdup __P((const char *)); -+int pstrcmp __P((const void *, const void *)); -+const char *const *findstring __P((const char *, const char *const *, size_t)); - - #define equal(s1, s2) (strcmp(s1, s2) == 0) - #define scopy(s1, s2) ((void)strcpy(s2, s1)) -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/nodes.c.pat bin_NetBSD-1.6release/src/bin/sh/nodes.c.pat ---- bin_NetBSD-1.6release.orig/src/bin/sh/nodes.c.pat 1997-04-12 12:18:24.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/nodes.c.pat 2003-02-08 14:35:42.000000000 +0000 -@@ -70,18 +70,22 @@ - * Make a copy of a parse tree. - */ - --union node * --copyfunc(n) -- union node *n; -+struct funcnode * -+copyfunc(union node *n) - { -- if (n == NULL) -- return NULL; -- funcblocksize = 0; -+ struct funcnode *f; -+ size_t blocksize; -+ -+ funcblocksize = offsetof(struct funcnode, n); - funcstringsize = 0; - calcsize(n); -- funcblock = ckmalloc(funcblocksize + funcstringsize); -- funcstring = (char *) funcblock + funcblocksize; -- return copynode(n); -+ blocksize = funcblocksize; -+ f = ckmalloc(blocksize + funcstringsize); -+ funcblock = (char *) f + offsetof(struct funcnode, n); -+ funcstring = (char *) f + blocksize; -+ copynode(n); -+ f->count = 0; -+ return f; - } - - -@@ -144,6 +148,12 @@ - nodesavestr(s) - char *s; - { -+#ifdef _GNU_SOURCE -+ char *rtn = funcstring; -+ -+ funcstring = stpcpy(funcstring, s) + 1; -+ return rtn; -+#else - register char *p = s; - register char *q = funcstring; - char *rtn = funcstring; -@@ -152,6 +162,7 @@ - continue; - funcstring = q; - return rtn; -+#endif - } - - -@@ -161,9 +172,8 @@ - */ - - void --freefunc(n) -- union node *n; -+freefunc(struct funcnode *f) - { -- if (n) -- ckfree(n); -+ if (f && --f->count < 0) -+ ckfree(f); - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/nodetypes bin_NetBSD-1.6release/src/bin/sh/nodetypes ---- bin_NetBSD-1.6release.orig/src/bin/sh/nodetypes 2002-05-16 11:41:21.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/nodetypes 2003-02-08 14:35:42.000000000 +0000 -@@ -52,14 +52,9 @@ - # The last two types should be followed by the text of a C declaration for - # the field. - --NSEMI nbinary # two commands separated by a semicolon -- type int -- ch1 nodeptr # the first child -- ch2 nodeptr # the second child -- - NCMD ncmd # a simple command - type int -- backgnd int # set to run command in background -+ assign nodeptr # variable assignments - args nodeptr # the arguments - redirect nodeptr # list of file redirections - -@@ -79,6 +74,11 @@ - NAND nbinary # the && operator - NOR nbinary # the || operator - -+NSEMI nbinary # two commands separated by a semicolon -+ type int -+ ch1 nodeptr # the first child -+ ch2 nodeptr # the second child -+ - NIF nif # the if statement. Elif clauses are handled - type int # using multiple if nodes. - test nodeptr # if test -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/options.c bin_NetBSD-1.6release/src/bin/sh/options.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/options.c 2001-02-27 11:04:47.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/options.c 2003-02-08 14:35:42.000000000 +0000 -@@ -75,11 +75,51 @@ - - char *minusc; /* argument to -c option */ - -+static const char *const optnames[NOPTS] = { -+ "errexit", -+ "noglob", -+ "ignoreeof", -+ "interactive", -+ "monitor", -+ "noexec", -+ "stdin", -+ "xtrace", -+ "verbose", -+ "vi", -+ "emacs", -+ "noclobber", -+ "allexport", -+ "notify", -+ "nounset", -+ "quietprofile", -+}; -+ -+const char optletters[NOPTS] = { -+ 'e', -+ 'f', -+ 'I', -+ 'i', -+ 'm', -+ 'n', -+ 's', -+ 'x', -+ 'v', -+ 'V', -+ 'E', -+ 'C', -+ 'a', -+ 'b', -+ 'u', -+ 'q', -+}; -+ -+char optlist[NOPTS]; -+ - - STATIC void options __P((int)); - STATIC void minus_o __P((char *, int)); - STATIC void setoption __P((int, int)); --STATIC int getopts __P((char *, char *, char **, char ***, char **)); -+STATIC int getopts __P((char *, char *, char **, int *, int *)); - - - /* -@@ -97,7 +137,7 @@ - if (argc > 0) - argptr++; - for (i = 0; i < NOPTS; i++) -- optlist[i].val = 2; -+ optlist[i] = 2; - options(1); - if (*argptr == NULL && minusc == NULL) - sflag = 1; -@@ -106,21 +146,22 @@ - if (mflag == 2) - mflag = iflag; - for (i = 0; i < NOPTS; i++) -- if (optlist[i].val == 2) -- optlist[i].val = 0; -+ if (optlist[i] == 2) -+ optlist[i] = 0; - arg0 = argv[0]; -- if (sflag == 0 && minusc == NULL) { -- commandname = argv[0]; -- arg0 = *argptr++; -- setinputfile(arg0, 0); -- commandname = arg0; -- } - /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ -- if (argptr && minusc && *argptr) -- arg0 = *argptr++; -+ if (*argptr) { -+ char *p = *argptr++; -+ if (!minusc) -+ setinputfile(p, 0); -+ arg0 = p; -+ } -+ if (!sflag) -+ commandname = arg0; - - shellparam.p = argptr; -- shellparam.reset = 1; -+ shellparam.optind = 1; -+ shellparam.optoff = -1; - /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ - while (*argptr) { - shellparam.nparam++; -@@ -210,12 +251,12 @@ - if (name == NULL) { - out1str("Current option settings\n"); - for (i = 0; i < NOPTS; i++) -- out1fmt("%-16s%s\n", optlist[i].name, -- optlist[i].val ? "on" : "off"); -+ out1fmt("%-16s%s\n", optnames[i], -+ optlist[i] ? "on" : "off"); - } else { - for (i = 0; i < NOPTS; i++) -- if (equal(name, optlist[i].name)) { -- setoption(optlist[i].letter, val); -+ if (equal(name, optnames[i])) { -+ setoption(optletters[i], val); - return; - } - error("Illegal option -o %s", name); -@@ -231,8 +272,8 @@ - int i; - - for (i = 0; i < NOPTS; i++) -- if (optlist[i].letter == flag) { -- optlist[i].val = val; -+ if (optletters[i] == flag) { -+ optlist[i] = val; - if (val) { - /* #%$ hack for ksh semantics */ - if (flag == 'V') -@@ -248,20 +289,6 @@ - - - --#ifdef mkinit --INCLUDE "options.h" -- --SHELLPROC { -- int i; -- -- for (i = 0; i < NOPTS; i++) -- optlist[i].val = 0; -- optschanged(); -- --} --#endif -- -- - /* - * Set the shell parameters. - */ -@@ -284,7 +311,8 @@ - shellparam.malloc = 1; - shellparam.nparam = nparam; - shellparam.p = newparam; -- shellparam.optnext = NULL; -+ shellparam.optind = 1; -+ shellparam.optoff = -1; - } - - -@@ -332,7 +360,8 @@ - } - ap2 = shellparam.p; - while ((*ap2++ = *ap1++) != NULL); -- shellparam.optnext = NULL; -+ shellparam.optind = 1; -+ shellparam.optoff = -1; - INTON; - return 0; - } -@@ -365,10 +394,8 @@ - getoptsreset(value) - const char *value; - { -- if (number(value) == 1) { -- shellparam.optnext = NULL; -- shellparam.reset = 1; -- } -+ shellparam.optind = number(value); -+ shellparam.optoff = -1; - } - - /* -@@ -387,50 +414,58 @@ - - if (argc < 3) - error("Usage: getopts optstring var [arg]"); -- else if (argc == 3) -+ else if (argc == 3) { - optbase = shellparam.p; -- else -+ if (shellparam.optind > shellparam.nparam + 1) { -+ shellparam.optind = 1; -+ shellparam.optoff = -1; -+ } -+ } -+ else { - optbase = &argv[3]; -- -- if (shellparam.reset == 1) { -- shellparam.optnext = optbase; -- shellparam.optptr = NULL; -- shellparam.reset = 0; -+ if (shellparam.optind > argc - 2) { -+ shellparam.optind = 1; -+ shellparam.optoff = -1; -+ } - } - -- return getopts(argv[1], argv[2], optbase, &shellparam.optnext, -- &shellparam.optptr); -+ return getopts(argv[1], argv[2], optbase, &shellparam.optind, -+ &shellparam.optoff); - } - - STATIC int --getopts(optstr, optvar, optfirst, optnext, optpptr) -+getopts(optstr, optvar, optfirst, optind, optoff) - char *optstr; - char *optvar; - char **optfirst; -- char ***optnext; -- char **optpptr; -+ int *optind; -+ int *optoff; - { - char *p, *q; - char c = '?'; - int done = 0; -- int ind = 0; - int err = 0; - char s[10]; -+ char **optnext = optfirst + *optind - 1; - -- if ((p = *optpptr) == NULL || *p == '\0') { -+ if (*optind <= 1 || *optoff < 0 || !(*(optnext - 1)) || -+ strlen(*(optnext - 1)) < *optoff) -+ p = NULL; -+ else -+ p = *(optnext - 1) + *optoff; -+ if (p == NULL || *p == '\0') { - /* Current word is done, advance */ -- if (*optnext == NULL) -+ if (optnext == NULL) - return 1; -- p = **optnext; -+ p = *optnext; - if (p == NULL || *p != '-' || *++p == '\0') { - atend: -- ind = *optnext - optfirst + 1; -- *optnext = NULL; -+ *optind = optnext - optfirst + 1; - p = NULL; - done = 1; - goto out; - } -- (*optnext)++; -+ optnext++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - goto atend; - } -@@ -455,7 +490,7 @@ - } - - if (*++q == ':') { -- if (*p == '\0' && (p = **optnext) == NULL) { -+ if (*p == '\0' && (p = *optnext) == NULL) { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; -@@ -470,30 +505,29 @@ - goto bad; - } - -- if (p == **optnext) -- (*optnext)++; -+ if (p == *optnext) -+ optnext++; - setvarsafe("OPTARG", p, 0); - p = NULL; - } - else -- setvarsafe("OPTARG", "", 0); -- ind = *optnext - optfirst + 1; -+ setvarsafe("OPTARG", nullstr, 0); -+ *optind = optnext - optfirst + 1; - goto out; - - bad: -- ind = 1; -- *optnext = NULL; -+ *optind = 1; - p = NULL; - out: -- *optpptr = p; -- fmtstr(s, sizeof(s), "%d", ind); -+ *optoff = p ? p - *(optnext - 1) : -1; -+ fmtstr(s, sizeof(s), "%d", *optind); - err |= setvarsafe("OPTIND", s, VNOFUNC); - s[0] = c; - s[1] = '\0'; - err |= setvarsafe(optvar, s, 0); - if (err) { -- *optnext = NULL; -- *optpptr = NULL; -+ *optind = 1; -+ *optoff = -1; - flushall(); - exraise(EXERROR); - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/options.h bin_NetBSD-1.6release/src/bin/sh/options.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/options.h 2001-02-05 11:15:31.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/options.h 2003-02-08 14:35:42.000000000 +0000 -@@ -41,61 +41,34 @@ - struct shparam { - int nparam; /* # of positional parameters (without $0) */ - unsigned char malloc; /* if parameter list dynamically allocated */ -- unsigned char reset; /* if getopts has been reset */ - char **p; /* parameter list */ -- char **optnext; /* next parameter to be processed by getopts */ -- char *optptr; /* used by getopts */ -+ int optind; /* next parameter to be processed by getopts */ -+ int optoff; /* used by getopts */ - }; - - - --#define eflag optlist[0].val --#define fflag optlist[1].val --#define Iflag optlist[2].val --#define iflag optlist[3].val --#define mflag optlist[4].val --#define nflag optlist[5].val --#define sflag optlist[6].val --#define xflag optlist[7].val --#define vflag optlist[8].val --#define Vflag optlist[9].val --#define Eflag optlist[10].val --#define Cflag optlist[11].val --#define aflag optlist[12].val --#define bflag optlist[13].val --#define uflag optlist[14].val --#define qflag optlist[15].val -+#define eflag optlist[0] -+#define fflag optlist[1] -+#define Iflag optlist[2] -+#define iflag optlist[3] -+#define mflag optlist[4] -+#define nflag optlist[5] -+#define sflag optlist[6] -+#define xflag optlist[7] -+#define vflag optlist[8] -+#define Vflag optlist[9] -+#define Eflag optlist[10] -+#define Cflag optlist[11] -+#define aflag optlist[12] -+#define bflag optlist[13] -+#define uflag optlist[14] -+#define qflag optlist[15] - - #define NOPTS 16 - --struct optent { -- const char *name; -- const char letter; -- char val; --}; -- --#ifdef DEFINE_OPTIONS --struct optent optlist[NOPTS] = { -- { "errexit", 'e', 0 }, -- { "noglob", 'f', 0 }, -- { "ignoreeof", 'I', 0 }, -- { "interactive",'i', 0 }, -- { "monitor", 'm', 0 }, -- { "noexec", 'n', 0 }, -- { "stdin", 's', 0 }, -- { "xtrace", 'x', 0 }, -- { "verbose", 'v', 0 }, -- { "vi", 'V', 0 }, -- { "emacs", 'E', 0 }, -- { "noclobber", 'C', 0 }, -- { "allexport", 'a', 0 }, -- { "notify", 'b', 0 }, -- { "nounset", 'u', 0 }, -- { "quietprofile", 'q', 0 }, --}; --#else --extern struct optent optlist[NOPTS]; --#endif -+extern const char optletters[NOPTS]; -+extern char optlist[NOPTS]; - - - extern char *minusc; /* argument to -c option */ -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/output.c bin_NetBSD-1.6release/src/bin/sh/output.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/output.c 2002-04-09 11:25:14.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/output.c 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: output.c,v 1.25 2002/04/09 00:52:05 thorpej Exp $ */ -+/* $NetBSD: output.c,v 1.26 2002/05/25 23:09:06 wiz Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -41,7 +41,7 @@ - #if 0 - static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95"; - #else --__RCSID("$NetBSD: output.c,v 1.25 2002/04/09 00:52:05 thorpej Exp $"); -+__RCSID("$NetBSD: output.c,v 1.26 2002/05/25 23:09:06 wiz Exp $"); - #endif - #endif /* not lint */ - -@@ -65,6 +65,10 @@ - #include <errno.h> - #include <unistd.h> - #include <stdlib.h> -+#ifdef USE_GLIBC_STDIO -+#include <fcntl.h> -+#endif -+#include <limits.h> - - #include "shell.h" - #include "syntax.h" -@@ -74,69 +78,126 @@ - - - #define OUTBUFSIZ BUFSIZ --#define BLOCK_OUT -2 /* output to a fixed block of memory */ - #define MEM_OUT -3 /* output to dynamically allocated memory */ --#define OUTPUT_ERR 01 /* error occurred on output */ - - --struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0}; --struct output errout = {NULL, 0, NULL, 100, 2, 0}; --struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0}; -+#ifdef USE_GLIBC_STDIO -+struct output output = { -+ stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 1, flags: 0 -+}; -+struct output errout = { -+ stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0 -+} -+#ifdef notyet -+struct output memout = { -+ stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0 -+}; -+#endif -+#else -+struct output output = { -+ nextc: 0, end: 0, buf: 0, bufsize: OUTBUFSIZ, fd: 1, flags: 0 -+}; -+struct output errout = { -+ nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0 -+}; -+#ifdef notyet -+struct output memout = { -+ nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0 -+}; -+#endif -+#endif - struct output *out1 = &output; - struct output *out2 = &errout; - - -+#ifndef USE_GLIBC_STDIO -+static void __outstr(const char *, size_t, struct output *); -+#endif -+static int xvsnprintf(char *, size_t, const char *, va_list); -+ - - #ifdef mkinit - - INCLUDE "output.h" - INCLUDE "memalloc.h" - -+INIT { -+#ifdef USE_GLIBC_STDIO -+ initstreams(); -+#endif -+} -+ - RESET { -+#ifdef notyet - out1 = &output; - out2 = &errout; -+#ifdef USE_GLIBC_STDIO -+ if (memout.stream != NULL) -+ __closememout(); -+#endif - if (memout.buf != NULL) { - ckfree(memout.buf); - memout.buf = NULL; - } -+#endif - } - - #endif - - --#ifdef notdef /* no longer used */ --/* -- * Set up an output file to write to memory rather than a file. -- */ -- --void --open_mem(block, length, file) -- char *block; -- int length; -- struct output *file; -- { -- file->nextc = block; -- file->nleft = --length; -- file->fd = BLOCK_OUT; -- file->flags = 0; --} --#endif -+#ifndef USE_GLIBC_STDIO -+static void -+__outstr(const char *p, size_t len, struct output *dest) { -+ size_t bufsize; -+ size_t offset; -+ size_t nleft; - -+ nleft = dest->end - dest->nextc; -+ if (nleft >= len) { -+buffered: -+ dest->nextc = mempcpy(dest->nextc, p, len); -+ return; -+ } - --void --out1str(p) -- const char *p; -- { -- outstr(p, out1); --} -+ bufsize = dest->bufsize; -+ if (!bufsize) { -+ ; -+ } else if (dest->buf == NULL) { -+ if (dest->fd == MEM_OUT && len > bufsize) { -+ bufsize = len; -+ } -+ offset = 0; -+ goto alloc; -+ } else if (dest->fd == MEM_OUT) { -+ offset = bufsize; -+ if (bufsize >= len) { -+ bufsize <<= 1; -+ } else { -+ bufsize += len; -+ } -+ if (bufsize < offset) -+ goto err; -+alloc: -+ INTOFF; -+ dest->buf = ckrealloc(dest->buf, bufsize); -+ dest->bufsize = bufsize; -+ dest->end = dest->buf + bufsize; -+ dest->nextc = dest->buf + offset; -+ INTON; -+ } else { -+ flushout(dest); -+ } - -+ nleft = dest->end - dest->nextc; -+ if (nleft > len) -+ goto buffered; - --void --out2str(p) -- const char *p; -- { -- outstr(p, out2); -+ if ((xwrite(dest->fd, p, len))) { -+err: -+ dest->flags |= OUTPUT_ERR; -+ } - } -+#endif - - - void -@@ -144,51 +205,36 @@ - const char *p; - struct output *file; - { -- while (*p) -- outc(*p++, file); -- if (file == out2) -- flushout(file); -+#ifdef USE_GLIBC_STDIO -+ INTOFF; -+ fputs(p, file->stream); -+ INTON; -+#else -+ size_t len; -+ -+ len = strlen(p); -+ __outstr(p, len, file); -+#endif - } - - --char out_junk[16]; -+#ifndef USE_GLIBC_STDIO - - - void --emptyoutbuf(dest) -- struct output *dest; -- { -- int offset; -- -- if (dest->fd == BLOCK_OUT) { -- dest->nextc = out_junk; -- dest->nleft = sizeof out_junk; -- dest->flags |= OUTPUT_ERR; -- } else if (dest->buf == NULL) { -- INTOFF; -- dest->buf = ckmalloc(dest->bufsize); -- dest->nextc = dest->buf; -- dest->nleft = dest->bufsize; -- INTON; -- } else if (dest->fd == MEM_OUT) { -- offset = dest->bufsize; -- INTOFF; -- dest->bufsize <<= 1; -- dest->buf = ckrealloc(dest->buf, dest->bufsize); -- dest->nleft = dest->bufsize - offset; -- dest->nextc = dest->buf + offset; -- INTON; -- } else { -- flushout(dest); -- } -- dest->nleft--; -+outcslow(char c, struct output *dest) -+{ -+ __outstr(&c, 1, dest); - } -+#endif - - - void - flushall() { - flushout(&output); -+#ifdef FLUSHERR - flushout(&errout); -+#endif - } - - -@@ -196,343 +242,93 @@ - flushout(dest) - struct output *dest; - { -+#ifdef USE_GLIBC_STDIO -+ INTOFF; -+ fflush(dest->stream); -+ INTON; -+#else -+ size_t len; - -- if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0) -+ len = dest->nextc - dest->buf; -+ if (dest->buf == NULL || !len || dest->fd < 0) - return; -- if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0) -- dest->flags |= OUTPUT_ERR; - dest->nextc = dest->buf; -- dest->nleft = dest->bufsize; --} -- -- --void --freestdout() { -- INTOFF; -- if (output.buf) { -- ckfree(output.buf); -- output.buf = NULL; -- output.nleft = 0; -- } -- INTON; -+ if ((xwrite(dest->fd, dest->buf, len))) -+ dest->flags |= OUTPUT_ERR; -+#endif - } - - - void --#ifdef __STDC__ - outfmt(struct output *file, const char *fmt, ...) --#else --void --outfmt(va_alist) -- va_dcl --#endif - { - va_list ap; --#ifndef __STDC__ -- struct output *file; -- const char *fmt; - -- va_start(ap); -- file = va_arg(ap, struct output *); -- fmt = va_arg(ap, const char *); --#else - va_start(ap, fmt); --#endif - doformat(file, fmt, ap); - va_end(ap); - } - - - void --#ifdef __STDC__ - out1fmt(const char *fmt, ...) --#else --out1fmt(va_alist) -- va_dcl --#endif - { - va_list ap; --#ifndef __STDC__ -- const char *fmt; - -- va_start(ap); -- fmt = va_arg(ap, const char *); --#else - va_start(ap, fmt); --#endif - doformat(out1, fmt, ap); - va_end(ap); - } - --void --#ifdef __STDC__ --dprintf(const char *fmt, ...) --#else --dprintf(va_alist) -- va_dcl --#endif --{ -- va_list ap; --#ifndef __STDC__ -- const char *fmt; -- -- va_start(ap); -- fmt = va_arg(ap, const char *); --#else -- va_start(ap, fmt); --#endif -- doformat(out2, fmt, ap); -- va_end(ap); -- flushout(out2); --} - --void --#ifdef __STDC__ -+int - fmtstr(char *outbuf, size_t length, const char *fmt, ...) --#else --fmtstr(va_alist) -- va_dcl --#endif - { - va_list ap; -- struct output strout; --#ifndef __STDC__ -- char *outbuf; -- size_t length; -- const char *fmt; -+ int ret; - -- va_start(ap); -- outbuf = va_arg(ap, char *); -- length = va_arg(ap, size_t); -- fmt = va_arg(ap, const char *); --#else - va_start(ap, fmt); --#endif -- strout.nextc = outbuf; -- strout.nleft = length; -- strout.fd = BLOCK_OUT; -- strout.flags = 0; -- doformat(&strout, fmt, ap); -- outc('\0', &strout); -- if (strout.flags & OUTPUT_ERR) -- outbuf[length - 1] = '\0'; -+ ret = xvsnprintf(outbuf, length, fmt, ap); - va_end(ap); -+ return ret; - } - --/* -- * Formatted output. This routine handles a subset of the printf formats: -- * - Formats supported: d, u, o, p, X, s, and c. -- * - The x format is also accepted but is treated like X. -- * - The l, ll and q modifiers are accepted. -- * - The - and # flags are accepted; # only works with the o format. -- * - Width and precision may be specified with any format except c. -- * - An * may be given for the width or precision. -- * - The obsolete practice of preceding the width with a zero to get -- * zero padding is not supported; use the precision field. -- * - A % may be printed by writing %% in the format string. -- */ -- --#define TEMPSIZE 24 -- --#ifdef BSD4_4 --#define HAVE_VASPRINTF 1 --#endif - -+#ifndef USE_GLIBC_STDIO - void - doformat(dest, f, ap) - struct output *dest; - const char *f; /* format string */ - va_list ap; - { --#if HAVE_VASPRINTF -+ struct stackmark smark; - char *s; -+ int len, ret; -+ size_t size; -+ va_list ap2; - -- vasprintf(&s, f, ap); -- outstr(s, dest); -- free(s); --#else /* !HAVE_VASPRINTF */ -- static const char digit[] = "0123456789ABCDEF"; -- char c; -- char temp[TEMPSIZE]; -- int flushleft; -- int sharp; -- int width; -- int prec; -- int islong; -- int isquad; -- char *p; -- int sign; --#ifdef BSD4_4 -- quad_t l; -- u_quad_t num; --#else -- long l; -- u_long num; --#endif -- unsigned base; -- int len; -- int size; -- int pad; -- -- while ((c = *f++) != '\0') { -- if (c != '%') { -- outc(c, dest); -- continue; -- } -- flushleft = 0; -- sharp = 0; -- width = 0; -- prec = -1; -- islong = 0; -- isquad = 0; -- for (;;) { -- if (*f == '-') -- flushleft++; -- else if (*f == '#') -- sharp++; -- else -- break; -- f++; -- } -- if (*f == '*') { -- width = va_arg(ap, int); -- f++; -- } else { -- while (is_digit(*f)) { -- width = 10 * width + digit_val(*f++); -- } -- } -- if (*f == '.') { -- if (*++f == '*') { -- prec = va_arg(ap, int); -- f++; -- } else { -- prec = 0; -- while (is_digit(*f)) { -- prec = 10 * prec + digit_val(*f++); -- } -- } -- } -- if (*f == 'l') { -- f++; -- if (*f == 'l') { -- isquad++; -- f++; -- } else -- islong++; -- } else if (*f == 'q') { -- isquad++; -- f++; -+ va_copy(ap2, ap); -+ size = dest->end - dest->nextc; -+ len = xvsnprintf(dest->nextc, size, f, ap2); -+ va_end(ap2); -+ if (len < 0) { -+ dest->flags |= OUTPUT_ERR; -+ return; - } -- switch (*f) { -- case 'd': --#ifdef BSD4_4 -- if (isquad) -- l = va_arg(ap, quad_t); -- else --#endif -- if (islong) -- l = va_arg(ap, long); -- else -- l = va_arg(ap, int); -- sign = 0; -- num = l; -- if (l < 0) { -- num = -l; -- sign = 1; -+ if (len < size) { -+ dest->nextc += len; -+ return; - } -- base = 10; -- goto number; -- case 'u': -- base = 10; -- goto uns_number; -- case 'o': -- base = 8; -- goto uns_number; -- case 'p': -- outc('0', dest); -- outc('x', dest); -- /*FALLTHROUGH*/ -- case 'x': -- /* we don't implement 'x'; treat like 'X' */ -- case 'X': -- base = 16; --uns_number: /* an unsigned number */ -- sign = 0; --#ifdef BSD4_4 -- if (isquad) -- num = va_arg(ap, u_quad_t); -- else --#endif -- if (islong) -- num = va_arg(ap, unsigned long); -+ setstackmark(&smark); -+ s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1); -+ ret = xvsnprintf(s, len + 1, f, ap); -+ if (ret == len) -+ __outstr(s, len, dest); - else -- num = va_arg(ap, unsigned int); --number: /* process a number */ -- p = temp + TEMPSIZE - 1; -- *p = '\0'; -- while (num) { -- *--p = digit[num % base]; -- num /= base; -- } -- len = (temp + TEMPSIZE - 1) - p; -- if (prec < 0) -- prec = 1; -- if (sharp && *f == 'o' && prec <= len) -- prec = len + 1; -- pad = 0; -- if (width) { -- size = len; -- if (size < prec) -- size = prec; -- size += sign; -- pad = width - size; -- if (flushleft == 0) { -- while (--pad >= 0) -- outc(' ', dest); -- } -- } -- if (sign) -- outc('-', dest); -- prec -= len; -- while (--prec >= 0) -- outc('0', dest); -- while (*p) -- outc(*p++, dest); -- while (--pad >= 0) -- outc(' ', dest); -- break; -- case 's': -- p = va_arg(ap, char *); -- pad = 0; -- if (width) { -- len = strlen(p); -- if (prec >= 0 && len > prec) -- len = prec; -- pad = width - len; -- if (flushleft == 0) { -- while (--pad >= 0) -- outc(' ', dest); -- } -- } -- prec++; -- while (--prec != 0 && *p) -- outc(*p++, dest); -- while (--pad >= 0) -- outc(' ', dest); -- break; -- case 'c': -- c = va_arg(ap, int); -- outc(c, dest); -- break; -- default: -- outc(*f, dest); -- break; -- } -- f++; -- } --#endif /* !HAVE_VASPRINTF */ -+ dest->flags |= OUTPUT_ERR; -+ popstackmark(&smark); - } -+#endif - - - -@@ -541,47 +337,63 @@ - */ - - int --xwrite(fd, buf, nbytes) -- int fd; -- char *buf; -- int nbytes; -- { -- int ntry; -- int i; -- int n; -+xwrite(int fd, const void *p, size_t n) -+{ -+ const char *buf = p; - -- n = nbytes; -- ntry = 0; -- for (;;) { -- i = write(fd, buf, n); -- if (i > 0) { -- if ((n -= i) <= 0) -- return nbytes; -- buf += i; -- ntry = 0; -- } else if (i == 0) { -- if (++ntry > 10) -- return nbytes - n; -- } else if (errno != EINTR) { -+ while (n) { -+ ssize_t i; -+ size_t m; -+ -+ m = n; -+ if (m > SSIZE_MAX) -+ m = SSIZE_MAX; -+ do { -+ i = write(fd, buf, m); -+ } while (i < 0 && errno == EINTR); -+ if (i < 0) - return -1; -+ buf += i; -+ n -= i; - } -- } -+ return 0; - } - - --/* -- * Version of ioctl that retries after a signal is caught. -- * XXX unused function -- */ -+#ifdef notyet -+#ifdef USE_GLIBC_STDIO -+void initstreams() { -+ output.stream = stdout; -+ errout.stream = stderr; -+} -+ -+ -+void -+openmemout() { -+ INTOFF; -+ memout.stream = open_memstream(&memout.buf, &memout.bufsize); -+ INTON; -+} -+ - - int --xioctl(fd, request, arg) -- int fd; -- unsigned long request; -- char * arg; -+__closememout() { -+ int error; -+ error = fclose(memout.stream); -+ memout.stream = NULL; -+ return error; -+} -+#endif -+#endif -+ -+ -+static int -+xvsnprintf(char *outbuf, size_t length, const char *fmt, va_list ap) - { -- int i; -+ int ret; - -- while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR); -- return i; -+ INTOFF; -+ ret = vsnprintf(outbuf, length, fmt, ap); -+ INTON; -+ return ret; - } -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/output.h bin_NetBSD-1.6release/src/bin/sh/output.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/output.h 1998-01-31 18:28:11.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/output.h 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: output.h,v 1.14 1998/01/31 12:37:55 christos Exp $ */ -+/* $NetBSD: output.h,v 1.15 2002/05/25 23:13:26 wiz Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -40,50 +40,76 @@ - - #ifndef OUTPUT_INCL - --#ifdef __STDC__ - #include <stdarg.h> --#else --#include <varargs.h> -+#ifdef USE_GLIBC_STDIO -+#include <stdio.h> - #endif -+#include <sys/types.h> - - struct output { -+#ifdef USE_GLIBC_STDIO -+ FILE *stream; -+#endif - char *nextc; -- int nleft; -+ char *end; - char *buf; -- int bufsize; -- short fd; -- short flags; -+ size_t bufsize; -+ int fd; -+ int flags; - }; - - extern struct output output; - extern struct output errout; -+#ifdef notyet - extern struct output memout; -+#endif - extern struct output *out1; - extern struct output *out2; - --void open_mem __P((char *, int, struct output *)); --void out1str __P((const char *)); --void out2str __P((const char *)); - void outstr __P((const char *, struct output *)); --void emptyoutbuf __P((struct output *)); -+#ifndef USE_GLIBC_STDIO -+void outcslow __P((char, struct output *)); -+#endif - void flushall __P((void)); - void flushout __P((struct output *)); --void freestdout __P((void)); - void outfmt __P((struct output *, const char *, ...)) - __attribute__((__format__(__printf__,2,3))); - void out1fmt __P((const char *, ...)) - __attribute__((__format__(__printf__,1,2))); --void dprintf __P((const char *, ...)) -- __attribute__((__format__(__printf__,1,2))); --void fmtstr __P((char *, size_t, const char *, ...)) -+int fmtstr __P((char *, size_t, const char *, ...)) - __attribute__((__format__(__printf__,3,4))); -+#ifndef USE_GLIBC_STDIO - void doformat __P((struct output *, const char *, va_list)); --int xwrite __P((int, char *, int)); --int xioctl __P((int, unsigned long, char *)); -+#endif -+int xwrite __P((int, const void *, size_t)); -+#ifdef notyet -+#ifdef USE_GLIBC_STDIO -+void initstreams __P((void)); -+void openmemout __P((void)); -+int __closememout __P((void)); -+#endif -+#endif - --#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c))) --#define out1c(c) outc(c, out1); --#define out2c(c) outc(c, out2); -+static inline void -+freestdout() -+{ -+ output.nextc = output.buf; -+ output.flags = 0; -+} -+ -+#define OUTPUT_ERR 01 /* error occurred on output */ -+ -+#ifdef USE_GLIBC_STDIO -+#define outc(c, o) putc((c), (o)->stream) -+#define doformat(d, f, a) vfprintf((d)->stream, (f), (a)) -+#else -+#define outc(c, file) ((file)->nextc == (file)->end ? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++)) -+#endif -+#define out1c(c) outc((c), out1) -+#define out2c(c) outc((c), out2) -+#define out1str(s) outstr((s), out1) -+#define out2str(s) outstr((s), out2) -+#define outerr(f) ((f)->flags & OUTPUT_ERR) - - #define OUTPUT_INCL - #endif -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/parser.c bin_NetBSD-1.6release/src/bin/sh/parser.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/parser.c 2002-05-16 11:41:21.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/parser.c 2003-02-08 14:35:42.000000000 +0000 -@@ -53,6 +53,7 @@ - #include "expand.h" /* defines rmescapes() */ - #include "eval.h" /* defines commandname */ - #include "redir.h" /* defines copyfd() */ -+#include "exec.h" /* defines find_builtin() */ - #include "syntax.h" - #include "options.h" - #include "input.h" -@@ -63,6 +64,7 @@ - #include "mystring.h" - #include "alias.h" - #include "show.h" -+#include "builtins.h" - #ifndef SMALL - #include "myhistedit.h" - #endif -@@ -76,8 +78,6 @@ - /* values returned by readtoken */ - #include "token.h" - --#define OPENBRACE '{' --#define CLOSEBRACE '}' - - - struct heredoc { -@@ -89,7 +89,6 @@ - - - --static int noalias = 0; /* when set, don't handle aliases */ - struct heredoc *heredoclist; /* list of here documents to read */ - int parsebackquote; /* nonzero if we are inside backquotes */ - int doprompt; /* if set, prompt the user */ -@@ -97,7 +96,7 @@ - int lasttoken; /* last token read */ - MKINIT int tokpushback; /* last token pushed back */ - char *wordtext; /* text of last word returned by readtoken */ --MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */ -+int checkkwd; - struct nodelist *backquotelist; - union node *redirnode; - struct heredoc *heredoc; -@@ -109,7 +108,7 @@ - STATIC union node *andor __P((void)); - STATIC union node *pipeline __P((void)); - STATIC union node *command __P((void)); --STATIC union node *simplecmd __P((union node **, union node *)); -+STATIC union node *simplecmd __P((void)); - STATIC union node *makename __P((void)); - STATIC void parsefname __P((void)); - STATIC void parseheredoc __P((void)); -@@ -123,6 +122,22 @@ - STATIC void setprompt __P((int)); - - -+static inline int -+goodname(const char *p) -+{ -+ return !*endofname(p); -+} -+ -+static inline int -+isassignment(const char *p) -+{ -+ const char *q = endofname(p); -+ if (p == q) -+ return 0; -+ return *q == '='; -+} -+ -+ - /* - * Read and parse a command. Returns NEOF on end of file. (NULL is a - * valid parse tree indicating a blank line.) -@@ -136,9 +151,7 @@ - tokpushback = 0; - doprompt = interact; - if (doprompt) -- setprompt(1); -- else -- setprompt(0); -+ setprompt(doprompt); - needprompt = 0; - t = readtoken(); - if (t == TEOF) -@@ -157,25 +170,25 @@ - union node *n1, *n2, *n3; - int tok; - -- checkkwd = 2; -- if (nlflag == 0 && tokendlist[peektoken()]) -+ checkkwd = CHKNL | CHKKWD | CHKALIAS; -+ if (nlflag == 2 && tokendlist[peektoken()]) - return NULL; - n1 = NULL; - for (;;) { - n2 = andor(); - tok = readtoken(); - if (tok == TBACKGND) { -- if (n2->type == NCMD || n2->type == NPIPE) { -- n2->ncmd.backgnd = 1; -- } else if (n2->type == NREDIR) { -- n2->type = NBACKGND; -+ if (n2->type == NPIPE) { -+ n2->npipe.backgnd = 1; - } else { -- n3 = (union node *)stalloc(sizeof (struct nredir)); -- n3->type = NBACKGND; -+ if (n2->type != NREDIR) { -+ n3 = stalloc(sizeof(struct nredir)); - n3->nredir.n = n2; - n3->nredir.redirect = NULL; - n2 = n3; - } -+ n2->type = NBACKGND; -+ } - } - if (n1 == NULL) { - n1 = n2; -@@ -195,12 +208,12 @@ - case TNL: - if (tok == TNL) { - parseheredoc(); -- if (nlflag) -+ if (nlflag == 1) - return n1; - } else { - tokpushback++; - } -- checkkwd = 2; -+ checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (tokendlist[peektoken()]) - return n1; - break; -@@ -211,7 +224,7 @@ - pungetc(); /* push back EOF on input */ - return n1; - default: -- if (nlflag) -+ if (nlflag == 1) - synexpect(-1); - tokpushback++; - return n1; -@@ -236,6 +249,7 @@ - tokpushback++; - return n1; - } -+ checkkwd = CHKNL | CHKKWD | CHKALIAS; - n2 = pipeline(); - n3 = (union node *)stalloc(sizeof (struct nbinary)); - n3->type = t; -@@ -255,8 +269,10 @@ - - negate = 0; - TRACE(("pipeline: entered\n")); -- while (readtoken() == TNOT) -+ if (readtoken() == TNOT) { - negate = !negate; -+ checkkwd = CHKKWD | CHKALIAS; -+ } else - tokpushback++; - n1 = command(); - if (readtoken() == TPIPE) { -@@ -269,6 +285,7 @@ - do { - prev = lp; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); -+ checkkwd = CHKNL | CHKKWD | CHKALIAS; - lp->n = command(); - prev->next = lp; - } while (readtoken() == TPIPE); -@@ -293,28 +310,16 @@ - union node *ap, **app; - union node *cp, **cpp; - union node *redir, **rpp; -- int t, negate = 0; -+ union node **rpp2; -+ int t; - -- checkkwd = 2; - redir = NULL; -- n1 = NULL; -- rpp = &redir; -- -- /* Check for redirection which may precede command */ -- while (readtoken() == TREDIR) { -- *rpp = n2 = redirnode; -- rpp = &n2->nfile.next; -- parsefname(); -- } -- tokpushback++; -- -- while (readtoken() == TNOT) { -- TRACE(("command: TNOT recognized\n")); -- negate = !negate; -- } -- tokpushback++; -+ rpp2 = &redir; - - switch (readtoken()) { -+ default: -+ synexpect(-1); -+ /* NOTREACHED */ - case TIF: - n1 = (union node *)stalloc(sizeof (struct nif)); - n1->type = NIF; -@@ -338,9 +343,7 @@ - n2->nif.elsepart = NULL; - tokpushback++; - } -- if (readtoken() != TFI) -- synexpect(TFI); -- checkkwd = 1; -+ t = TFI; - break; - case TWHILE: - case TUNTIL: { -@@ -353,9 +356,7 @@ - synexpect(TDO); - } - n1->nbinary.ch2 = list(0); -- if (readtoken() != TDONE) -- synexpect(TDONE); -- checkkwd = 1; -+ t = TDONE; - break; - } - case TFOR: -@@ -364,7 +365,8 @@ - n1 = (union node *)stalloc(sizeof (struct nfor)); - n1->type = NFOR; - n1->nfor.var = wordtext; -- if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) { -+ checkkwd = CHKKWD | CHKALIAS; -+ if (readtoken() == TIN) { - app = ≈ - while (readtoken() == TWORD) { - n2 = (union node *)stalloc(sizeof (struct narg)); -@@ -379,11 +381,9 @@ - if (lasttoken != TNL && lasttoken != TSEMI) - synexpect(-1); - } else { -- static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, -- '@', '=', '\0'}; - n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; -- n2->narg.text = argvars; -+ n2->narg.text = (char *)dolatstr; - n2->narg.backquote = NULL; - n2->narg.next = NULL; - n1->nfor.args = n2; -@@ -394,17 +394,11 @@ - if (lasttoken != TNL && lasttoken != TSEMI) - tokpushback++; - } -- checkkwd = 2; -- if ((t = readtoken()) == TDO) -- t = TDONE; -- else if (t == TBEGIN) -- t = TEND; -- else -- synexpect(-1); -+ checkkwd = CHKNL | CHKKWD | CHKALIAS; -+ if (readtoken() != TDO) -+ synexpect(TDO); - n1->nfor.body = list(0); -- if (readtoken() != t) -- synexpect(t); -- checkkwd = 1; -+ t = TDONE; - break; - case TCASE: - n1 = (union node *)stalloc(sizeof (struct ncase)); -@@ -416,13 +410,18 @@ - n2->narg.text = wordtext; - n2->narg.backquote = backquotelist; - n2->narg.next = NULL; -- while (readtoken() == TNL); -- if (lasttoken != TWORD || ! equal(wordtext, "in")) -- synerror("expecting \"in\""); -- cpp = &n1->ncase.cases; -- noalias = 1; -- checkkwd = 2, readtoken(); - do { -+ checkkwd = CHKKWD | CHKALIAS; -+ } while (readtoken() == TNL); -+ if (lasttoken != TIN) -+ synexpect(TIN); -+ cpp = &n1->ncase.cases; -+next_case: -+ checkkwd = CHKNL | CHKKWD; -+ t = readtoken(); -+ while(t != TESAC) { -+ if (lasttoken == TLP) -+ readtoken(); - *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); - cp->type = NCLIST; - app = &cp->nclist.pattern; -@@ -431,73 +430,52 @@ - ap->type = NARG; - ap->narg.text = wordtext; - ap->narg.backquote = backquotelist; -- if (checkkwd = 2, readtoken() != TPIPE) -+ if (readtoken() != TPIPE) - break; - app = &ap->narg.next; - readtoken(); - } - ap->narg.next = NULL; -- noalias = 0; -- if (lasttoken != TRP) { -+ if (lasttoken != TRP) - synexpect(TRP); -- } -- cp->nclist.body = list(0); -+ cp->nclist.body = list(2); - -- checkkwd = 2; -+ cpp = &cp->nclist.next; -+ -+ checkkwd = CHKNL | CHKKWD; - if ((t = readtoken()) != TESAC) { -- if (t != TENDCASE) { -- noalias = 0; -+ if (t != TENDCASE) - synexpect(TENDCASE); -- } else { -- noalias = 1; -- checkkwd = 2; -- readtoken(); -+ else -+ goto next_case; - } - } -- cpp = &cp->nclist.next; -- } while(lasttoken != TESAC); -- noalias = 0; - *cpp = NULL; -- checkkwd = 1; -- break; -+ goto redir; - case TLP: - n1 = (union node *)stalloc(sizeof (struct nredir)); - n1->type = NSUBSHELL; - n1->nredir.n = list(0); - n1->nredir.redirect = NULL; -- if (readtoken() != TRP) -- synexpect(TRP); -- checkkwd = 1; -+ t = TRP; - break; - case TBEGIN: - n1 = list(0); -- if (readtoken() != TEND) -- synexpect(TEND); -- checkkwd = 1; -+ t = TEND; - break; -- /* Handle an empty command like other simple commands. */ -- case TSEMI: -- /* -- * An empty command before a ; doesn't make much sense, and -- * should certainly be disallowed in the case of `if ;'. -- */ -- if (!redir) -- synexpect(-1); -- case TAND: -- case TOR: -- case TNL: -- case TEOF: - case TWORD: -- case TRP: -+ case TREDIR: - tokpushback++; -- n1 = simplecmd(rpp, redir); -- goto checkneg; -- default: -- synexpect(-1); -- /* NOTREACHED */ -+ return simplecmd(); - } - -+ if (readtoken() != t) -+ synexpect(t); -+ -+redir: - /* Now check for redirection which may follow command */ -+ checkkwd = CHKKWD | CHKALIAS; -+ rpp = rpp2; - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; -@@ -515,92 +493,87 @@ - n1->nredir.redirect = redir; - } - --checkneg: -- if (negate) { -- n2 = (union node *)stalloc(sizeof (struct nnot)); -- n2->type = NNOT; -- n2->nnot.com = n1; -- return n2; -- } -- else - return n1; - } - - - STATIC union node * --simplecmd(rpp, redir) -- union node **rpp, *redir; -- { -+simplecmd() { - union node *args, **app; -- union node **orig_rpp = rpp; -- union node *n = NULL, *n2; -- int negate = 0; -- -- /* If we don't have any redirections already, then we must reset */ -- /* rpp to be the address of the local redir variable. */ -- if (redir == 0) -- rpp = &redir; -+ union node *n = NULL; -+ union node *vars, **vpp; -+ union node **rpp, *redir; -+ int savecheckkwd; - - args = NULL; - app = &args; -- /* -- * We save the incoming value, because we need this for shell -- * functions. There can not be a redirect or an argument between -- * the function name and the open parenthesis. -- */ -- orig_rpp = rpp; -- -- while (readtoken() == TNOT) { -- TRACE(("command: TNOT recognized\n")); -- negate = !negate; -- } -- tokpushback++; -+ vars = NULL; -+ vpp = &vars; -+ redir = NULL; -+ rpp = &redir; - -+ savecheckkwd = CHKALIAS; - for (;;) { -- if (readtoken() == TWORD) { -+ checkkwd = savecheckkwd; -+ switch (readtoken()) { -+ case TWORD: - n = (union node *)stalloc(sizeof (struct narg)); - n->type = NARG; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; -+ if (savecheckkwd && isassignment(wordtext)) { -+ *vpp = n; -+ vpp = &n->narg.next; -+ } else { - *app = n; - app = &n->narg.next; -- } else if (lasttoken == TREDIR) { -+ savecheckkwd = 0; -+ } -+ break; -+ case TREDIR: - *rpp = n = redirnode; - rpp = &n->nfile.next; - parsefname(); /* read name of redirection file */ -- } else if (lasttoken == TLP && app == &args->narg.next -- && rpp == orig_rpp) { -+ break; -+ case TLP: -+ if ( -+ args && app == &args->narg.next && -+ !vars && !redir -+ ) { -+ struct builtincmd *bcmd; -+ const char *name; -+ - /* We have a function */ - if (readtoken() != TRP) - synexpect(TRP); --#ifdef notdef -- if (! goodname(n->narg.text)) -+ name = n->narg.text; -+ if ( -+ !goodname(name) || ( -+ (bcmd = find_builtin(name)) && -+ bcmd->flags & BUILTIN_SPECIAL -+ ) -+ ) - synerror("Bad function name"); --#endif - n->type = NDEFUN; -+ checkkwd = CHKNL | CHKKWD | CHKALIAS; - n->narg.next = command(); -- goto checkneg; -- } else { -+ return n; -+ } -+ /* fall through */ -+ default: - tokpushback++; -- break; -+ goto out; - } - } -+out: - *app = NULL; -+ *vpp = NULL; - *rpp = NULL; - n = (union node *)stalloc(sizeof (struct ncmd)); - n->type = NCMD; -- n->ncmd.backgnd = 0; - n->ncmd.args = args; -+ n->ncmd.assign = vars; - n->ncmd.redirect = redir; -- --checkneg: -- if (negate) { -- n2 = (union node *)stalloc(sizeof (struct nnot)); -- n2->type = NNOT; -- n2->nnot.com = n; -- return n2; -- } -- else - return n; - } - -@@ -682,9 +655,10 @@ - struct heredoc *here; - union node *n; - -- while (heredoclist) { - here = heredoclist; -- heredoclist = here->next; -+ heredoclist = 0; -+ -+ while (here) { - if (needprompt) { - setprompt(2); - needprompt = 0; -@@ -697,6 +671,7 @@ - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - here->here->nhere.doc = n; -+ here = here->next; - } - } - -@@ -712,53 +687,51 @@ - STATIC int - readtoken() { - int t; -- int savecheckkwd = checkkwd; - #ifdef DEBUG - int alreadyseen = tokpushback; - #endif -- struct alias *ap; - -- top: -+top: - t = xxreadtoken(); - -- if (checkkwd) { - /* - * eat newlines - */ -- if (checkkwd == 2) { -- checkkwd = 0; -+ if (checkkwd & CHKNL) { - while (t == TNL) { - parseheredoc(); - t = xxreadtoken(); - } -- } else -- checkkwd = 0; -+ } -+ -+ if (t != TWORD || quoteflag) { -+ goto out; -+ } -+ - /* -- * check for keywords and aliases -+ * check for keywords - */ -- if (t == TWORD && !quoteflag) -- { -+ if (checkkwd & CHKKWD) { - const char *const *pp; - -- for (pp = parsekwd; *pp; pp++) { -- if (**pp == *wordtext && equal(*pp, wordtext)) -- { -- lasttoken = t = pp - -- parsekwd + KWDOFFSET; -+ if ((pp = findkwd(wordtext))) { -+ lasttoken = t = pp - parsekwd + KWDOFFSET; - TRACE(("keyword %s recognized\n", tokname[t])); - goto out; - } - } -- if(!noalias && -- (ap = lookupalias(wordtext, 1)) != NULL) { -- pushstring(ap->val, strlen(ap->val), ap); -- checkkwd = savecheckkwd; -+ -+ if (checkkwd & CHKALIAS) { -+ struct alias *ap; -+ if ((ap = lookupalias(wordtext, 1)) != NULL) { -+ if (*ap->val) { -+ pushstring(ap->val, ap); -+ } - goto top; - } - } - out: -- checkkwd = (t == TNOT) ? savecheckkwd : 0; -- } -+ checkkwd = 0; - #ifdef DEBUG - if (!alreadyseen) - TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); -@@ -804,10 +777,9 @@ - startlinno = plinno; - for (;;) { /* until token or start of word found */ - c = pgetc_macro(); -- if (c == ' ' || c == '\t') -- continue; /* quick check for white space first */ - switch (c) { - case ' ': case '\t': -+ case PEOA: - continue; - case '#': - while ((c = pgetc()) != '\n' && c != PEOF); -@@ -818,8 +790,6 @@ - startlinno = ++plinno; - if (doprompt) - setprompt(2); -- else -- setprompt(0); - continue; - } - pungetc(); -@@ -879,28 +849,6 @@ - #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} - #define PARSEARITH() {goto parsearith; parsearith_return:;} - --/* -- * Keep track of nested doublequotes in dblquote and doublequotep. -- * We use dblquote for the first 32 levels, and we expand to a malloc'ed -- * region for levels above that. Usually we never need to malloc. -- * This code assumes that an int is 32 bits. We don't use uint32_t, -- * because the rest of the code does not. -- */ --#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \ -- (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32)))) -- --#define SETDBLQUOTE() \ -- if (varnest < 32) \ -- dblquote |= (1 << varnest); \ -- else \ -- dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32)) -- --#define CLRDBLQUOTE() \ -- if (varnest < 32) \ -- dblquote &= ~(1 << varnest); \ -- else \ -- dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32)) -- - STATIC int - readtoken1(firstc, syntax, eofmark, striptabs) - int firstc; -@@ -914,24 +862,22 @@ - char line[EOFMARKLEN + 1]; - struct nodelist *bqlist; - int quotef; -- int *dblquotep = NULL; -- size_t maxnest = 32; - int dblquote; - int varnest; /* levels of variables expansion */ - int arinest; /* levels of arithmetic expansion */ - int parenlevel; /* levels of parens in arithmetic */ -+ int dqvarnest; /* levels of variables expansion within double quotes */ - int oldstyle; - char const *prevsyntax; /* syntax before arithmetic */ - #if __GNUC__ - /* Avoid longjmp clobbering */ -- (void) &maxnest; -- (void) &dblquotep; - (void) &out; - (void) "ef; - (void) &dblquote; - (void) &varnest; - (void) &arinest; - (void) &parenlevel; -+ (void) &dqvarnest; - (void) &oldstyle; - (void) &prevsyntax; - (void) &syntax; -@@ -939,14 +885,14 @@ - - startlinno = plinno; - dblquote = 0; -- varnest = 0; -- if (syntax == DQSYNTAX) { -- SETDBLQUOTE(); -- } -+ if (syntax == DQSYNTAX) -+ dblquote = 1; - quotef = 0; - bqlist = NULL; -+ varnest = 0; - arinest = 0; - parenlevel = 0; -+ dqvarnest = 0; - - STARTSTACKSTR(out); - loop: { /* for each line, until end of word */ -@@ -962,7 +908,7 @@ - #endif - CHECKEND(); /* set c to PEOF if at end of here document */ - for (;;) { /* until end of line or end of word */ -- CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ -+ CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ - switch(syntax[c]) { - case CNL: /* '\n' */ - if (syntax == BASESYNTAX) -@@ -971,82 +917,76 @@ - plinno++; - if (doprompt) - setprompt(2); -- else -- setprompt(0); - c = pgetc(); - goto loop; /* continue outer loop */ - case CWORD: - USTPUTC(c, out); - break; - case CCTL: -- if (eofmark == NULL || ISDBLQUOTE()) -+ if (eofmark == NULL || dblquote) - USTPUTC(CTLESC, out); - USTPUTC(c, out); - break; - case CBACK: /* backslash */ -- c = pgetc(); -+ c = pgetc2(); - if (c == PEOF) { -+ USTPUTC(CTLESC, out); - USTPUTC('\\', out); - pungetc(); - } else if (c == '\n') { - if (doprompt) - setprompt(2); -- else -- setprompt(0); - } else { -- if (ISDBLQUOTE() && c != '\\' && -- c != '`' && c != '$' && -- (c != '"' || eofmark != NULL)) -+ if ( -+ dblquote && -+ c != '\\' && c != '`' && -+ c != '$' && ( -+ c != '"' || -+ eofmark != NULL -+ ) -+ ) { -+ USTPUTC(CTLESC, out); - USTPUTC('\\', out); -+ } - if (SQSYNTAX[c] == CCTL) - USTPUTC(CTLESC, out); -- else if (eofmark == NULL) -- USTPUTC(CTLQUOTEMARK, out); - USTPUTC(c, out); - quotef++; - } - break; - case CSQUOTE: -- if (syntax != SQSYNTAX) { -- if (eofmark == NULL) -- USTPUTC(CTLQUOTEMARK, out); - syntax = SQSYNTAX; -- break; -+quotemark: -+ if (eofmark == NULL) { -+ USTPUTC(CTLQUOTEMARK, out); - } -- /* FALLTHROUGH */ -+ break; - case CDQUOTE: -+ syntax = DQSYNTAX; -+ dblquote = 1; -+ goto quotemark; -+ case CENDQUOTE: - if (eofmark != NULL && arinest == 0 && - varnest == 0) { - USTPUTC(c, out); - } else { -- if (arinest) { -- if (c != '"' || ISDBLQUOTE()) { -- syntax = ARISYNTAX; -- CLRDBLQUOTE(); -- } else { -- syntax = DQSYNTAX; -- SETDBLQUOTE(); -- USTPUTC(CTLQUOTEMARK, out); -- } -- } else if (eofmark == NULL) { -- if (c != '"' || ISDBLQUOTE()) { -+ if (dqvarnest == 0) { - syntax = BASESYNTAX; -- CLRDBLQUOTE(); -- } else { -- syntax = DQSYNTAX; -- SETDBLQUOTE(); -- USTPUTC(CTLQUOTEMARK, out); -- } -+ dblquote = 0; - } - quotef++; -+ goto quotemark; - } - break; - case CVAR: /* '$' */ - PARSESUB(); /* parse substitution */ - break; -- case CENDVAR: /* CLOSEBRACE */ -- if (varnest > 0 && !ISDBLQUOTE()) { -+ case CENDVAR: /* '}' */ -+ if (varnest > 0) { - varnest--; -+ if (dqvarnest > 0) { -+ dqvarnest--; -+ } - USTPUTC(CTLENDVAR, out); - } else { - USTPUTC(c, out); -@@ -1066,9 +1006,9 @@ - USTPUTC(CTLENDARI, out); - syntax = prevsyntax; - if (syntax == DQSYNTAX) -- SETDBLQUOTE(); -+ dblquote = 1; - else -- CLRDBLQUOTE(); -+ dblquote = 0; - } else - USTPUTC(')', out); - } else { -@@ -1086,11 +1026,15 @@ - break; - case CEOF: - goto endword; /* exit outer loop */ -+ case CIGN: -+ break; - default: - if (varnest == 0) - goto endword; /* exit outer loop */ -+ if (c != PEOA) { - USTPUTC(c, out); - } -+ } - c = pgetc_macro(); - } - } -@@ -1122,8 +1066,6 @@ - backquotelist = bqlist; - grabstackblock(len); - wordtext = out; -- if (dblquotep != NULL) -- ckfree(dblquotep); - return lasttoken = TWORD; - /* end of readtoken routine */ - -@@ -1137,9 +1079,13 @@ - - checkend: { - if (eofmark) { -+ if (c == PEOA) { -+ c = pgetc2(); -+ } - if (striptabs) { -- while (c == '\t') -- c = pgetc(); -+ while (c == '\t') { -+ c = pgetc2(); -+ } - } - if (c == *eofmark) { - if (pfgets(line, sizeof line) != NULL) { -@@ -1152,7 +1098,7 @@ - plinno++; - needprompt = doprompt; - } else { -- pushstring(line, strlen(line), NULL); -+ pushstring(line, NULL); - } - } - } -@@ -1238,7 +1184,10 @@ - static const char types[] = "}-+?="; - - c = pgetc(); -- if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) { -+ if ( -+ c <= PEOA || -+ (c != '(' && c != '{' && !is_name(c) && !is_special(c)) -+ ) { - USTPUTC('$', out); - pungetc(); - } else if (c == '(') { /* $(command) or $((arith)) */ -@@ -1253,10 +1202,10 @@ - typeloc = out - stackblock(); - USTPUTC(VSNORMAL, out); - subtype = VSNORMAL; -- if (c == OPENBRACE) { -+ if (c == '{') { - c = pgetc(); - if (c == '#') { -- if ((c = pgetc()) == CLOSEBRACE) -+ if ((c = pgetc()) == '}') - c = '#'; - else - subtype = VSLENGTH; -@@ -1264,11 +1213,11 @@ - else - subtype = 0; - } -- if (is_name(c)) { -+ if (c > PEOA && is_name(c)) { - do { - STPUTC(c, out); - c = pgetc(); -- } while (is_in_name(c)); -+ } while (c > PEOA && is_in_name(c)); - } else if (is_digit(c)) { - do { - USTPUTC(c, out); -@@ -1313,15 +1262,13 @@ - } else { - pungetc(); - } -- if (ISDBLQUOTE() || arinest) -+ if (dblquote || arinest) - flags |= VSQUOTE; - *(stackblock() + typeloc) = subtype | flags; - if (subtype != VSNORMAL) { - varnest++; -- if (varnest >= maxnest) { -- dblquotep = ckrealloc(dblquotep, maxnest / 8); -- dblquotep[(maxnest / 32) - 1] = 0; -- maxnest += 32; -+ if (dblquote || arinest) { -+ dqvarnest++; - } - } - } -@@ -1343,7 +1290,7 @@ - char *volatile str; - struct jmploc jmploc; - struct jmploc *volatile savehandler; -- int savelen; -+ size_t savelen; - int saveprompt; - #ifdef __GNUC__ - (void) &saveprompt; -@@ -1373,7 +1320,7 @@ - reread it as input, interpreting it normally. */ - char *pout; - int pc; -- int psavelen; -+ size_t psavelen; - char *pstr; - - -@@ -1392,8 +1339,6 @@ - plinno++; - if (doprompt) - setprompt(2); -- else -- setprompt(0); - /* - * If eating a newline, avoid putting - * the newline into the new character -@@ -1403,18 +1348,21 @@ - continue; - } - if (pc != '\\' && pc != '`' && pc != '$' -- && (!ISDBLQUOTE() || pc != '"')) -+ && (!dblquote || pc != '"')) - STPUTC('\\', pout); -+ if (pc > PEOA) { - break; -- -- case '\n': -- plinno++; -- needprompt = doprompt; -- break; -+ } -+ /* fall through */ - - case PEOF: -+ case PEOA: - startlinno = plinno; - synerror("EOF in backquote substitution"); -+ -+ case '\n': -+ plinno++; -+ needprompt = doprompt; - break; - - default: -@@ -1427,7 +1375,7 @@ - psavelen = pout - stackblock(); - if (psavelen > 0) { - pstr = grabstackstr(pout); -- setinputstring(pstr, 1); -+ setinputstring(pstr); - } - } - nlpp = &bqlist; -@@ -1442,7 +1390,7 @@ - doprompt = 0; - } - -- n = list(0); -+ n = list(2); - - if (oldstyle) - doprompt = saveprompt; -@@ -1473,7 +1421,7 @@ - } - parsebackquote = savepbq; - handler = savehandler; -- if (arinest || ISDBLQUOTE()) -+ if (arinest || dblquote) - USTPUTC(CTLBACKQ | CTLQUOTE, out); - else - USTPUTC(CTLBACKQ, out); -@@ -1492,7 +1440,7 @@ - prevsyntax = syntax; - syntax = ARISYNTAX; - USTPUTC(CTLARI, out); -- if (ISDBLQUOTE()) -+ if (dblquote) - USTPUTC('"',out); - else - USTPUTC(' ',out); -@@ -1511,6 +1459,7 @@ - - - #ifdef mkinit -+INCLUDE "parser.h" - RESET { - tokpushback = 0; - checkkwd = 0; -@@ -1543,23 +1492,23 @@ - - - /* -- * Return true if the argument is a legal variable name (a letter or -- * underscore followed by zero or more letters, underscores, and digits). -+ * Return of a legal variable name (a letter or underscore followed by zero or -+ * more letters, underscores, and digits). - */ - --int --goodname(char *name) -+char * -+endofname(const char *name) - { - char *p; - -- p = name; -+ p = (char *) name; - if (! is_name(*p)) -- return 0; -+ return p; - while (*++p) { - if (! is_in_name(*p)) -- return 0; -+ break; - } -- return 1; -+ return p; - } - - -@@ -1587,13 +1536,9 @@ - - - STATIC void --synerror(msg) -- const char *msg; -- { -- if (commandname) -- outfmt(&errout, "%s: %d: ", commandname, startlinno); -- outfmt(&errout, "Syntax error: %s\n", msg); -- error((char *)NULL); -+synerror(const char *msg) -+{ -+ error("Syntax error: %s", msg); - /* NOTREACHED */ - } - -@@ -1618,7 +1563,7 @@ - { - switch (whichprompt) { - case 0: -- return ""; -+ return nullstr; - case 1: - return ps1val(); - case 2: -@@ -1627,3 +1572,10 @@ - return "<internal prompt error>"; - } - } -+ -+const char *const * -+findkwd(const char *s) { -+ return findstring( -+ s, parsekwd, sizeof(parsekwd) / sizeof(const char *) -+ ); -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/parser.h bin_NetBSD-1.6release/src/bin/sh/parser.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/parser.h 2001-01-12 16:50:39.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/parser.h 2003-02-08 14:35:42.000000000 +0000 -@@ -60,12 +60,17 @@ - #define VSPLUS 0x3 /* ${var+text} */ - #define VSQUESTION 0x4 /* ${var?message} */ - #define VSASSIGN 0x5 /* ${var=text} */ --#define VSTRIMLEFT 0x6 /* ${var#pattern} */ --#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */ --#define VSTRIMRIGHT 0x8 /* ${var%pattern} */ --#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ -+#define VSTRIMRIGHT 0x6 /* ${var%pattern} */ -+#define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */ -+#define VSTRIMLEFT 0x8 /* ${var#pattern} */ -+#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ - #define VSLENGTH 0xa /* ${#var} */ - -+/* values of checkkwd variable */ -+#define CHKALIAS 0x1 -+#define CHKKWD 0x2 -+#define CHKNL 0x4 -+ - - /* - * NEOF is returned by parsecmd when it encounters an end of file. It -@@ -75,9 +80,12 @@ - extern int tokpushback; - #define NEOF ((union node *)&tokpushback) - extern int whichprompt; /* 1 == PS1, 2 == PS2 */ -+extern int checkkwd; -+extern int startlinno; /* line # where last token started */ - - - union node *parsecmd(int); - void fixredir(union node *, const char *, int); --int goodname(char *); - const char *getprompt(void *); -+const char *const *findkwd(const char *); -+char *endofname(const char *); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/redir.c bin_NetBSD-1.6release/src/bin/sh/redir.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/redir.c 2002-05-16 11:41:22.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/redir.c 2003-02-08 14:35:42.000000000 +0000 -@@ -45,6 +45,7 @@ - #endif - #endif /* not lint */ - -+#include <sys/stat.h> - #include <sys/types.h> - #include <sys/param.h> /* PIPE_BUF */ - #include <signal.h> -@@ -80,21 +81,22 @@ - MKINIT - struct redirtab { - struct redirtab *next; -- short renamed[10]; -+ int renamed[10]; -+ int nullredirs; - }; - - - MKINIT struct redirtab *redirlist; -+MKINIT int nullredirs; - --/* -- * We keep track of whether or not fd0 has been redirected. This is for -- * background commands, where we want to redirect fd0 to /dev/null only -- * if it hasn't already been redirected. --*/ --int fd0_redirected = 0; -- --STATIC void openredirect __P((union node *, char[10 ])); -+STATIC int openredirect __P((union node *)); -+#ifdef notyet -+STATIC void dupredirect __P((union node *, int, char[10 ])); -+#else -+STATIC void dupredirect __P((union node *, int)); -+#endif - STATIC int openhere __P((union node *)); -+STATIC int noclobberopen __P((const char *)); - - - /* -@@ -111,137 +113,173 @@ - int flags; - { - union node *n; -- struct redirtab *sv = NULL; -+ struct redirtab *sv; - int i; - int fd; -- int try; -+ int newfd; -+ int *p; -+#if notyet - char memory[10]; /* file descriptors to write to memory */ - - for (i = 10 ; --i >= 0 ; ) - memory[i] = 0; - memory[1] = flags & REDIR_BACKQ; -+#endif -+ if (!redir) { -+ if (flags & REDIR_PUSH) -+ nullredirs++; -+ return; -+ } -+ sv = NULL; -+ INTOFF; - if (flags & REDIR_PUSH) { -- sv = ckmalloc(sizeof (struct redirtab)); -+ struct redirtab *q; -+ q = ckmalloc(sizeof (struct redirtab)); -+ q->next = redirlist; -+ redirlist = q; -+ q->nullredirs = nullredirs; - for (i = 0 ; i < 10 ; i++) -- sv->renamed[i] = EMPTY; -- sv->next = redirlist; -- redirlist = sv; -+ q->renamed[i] = EMPTY; -+ nullredirs = 0; -+ sv = q; - } -- for (n = redir ; n ; n = n->nfile.next) { -+ n = redir; -+ do { - fd = n->nfile.fd; -- try = 0; - if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && - n->ndup.dupfd == fd) - continue; /* redirect from/to same file descriptor */ - -- if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { -- INTOFF; --again: -- if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { -- switch (errno) { -- case EBADF: -- if (!try) { -- openredirect(n, memory); -- try++; -- goto again; -- } -- /* FALLTHROUGH*/ -- default: -- INTON; -- error("%d: %s", fd, strerror(errno)); -+ newfd = openredirect(n); -+ if (fd == newfd) -+ continue; -+ if (sv && *(p = &sv->renamed[fd]) == EMPTY) { -+ int i = fcntl(fd, F_DUPFD, 10); -+ if (i == -1) { -+ i = errno; -+ if (i != EBADF) { -+ const char *m = strerror(i); -+ close(newfd); -+ error("%d: %s", fd, m); - /* NOTREACHED */ - } -- } -- if (!try) { -- sv->renamed[fd] = i; -+ } else { -+ *p = i; - close(fd); - } -- INTON; - } else { - close(fd); - } -- if (fd == 0) -- fd0_redirected++; -- if (!try) -- openredirect(n, memory); -- } -+#ifdef notyet -+ dupredirect(n, newfd, memory); -+#else -+ dupredirect(n, newfd); -+#endif -+ } while ((n = n->nfile.next)); -+ INTON; -+#ifdef notyet - if (memory[1]) - out1 = &memout; - if (memory[2]) - out2 = &memout; -+#endif - } - - --STATIC void --openredirect(redir, memory) -+STATIC int -+openredirect(redir) - union node *redir; -- char memory[10]; - { -- int fd = redir->nfile.fd; - char *fname; - int f; -- int flags = O_WRONLY|O_CREAT|O_TRUNC; - -- /* -- * We suppress interrupts so that we won't leave open file -- * descriptors around. This may not be such a good idea because -- * an open of a device or a fifo can block indefinitely. -- */ -- INTOFF; -- memory[fd] = 0; - switch (redir->nfile.type) { - case NFROM: - fname = redir->nfile.expfname; -- if ((f = open(fname, O_RDONLY)) < 0) -+ if ((f = open64(fname, O_RDONLY)) < 0) - goto eopen; - break; - case NFROMTO: - fname = redir->nfile.expfname; -- if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) -+ if ((f = open64(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) - goto ecreate; - break; - case NTO: -- if (Cflag) -- flags |= O_EXCL; -+ /* Take care of noclobber mode. */ -+ if (Cflag) { -+ fname = redir->nfile.expfname; -+ if ((f = noclobberopen(fname)) < 0) -+ goto ecreate; -+ break; -+ } - /* FALLTHROUGH */ - case NCLOBBER: - fname = redir->nfile.expfname; -- if ((f = open(fname, flags, 0666)) < 0) -+ if ((f = open64(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) - goto ecreate; - break; - case NAPPEND: - fname = redir->nfile.expfname; -- if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) -+ if ((f = open64(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) - goto ecreate; - break; -+ default: -+#ifdef DEBUG -+ abort(); -+#endif -+ /* Fall through to eliminate warning. */ - case NTOFD: - case NFROMFD: -+ f = -1; -+ break; -+ case NHERE: -+ case NXHERE: -+ f = openhere(redir); -+ break; -+ } -+ -+ return f; -+ecreate: -+ error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); -+eopen: -+ error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); -+} -+ -+ -+STATIC void -+#ifdef notyet -+dupredirect(redir, f, memory) -+#else -+dupredirect(redir, f) -+#endif -+ union node *redir; -+ int f; -+#ifdef notyet -+ char memory[10]; -+#endif -+ { -+ int fd = redir->nfile.fd; -+ -+#ifdef notyet -+ memory[fd] = 0; -+#endif -+ if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { - if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ -+#ifdef notyet - if (memory[redir->ndup.dupfd]) - memory[fd] = 1; - else -+#endif - copyfd(redir->ndup.dupfd, fd); - } -- INTON; - return; -- case NHERE: -- case NXHERE: -- f = openhere(redir); -- break; -- default: -- abort(); - } - - if (f != fd) { - copyfd(f, fd); - close(f); - } -- INTON; - return; --ecreate: -- error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); --eopen: -- error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); - } - - -@@ -256,7 +294,7 @@ - union node *redir; - { - int pip[2]; -- int len = 0; -+ size_t len = 0; - - if (pipe(pip) < 0) - error("Pipe call failed"); -@@ -294,24 +332,26 @@ - */ - - void --popredir() { -+popredir(int drop) { - struct redirtab *rp = redirlist; - int i; - -+ INTOFF; -+ if (--nullredirs >= 0) -+ goto out; - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] != EMPTY) { -- if (i == 0) -- fd0_redirected--; -+ if (!drop) { - close(i); -- if (rp->renamed[i] >= 0) { - copyfd(rp->renamed[i], i); -- close(rp->renamed[i]); - } -+ close(rp->renamed[i]); - } - } -- INTOFF; - redirlist = rp->next; -+ nullredirs = rp->nullredirs; - ckfree(rp); -+out: - INTON; - } - -@@ -324,38 +364,22 @@ - INCLUDE "redir.h" - - RESET { -- while (redirlist) -- popredir(); --} -- --SHELLPROC { -- clearredir(); -+ clearredir(0); - } - - #endif - --/* Return true if fd 0 has already been redirected at least once. */ --int --fd0_redirected_p () { -- return fd0_redirected != 0; --} -- - /* - * Discard all saved file descriptors. - */ - - void --clearredir() { -- struct redirtab *rp; -- int i; -- -- for (rp = redirlist ; rp ; rp = rp->next) { -- for (i = 0 ; i < 10 ; i++) { -- if (rp->renamed[i] >= 0) { -- close(rp->renamed[i]); -- } -- rp->renamed[i] = EMPTY; -- } -+clearredir(int drop) { -+ for (;;) { -+ nullredirs = 0; -+ if (!redirlist) -+ break; -+ popredir(drop); - } - } - -@@ -368,18 +392,104 @@ - */ - - int --copyfd(from, to) -- int from; -- int to; -+copyfd(int from, int to) - { - int newfd; - - newfd = fcntl(from, F_DUPFD, to); - if (newfd < 0) { -- if (errno == EMFILE) -+ int errno2 = errno; -+ if (errno2 == EMFILE) - return EMPTY; - else -- error("%d: %s", from, strerror(errno)); -+ error("%d: %s", from, strerror(errno2)); - } - return newfd; - } -+ -+ -+/* -+ * Open a file in noclobber mode. -+ * The code was copied from bash. -+ */ -+int -+noclobberopen(fname) -+ const char *fname; -+{ -+ int r, fd; -+ struct stat64 finfo, finfo2; -+ -+ /* -+ * If the file exists and is a regular file, return an error -+ * immediately. -+ */ -+ r = stat64(fname, &finfo); -+ if (r == 0 && S_ISREG(finfo.st_mode)) { -+ errno = EEXIST; -+ return -1; -+ } -+ -+ /* -+ * If the file was not present (r != 0), make sure we open it -+ * exclusively so that if it is created before we open it, our open -+ * will fail. Make sure that we do not truncate an existing file. -+ * Note that we don't turn on O_EXCL unless the stat failed -- if the -+ * file was not a regular file, we leave O_EXCL off. -+ */ -+ if (r != 0) -+ return open64(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); -+ fd = open64(fname, O_WRONLY|O_CREAT, 0666); -+ -+ /* If the open failed, return the file descriptor right away. */ -+ if (fd < 0) -+ return fd; -+ -+ /* -+ * OK, the open succeeded, but the file may have been changed from a -+ * non-regular file to a regular file between the stat and the open. -+ * We are assuming that the O_EXCL open handles the case where FILENAME -+ * did not exist and is symlinked to an existing file between the stat -+ * and open. -+ */ -+ -+ /* -+ * If we can open it and fstat the file descriptor, and neither check -+ * revealed that it was a regular file, and the file has not been -+ * replaced, return the file descriptor. -+ */ -+ if (fstat64(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) && -+ finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino) -+ return fd; -+ -+ /* The file has been replaced. badness. */ -+ close(fd); -+ errno = EEXIST; -+ return -1; -+} -+ -+ -+int -+redirectsafe(union node *redir, int flags) -+{ -+ int err; -+ int e; -+ volatile int saveint; -+ struct jmploc *volatile savehandler = handler; -+ struct jmploc jmploc; -+ -+ SAVEINT(saveint); -+ exception = -1; -+ if (setjmp(jmploc.loc)) -+ err = 2; -+ else { -+ handler = &jmploc; -+ redirect(redir, flags); -+ err = 0; -+ } -+ handler = savehandler; -+ e = exception; -+ if (e >= 0 && e != EXERROR) -+ longjmp(handler->loc, 1); -+ RESTOREINT(saveint); -+ return err; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/redir.h bin_NetBSD-1.6release/src/bin/sh/redir.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/redir.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/redir.h 2003-02-08 14:35:42.000000000 +0000 -@@ -40,12 +40,14 @@ - - /* flags passed to redirect */ - #define REDIR_PUSH 01 /* save previous values of file descriptors */ -+#ifdef notyet - #define REDIR_BACKQ 02 /* save the command output in memory */ -+#endif - - union node; - void redirect __P((union node *, int)); --void popredir __P((void)); --int fd0_redirected_p __P((void)); --void clearredir __P((void)); -+void popredir __P((int)); -+void clearredir __P((int)); - int copyfd __P((int, int)); -+int redirectsafe __P((union node *, int)); - -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/regularbltins.def bin_NetBSD-1.6release/src/bin/sh/regularbltins.def ---- bin_NetBSD-1.6release.orig/src/bin/sh/regularbltins.def 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/regularbltins.def 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,16 @@ -+alias -+bg -+cd -+command -+false -+fc -+fg -+getopts -+jobs -+kill -+newgrp -+read -+true -+umask -+unalias -+wait -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/setmode.c bin_NetBSD-1.6release/src/bin/sh/setmode.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/setmode.c 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/setmode.c 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,486 @@ -+/* $NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $ */ -+ -+/* -+ * Copyright (c) 1989, 1993, 1994 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * This code is derived from software contributed to Berkeley by -+ * Dave Borman at Cray Research, Inc. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+#include <sys/cdefs.h> -+#if defined(LIBC_SCCS) && !defined(lint) -+#if 0 -+static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94"; -+#else -+__RCSID("$NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $"); -+#endif -+#endif /* LIBC_SCCS and not lint */ -+ -+#include <sys/types.h> -+#include <sys/stat.h> -+ -+#include <assert.h> -+#include <ctype.h> -+#include <errno.h> -+#include <signal.h> -+#include <stdlib.h> -+#include <unistd.h> -+ -+#ifdef SETMODE_DEBUG -+#include <stdio.h> -+#endif -+ -+#ifdef __weak_alias -+__weak_alias(getmode,_getmode) -+__weak_alias(setmode,_setmode) -+#endif -+ -+#ifdef __GLIBC__ -+#define S_ISTXT __S_ISVTX -+#endif -+ -+#define SET_LEN 6 /* initial # of bitcmd struct to malloc */ -+#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ -+ -+typedef struct bitcmd { -+ char cmd; -+ char cmd2; -+ mode_t bits; -+} BITCMD; -+ -+#define CMD2_CLR 0x01 -+#define CMD2_SET 0x02 -+#define CMD2_GBITS 0x04 -+#define CMD2_OBITS 0x08 -+#define CMD2_UBITS 0x10 -+ -+static BITCMD *addcmd __P((BITCMD *, int, int, int, u_int)); -+static void compress_mode __P((BITCMD *)); -+#ifdef SETMODE_DEBUG -+static void dumpmode __P((BITCMD *)); -+#endif -+ -+/* -+ * Given the old mode and an array of bitcmd structures, apply the operations -+ * described in the bitcmd structures to the old mode, and return the new mode. -+ * Note that there is no '=' command; a strict assignment is just a '-' (clear -+ * bits) followed by a '+' (set bits). -+ */ -+mode_t -+getmode(bbox, omode) -+ const void *bbox; -+ mode_t omode; -+{ -+ const BITCMD *set; -+ mode_t clrval, newmode, value; -+ -+ _DIAGASSERT(bbox != NULL); -+ -+ set = (const BITCMD *)bbox; -+ newmode = omode; -+ for (value = 0;; set++) -+ switch(set->cmd) { -+ /* -+ * When copying the user, group or other bits around, we "know" -+ * where the bits are in the mode so that we can do shifts to -+ * copy them around. If we don't use shifts, it gets real -+ * grundgy with lots of single bit checks and bit sets. -+ */ -+ case 'u': -+ value = (newmode & S_IRWXU) >> 6; -+ goto common; -+ -+ case 'g': -+ value = (newmode & S_IRWXG) >> 3; -+ goto common; -+ -+ case 'o': -+ value = newmode & S_IRWXO; -+common: if (set->cmd2 & CMD2_CLR) { -+ clrval = -+ (set->cmd2 & CMD2_SET) ? S_IRWXO : value; -+ if (set->cmd2 & CMD2_UBITS) -+ newmode &= ~((clrval<<6) & set->bits); -+ if (set->cmd2 & CMD2_GBITS) -+ newmode &= ~((clrval<<3) & set->bits); -+ if (set->cmd2 & CMD2_OBITS) -+ newmode &= ~(clrval & set->bits); -+ } -+ if (set->cmd2 & CMD2_SET) { -+ if (set->cmd2 & CMD2_UBITS) -+ newmode |= (value<<6) & set->bits; -+ if (set->cmd2 & CMD2_GBITS) -+ newmode |= (value<<3) & set->bits; -+ if (set->cmd2 & CMD2_OBITS) -+ newmode |= value & set->bits; -+ } -+ break; -+ -+ case '+': -+ newmode |= set->bits; -+ break; -+ -+ case '-': -+ newmode &= ~set->bits; -+ break; -+ -+ case 'X': -+ if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH)) -+ newmode |= set->bits; -+ break; -+ -+ case '\0': -+ default: -+#ifdef SETMODE_DEBUG -+ (void)printf("getmode:%04o -> %04o\n", omode, newmode); -+#endif -+ return (newmode); -+ } -+} -+ -+#define ADDCMD(a, b, c, d) do { \ -+ if (set >= endset) { \ -+ BITCMD *newset; \ -+ setlen += SET_LEN_INCR; \ -+ newset = realloc(saveset, sizeof(BITCMD) * setlen); \ -+ if (newset == NULL) { \ -+ free(saveset); \ -+ return (NULL); \ -+ } \ -+ set = newset + (set - saveset); \ -+ saveset = newset; \ -+ endset = newset + (setlen - 2); \ -+ } \ -+ set = addcmd(set, (a), (b), (c), (d)); \ -+} while (/*CONSTCOND*/0) -+ -+#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) -+ -+void * -+setmode(p) -+ const char *p; -+{ -+ int perm, who; -+ char op, *ep; -+ BITCMD *set, *saveset, *endset; -+ sigset_t sigset, sigoset; -+ mode_t mask; -+ int equalopdone = 0; /* pacify gcc */ -+ int permXbits, setlen; -+ -+ if (!*p) -+ return (NULL); -+ -+ /* -+ * Get a copy of the mask for the permissions that are mask relative. -+ * Flip the bits, we want what's not set. Since it's possible that -+ * the caller is opening files inside a signal handler, protect them -+ * as best we can. -+ */ -+ sigfillset(&sigset); -+ (void)sigprocmask(SIG_BLOCK, &sigset, &sigoset); -+ (void)umask(mask = umask(0)); -+ mask = ~mask; -+ (void)sigprocmask(SIG_SETMASK, &sigoset, NULL); -+ -+ setlen = SET_LEN + 2; -+ -+ if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL) -+ return (NULL); -+ saveset = set; -+ endset = set + (setlen - 2); -+ -+ /* -+ * If an absolute number, get it and return; disallow non-octal digits -+ * or illegal bits. -+ */ -+ if (isdigit((unsigned char)*p)) { -+ perm = (mode_t)strtol(p, &ep, 8); -+ if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) { -+ free(saveset); -+ return (NULL); -+ } -+ ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask); -+ set->cmd = 0; -+ return (saveset); -+ } -+ -+ /* -+ * Build list of structures to set/clear/copy bits as described by -+ * each clause of the symbolic mode. -+ */ -+ for (;;) { -+ /* First, find out which bits might be modified. */ -+ for (who = 0;; ++p) { -+ switch (*p) { -+ case 'a': -+ who |= STANDARD_BITS; -+ break; -+ case 'u': -+ who |= S_ISUID|S_IRWXU; -+ break; -+ case 'g': -+ who |= S_ISGID|S_IRWXG; -+ break; -+ case 'o': -+ who |= S_IRWXO; -+ break; -+ default: -+ goto getop; -+ } -+ } -+ -+getop: if ((op = *p++) != '+' && op != '-' && op != '=') { -+ free(saveset); -+ return (NULL); -+ } -+ if (op == '=') -+ equalopdone = 0; -+ -+ who &= ~S_ISTXT; -+ for (perm = 0, permXbits = 0;; ++p) { -+ switch (*p) { -+ case 'r': -+ perm |= S_IRUSR|S_IRGRP|S_IROTH; -+ break; -+ case 's': -+ /* -+ * If specific bits where requested and -+ * only "other" bits ignore set-id. -+ */ -+ if (who == 0 || (who & ~S_IRWXO)) -+ perm |= S_ISUID|S_ISGID; -+ break; -+ case 't': -+ /* -+ * If specific bits where requested and -+ * only "other" bits ignore set-id. -+ */ -+ if (who == 0 || (who & ~S_IRWXO)) { -+ who |= S_ISTXT; -+ perm |= S_ISTXT; -+ } -+ break; -+ case 'w': -+ perm |= S_IWUSR|S_IWGRP|S_IWOTH; -+ break; -+ case 'X': -+ permXbits = S_IXUSR|S_IXGRP|S_IXOTH; -+ break; -+ case 'x': -+ perm |= S_IXUSR|S_IXGRP|S_IXOTH; -+ break; -+ case 'u': -+ case 'g': -+ case 'o': -+ /* -+ * When ever we hit 'u', 'g', or 'o', we have -+ * to flush out any partial mode that we have, -+ * and then do the copying of the mode bits. -+ */ -+ if (perm) { -+ ADDCMD(op, who, perm, mask); -+ perm = 0; -+ } -+ if (op == '=') -+ equalopdone = 1; -+ if (op == '+' && permXbits) { -+ ADDCMD('X', who, permXbits, mask); -+ permXbits = 0; -+ } -+ ADDCMD(*p, who, op, mask); -+ break; -+ -+ default: -+ /* -+ * Add any permissions that we haven't already -+ * done. -+ */ -+ if (perm || (op == '=' && !equalopdone)) { -+ if (op == '=') -+ equalopdone = 1; -+ ADDCMD(op, who, perm, mask); -+ perm = 0; -+ } -+ if (permXbits) { -+ ADDCMD('X', who, permXbits, mask); -+ permXbits = 0; -+ } -+ goto apply; -+ } -+ } -+ -+apply: if (!*p) -+ break; -+ if (*p != ',') -+ goto getop; -+ ++p; -+ } -+ set->cmd = 0; -+#ifdef SETMODE_DEBUG -+ (void)printf("Before compress_mode()\n"); -+ dumpmode(saveset); -+#endif -+ compress_mode(saveset); -+#ifdef SETMODE_DEBUG -+ (void)printf("After compress_mode()\n"); -+ dumpmode(saveset); -+#endif -+ return (saveset); -+} -+ -+static BITCMD * -+addcmd(set, op, who, oparg, mask) -+ BITCMD *set; -+ int oparg, who; -+ int op; -+ u_int mask; -+{ -+ -+ _DIAGASSERT(set != NULL); -+ -+ switch (op) { -+ case '=': -+ set->cmd = '-'; -+ set->bits = who ? who : STANDARD_BITS; -+ set++; -+ -+ op = '+'; -+ /* FALLTHROUGH */ -+ case '+': -+ case '-': -+ case 'X': -+ set->cmd = op; -+ set->bits = (who ? who : mask) & oparg; -+ break; -+ -+ case 'u': -+ case 'g': -+ case 'o': -+ set->cmd = op; -+ if (who) { -+ set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) | -+ ((who & S_IRGRP) ? CMD2_GBITS : 0) | -+ ((who & S_IROTH) ? CMD2_OBITS : 0); -+ set->bits = (mode_t)~0; -+ } else { -+ set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS; -+ set->bits = mask; -+ } -+ -+ if (oparg == '+') -+ set->cmd2 |= CMD2_SET; -+ else if (oparg == '-') -+ set->cmd2 |= CMD2_CLR; -+ else if (oparg == '=') -+ set->cmd2 |= CMD2_SET|CMD2_CLR; -+ break; -+ } -+ return (set + 1); -+} -+ -+#ifdef SETMODE_DEBUG -+static void -+dumpmode(set) -+ BITCMD *set; -+{ -+ -+ _DIAGASSERT(set != NULL); -+ -+ for (; set->cmd; ++set) -+ (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n", -+ set->cmd, set->bits, set->cmd2 ? " cmd2:" : "", -+ set->cmd2 & CMD2_CLR ? " CLR" : "", -+ set->cmd2 & CMD2_SET ? " SET" : "", -+ set->cmd2 & CMD2_UBITS ? " UBITS" : "", -+ set->cmd2 & CMD2_GBITS ? " GBITS" : "", -+ set->cmd2 & CMD2_OBITS ? " OBITS" : ""); -+} -+#endif -+ -+/* -+ * Given an array of bitcmd structures, compress by compacting consecutive -+ * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u', -+ * 'g' and 'o' commands continue to be separate. They could probably be -+ * compacted, but it's not worth the effort. -+ */ -+static void -+compress_mode(set) -+ BITCMD *set; -+{ -+ BITCMD *nset; -+ int setbits, clrbits, Xbits, op; -+ -+ _DIAGASSERT(set != NULL); -+ -+ for (nset = set;;) { -+ /* Copy over any 'u', 'g' and 'o' commands. */ -+ while ((op = nset->cmd) != '+' && op != '-' && op != 'X') { -+ *set++ = *nset++; -+ if (!op) -+ return; -+ } -+ -+ for (setbits = clrbits = Xbits = 0;; nset++) { -+ if ((op = nset->cmd) == '-') { -+ clrbits |= nset->bits; -+ setbits &= ~nset->bits; -+ Xbits &= ~nset->bits; -+ } else if (op == '+') { -+ setbits |= nset->bits; -+ clrbits &= ~nset->bits; -+ Xbits &= ~nset->bits; -+ } else if (op == 'X') -+ Xbits |= nset->bits & ~setbits; -+ else -+ break; -+ } -+ if (clrbits) { -+ set->cmd = '-'; -+ set->cmd2 = 0; -+ set->bits = clrbits; -+ set++; -+ } -+ if (setbits) { -+ set->cmd = '+'; -+ set->cmd2 = 0; -+ set->bits = setbits; -+ set++; -+ } -+ if (Xbits) { -+ set->cmd = 'X'; -+ set->cmd2 = 0; -+ set->bits = Xbits; -+ set++; -+ } -+ } -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/sh.1 bin_NetBSD-1.6release/src/bin/sh/sh.1 ---- bin_NetBSD-1.6release.orig/src/bin/sh/sh.1 2002-05-16 11:41:22.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/sh.1 2003-02-08 14:35:42.000000000 +0000 -@@ -188,7 +188,7 @@ - or - .Ic until ; - or if the command is the left hand operand of an --.Dq \*[Am]\*[Am] -+.Dq && - or - .Dq || - operator. -@@ -256,9 +256,9 @@ - operators (their meaning is discussed later). Following is a list of operators: - .Bl -ohang -offset indent - .It "Control operators:" --.Dl \*[Am] \*[Am]\*[Am] \&( \&) \&; ;; | || \*[Lt]newline\*[Gt] -+.Dl & && \&( \&) \&; ;; | || \*[Lt]newline\*[Gt] - .It "Redirection operators:" --.Dl \*[Lt] \*[Gt] \*[Gt]| \*[Lt]\*[Lt] \*[Gt]\*[Gt] \*[Lt]\*[Am] \*[Gt]\*[Am] \*[Lt]\*[Lt]- \*[Lt]\*[Gt] -+.Dl \*[Lt] \*[Gt] \*[Gt]| \*[Lt]\*[Lt] \*[Gt]\*[Gt] \*[Lt]& \*[Gt]& \*[Lt]\*[Lt]- \*[Lt]\*[Gt] - .El - .Ss Quoting - Quoting is used to remove the special meaning of certain characters or -@@ -381,13 +381,13 @@ - Append standard output (or n) to file. - .It [n] Ns \*[Lt] file - Redirect standard input (or n) from file. --.It [n1] Ns \*[Lt]\*[Am] Ns n2 -+.It [n1] Ns \*[Lt]& Ns n2 - Duplicate standard input (or n1) from file descriptor n2. --.It [n] Ns \*[Lt]\*[Am]- -+.It [n] Ns \*[Lt]&- - Close standard input (or n). --.It [n1] Ns \*[Gt]\*[Am] Ns n2 -+.It [n1] Ns \*[Gt]& Ns n2 - Duplicate standard output (or n1) from n2. --.It [n] Ns \*[Gt]\*[Am]- -+.It [n] Ns \*[Gt]&- - Close standard output (or n). - .It [n] Ns \*[Lt]\*[Gt] file - Open file for reading and writing on standard input (or n). -@@ -525,27 +525,27 @@ - takes place before redirection, it can be modified by redirection. For - example: - .Pp --.Dl $ command1 2\*[Gt]\*[Am]1 | command2 -+.Dl $ command1 2\*[Gt]&1 | command2 - .Pp - sends both the standard output and standard error of command1 - to the standard input of command2. - .Pp - A ; or \*[Lt]newline\*[Gt] terminator causes the preceding AND-OR-list (described --next) to be executed sequentially; a \*[Am] causes asynchronous execution of -+next) to be executed sequentially; a & causes asynchronous execution of - the preceding AND-OR-list. - .Pp - Note that unlike some other shells, each process in the pipeline is a - child of the invoking shell (unless it is a shell builtin, in which case - it executes in the current shell -- but any effect it has on the - environment is wiped). --.Ss Background Commands -- \*[Am] --If a command is terminated by the control operator ampersand (\*[Am]), the -+.Ss Background Commands -- & -+If a command is terminated by the control operator ampersand (&), the - shell executes the command asynchronously -- that is, the shell does not - wait for the command to finish before executing the next command. - .Pp - The format for running a command in background is: - .Pp --.Dl command1 \*[Am] [command2 \*[Am] ...] -+.Dl command1 & [command2 & ...] - .Pp - If the shell is not interactive, the standard input of an asynchronous - command is set to -@@ -558,17 +558,17 @@ - command and immediately proceed onto the next command; otherwise it waits - for the command to terminate before proceeding to the next one. - .Ss Short-Circuit List Operators --.Dq \*[Am]\*[Am] -+.Dq && - and - .Dq || - are AND-OR list operators. --.Dq \*[Am]\*[Am] -+.Dq && - executes the first command, and then executes the second command iff the - exit status of the first command is zero. - .Dq || - is similar, but executes the second command iff the exit status of the first - command is nonzero. --.Dq \*[Am]\*[Am] -+.Dq && - and - .Dq || - both have the same priority. -@@ -646,7 +646,7 @@ - they were one program: - .Pp - .Bd -literal -offset indent --{ echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting -+{ printf \*q hello \*q ; printf \*q world\\n" ; } \*[Gt] greeting - .Ed - .Pp - Note that -@@ -961,11 +961,11 @@ - .Ss Shell Patterns - A pattern consists of normal characters, which match themselves, - and meta-characters. The meta-characters are --.Dq ! , -+.Dq \&! , - .Dq * , --.Dq ? , -+.Dq \&? , - and --.Dq [ . -+.Dq \&[ . - These characters lose their special meanings if they are quoted. When - command or variable substitution is performed and the dollar sign or back - quotes are not double quoted, the value of the variable or the output of -@@ -999,14 +999,10 @@ - .Ss Builtins - This section lists the builtin commands which are builtin because they - need to perform some operation that can't be performed by a separate --process. In addition to these, there are several other commands that may --be builtin for efficiency (e.g. --.Xr printf 1 , --.Xr echo 1 , --.Xr test 1 , --etc). -+process. - .Bl -tag -width 5n - .It : -+.It true - A null command that returns a 0 (true) exit value. - .It \&. file - The commands in the specified file are read and executed by the shell. -@@ -1032,9 +1028,12 @@ - .It command Ar command Ar arg ... - Execute the specified builtin command. (This is useful when you - have a shell function with the same name as a builtin command.) --.It cd Op Ar directory -+.It cd Ar - -+.It Xo cd Op Fl LP -+.Op Ar directory -+.Xc - Switch to the specified directory (default --.Ev $HOME ) . -+.Ev HOME ) . - If an entry for - .Ev CDPATH - appears in the environment of the -@@ -1048,13 +1047,61 @@ - .Ev CDPATH - is the same as that of - .Ev PATH . --In an interactive shell, the -+If a single dash is specified as the argument, it will be replaced by the -+value of -+.Ev OLDPWD . -+The - .Ic cd - command will print out the name of the - directory that it actually switched to if this is different from the name - that the user gave. These may be different either because the - .Ev CDPATH --mechanism was used or because a symbolic link was crossed. -+mechanism was used or because the argument is a single dash. -+The -+.Fl P -+option causes the physical directory structure to be used, that is, all -+symbolic links are resolved to their repective values. The -+.Fl L -+option turns off the effect of any preceding -+.Fl P -+options. -+.It Xo echo Op Fl n -+.Ar args... -+.Xc -+Print the arguments on the standard output, separated by spaces. -+Unless the -+.Fl n -+option is present, a newline is output following the arguments. -+.Pp -+If any of the following sequences of characters is encountered during -+output, the sequence is not output. Instead, the specified action is -+performed: -+.Bl -tag -width indent -+.It Li \eb -+A backspace character is output. -+.It Li \ec -+Subsequent output is suppressed. This is normally used at the end of the -+last argument to suppress the trailing newline that -+.Ic echo -+would otherwise output. -+.It Li \ef -+Output a form feed. -+.It Li \en -+Output a newline character. -+.It Li \er -+Output a carriage return. -+.It Li \et -+Output a (horizontal) tab character. -+.It Li \ev -+Output a vertical tab. -+.It Li \e0 Ns Ar digits -+Output the character whose value is given by zero to three octal digits. -+If there are zero digits, a nul character is output. -+.It Li \e\e -+Output a backslash. -+.El -+.Pp -+All other backslash sequences elicit undefined behaviour. - .It eval Ar string ... - Concatenate all the arguments with spaces. Then re-parse and execute - the command. -@@ -1217,7 +1264,7 @@ - will set the variable - .Va var - to a --.Dq ? ; -+.Dq \&? ; - .Ic getopts - will then unset - .Ev OPTARG -@@ -1236,7 +1283,7 @@ - otherwise, it will set - .Va var - to --.Dq ? . -+.Dq \&? . - .Pp - The following code fragment shows how one might process the arguments - for a command that can take the options -@@ -1295,7 +1342,7 @@ - .It jobs - This command lists out all the background processes - which are children of the current shell process. --.It pwd -+.It pwd Op Fl LP - Print the current directory. The builtin command may - differ from the program of the same name because the - builtin command remembers what the current directory -@@ -1304,6 +1351,14 @@ - renamed, the builtin version of - .Ic pwd - will continue to print the old name for the directory. -+The -+.Fl P -+option causes the phyical value of the current working directory to be shown, -+that is, all symbolic links are resolved to their repective values. The -+.Fl L -+option turns off the effect of any preceding -+.Fl P -+options. - .It Xo read Op Fl p Ar prompt - .Op Fl r - .Ar variable -@@ -1314,7 +1369,9 @@ - option is specified and the standard input is a terminal. Then a line is - read from the standard input. The trailing newline is deleted from the - line and the line is split as described in the section on word splitting --above, and the pieces are assigned to the variables in order. If there are -+above, and the pieces are assigned to the variables in order. -+At least one variable must be specified. -+If there are - more pieces than variables, the remaining pieces (along with the - characters in - .Ev IFS -@@ -1346,6 +1403,225 @@ - .Fl p - option specified the output will be formatted suitably for non-interactive use. - .Pp -+.It Xo printf Ar format -+.Op Ar arguments ... -+.Xc -+.Ic printf -+formats and prints its arguments, after the first, under control -+of the -+.Ar format . -+The -+.Ar format -+is a character string which contains three types of objects: plain characters, -+which are simply copied to standard output, character escape sequences which -+are converted and copied to the standard output, and format specifications, -+each of which causes printing of the next successive -+.Ar argument . -+.Pp -+The -+.Ar arguments -+after the first are treated as strings if the corresponding format is -+either -+.Cm b , -+.Cm c -+or -+.Cm s ; -+otherwise it is evaluated as a C constant, with the following extensions: -+.Pp -+.Bl -bullet -offset indent -compact -+.It -+A leading plus or minus sign is allowed. -+.It -+If the leading character is a single or double quote, the value is the -+.Tn ASCII -+code of the next character. -+.El -+.Pp -+The format string is reused as often as necessary to satisfy the -+.Ar arguments . -+Any extra format specifications are evaluated with zero or the null -+string. -+.Pp -+Character escape sequences are in backslash notation as defined in -+.St -ansiC . -+The characters and their meanings -+are as follows: -+.Bl -tag -width Ds -offset indent -+.It Cm \ee -+Write an \*[Lt]escape\*[Gt] character. -+.It Cm \ea -+Write a \*[Lt]bell\*[Gt] character. -+.It Cm \eb -+Write a \*[Lt]backspace\*[Gt] character. -+.It Cm \ef -+Write a \*[Lt]form-feed\*[Gt] character. -+.It Cm \en -+Write a \*[Lt]new-line\*[Gt] character. -+.It Cm \er -+Write a \*[Lt]carriage return\*[Gt] character. -+.It Cm \et -+Write a \*[Lt]tab\*[Gt] character. -+.It Cm \ev -+Write a \*[Lt]vertical tab\*[Gt] character. -+.It Cm \e\' -+Write a \*[Lt]single quote\*[Gt] character. -+.It Cm \e\e -+Write a backslash character. -+.It Cm \e Ns Ar num -+Write an 8-bit character whose -+.Tn ASCII -+value is the 1-, 2-, or 3-digit -+octal number -+.Ar num . -+.El -+.Pp -+Each format specification is introduced by the percent character -+(``%''). -+The remainder of the format specification includes, -+in the following order: -+.Bl -tag -width Ds -+.It "Zero or more of the following flags:" -+.Bl -tag -width Ds -+.It Cm # -+A `#' character -+specifying that the value should be printed in an ``alternative form''. -+For -+.Cm c , -+.Cm d , -+and -+.Cm s , -+formats, this option has no effect. For the -+.Cm o -+formats the precision of the number is increased to force the first -+character of the output string to a zero. For the -+.Cm x -+.Pq Cm X -+format, a non-zero result has the string -+.Li 0x -+.Pq Li 0X -+prepended to it. For -+.Cm e , -+.Cm E , -+.Cm f , -+.Cm g , -+and -+.Cm G , -+formats, the result will always contain a decimal point, even if no -+digits follow the point (normally, a decimal point only appears in the -+results of those formats if a digit follows the decimal point). For -+.Cm g -+and -+.Cm G -+formats, trailing zeros are not removed from the result as they -+would otherwise be; -+.It Cm \&\- -+A minus sign `\-' which specifies -+.Em left adjustment -+of the output in the indicated field; -+.It Cm \&+ -+A `+' character specifying that there should always be -+a sign placed before the number when using signed formats. -+.It Sq \&\ \& -+A space specifying that a blank should be left before a positive number -+for a signed format. A `+' overrides a space if both are used; -+.It Cm \&0 -+A zero `0' character indicating that zero-padding should be used -+rather than blank-padding. A `\-' overrides a `0' if both are used; -+.El -+.It "Field Width:" -+An optional digit string specifying a -+.Em field width ; -+if the output string has fewer characters than the field width it will -+be blank-padded on the left (or right, if the left-adjustment indicator -+has been given) to make up the field width (note that a leading zero -+is a flag, but an embedded zero is part of a field width); -+.It Precision : -+An optional period, -+.Sq Cm \&.\& , -+followed by an optional digit string giving a -+.Em precision -+which specifies the number of digits to appear after the decimal point, -+for -+.Cm e -+and -+.Cm f -+formats, or the maximum number of characters to be printed -+from a string; if the digit string is missing, the precision is treated -+as zero; -+.It Format : -+A character which indicates the type of format to use (one of -+.Cm diouxXfwEgGbcs ) . -+.El -+.Pp -+A field width or precision may be -+.Sq Cm \&* -+instead of a digit string. -+In this case an -+.Ar argument -+supplies the field width or precision. -+.Pp -+The format characters and their meanings are: -+.Bl -tag -width Fl -+.It Cm diouXx -+The -+.Ar argument -+is printed as a signed decimal (d or i), unsigned octal, unsigned decimal, -+or unsigned hexadecimal (X or x), respectively. -+.It Cm f -+The -+.Ar argument -+is printed in the style -+.Sm off -+.Pf [\-]ddd Cm \&. No ddd -+.Sm on -+where the number of d's -+after the decimal point is equal to the precision specification for -+the argument. -+If the precision is missing, 6 digits are given; if the precision -+is explicitly 0, no digits and no decimal point are printed. -+.It Cm eE -+The -+.Ar argument -+is printed in the style -+.Sm off -+.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd -+.Sm on -+where there -+is one digit before the decimal point and the number after is equal to -+the precision specification for the argument; when the precision is -+missing, 6 digits are produced. -+An upper-case E is used for an `E' format. -+.It Cm gG -+The -+.Ar argument -+is printed in style -+.Cm f -+or in style -+.Cm e -+.Pq Cm E -+whichever gives full precision in minimum space. -+.It Cm b -+Characters from the string -+.Ar argument -+are printed with backslash-escape sequences expanded as in -+.Ic echo . -+.It Cm c -+The first character of -+.Ar argument -+is printed. -+.It Cm s -+Characters from the string -+.Ar argument -+are printed until the end is reached or until the number of characters -+indicated by the precision specification is reached; however if the -+precision is 0 or missing, all characters in the string are printed. -+.It Cm \&% -+Print a `%'; no argument is used. -+.El -+.Pp -+In no case does a non-existent or small field width cause truncation of -+a field; padding takes place only if the specified field width exceeds -+the actual width. - .It Xo set - .Oo { - .Fl options | Cm +options | Cm -- } -@@ -1392,15 +1668,248 @@ - and so on, decreasing - the value of - .Va $# --by one. If there are zero positional parameters, -+by one. If n is greater than the number of positional parameters, - .Ic shift --does nothing. --.It Xo trap --.Op Fl l --.Xc -+will issue an error message, and exit with return status 2. -+.It test Ar expression -+.It \&[ Ar expression Cm ] -+The -+.Ic test -+utility evaluates the expression and, if it evaluates -+to true, returns a zero (true) exit status; otherwise -+it returns 1 (false). -+If there is no expression, test also -+returns 1 (false). -+.Pp -+All operators and flags are separate arguments to the -+.Ic test -+utility. -+.Pp -+The following primaries are used to construct expression: -+.Bl -tag -width Ar -+.It Fl b Ar file -+True if -+.Ar file -+exists and is a block special -+file. -+.It Fl c Ar file -+True if -+.Ar file -+exists and is a character -+special file. -+.It Fl d Ar file -+True if -+.Ar file -+exists and is a directory. -+.It Fl e Ar file -+True if -+.Ar file -+exists (regardless of type). -+.It Fl f Ar file -+True if -+.Ar file -+exists and is a regular file. -+.It Fl g Ar file -+True if -+.Ar file -+exists and its set group ID flag -+is set. -+.It Fl h Ar file -+True if -+.Ar file -+exists and is a symbolic link. -+.It Fl k Ar file -+True if -+.Ar file -+exists and its sticky bit is set. -+.It Fl n Ar string -+True if the length of -+.Ar string -+is nonzero. -+.It Fl p Ar file -+True if -+.Ar file -+is a named pipe -+.Po Tn FIFO Pc . -+.It Fl r Ar file -+True if -+.Ar file -+exists and is readable. -+.It Fl s Ar file -+True if -+.Ar file -+exists and has a size greater -+than zero. -+.It Fl t Ar file_descriptor -+True if the file whose file descriptor number -+is -+.Ar file_descriptor -+is open and is associated with a terminal. -+.It Fl u Ar file -+True if -+.Ar file -+exists and its set user ID flag -+is set. -+.It Fl w Ar file -+True if -+.Ar file -+exists and is writable. -+True -+indicates only that the write flag is on. -+The file is not writable on a read-only file -+system even if this test indicates true. -+.It Fl x Ar file -+True if -+.Ar file -+exists and is executable. -+True -+indicates only that the execute flag is on. -+If -+.Ar file -+is a directory, true indicates that -+.Ar file -+can be searched. -+.It Fl z Ar string -+True if the length of -+.Ar string -+is zero. -+.It Fl L Ar file -+True if -+.Ar file -+exists and is a symbolic link. -+This operator is retained for compatibility with previous versions of -+this program. Do not rely on its existence; use -+.Fl h -+instead. -+.It Fl O Ar file -+True if -+.Ar file -+exists and its owner matches the effective user id of this process. -+.It Fl G Ar file -+True if -+.Ar file -+exists and its group matches the effective group id of this process. -+.It Fl S Ar file -+True if -+.Ar file -+exists and is a socket. -+.It Ar file1 Fl nt Ar file2 -+True if -+.Ar file1 -+exists and is newer than -+.Ar file2 . -+.It Ar file1 Fl ot Ar file2 -+True if -+.Ar file1 -+exists and is older than -+.Ar file2 . -+.It Ar file1 Fl ef Ar file2 -+True if -+.Ar file1 -+and -+.Ar file2 -+exist and refer to the same file. -+.It Ar string -+True if -+.Ar string -+is not the null -+string. -+.It Ar \&s\&1 Cm \&= Ar \&s\&2 -+True if the strings -+.Ar \&s\&1 -+and -+.Ar \&s\&2 -+are identical. -+.It Ar \&s\&1 Cm \&!= Ar \&s\&2 -+True if the strings -+.Ar \&s\&1 -+and -+.Ar \&s\&2 -+are not identical. -+.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2 -+True if string -+.Ar \&s\&1 -+comes before -+.Ar \&s\&2 -+based on the ASCII value of their characters. -+.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2 -+True if string -+.Ar \&s\&1 -+comes after -+.Ar \&s\&2 -+based on the ASCII value of their characters. -+.It Ar \&n\&1 Fl \&eq Ar \&n\&2 -+True if the integers -+.Ar \&n\&1 -+and -+.Ar \&n\&2 -+are algebraically -+equal. -+.It Ar \&n\&1 Fl \&ne Ar \&n\&2 -+True if the integers -+.Ar \&n\&1 -+and -+.Ar \&n\&2 -+are not -+algebraically equal. -+.It Ar \&n\&1 Fl \> Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically -+greater than the integer -+.Ar \&n\&2 . -+.It Ar \&n\&1 Fl \&ge Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically -+greater than or equal to the integer -+.Ar \&n\&2 . -+.It Ar \&n\&1 Fl \< Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically less -+than the integer -+.Ar \&n\&2 . -+.It Ar \&n\&1 Fl \&le Ar \&n\&2 -+True if the integer -+.Ar \&n\&1 -+is algebraically less -+than or equal to the integer -+.Ar \&n\&2 . -+.El -+.Pp -+These primaries can be combined with the following operators: -+.Bl -tag -width Ar -+.It Cm \&! Ar expression -+True if -+.Ar expression -+is false. -+.It Ar expression1 Fl a Ar expression2 -+True if both -+.Ar expression1 -+and -+.Ar expression2 -+are true. -+.It Ar expression1 Fl o Ar expression2 -+True if either -+.Ar expression1 -+or -+.Ar expression2 -+are true. -+.It Cm \&( Ns Ar expression Ns Cm \&) -+True if expression is true. -+.El -+.Pp -+The -+.Fl a -+operator has higher precedence than the -+.Fl o -+operator. -+.It times -+Print the accumulated user and system times for the shell and for processes -+run from the shell. The return status is 0. - .It Xo trap --.Op Ar action --.Ar signal ... -+.Op Ar action Ar signal ... - .Xc - Cause the shell to parse and execute action when any of the specified - signals are received. The signals are specified by signal number or as -@@ -1420,11 +1929,6 @@ - .Ic trap - command has no effect on signals that were - ignored on entry to the shell. --Issuing --.Ic trap --with option --.Ar -l --will print a list of valid signal names. - .Ic trap - without any arguments cause it to write a list of signals and their - associated action to the standard output in a format that is suitable -@@ -1436,10 +1940,6 @@ - .Pp - List trapped signals and their corresponding action - .Pp --.Dl trap -l --.Pp --Print a list of valid signals --.Pp - .Dl trap '' SIGINT QUIT tstp 30 - .Pp - Ignore signals INT QUIT TSTP USR1 -@@ -1614,6 +2114,17 @@ - children of the shell, and is used in the history editing modes. - .It Ev HISTSIZE - The number of lines in the history buffer for the shell. -+.It Ev PWD -+The logical value of the current working directory. This is set by the -+.Ic cd -+command. -+.It Ev OLDPWD -+The previous logical value of the current working directory. This is set by -+the -+.Ic cd -+command. -+.It Ev PPID -+The process ID of the parent process of the shell. - .El - .Sh FILES - .Bl -item -width HOMEprofilexxxx -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/shell.h bin_NetBSD-1.6release/src/bin/sh/shell.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/shell.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/shell.h 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: shell.h,v 1.13 2000/05/22 10:18:47 elric Exp $ */ -+/* $NetBSD: shell.h,v 1.14 2002/05/25 23:09:06 wiz Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -52,23 +52,18 @@ - */ - - -+#ifndef JOBS - #define JOBS 1 -+#endif - #ifndef BSD - #define BSD 1 - #endif - --#ifdef __STDC__ - typedef void *pointer; - #ifndef NULL - #define NULL (void *)0 - #endif --#else /* not __STDC__ */ --typedef char *pointer; --#ifndef NULL --#define NULL 0 --#endif --#endif /* not __STDC__ */ --#define STATIC /* empty */ -+#define STATIC static - #define MKINIT /* empty */ - - #include <sys/cdefs.h> -@@ -81,3 +76,7 @@ - #else - #define TRACE(param) - #endif -+ -+#if defined(__GNUC__) && __GNUC__ < 3 -+#define va_copy __va_copy -+#endif -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/show.c bin_NetBSD-1.6release/src/bin/sh/show.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/show.c 2002-05-16 11:41:22.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/show.c 2003-02-08 14:35:42.000000000 +0000 -@@ -1,4 +1,4 @@ --/* $NetBSD: show.c,v 1.21 2002/05/15 16:33:35 christos Exp $ */ -+/* $NetBSD: show.c,v 1.22 2002/05/25 23:09:06 wiz Exp $ */ - - /*- - * Copyright (c) 1991, 1993 -@@ -41,16 +41,12 @@ - #if 0 - static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; - #else --__RCSID("$NetBSD: show.c,v 1.21 2002/05/15 16:33:35 christos Exp $"); -+__RCSID("$NetBSD: show.c,v 1.22 2002/05/25 23:09:06 wiz Exp $"); - #endif - #endif /* not lint */ - - #include <stdio.h> --#ifdef __STDC__ - #include <stdarg.h> --#else --#include <varargs.h> --#endif - - #include "shell.h" - #include "parser.h" -@@ -276,7 +272,6 @@ - putc('\t', fp); - } - } --#endif - - - -@@ -294,7 +289,6 @@ - #endif - - --#ifdef DEBUG - void - trputc(c) - int c; -@@ -305,36 +299,22 @@ - if (c == '\n') - fflush(tracefile); - } --#endif - - void --#ifdef __STDC__ - trace(const char *fmt, ...) --#else --trace(va_alist) -- va_dcl --#endif - { --#ifdef DEBUG - va_list va; --#ifdef __STDC__ -+ - va_start(va, fmt); --#else -- char *fmt; -- va_start(va); -- fmt = va_arg(va, char *); --#endif - if (tracefile != NULL) { - (void) vfprintf(tracefile, fmt, va); - if (strchr(fmt, '\n')) - (void) fflush(tracefile); - } - va_end(va); --#endif - } - - --#ifdef DEBUG - void - trputs(s) - const char *s; -@@ -386,14 +366,12 @@ - } - putc('"', tracefile); - } --#endif - - - void - trargs(ap) - char **ap; - { --#ifdef DEBUG - if (tracefile == NULL) - return; - while (*ap) { -@@ -404,11 +382,9 @@ - putc('\n', tracefile); - } - fflush(tracefile); --#endif - } - - --#ifdef DEBUG - void - opentrace() { - char s[100]; -@@ -421,7 +397,7 @@ - #ifdef not_this_way - { - char *p; -- if ((p = getenv("HOME")) == NULL) { -+ if ((p = getenv(homestr)) == NULL) { - if (geteuid() == 0) - p = "/"; - else -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/specialbltins.def bin_NetBSD-1.6release/src/bin/sh/specialbltins.def ---- bin_NetBSD-1.6release.orig/src/bin/sh/specialbltins.def 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/specialbltins.def 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,16 @@ -+. -+: -+break -+builtin -+continue -+eval -+exec -+exit -+export -+readonly -+return -+set -+shift -+times -+trap -+unset -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/trap.c bin_NetBSD-1.6release/src/bin/sh/trap.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/trap.c 2001-03-18 11:04:44.000000000 +0000 -+++ bin_NetBSD-1.6release/src/bin/sh/trap.c 2003-02-08 14:35:42.000000000 +0000 -@@ -48,6 +48,7 @@ - #include <signal.h> - #include <unistd.h> - #include <stdlib.h> -+#include <string.h> - - #include "shell.h" - #include "main.h" -@@ -63,6 +64,9 @@ - #include "trap.h" - #include "mystring.h" - -+#ifdef HETIO -+#include "hetio.h" -+#endif - - /* - * Sigmode records the current value of the signal handlers for the various -@@ -77,59 +81,24 @@ - #define S_RESET 5 /* temporary - to reset a hard ignored sig */ - - --char *trap[NSIG+1]; /* trap handler commands */ --MKINIT char sigmode[NSIG]; /* current value of signal */ --char gotsig[NSIG]; /* indicates specified signal received */ --int pendingsigs; /* indicates some signal received */ -- --static int getsigaction __P((int, sig_t *)); --static int signame_to_signum __P((const char *)); --void printsignals __P((void)); -- --/* -- * return the signal number described by `p' (as a number or a name) -- * or -1 if it isn't one -- */ -- --static int --signame_to_signum(p) -- const char *p; --{ -- int i; -- -- if (is_number(p)) -- return number(p); -- -- if (strcasecmp(p, "exit") == 0 ) -- return 0; -+/* trap handler commands */ -+char *trap[NSIG]; -+/* current value of signal */ -+STATIC char sigmode[NSIG - 1]; -+/* indicates specified signal received */ -+STATIC char gotsig[NSIG - 1]; -+/* last pending signal */ -+volatile sig_atomic_t pendingsigs; - -- if (strncasecmp(p, "sig", 3) == 0) -- p += 3; -+extern char *signal_names[]; - -- for (i = 0; i < NSIG; ++i) -- if (strcasecmp (p, sys_signame[i]) == 0) -- return i; -- return -1; -+#ifdef mkinit -+INCLUDE <signal.h> -+INIT { -+ signal(SIGCHLD, SIG_DFL); - } -+#endif - --/* -- * Print a list of valid signal names -- */ --void --printsignals(void) --{ -- int n; -- -- out1str("EXIT "); -- -- for (n = 1; n < NSIG; n++) { -- out1fmt("%s", sys_signame[n]); -- if ((n == NSIG/2) || n == (NSIG - 1)) -- out1str("\n"); -- else -- out1c(' '); -- } --} - - /* - * The trap builtin. -@@ -144,55 +113,37 @@ - char **ap; - int signo; - -- if (argc <= 1) { -- for (signo = 0 ; signo <= NSIG ; signo++) { -- if (trap[signo] != NULL) -- out1fmt("trap -- '%s' %s\n", trap[signo], -- (signo) ? sys_signame[signo] : "EXIT"); -+ nextopt(nullstr); -+ ap = argptr; -+ if (!*ap) { -+ for (signo = 0 ; signo < NSIG ; signo++) { -+ if (trap[signo] != NULL) { -+ out1fmt( -+ "trap -- %s %s\n", -+ single_quote(trap[signo]), -+ signal_names[signo] -+ ); - } -- return 0; - } -- ap = argv + 1; -- -- action = NULL; -- -- if (strcmp(*ap, "--") == 0) -- if (*++ap == NULL) -- return 0; -- -- if (signame_to_signum(*ap) == -1) { -- if ((*ap)[0] =='-') { -- if ((*ap)[1] == NULL) -- ap++; -- else if ((*ap)[1] == 'l' && (*ap)[2] == NULL) { -- printsignals(); - return 0; - } -- else -- error("bad option %s\n", *ap); -- } -+ if (!ap[1]) -+ action = NULL; - else - action = *ap++; -- } -- - while (*ap) { -- if (is_number(*ap)) -- signo = number(*ap); -- else -- signo = signame_to_signum(*ap); -- -- if (signo < 0 || signo > NSIG) -+ if ((signo = decode_signal(*ap, 0)) < 0) - error("%s: bad trap", *ap); -- - INTOFF; -- if (action) -+ if (action) { -+ if (action[0] == '-' && action[1] == '\0') -+ action = NULL; -+ else - action = savestr(action); -- -+ } - if (trap[signo]) - ckfree(trap[signo]); -- - trap[signo] = action; -- - if (signo != 0) - setsignal(signo); - INTON; -@@ -211,7 +162,7 @@ - clear_traps() { - char **tp; - -- for (tp = trap ; tp <= &trap[NSIG] ; tp++) { -+ for (tp = trap ; tp < &trap[NSIG] ; tp++) { - if (*tp && **tp) { /* trap not NULL or SIG_IGN */ - INTOFF; - ckfree(*tp); -@@ -230,13 +181,13 @@ - * out what it should be set to. - */ - --long -+void - setsignal(signo) - int signo; - { - int action; -- sig_t sigact = SIG_DFL; - char *t; -+ struct sigaction act; - - if ((t = trap[signo]) == NULL) - action = S_DFL; -@@ -279,15 +230,15 @@ - /* - * current setting unknown - */ -- if (!getsigaction(signo, &sigact)) { -+ if (sigaction(signo, 0, &act) == -1) { - /* - * Pretend it worked; maybe we should give a warning - * here, but other shells don't. We don't alter - * sigmode, so that we retry every time. - */ -- return 0; -+ return; - } -- if (sigact == SIG_IGN) { -+ if (act.sa_handler == SIG_IGN) { - if (mflag && (signo == SIGTSTP || - signo == SIGTTIN || signo == SIGTTOU)) { - *t = S_IGN; /* don't hard ignore these */ -@@ -298,31 +249,21 @@ - } - } - if (*t == S_HARD_IGN || *t == action) -- return 0; -+ return; - switch (action) { -- case S_DFL: sigact = SIG_DFL; break; -- case S_CATCH: sigact = onsig; break; -- case S_IGN: sigact = SIG_IGN; break; -+ case S_CATCH: -+ act.sa_handler = onsig; -+ break; -+ case S_IGN: -+ act.sa_handler = SIG_IGN; -+ break; -+ default: -+ act.sa_handler = SIG_DFL; - } - *t = action; -- siginterrupt(signo, 1); -- return (long)signal(signo, sigact); --} -- --/* -- * Return the current setting for sig w/o changing it. -- */ --static int --getsigaction(signo, sigact) -- int signo; -- sig_t *sigact; --{ -- struct sigaction sa; -- -- if (sigaction(signo, (struct sigaction *)0, &sa) == -1) -- return 0; -- *sigact = (sig_t) sa.sa_handler; -- return 1; -+ act.sa_flags = 0; -+ sigfillset(&act.sa_mask); -+ sigaction(signo, &act, 0); - } - - /* -@@ -340,22 +281,6 @@ - } - - --#ifdef mkinit --INCLUDE <signal.h> --INCLUDE "trap.h" -- --SHELLPROC { -- char *sm; -- -- clear_traps(); -- for (sm = sigmode ; sm < sigmode + NSIG ; sm++) { -- if (*sm == S_IGN) -- *sm = S_HARD_IGN; -- } --} --#endif -- -- - - /* - * Signal handler. -@@ -365,13 +290,15 @@ - onsig(signo) - int signo; - { -- signal(signo, onsig); - if (signo == SIGINT && trap[SIGINT] == NULL) { -- onint(); -+ if (suppressint) { -+ (*(sig_atomic_t *) &intpending)++; - return; - } -+ onint(); -+ } - gotsig[signo - 1] = 1; -- pendingsigs++; -+ pendingsigs = signo; - } - - -@@ -383,23 +310,15 @@ - - void - dotrap() { -- int i; -+ char *p; - int savestatus; - -- for (;;) { -- for (i = 1 ; ; i++) { -- if (gotsig[i - 1]) -- break; -- if (i >= NSIG) -- goto done; -- } -- gotsig[i - 1] = 0; -+ while (pendingsigs = 0, barrier(), (p = memchr(gotsig, 1, NSIG - 1))) { -+ *p = 0; - savestatus=exitstatus; -- evalstring(trap[i], 0); -+ evalstring(trap[p - gotsig + 1], 0); - exitstatus=savestatus; - } --done: -- pendingsigs = 0; - } - - -@@ -415,12 +334,12 @@ - { - static int is_interactive; - -- if (on == is_interactive) -+ if (++on == is_interactive) - return; -+ is_interactive = on; - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); -- is_interactive = on; - } - - -@@ -430,29 +349,48 @@ - */ - - void --exitshell(status) -- int status; -+exitshell(void) - { -- struct jmploc loc1, loc2; -+ struct jmploc loc; - char *p; -+ int status; - -+ status = exitstatus; - TRACE(("exitshell(%d) pid=%d\n", status, getpid())); -- if (setjmp(loc1.loc)) { -- goto l1; -- } -- if (setjmp(loc2.loc)) { -- goto l2; -+#ifdef HETIO -+ hetio_reset_term(); -+#endif -+ if (setjmp(loc.loc)) { -+ goto out; - } -- handler = &loc1; -+ handler = &loc; - if ((p = trap[0]) != NULL && *p != '\0') { - trap[0] = NULL; - evalstring(p, 0); - } --l1: handler = &loc2; /* probably unnecessary */ - flushall(); --#if JOBS -- setjobctl(0); --#endif --l2: _exit(status); -+out: -+ _exit(status); - /* NOTREACHED */ - } -+ -+int decode_signal(const char *string, int minsig) -+{ -+ int signo; -+ -+ if (is_number(string)) { -+ signo = atoi(string); -+ if (signo >= NSIG) { -+ return -1; -+ } -+ return signo; -+ } -+ -+ for (signo = minsig; signo < NSIG; signo++) { -+ if (!strcasecmp(string, signal_names[signo])) { -+ return signo; -+ } -+ } -+ -+ return -1; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/trap.h bin_NetBSD-1.6release/src/bin/sh/trap.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/trap.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/trap.h 2003-02-08 14:35:42.000000000 +0000 -@@ -38,13 +38,17 @@ - * @(#)trap.h 8.3 (Berkeley) 6/5/95 - */ - --extern int pendingsigs; -+#include <signal.h> -+ -+extern volatile sig_atomic_t pendingsigs; -+extern char *trap[]; - - int trapcmd __P((int, char **)); - void clear_traps __P((void)); --long setsignal __P((int)); -+void setsignal __P((int)); - void ignoresig __P((int)); - void onsig __P((int)); - void dotrap __P((void)); - void setinteractive __P((int)); --void exitshell __P((int)) __attribute__((noreturn)); -+void exitshell __P((void)) __attribute__((noreturn)); -+int decode_signal __P((const char *, int)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/var.c bin_NetBSD-1.6release/src/bin/sh/var.c ---- bin_NetBSD-1.6release.orig/src/bin/sh/var.c 2002-05-16 11:41:23.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/var.c 2003-02-08 14:35:42.000000000 +0000 -@@ -67,6 +67,7 @@ - #include "error.h" - #include "mystring.h" - #include "parser.h" -+#include "mail.h" - #ifndef SMALL - #include "myhistedit.h" - #endif -@@ -75,76 +76,56 @@ - #define VTABSIZE 39 - - --struct varinit { -- struct var *var; -- int flags; -- const char *text; -- void (*func) __P((const char *)); --}; -- -+struct localvar *localvars; - --#if ATTY --struct var vatty; --#endif --#ifndef SMALL --struct var vhistsize; --struct var vterm; -+const char defpathvar[] = -+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; -+#ifdef IFS_BROKEN -+const char defifsvar[] = "IFS= \t\n"; -+#else -+const char defifs[] = " \t\n"; - #endif --struct var vifs; --struct var vmail; --struct var vmpath; --struct var vpath; --struct var vps1; --struct var vps2; --struct var vvers; --struct var voptind; - --const struct varinit varinit[] = { -+struct var varinit[] = { - #if ATTY -- { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", -- NULL }, -+ { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", 0 }, - #endif --#ifndef SMALL -- { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", -- sethistsize }, -+#ifdef IFS_BROKEN -+ { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 }, -+#else -+ { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=", 0 }, - #endif -- { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", -- NULL }, -- { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", -- NULL }, -- { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", -- NULL }, -- { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, -- changepath }, -- /* -- * vps1 depends on uid -- */ -- { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", -- NULL }, -+ { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", changemail }, -+ { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", changemail }, -+ { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, -+ { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, -+ { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, -+ { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, - #ifndef SMALL -- { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", -- setterm }, -+ { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", 0 }, -+ { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", sethistsize }, - #endif -- { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1", -- getoptsreset }, -- { NULL, 0, NULL, -- NULL } - }; - --struct var *vartab[VTABSIZE]; -+STATIC struct var *vartab[VTABSIZE]; - - STATIC struct var **hashvar __P((const char *)); --STATIC int varequal __P((const char *, const char *)); -+STATIC void showvars __P((const char *, int, int)); -+STATIC struct var **findvar __P((struct var **, const char *)); - - /* - * Initialize the varable symbol tables and import the environment - */ - - #ifdef mkinit -+INCLUDE <unistd.h> -+INCLUDE "cd.h" -+INCLUDE "output.h" - INCLUDE "var.h" - MKINIT char **environ; - INIT { - char **envp; -+ static char ppid[32 + 5] = "PPID="; - - initvar(); - for (envp = environ ; *envp ; envp++) { -@@ -152,41 +133,37 @@ - setvareq(*envp, VEXPORT|VTEXTFIXED); - } - } -+ -+ fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid()); -+ setvareq(ppid, VTEXTFIXED); -+ setpwd(0, 0); - } - #endif - - - /* - * This routine initializes the builtin variables. It is called when the -- * shell is initialized and again when a shell procedure is spawned. -+ * shell is initialized. - */ - - void - initvar() { -- const struct varinit *ip; - struct var *vp; -+ struct var *end; - struct var **vpp; - -- for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { -- if ((vp->flags & VEXPORT) == 0) { -- vpp = hashvar(ip->text); -+ vp = varinit; -+ end = vp + sizeof(varinit) / sizeof(varinit[0]); -+ do { -+ vpp = hashvar(vp->text); - vp->next = *vpp; - *vpp = vp; -- vp->text = strdup(ip->text); -- vp->flags = ip->flags; -- vp->func = ip->func; -- } -- } -+ } while (++vp < end); - /* - * PS1 depends on uid - */ -- if ((vps1.flags & VEXPORT) == 0) { -- vpp = hashvar("PS1="); -- vps1.next = *vpp; -- *vpp = &vps1; -- vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); -- vps1.flags = VSTRFIXED|VTEXTFIXED; -- } -+ if (!geteuid()) -+ vps1.text = "PS1=# "; - } - - /* -@@ -198,20 +175,21 @@ - const char *name, *val; - int flags; - { -- struct jmploc jmploc; -+ int err; -+ volatile int saveint; - struct jmploc *volatile savehandler = handler; -- int err = 0; --#ifdef __GNUC__ -- (void) &err; --#endif -+ struct jmploc jmploc; - -+ SAVEINT(saveint); - if (setjmp(jmploc.loc)) - err = 1; - else { - handler = &jmploc; - setvar(name, val, flags); -+ err = 0; - } - handler = savehandler; -+ RESTOREINT(saveint); - return err; - } - -@@ -225,45 +203,31 @@ - const char *name, *val; - int flags; - { -- const char *p; -- const char *q; -- char *d; -- int len; -- int namelen; -+ char *p, *q; -+ size_t namelen; - char *nameeq; -- int isbad; -+ size_t vallen; - -- isbad = 0; -- p = name; -- if (! is_name(*p)) -- isbad = 1; -- p++; -- for (;;) { -- if (! is_in_name(*p)) { -- if (*p == '\0' || *p == '=') -- break; -- isbad = 1; -- } -- p++; -- } -+ q = endofname(name); -+ p = strchrnul(q, '='); - namelen = p - name; -- if (isbad) -+ if (!namelen || p != q) - error("%.*s: bad variable name", namelen, name); -- len = namelen + 2; /* 2 is space for '=' and '\0' */ -+ vallen = 0; - if (val == NULL) { - flags |= VUNSET; - } else { -- len += strlen(val); -+ vallen = strlen(val); - } -- d = nameeq = ckmalloc(len); -- q = name; -- while (--namelen >= 0) -- *d++ = *q++; -- *d++ = '='; -- *d = '\0'; -- if (val) -- scopy(val, d); -+ INTOFF; -+ p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen); -+ *p++ = '='; -+ if (vallen) { -+ p = mempcpy(p, val, vallen); -+ } -+ *p = '\0'; - setvareq(nameeq, flags); -+ INTON; - } - - -@@ -282,16 +246,15 @@ - { - struct var *vp, **vpp; - -- if (aflag) -- flags |= VEXPORT; - vpp = hashvar(s); -- for (vp = *vpp ; vp ; vp = vp->next) { -- if (varequal(s, vp->text)) { -+ flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); -+ vp = *findvar(vpp, s); -+ INTOFF; -+ if (vp) { - if (vp->flags & VREADONLY) { - size_t len = strchr(s, '=') - s; - error("%.*s: is read only", len, s); - } -- INTOFF; - - if (vp->func && (flags & VNOFUNC) == 0) - (*vp->func)(strchr(s, '=') + 1); -@@ -299,27 +262,17 @@ - if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(vp->text); - -- vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); -- vp->flags |= flags; -- vp->text = s; -- -- /* -- * We could roll this to a function, to handle it as -- * a regular variable function callback, but why bother? -- */ -- if (vp == &vmpath || (vp == &vmail && ! mpathset())) -- chkmail(1); -- INTON; -- return; -- } -- } -+ flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VUNSET); -+ } else { - /* not found */ - vp = ckmalloc(sizeof (*vp)); -- vp->flags = flags; -- vp->text = s; - vp->next = *vpp; - vp->func = NULL; - *vpp = vp; -+ } -+ vp->text = s; -+ vp->flags = flags; -+ INTON; - } - - -@@ -329,14 +282,13 @@ - */ - - void --listsetvar(list) -- struct strlist *list; -- { -+listsetvar(struct strlist *list, int flags) -+{ - struct strlist *lp; - - INTOFF; - for (lp = list ; lp ; lp = lp->next) { -- setvareq(savestr(lp->text), 0); -+ setvareq(savestr(lp->text), flags); - } - INTON; - } -@@ -353,45 +305,29 @@ - { - struct var *v; - -- for (v = *hashvar(name) ; v ; v = v->next) { -- if (varequal(v->text, name)) { -- if (v->flags & VUNSET) -- return NULL; -+ if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) { - return strchr(v->text, '=') + 1; - } -- } - return NULL; - } - - - - /* -- * Search the environment of a builtin command. If the second argument -- * is nonzero, return the value of a variable even if it hasn't been -- * exported. -+ * Search the environment of a builtin command. - */ - - char * --bltinlookup(name, doall) -+bltinlookup(name) - const char *name; -- int doall; - { - struct strlist *sp; -- struct var *v; - - for (sp = cmdenviron ; sp ; sp = sp->next) { - if (varequal(sp->text, name)) - return strchr(sp->text, '=') + 1; - } -- for (v = *hashvar(name) ; v ; v = v->next) { -- if (varequal(v->text, name)) { -- if ((v->flags & VUNSET) -- || (!doall && (v->flags & VEXPORT) == 0)) -- return NULL; -- return strchr(v->text, '=') + 1; -- } -- } -- return NULL; -+ return lookupvar(name); - } - - -@@ -403,66 +339,28 @@ - - char ** - environment() { -- int nenv; - struct var **vpp; - struct var *vp; -- char **env; - char **ep; -+ void *epend; - -- nenv = 0; -- for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { -- for (vp = *vpp ; vp ; vp = vp->next) -- if (vp->flags & VEXPORT) -- nenv++; -- } -- ep = env = stalloc((nenv + 1) * sizeof *env); -- for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { -+ STARTSTACKSTR(ep); -+ epend = sstrend; -+ vpp = vartab; -+ do { - for (vp = *vpp ; vp ; vp = vp->next) -- if (vp->flags & VEXPORT) -- *ep++ = vp->text; -- } -- *ep = NULL; -- return env; --} -- -- --/* -- * Called when a shell procedure is invoked to clear out nonexported -- * variables. It is also necessary to reallocate variables of with -- * VSTACK set since these are currently allocated on the stack. -- */ -- --#ifdef mkinit --void shprocvar __P((void)); -- --SHELLPROC { -- shprocvar(); --} --#endif -- --void --shprocvar() { -- struct var **vpp; -- struct var *vp, **prev; -- -- for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { -- for (prev = vpp ; (vp = *prev) != NULL ; ) { -- if ((vp->flags & VEXPORT) == 0) { -- *prev = vp->next; -- if ((vp->flags & VTEXTFIXED) == 0) -- ckfree(vp->text); -- if ((vp->flags & VSTRFIXED) == 0) -- ckfree(vp); -- } else { -- if (vp->flags & VSTACK) { -- vp->text = savestr(vp->text); -- vp->flags &=~ VSTACK; -- } -- prev = &vp->next; -- } -+ if (vp->flags & VEXPORT && !(vp->flags & VUNSET)) { -+ if (ep == epend) { -+ ep = growstackstr(); -+ epend = sstrend; - } -+ *ep++ = (char *) vp->text; - } -- initvar(); -+ } while (++vpp < vartab + VTABSIZE); -+ if (ep == epend) -+ ep = growstackstr(); -+ *ep++ = NULL; -+ return grabstackstr(ep); - } - - -@@ -478,15 +376,7 @@ - int argc; - char **argv; - { -- struct var **vpp; -- struct var *vp; -- -- for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { -- for (vp = *vpp ; vp ; vp = vp->next) { -- if ((vp->flags & VUNSET) == 0) -- out1fmt("%s\n", vp->text); -- } -- } -+ showvars(nullstr, VUNSET, VUNSET); - return 0; - } - -@@ -501,45 +391,28 @@ - int argc; - char **argv; - { -- struct var **vpp; - struct var *vp; - char *name; - const char *p; -+ char **aptr; - int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; -- int pflag; -+ int notp; - -- listsetvar(cmdenviron); -- pflag = (nextopt("p") == 'p'); -- if (argc > 1 && !pflag) { -- while ((name = *argptr++) != NULL) { -+ notp = nextopt("p") - 'p'; -+ if (notp && ((name = *(aptr = argptr)))) { -+ do { - if ((p = strchr(name, '=')) != NULL) { - p++; - } else { -- vpp = hashvar(name); -- for (vp = *vpp ; vp ; vp = vp->next) { -- if (varequal(vp->text, name)) { -+ if ((vp = *findvar(hashvar(name), name))) { - vp->flags |= flag; -- goto found; -- } -+ continue; - } - } - setvar(name, p, flag); --found:; -- } -- } else { -- for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { -- for (vp = *vpp ; vp ; vp = vp->next) { -- if ((vp->flags & flag) == 0) -- continue; -- if (pflag) { -- out1fmt("%s %s\n", argv[0], vp->text); -+ } while ((name = *++aptr) != NULL); - } else { -- for (p = vp->text ; *p != '=' ; p++) -- out1c(*p); -- out1c('\n'); -- } -- } -- } -+ showvars(argv[0], flag, 0); - } - return 0; - } -@@ -589,7 +462,7 @@ - vp = NULL; - } else { - vpp = hashvar(name); -- for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next); -+ vp = *findvar(vpp, name); - if (vp == NULL) { - if (strchr(name, '=')) - setvareq(savestr(name), VSTRFIXED); -@@ -684,7 +557,7 @@ - - for (ap = argptr; *ap ; ap++) { - if (flg_func) -- ret |= unsetfunc(*ap); -+ unsetfunc(*ap); - if (flg_var) - ret |= unsetvar(*ap); - } -@@ -703,9 +576,9 @@ - struct var **vpp; - struct var *vp; - -- vpp = hashvar(s); -- for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { -- if (varequal(vp->text, s)) { -+ vpp = findvar(hashvar(s), s); -+ vp = *vpp; -+ if (vp) { - if (vp->flags & VREADONLY) - return (1); - INTOFF; -@@ -722,9 +595,8 @@ - INTON; - return (0); - } -- } - -- return (1); -+ return (0); - } - - -@@ -753,7 +625,7 @@ - * either '=' or '\0'. - */ - --STATIC int -+int - varequal(p, q) - const char *p, *q; - { -@@ -765,3 +637,44 @@ - return 1; - return 0; - } -+ -+STATIC void -+showvars(const char *prefix, int mask, int xor) -+{ -+ struct var **vpp; -+ struct var *vp; -+ const char *sep = *prefix ? spcstr : prefix; -+ -+ vpp = vartab; -+ do { -+ for (vp = *vpp ; vp ; vp = vp->next) { -+ if ((vp->flags & mask) ^ xor) { -+ const char *p; -+ const char *q; -+ int len; -+ -+ p = strchr(vp->text, '='); -+ q = nullstr; -+ if (!(vp->flags & VUNSET)) -+ q = single_quote(++p); -+ len = p - vp->text; -+ -+ out1fmt( -+ "%s%s%.*s%s\n", prefix, sep, len, -+ vp->text, q -+ ); -+ } -+ } -+ } while (++vpp < vartab + VTABSIZE); -+} -+ -+STATIC struct var ** -+findvar(struct var **vpp, const char *name) -+{ -+ for (; *vpp; vpp = &(*vpp)->next) { -+ if (varequal((*vpp)->text, name)) { -+ break; -+ } -+ } -+ return vpp; -+} -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/var.h bin_NetBSD-1.6release/src/bin/sh/var.h ---- bin_NetBSD-1.6release.orig/src/bin/sh/var.h 2000-05-23 11:03:19.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/var.h 2003-02-08 14:35:42.000000000 +0000 -@@ -55,7 +55,7 @@ - struct var { - struct var *next; /* next entry in hash list */ - int flags; /* flags are defined above */ -- char *text; /* name=value */ -+ const char *text; /* name=value */ - void (*func) __P((const char *)); - /* function to be called when */ - /* the variable gets set/unset */ -@@ -66,26 +66,38 @@ - struct localvar *next; /* next local variable in list */ - struct var *vp; /* the variable that was made local */ - int flags; /* saved flags */ -- char *text; /* saved text */ -+ const char *text; /* saved text */ - }; - - --struct localvar *localvars; -+extern struct localvar *localvars; -+extern struct var varinit[]; - - #if ATTY --extern struct var vatty; -+#define vatty varinit[0] -+#define vifs varinit[1] -+#else -+#define vifs varinit[0] - #endif --extern struct var vifs; --extern struct var vmail; --extern struct var vmpath; --extern struct var vpath; --extern struct var vps1; --extern struct var vps2; -+#define vmail (&vifs)[1] -+#define vmpath (&vmail)[1] -+#define vpath (&vmpath)[1] -+#define vps1 (&vpath)[1] -+#define vps2 (&vps1)[1] -+#define voptind (&vps2)[1] - #ifndef SMALL --extern struct var vterm; --extern struct var vtermcap; --extern struct var vhistsize; -+#define vterm (&voptind)[1] -+#define vhistsize (&vterm)[1] -+#endif -+ -+#ifdef IFS_BROKEN -+extern const char defifsvar[]; -+#define defifs (defifsvar + 4) -+#else -+extern const char defifs[]; - #endif -+extern const char defpathvar[]; -+#define defpath (defpathvar + 5) - - /* - * The following macros access the values of the above variables. -@@ -115,11 +127,10 @@ - void setvar __P((const char *, const char *, int)); - void setvareq __P((char *, int)); - struct strlist; --void listsetvar __P((struct strlist *)); -+void listsetvar __P((struct strlist *, int)); - char *lookupvar __P((const char *)); --char *bltinlookup __P((const char *, int)); -+char *bltinlookup __P((const char *)); - char **environment __P((void)); --void shprocvar __P((void)); - int showvarscmd __P((int, char **)); - int exportcmd __P((int, char **)); - int localcmd __P((int, char **)); -@@ -129,3 +140,4 @@ - int unsetcmd __P((int, char **)); - int unsetvar __P((const char *)); - int setvarsafe __P((const char *, const char *, int)); -+int varequal __P((const char *, const char *)); -diff --minimal -ruPb bin_NetBSD-1.6release.orig/src/bin/sh/yaccfe.sh bin_NetBSD-1.6release/src/bin/sh/yaccfe.sh ---- bin_NetBSD-1.6release.orig/src/bin/sh/yaccfe.sh 1970-01-01 01:00:00.000000000 +0100 -+++ bin_NetBSD-1.6release/src/bin/sh/yaccfe.sh 2003-02-08 14:35:42.000000000 +0000 -@@ -0,0 +1,29 @@ -+#!/bin/sh -+# -+# Quick script to reformat yacc commands -+# so byacc isnt required. -+# -+# Expects: -+# yacc -d -o yourfile.c yourfile.y -+# Executes: -+# yacc -d -b yourfile yourfile.y -+# mv yourfile.tab.c yourfile.c -+# mv yourfile.tab.h yourfile.h -+# -+ -+yaccbin="/usr/bin/yacc" -+yaccflags="-d" -+ -+[ ! ${#} -gt 0 ] && exit 1 -+while getopts ":o:" opt -+do -+ case $opt in -+ o) output=${OPTARG%*.c} ;; -+ ?) ;; -+ esac -+done -+${yaccbin} ${yaccflags} -b ${output} ${output}.y || exit 1 -+for files in ${output}.tab.{c,h} -+do -+ mv ${files} $(sed 's/.tab//' <<< ${files}) || exit 1 -+done diff --git a/app-shells/ash/files/digest-ash-1.6 b/app-shells/ash/files/digest-ash-1.6 index 5eb33abde8d6..624c465466b8 100644 --- a/app-shells/ash/files/digest-ash-1.6 +++ b/app-shells/ash/files/digest-ash-1.6 @@ -1 +1,2 @@ MD5 7e8fbb3654eeb6b57c1ec384c2d1b156 bin.tar.gz 850570 +MD5 c5ad9680e31827b358b88d2e39336d8f dash-ash-hetio-yacc.diff.bz2 98271 |