summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeemant Kulleen <seemant@gentoo.org>2003-02-11 11:18:13 +0000
committerSeemant Kulleen <seemant@gentoo.org>2003-02-11 11:18:13 +0000
commit9316d3911976e9a761cde4c50282d635da97b77d (patch)
tree610c36bd6435c46043ec30b277409c582ab72dc2 /app-shells/ash/files
parentadded a patch (diff)
downloadgentoo-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.diff17336
-rw-r--r--app-shells/ash/files/digest-ash-1.61
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 \&gt 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 \&lt 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&LTOSTOP) */
-+ 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 = &ap;
- 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) &quotef;
- (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 \&gt 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 \&lt 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