[Frugalware-darcs] frugalware-current: ash-0.4.0-5-i686

VMiklos vmiklos at frugalware.org
Sun Jun 3 20:22:00 CEST 2007


Darcsweb-Url: http://darcs.frugalware.org/darcsweb/darcsweb.cgi?r=frugalware-current;a=darcs_commitdiff;h=20070603150758-e2957-6bc5dec56c3bec19307c5c7c3ad8cd72389b7f51.gz;

[ash-0.4.0-5-i686
VMiklos <vmiklos at frugalware.org>**20070603150758
 moved ash-0.4.0.diff to ftp
] {
hunk ./source/apps/ash/FrugalBuild 6
-pkgrel=4
+pkgrel=5
hunk ./source/apps/ash/FrugalBuild 12
-up2date="lynx -dump http://slackware.at/data/slackware-current/source/ap/ash/|grep ash-[0-9\.]*tar\.gz$|sed -n -e 's/.*h-\(.*\)\.tar\.gz$/\1/' -e '1 p'"
+up2date="lynx -dump ftp://ftp.slackware.com/pub/slackware/slackware-current/source/ap/ash|Flasttar"
hunk ./source/apps/ash/FrugalBuild 14
-	$pkgname-$pkgver.diff $pkgname-$pkgver-gcc4.diff)
+	http://ftp.frugalware.org/pub/other/sources/ash/$pkgname-$pkgver.diff.bz2 \
+	$pkgname-$pkgver-gcc4.diff)
hunk ./source/apps/ash/FrugalBuild 17
-          '66c9637ab925043279e7e270b13b353ff8350b8b' \
+          '964d796a695a2053107593c1c7b44acee6c36d6d' \
hunk ./source/apps/ash/ash-0.4.0.diff 1
-Author: VMiklos <vmiklos at frugalware.org>
-Author: Tushar Teredesai <tushar at linuxfromscratch.org>
-Description: This is a collection of patches from Debian, Slackware, LFS, etc.
-(don't you love Open Source:-) along with a minor bison related fix
-from me (Tushar). Additionally I removed debian specific stuff.
-diff -Nur ash-0.4.0.orig/Makefile ash-0.4.0.fixed/Makefile
---- ash-0.4.0.orig/Makefile	2001-01-12 10:50:34.000000000 -0600
-+++ ash-0.4.0.fixed/Makefile	2003-10-01 21:08:15.000000000 -0500
-@@ -7,56 +7,69 @@
- SHSRCS=	alias.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
-+	test.c setmode.c test.c hetio.c
-+GENSRCS=builtins.c builtins.h init.c nodes.c arith.c arith.h lex.yy.c \
-+	nodes.h syntax.c syntax.h token.h signames.c
- SRCS=	${SHSRCS} ${GENSRCS}
- 
--LDADD+=	-ll -ledit -ltermcap
--DPADD+=	${LIBL} ${LIBEDIT} ${LIBTERMCAP}
-+OBJS=alias.o cd.o bltin/echo.o error.o eval.o exec.o expand.o \
-+	histedit.o input.o jobs.o mail.o main.o memalloc.o miscbltin.o \
-+	mystring.o options.o output.o parser.o redir.o show.o \
-+	trap.o var.o bltin/test.o signames.o \
-+	builtins.o init.o nodes.o syntax.o arith.o lex.yy.o \
-+	setmode.o bltin/times.o hetio.o
-+
-+OPT_FLAGS=
-+LDFLAGS=
-+CFLAGS+=-DSHELL -I. -DNO_HISTORY -DBSD=1 -DSMALL -D_GNU_SOURCE \
-+	-DGLOB_BROKEN -D__COPYRIGHT\(x\)= -D__RCSID\(x\)= -D_DIAGASSERT\(x\)= \
-+	-DHETIO
-+
-+all: $(PROG)
-+
-+$(PROG): build-tools $(GENSRCS) $(GENHDRS) $(OBJS)
-+	$(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDLIBS) -lfl
-+	
-+lex.yy.c: arith_lex.l
-+	flex -8 $< 
-+	
-+CLEANFILES+= mkinit mkinit.o mknodes mknodes.o \
-+	mksyntax mksyntax.o
-+	
-+CLEANFILES+= ${GENSRCS} ${GENHDRS}
-+
-+build-tools: mkinit mknodes mksyntax
-+
-+.ORDER: builtins.c builtins.h
-+builtins.c builtins.h: mkbuiltins builtins.def
-+	sh mkbuiltins shell.h builtins.def `pwd`
-+
-+INIT_DEPS = alias.c eval.c exec.c input.c jobs.c options.c parser.c \
-+	redir.c trap.c var.c output.c
-+	
-+init.c: mkinit $(INIT_DEPS)
-+	./mkinit $(INIT_DEPS)
-+
-+mkinit: mkinit.o
-+mknodes: mknodes.o
-+mksyntax: mksyntax.o
- 
--LFLAGS= -8	# 8-bit lex scanner for arithmetic
--YFLAGS=	-d
--
--CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
--
--.PATH:	${.CURDIR}/bltin ${.CURDIR}/../../usr.bin/printf ${.CURDIR}/../test
--
--CLEANFILES+= mkinit mknodes mksyntax
--CLEANFILES+= ${GENSRCS} y.tab.h
--
--token.h: mktokens
--	sh ${.ALLSRC}
--
--builtins.c builtins.h: mkbuiltins shell.h builtins.def
--	sh ${.ALLSRC} ${.OBJDIR}
--
--init.c: mkinit ${SHSRCS}
--	./${.ALLSRC}
-+signames.c: mksignames
-+	./mksignames
- 
- nodes.c nodes.h: mknodes nodetypes nodes.c.pat
--	./${.ALLSRC}
-+	./mknodes ./nodetypes ./nodes.c.pat
- 
- syntax.c syntax.h: mksyntax
--	./${.ALLSRC}
--
--mkinit: mkinit.c
--	${HOST_LINK.c} -o mkinit ${.IMPSRC}
--
--mknodes: mknodes.c
--	${HOST_LINK.c} -o mknodes ${.IMPSRC}
-+	./mksyntax
- 
--.if	(${MACHINE_ARCH} == "powerpc") || \
--	(${MACHINE_ARCH} == "arm32") || \
--	(${MACHINE_ARCH} == "arm26")
--TARGET_CHARFLAG= -DTARGET_CHAR="u_int8_t"
--.else
--TARGET_CHARFLAG= -DTARGET_CHAR="int8_t"
--.endif
-+arith.c arith.h: arith.y
-+	yacc -d arith.y
-+	mv y.tab.h arith.h
-+	mv y.tab.c arith.c
- 
--mksyntax: mksyntax.c
--	${HOST_LINK.c} ${TARGET_CHARFLAG} -o mksyntax ${.IMPSRC}
--
--.include <bsd.prog.mk>
-+token.h: mktokens
-+	sh ./mktokens
- 
--${OBJS}: builtins.h nodes.h syntax.h token.h
-+clean:
-+	rm -f $(PROG) $(OBJS) $(CLEANFILES) core
-diff -Nur ash-0.4.0.orig/arith.y ash-0.4.0.fixed/arith.y
---- ash-0.4.0.orig/arith.y	1999-07-09 06:02:05.000000000 -0500
-+++ ash-0.4.0.fixed/arith.y	2003-10-02 00:53:57.000000000 -0500
-@@ -150,43 +150,43 @@
- %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
- %%
- 
--exp:	expr = {
-+exp:	expr {
- 			return ($1);
- 		}
- 	;
- 
- 
--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_BOR expr	= { $$ = $1 | $3; }
--	| expr ARITH_BXOR expr	= { $$ = $1 ^ $3; }
--	| expr ARITH_BAND expr	= { $$ = $1 & $3; }
--	| expr ARITH_EQ expr	= { $$ = $1 == $3; }
--	| expr ARITH_GT expr	= { $$ = $1 > $3; }
--	| expr ARITH_GE expr	= { $$ = $1 >= $3; }
--	| expr ARITH_LT expr	= { $$ = $1 < $3; }
--	| expr ARITH_LE expr	= { $$ = $1 <= $3; }
--	| expr ARITH_NE expr	= { $$ = $1 != $3; }
--	| expr ARITH_LSHIFT expr = { $$ = $1 << $3; }
--	| expr ARITH_RSHIFT expr = { $$ = $1 >> $3; }
--	| expr ARITH_ADD expr	= { $$ = $1 + $3; }
--	| expr ARITH_SUB expr	= { $$ = $1 - $3; }
--	| expr ARITH_MUL expr	= { $$ = $1 * $3; }
--	| expr ARITH_DIV expr	= {
-+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_BOR expr	{ $$ = $1 | $3; }
-+	| expr ARITH_BXOR expr	{ $$ = $1 ^ $3; }
-+	| expr ARITH_BAND expr	{ $$ = $1 & $3; }
-+	| expr ARITH_EQ expr	{ $$ = $1 == $3; }
-+	| expr ARITH_GT expr	{ $$ = $1 > $3; }
-+	| expr ARITH_GE expr	{ $$ = $1 >= $3; }
-+	| expr ARITH_LT expr	{ $$ = $1 < $3; }
-+	| expr ARITH_LE expr	{ $$ = $1 <= $3; }
-+	| expr ARITH_NE expr	{ $$ = $1 != $3; }
-+	| expr ARITH_LSHIFT expr { $$ = $1 << $3; }
-+	| expr ARITH_RSHIFT expr { $$ = $1 >> $3; }
-+	| expr ARITH_ADD expr	{ $$ = $1 + $3; }
-+	| expr ARITH_SUB expr	{ $$ = $1 - $3; }
-+	| expr ARITH_MUL expr	{ $$ = $1 * $3; }
-+	| expr ARITH_DIV expr	{
- 			if ($3 == 0)
- 				yyerror("division by zero");
- 			$$ = $1 / $3;
- 			}
--	| expr ARITH_REM expr   = {
-+	| expr ARITH_REM expr   {
- 			if ($3 == 0)
- 				yyerror("division by zero");
- 			$$ = $1 % $3;
- 			}
--	| ARITH_NOT expr	= { $$ = !($2); }
--	| ARITH_BNOT expr	= { $$ = ~($2); }
--	| ARITH_SUB expr %prec ARITH_UNARYMINUS = { $$ = -($2); }
--	| ARITH_ADD expr %prec ARITH_UNARYPLUS = { $$ = $2; }
-+	| ARITH_NOT expr	{ $$ = !($2); }
-+	| ARITH_BNOT expr	{ $$ = ~($2); }
-+	| ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); }
-+	| ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; }
- 	| ARITH_NUM
- 	;
- %%
-@@ -195,7 +195,6 @@
- 	const char *s;
- {
- 
--	yyerrok;
- 	yyclearin;
- 	arith_lex_reset();	/* reprime lex */
- 	error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
-diff -Nur ash-0.4.0.orig/bltin/bltin.h ash-0.4.0.fixed/bltin/bltin.h
---- ash-0.4.0.orig/bltin/bltin.h	1997-07-05 06:12:37.000000000 -0500
-+++ ash-0.4.0.fixed/bltin/bltin.h	2003-10-01 21:08:15.000000000 -0500
-@@ -46,8 +46,10 @@
- 
- #include "../shell.h"
- #include "../mystring.h"
-+#include "../memalloc.h"
- #ifdef SHELL
- #include "../output.h"
-+#ifndef _GNU_SOURCE
- #define stdout out1
- #define stderr out2
- #define printf out1fmt
-@@ -56,12 +58,13 @@
- #define fprintf outfmt
- #define fputs outstr
- #define fflush flushout
--#define INITARGS(argv)
- #define warnx(a, b, c) {				\
- 	char buf[64];					\
- 	(void)snprintf(buf, sizeof(buf), a, b, c);	\
- 	error("%s", buf);				\
- }
-+#endif
-+#define INITARGS(argv)
- 
- #else
- #undef NULL
-diff -Nur ash-0.4.0.orig/bltin/echo.c ash-0.4.0.fixed/bltin/echo.c
---- ash-0.4.0.orig/bltin/echo.c	1996-11-03 06:06:22.000000000 -0600
-+++ ash-0.4.0.fixed/bltin/echo.c	2003-10-01 21:08:15.000000000 -0500
-@@ -44,7 +44,13 @@
- 
- #define main echocmd
- 
-+#ifdef _GNU_SOURCE
-+#include <stdio.h>
-+
-+#include "../mystring.h"
-+#else
- #include "bltin.h"
-+#endif
- 
- /* #define eflag 1 */
- 
-@@ -53,7 +59,6 @@
- 	register char **ap;
- 	register char *p;
- 	register char c;
--	int count;
- 	int nflag = 0;
- #ifndef eflag
- 	int eflag = 0;
-@@ -62,34 +67,42 @@
- 	ap = argv;
- 	if (argc)
- 		ap++;
--	if ((p = *ap) != NULL) {
-+	while ((p = *ap) != NULL && *p == '-') {
- 		if (equal(p, "-n")) {
--			nflag++;
--			ap++;
-+			nflag = 1;
- 		} else if (equal(p, "-e")) {
- #ifndef eflag
--			eflag++;
-+			eflag = 1;
-+#endif
-+		} else if (equal(p, "-E")) {
-+#ifndef eflag
-+			eflag = 0;
- #endif
--			ap++;
- 		}
-+		else break;
-+		ap++;
- 	}
- 	while ((p = *ap++) != NULL) {
- 		while ((c = *p++) != '\0') {
- 			if (c == '\\' && eflag) {
--				switch (*p++) {
-+				switch (c = *p++) {
-+				case 'a':  c = '\007'; break;
- 				case 'b':  c = '\b';  break;
- 				case 'c':  return 0;		/* exit */
-+				case 'e':  c = '\033';  break;
- 				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');
-+				case '0': case '1': case '2': case '3':
-+				case '4': case '5': case '6': case '7':
-+					c -= '0';
-+					if (*p >= '0' && *p <= '7')
-+						c = c * 8 + (*p++ - '0');
-+					if (*p >= '0' && *p <= '7')
-+					c = c * 8 + (*p++ - '0');
- 					break;
- 				default:
- 					p--;
-@@ -103,5 +116,12 @@
- 	}
- 	if (! nflag)
- 		putchar('\n');
-+#ifdef _GNU_SOURCE
-+	fflush(stdout);
-+	if (ferror(stdout)) {
-+		clearerr(stdout);
-+		return 1;
-+	}
-+#endif
- 	return 0;
- }
-diff -Nur ash-0.4.0.orig/bltin/test.c ash-0.4.0.fixed/bltin/test.c
---- ash-0.4.0.orig/bltin/test.c	1969-12-31 18:00:00.000000000 -0600
-+++ ash-0.4.0.fixed/bltin/test.c	2003-10-01 21:08:15.000000000 -0500
-@@ -0,0 +1,583 @@
-+/*	$NetBSD: test.c,v 1.22 2000/04/09 23:24:59 christos 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.22 2000/04/09 23:24:59 christos Exp $");
-+#endif
-+
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <unistd.h>
-+#include <ctype.h>
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <err.h>
-+#ifdef __STDC__
-+#include <stdarg.h>
-+#else
-+#include <varargs.h>
-+#endif
-+
-+/* 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 gid_t *group_array = NULL;
-+static int ngroups;
-+
-+static void syntax __P((const char *, const char *));
-+static int oexpr __P((enum token));
-+static int aexpr __P((enum token));
-+static int nexpr __P((enum token));
-+static int primary __P((enum token));
-+static int binop __P((void));
-+static int filstat __P((char *, enum token));
-+static enum token t_lex __P((char *));
-+static int isoperand __P((void));
-+static int getn __P((const char *));
-+static int newerf __P((const char *, const char *));
-+static int olderf __P((const char *, const char *));
-+static int equalf __P((const char *, const char *));
-+static int test_eaccess();
-+static int bash_group_member();
-+static void initialize_group_array();
-+
-+#if defined(SHELL)
-+extern void error __P((const char *, ...)) __attribute__((__noreturn__));
-+#else
-+static void error __P((const char *, ...)) __attribute__((__noreturn__));
-+
-+static void
-+#ifdef __STDC__
-+error(const char *msg, ...)
-+#else
-+error(va_alist)
-+	va_dcl
-+#endif
-+{
-+	va_list ap;
-+#ifndef __STDC__
-+	const char *msg;
-+
-+	va_start(ap);
-+	msg = va_arg(ap, const char *);
-+#else
-+	va_start(ap, msg);
-+#endif
-+	verrx(2, msg, ap);
-+	/*NOTREACHED*/
-+	va_end(ap);
-+}
-+#endif
-+
-+#ifdef SHELL
-+int testcmd __P((int, char **));
-+
-+int
-+testcmd(argc, argv)
-+	int argc;
-+	char **argv;
-+#else
-+int main __P((int, char **));
-+
-+int
-+main(argc, argv)
-+	int argc;
-+	char **argv;
-+#endif
-+{
-+	int	res;
-+
-+
-+	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(op, msg)
-+	const char	*op;
-+	const char	*msg;
-+{
-+	if (op && *op)
-+		error("%s: %s", op, msg);
-+	else
-+		error("%s", msg);
-+}
-+
-+static int
-+oexpr(n)
-+	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(n)
-+	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(n)
-+	enum token n;			/* token */
-+{
-+	if (n == UNOT)
-+		return !nexpr(t_lex(*++t_wp));
-+	return primary(n);
-+}
-+
-+static int
-+primary(n)
-+	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()
-+{
-+	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(nm, mode)
-+	char *nm;
-+	enum token mode;
-+{
-+	struct stat s;
-+
-+	if (mode == FILSYM ? lstat(nm, &s) : stat(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(s)
-+	char *s;
-+{
-+	struct t_op const *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()
-+{
-+	struct t_op const *op = ops;
-+	char *s;
-+	char *t;
-+
-+	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(s)
-+	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 (f1, f2)
-+const char *f1, *f2;
-+{
-+	struct stat b1, b2;
-+
-+	return (stat (f1, &b1) == 0 &&
-+		stat (f2, &b2) == 0 &&
-+		b1.st_mtime > b2.st_mtime);
-+}
-+
-+static int
-+olderf (f1, f2)
-+const char *f1, *f2;
-+{
-+	struct stat b1, b2;
-+
-+	return (stat (f1, &b1) == 0 &&
-+		stat (f2, &b2) == 0 &&
-+		b1.st_mtime < b2.st_mtime);
-+}
-+
-+static int
-+equalf (f1, f2)
-+const char *f1, *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 (path, mode)
-+char *path;
-+int mode;
-+{
-+	struct stat st;
-+	int euid = geteuid();
-+
-+	if (stat (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);
-+}
-+
-+static void
-+initialize_group_array ()
-+{
-+	ngroups = getgroups(0, NULL);
-+	group_array = malloc(ngroups * sizeof(gid_t));
-+	if (!group_array)
-+		error(strerror(ENOMEM));
-+	getgroups(ngroups, group_array);
-+}
-+
-+/* Return non-zero if GID is one that we have in our groups list. */
-+static int
-+bash_group_member (gid)
-+gid_t gid;
-+{
-+	register int i;
-+
-+	/* Short-circuit if possible, maybe saving a call to getgroups(). */
-+	if (gid == getgid() || gid == getegid())
-+		return (1);
-+
-+	if (ngroups == 0)
-+		initialize_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 -Nur ash-0.4.0.orig/bltin/times.c ash-0.4.0.fixed/bltin/times.c
---- ash-0.4.0.orig/bltin/times.c	1969-12-31 18:00:00.000000000 -0600
-+++ ash-0.4.0.fixed/bltin/times.c	2003-10-01 21:08:15.000000000 -0500
-@@ -0,0 +1,30 @@
-+#ifdef _GNU_SOURCE
-+/*
-+ * Copyright (c) 1999 Herbert Xu <herbert at debian.org>
-+ * This file contains code for the times builtin.
-+ * $Id: ash-0.4.0-cumulative_fixes-1.patch,v 1.1 2004/06/04 10:32:01 jim Exp $
-+ */
-+
-+#include <stdio.h>
-+#include <sys/times.h>
-+#include <unistd.h>
-+
-+#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;
-+}
-+#endif	/* _GNU_SOURCE */
-diff -Nur ash-0.4.0.orig/builtins.def ash-0.4.0.fixed/builtins.def
---- ash-0.4.0.orig/builtins.def	2000-04-10 06:02:58.000000000 -0500
-+++ ash-0.4.0.fixed/builtins.def	2003-10-01 21:08:15.000000000 -0500
-@@ -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
-@@ -70,6 +71,7 @@
- hashcmd		hash
- jobidcmd	jobid
- jobscmd		jobs
-+killcmd -j	kill
- #linecmd		line
- localcmd	local
- #nlechocmd	nlecho
-@@ -91,3 +93,4 @@
- aliascmd	alias
- ulimitcmd	ulimit
- testcmd		test [
-+timescmd	times
-diff -Nur ash-0.4.0.orig/cd.c ash-0.4.0.fixed/cd.c
---- ash-0.4.0.orig/cd.c	1999-07-09 06:02:05.000000000 -0500
-+++ ash-0.4.0.fixed/cd.c	2003-10-01 21:08:15.000000000 -0500
-@@ -244,6 +244,7 @@
- 		curdir = NULL;
- 		getpwd();
- 		setvar("PWD", curdir, VEXPORT|VTEXTFIXED);
-+		setvar("OLDPWD", prevdir, VEXPORT|VTEXTFIXED);
- 		INTON;
- 		return;
- 	}
-@@ -275,6 +276,7 @@
- 	prevdir = curdir;
- 	curdir = savestr(stackblock());
- 	setvar("PWD", curdir, VEXPORT|VTEXTFIXED);
-+	setvar("OLDPWD", prevdir, VEXPORT|VTEXTFIXED);
- 	INTON;
- }
- 
-@@ -319,7 +321,7 @@
- 	 * c implementation of getcwd, that does not open a pipe to
- 	 * /bin/pwd.
- 	 */
--#if defined(__NetBSD__) || defined(__SVR4)
-+#if defined(__NetBSD__) || defined(__SVR4) || defined(__GLIBC__)
- 		
- 	if (getcwd(buf, sizeof(buf)) == NULL) {
- 		char *pwd = getenv("PWD");
-diff -Nur ash-0.4.0.orig/error.c ash-0.4.0.fixed/error.c
---- ash-0.4.0.orig/error.c	2001-01-12 10:50:35.000000000 -0600
-+++ ash-0.4.0.fixed/error.c	2003-10-01 21:08:15.000000000 -0500
-@@ -233,6 +233,7 @@
- 	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
- 	{ ENOTDIR,	E_EXEC,	"not found" },
- 	{ EISDIR,	ALL,	"is a directory" },
-+	{ EEXIST,	E_CREAT,"file exists" },
- #ifdef notdef
- 	{ EMFILE,	ALL,	"too many open files" },
- #endif
-diff -Nur ash-0.4.0.orig/error.h ash-0.4.0.fixed/error.h
---- ash-0.4.0.orig/error.h	1999-07-09 06:02:05.000000000 -0500
-+++ ash-0.4.0.fixed/error.h	2003-10-01 21:08:15.000000000 -0500
-@@ -102,7 +102,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 -Nur ash-0.4.0.orig/eval.c ash-0.4.0.fixed/eval.c
---- ash-0.4.0.orig/eval.c	2000-05-23 05:03:18.000000000 -0500
-+++ ash-0.4.0.fixed/eval.c	2003-10-01 21:08:15.000000000 -0500
-@@ -45,7 +45,9 @@
- #endif
- #endif /* not lint */
- 
-+#include <sys/types.h>
- #include <signal.h>
-+#include <malloc.h>
- #include <unistd.h>
- 
- /*
-@@ -101,6 +103,8 @@
- STATIC void evalpipe __P((union node *));
- STATIC void evalcommand __P((union node *, int, struct backcmd *));
- STATIC void prehash __P((union node *));
-+STATIC int is_assignment_builtin __P((const char *));
-+STATIC const char *get_standard_path __P((void));
- 
- 
- /*
-@@ -257,6 +261,11 @@
- 		evalcase(n, flags);
- 		break;
- 	case NDEFUN:
-+		if (is_special_builtin(n->narg.text)) {
-+			outfmt(out2, "%s is a special built-in\n", n->narg.text);
-+			exitstatus = 1;
-+			break;
-+		}
- 		defun(n->narg.text, n->narg.next);
- 		exitstatus = 0;
- 		break;
-@@ -442,6 +451,7 @@
- 		case NFROM:
- 		case NTO:
- 		case NAPPEND:
-+		case NTOOV:
- 			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
- 			redir->nfile.expfname = fn.list->text;
- 			break;
-@@ -497,9 +507,14 @@
- 				close(0);
- 				copyfd(prevfd, 0);
- 				close(prevfd);
-+				if (pip[0] == 0) {
-+					pip[0] = -1;
-+				}
- 			}
- 			if (pip[1] >= 0) {
--				close(pip[0]);
-+				if (pip[0] >= 0) {
-+					close(pip[0]);
-+				}
- 				if (pip[1] != 1) {
- 					close(1);
- 					copyfd(pip[1], 1);
-@@ -607,6 +622,7 @@
- 	int argc;
- 	char **envp;
- 	int varflag;
-+	int pseudovarflag;
- 	struct strlist *sp;
- 	int mode;
- 	int pip[2];
-@@ -619,12 +635,17 @@
- 	struct localvar *volatile savelocalvars;
- 	volatile int e;
- 	char *lastarg;
-+	int not_special;
-+	const char *path;
-+	const char *standard_path;
- #if __GNUC__
- 	/* Avoid longjmp clobbering */
- 	(void) &argv;
- 	(void) &argc;
- 	(void) &lastarg;
- 	(void) &flags;
-+	(void) &not_special;
-+	(void) &standard_path;
- #endif
- 
- 	/* First expand the arguments. */
-@@ -632,21 +653,31 @@
- 	setstackmark(&smark);
- 	arglist.lastp = &arglist.list;
- 	varlist.lastp = &varlist.list;
-+	arglist.list = 0;
- 	varflag = 1;
-+	pseudovarflag = 0;
- 	oexitstatus = exitstatus;
- 	exitstatus = 0;
-+	not_special = 0;
-+	path = pathval();
-+	standard_path = NULL;
- 	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
- 		char *p = argp->narg.text;
--		if (varflag && is_name(*p)) {
-+		if ((varflag || pseudovarflag) && is_name(*p)) {
- 			do {
- 				p++;
- 			} while (is_in_name(*p));
- 			if (*p == '=') {
--				expandarg(argp, &varlist, EXP_VARTILDE);
-+				if (varflag)
-+					expandarg(argp, &varlist, EXP_VARTILDE);
-+				else
-+					expandarg(argp, &arglist, EXP_VARTILDE);
- 				continue;
- 			}
- 		}
- 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
-+		if (varflag && arglist.list && is_assignment_builtin(arglist.list->text))
-+			pseudovarflag = 1;
- 		varflag = 0;
- 	}
- 	*arglist.lastp = NULL;
-@@ -688,37 +719,75 @@
- 		cmdentry.u.index = BLTINCMD;
- 	} else {
- 		static const char PATH[] = "PATH=";
--		const char *path = pathval();
-+		const char *oldpath = NULL;
-+		int findflag = DO_ERR;
- 
- 		/*
- 		 * 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)
-+			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
- 				path = sp->text + sizeof(PATH) - 1;
--
--		find_command(argv[0], &cmdentry, DO_ERR, path);
--		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
--			exitstatus = 127;
--			flushout(&errout);
--			return;
--		}
--		/* implement the bltin builtin here */
--		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
--			for (;;) {
-+				findflag |= DO_BRUTE;
-+			}
-+		for(;;) {
-+			find_command(argv[0], &cmdentry, findflag, path);
-+			if (oldpath) {
-+				path = oldpath;
-+				oldpath = NULL;
-+			}
-+			if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
-+				exitstatus = 127;
-+				flushout(&errout);
-+				goto out;
-+			}
-+			/* implement the bltin builtin here */
-+			if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
-+				not_special = 1;
-+				for(;;) {
-+					argv++;
-+					if (--argc == 0)
-+						break;
-+					if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
-+						outfmt(&errout, "%s: not found\n", *argv);
-+						exitstatus = 127;
-+						flushout(&errout);
-+						goto out;
-+					}
-+					if (cmdentry.u.index != BLTINCMD)
-+						break;
-+				}
-+			}
-+			if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == COMMANDCMD) {
-+				not_special = 1;
- 				argv++;
--				if (--argc == 0)
--					break;
--				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
--					outfmt(&errout, "%s: not found\n", *argv);
--					exitstatus = 127;
--					flushout(&errout);
--					return;
-+				if (--argc == 0) {
-+					exitstatus = 0;
-+					goto out;
- 				}
--				if (cmdentry.u.index != BLTINCMD)
--					break;
-+				if (*argv[0] == '-') {
-+					if (!equal(argv[0], "-p")) {
-+						argv--;
-+						argc++;
-+						break;
-+					}
-+					argv++;
-+					if (--argc == 0) {
-+						exitstatus = 0;
-+						goto out;
-+					}
-+					if (!standard_path) {
-+						standard_path = get_standard_path();
-+					}
-+					oldpath = path;
-+					path = standard_path;
-+					findflag |= DO_BRUTE;
-+				}
-+				findflag |= DO_NOFUN;
-+				continue;
- 			}
-+			break;
- 		}
- 	}
- 
-@@ -756,13 +825,12 @@
- #ifdef DEBUG
- 		trputs("Shell function:  ");  trargs(argv);
- #endif
-+		exitstatus = oexitstatus;
- 		redirect(cmd->ncmd.redirect, REDIR_PUSH);
- 		saveparam = shellparam;
- 		shellparam.malloc = 0;
--		shellparam.reset = 1;
- 		shellparam.nparam = argc - 1;
- 		shellparam.p = argv + 1;
--		shellparam.optnext = NULL;
- 		INTOFF;
- 		savelocalvars = localvars;
- 		localvars = NULL;
-@@ -772,6 +840,8 @@
- 				freeparam((volatile struct shparam *)
- 				    &saveparam);
- 			} else {
-+				saveparam.optind = shellparam.optind;
-+				saveparam.optoff = shellparam.optoff;
- 				freeparam(&shellparam);
- 				shellparam = saveparam;
- 			}
-@@ -790,6 +860,8 @@
- 		INTOFF;
- 		poplocalvars();
- 		localvars = savelocalvars;
-+		saveparam.optind = shellparam.optind;
-+		saveparam.optoff = shellparam.optoff;
- 		freeparam(&shellparam);
- 		shellparam = saveparam;
- 		handler = savehandler;
-@@ -807,9 +879,13 @@
- #endif
- 		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
- 		if (flags == EV_BACKCMD) {
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+			openmemout();
-+#else
- 			memout.nleft = 0;
- 			memout.nextc = memout.buf;
- 			memout.bufsize = 64;
-+#endif
- 			mode |= REDIR_BACKQ;
- 		}
- 		redirect(cmd->ncmd.redirect, mode);
-@@ -832,6 +908,8 @@
- 		out1 = &output;
- 		out2 = &errout;
- 		freestdout();
-+		if (!not_special && is_special_builtin(commandname))
-+			listsetvar(cmdenviron);
- 		cmdenviron = NULL;
- 		if (e != EXSHELLPROC) {
- 			commandname = savecmdname;
-@@ -854,10 +932,18 @@
- 		if (cmdentry.u.index != EXECCMD)
- 			popredir();
- 		if (flags == EV_BACKCMD) {
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+			closememout();
-+#endif
- 			backcmd->buf = memout.buf;
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+			backcmd->nleft = memout.bufsize;
-+#else
- 			backcmd->nleft = memout.nextc - memout.buf;
-+#endif
- 			memout.buf = NULL;
- 		}
-+		cmdenviron = NULL;
- 	} else {
- #ifdef DEBUG
- 		trputs("normal command:  ");  trargs(argv);
-@@ -867,7 +953,7 @@
- 		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);
- 	}
- 	goto out;
- 
-@@ -1026,3 +1112,48 @@
- 	}
- 	return 0;
- }
-+
-+STATIC int
-+is_assignment_builtin (command)
-+	const char *command;
-+{
-+	static const char *assignment_builtins[] = {
-+		"alias", "declare", "export", "local", "readonly", "typeset",
-+		(char *)NULL
-+	};
-+	int i;
-+
-+	for (i = 0; assignment_builtins[i]; i++)
-+		if (strcmp(command, assignment_builtins[i]) == 0) return 1;
-+	return 0;
-+}
-+
-+int
-+is_special_builtin(name)
-+	const char *name;
-+{
-+	static const char *special_builtins[] = {
-+		"break", ":", ".", "continue", "eval", "exec", "exit",
-+		"export", "readonly", "return", "set", "shift", "times",
-+		"trap", "unset", (char *)NULL
-+	};
-+	int i;
-+
-+	if (!name) return 0;
-+	for (i = 0; special_builtins[i]; i++)
-+		if (equal(name, special_builtins[i])) return 1;
-+	return 0;
-+}
-+
-+STATIC const char *
-+get_standard_path()
-+{
-+	char *p;
-+	size_t len;
-+
-+	len = confstr(_CS_PATH, NULL, 0);
-+	p = stalloc(len + 2);
-+	*p = '\0';
-+	confstr(_CS_PATH, p, len);
-+	return p;
-+}
-diff -Nur ash-0.4.0.orig/eval.h ash-0.4.0.fixed/eval.h
---- ash-0.4.0.orig/eval.h	2000-01-28 06:03:00.000000000 -0600
-+++ ash-0.4.0.fixed/eval.h	2003-10-01 21:08:15.000000000 -0500
-@@ -61,6 +61,7 @@
- int falsecmd __P((int, char **));
- int truecmd __P((int, char **));
- int execcmd __P((int, char **));
-+int is_special_builtin __P((const char *));
- 
- /* in_function returns nonzero if we are currently evaluating a function */
- #define in_function()	funcnest
-diff -Nur ash-0.4.0.orig/exec.c ash-0.4.0.fixed/exec.c
---- ash-0.4.0.orig/exec.c	2001-01-12 10:50:35.000000000 -0600
-+++ ash-0.4.0.fixed/exec.c	2003-10-01 21:08:15.000000000 -0500
-@@ -51,6 +51,7 @@
- #include <fcntl.h>
- #include <errno.h>
- #include <stdlib.h>
-+#include <sysexits.h>
- 
- /*
-  * When commands are first encountered, they are entered in a hash table.
-@@ -108,6 +109,9 @@
- STATIC void clearcmdentry __P((int));
- STATIC struct tblentry *cmdlookup __P((char *, int));
- STATIC void delete_cmd_entry __P((void));
-+STATIC int describe_command __P((char *, int));
-+STATIC int path_change __P((const char *, int *));
-+STATIC int is_regular_builtin __P((const char *));
- 
- 
- 
-@@ -125,6 +129,10 @@
- 	char *cmdname;
- 	int e;
- 
-+	if (fd2 >= 0 && fd2 != 2) {
-+		close(fd2);
-+	}
-+
- 	if (strchr(argv[0], '/') != NULL) {
- 		tryexec(argv[0], argv, envp);
- 		e = errno;
-@@ -164,7 +172,7 @@
- 	char **envp;
- 	{
- 	int e;
--#ifndef BSD
-+#if !defined(BSD) && !defined(linux)
- 	char *p;
- #endif
- 
-@@ -180,7 +188,7 @@
- 		initshellproc();
- 		setinputfile(cmd, 0);
- 		commandname = arg0 = savestr(argv[0]);
--#ifndef BSD
-+#if !defined(BSD) && !defined(linux)
- 		pgetc(); pungetc();		/* fill up input buffer */
- 		p = parsenextc;
- 		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
-@@ -195,7 +203,7 @@
- }
- 
- 
--#ifndef BSD
-+#if !defined(BSD) && !defined(linux)
- /*
-  * Execute an interpreter introduced by "#!", for systems where this
-  * feature has not been built into the kernel.  If the interpreter is
-@@ -351,27 +359,29 @@
- 	if (*argptr == NULL) {
- 		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
- 			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
--				printentry(cmdp, verbose);
-+				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 */
--				cmdp = cmdlookup(name, 0);
--				printentry(cmdp, verbose);
--			}
-+		if (entry.cmdtype == CMDUNKNOWN) c = 1;
-+		else if (verbose) {
-+			cmdp = cmdlookup(name, 0);
-+			if (cmdp) printentry(cmdp, verbose);
- 			flushall();
- 		}
- 		argptr++;
- 	}
--	return 0;
-+	return c;
- }
- 
- 
-@@ -435,6 +445,10 @@
- 	struct stat statb;
- 	int e;
- 	int i;
-+	int bltin;
-+	int firstchange;
-+	int updatetbl;
-+	int regular;
- 
- 	/* If name contains a slash, don't use the hash table */
- 	if (strchr(name, '/') != NULL) {
-@@ -459,12 +473,54 @@
- 		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)
--		goto success;
-+	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;
-+		}
-+	}
-+
-+	if ((regular = is_regular_builtin(name))) {
-+		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 ((bltin < 0 || regular) && (i = find_builtin(name)) >= 0) {
-+		if (!updatetbl) {
-+			entry->cmdtype = CMDBUILTIN;
-+			entry->u.index = i;
-+			return;
-+		}
- 		INTOFF;
- 		cmdp = cmdlookup(name, 1);
- 		cmdp->cmdtype = CMDBUILTIN;
-@@ -475,7 +531,7 @@
- 
- 	/* 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
-@@ -488,26 +544,38 @@
- 	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 ((i = find_builtin(name)) >= 0) {
-+					if (!updatetbl) {
-+						entry->cmdtype = CMDBUILTIN;
-+						entry->u.index = i;
-+						return;
-+					}
-+					INTOFF;
-+					cmdp = cmdlookup(name, 1);
-+					cmdp->cmdtype = CMDBUILTIN;
-+					cmdp->param.index = i;
-+					INTON;
-+					goto success;
-+				} else {
-+					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;
- 		}
-@@ -522,7 +590,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);
-@@ -544,6 +612,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;
-@@ -553,7 +628,7 @@
- 	}
- 
- 	/* 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));
-@@ -618,37 +693,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;
- }
-@@ -838,11 +888,9 @@
- 	{
- 	struct cmdentry entry;
- 
--	INTOFF;
- 	entry.cmdtype = CMDFUNCTION;
- 	entry.u.func = copyfunc(func);
- 	addcmdentry(name, &entry);
--	INTON;
- }
- 
- 
-@@ -945,3 +993,189 @@
- 	}
- 	return err;
- }
-+
-+STATIC int
-+describe_command(command, verbose)
-+	char *command;
-+	int verbose;
-+{
-+	struct cmdentry entry;
-+	struct tblentry *cmdp;
-+	char **pp;
-+	struct alias *ap;
-+	extern char *const parsekwd[];
-+
-+	for (pp = (char **)parsekwd; *pp; pp++)
-+		if (**pp == *command && equal(*pp, command))
-+			break;
-+
-+	if (*pp) {
-+		if (verbose) {
-+			out1fmt("%s is a reserved word\n", command);
-+		} else {
-+			out1fmt("%s\n", command);
-+		}
-+		return 0;
-+	}
-+
-+	/* Then look at the aliases */
-+	if ((ap = lookupalias(command, 1)) != NULL) {
-+		if (verbose) {
-+			out1fmt("%s is aliased to `%s'\n", command, ap->val);
-+		} else {
-+			out1fmt("alias %s='%s'\n", command, ap->val);
-+		}
-+		return 0;
-+	}
-+
-+	/* Then check if it is a tracked alias */
-+	if ((cmdp = cmdlookup(command, 0)) != NULL) {
-+		entry.cmdtype = cmdp->cmdtype;
-+		entry.u = cmdp->param;
-+	}
-+	else {
-+		/* Finally use brute force */
-+		find_command(command, &entry, DO_ABS, pathval());
-+	}
-+
-+	switch (entry.cmdtype) {
-+	case CMDNORMAL: {
-+		int j = entry.u.index;
-+		const char *path = pathval();
-+		char *name;
-+		if (j == -1) 
-+			name = command;
-+		else {
-+			do { 
-+				name = padvance(&path, command);
-+				stunalloc(name);
-+			} while (--j >= 0);
-+		}
-+		if (verbose) {
-+			out1fmt("%s is %s\n", command, name);
-+		} else {
-+			out1fmt("%s\n", name);
-+		}
-+		break;
-+	}
-+	case CMDFUNCTION:
-+		if (verbose) {
-+			out1fmt("%s is a function\n", command);
-+		} else {
-+			out1fmt("%s\n", command);
-+		}
-+		break;
-+	case CMDBUILTIN:
-+		if (verbose) {
-+			if (is_special_builtin(command)) {
-+				out1fmt("%s is a special built-in utility\n", command);
-+			} else {
-+				out1fmt("%s is a built-in utility\n", command);
-+			}
-+		} else {
-+			out1fmt("%s\n", command);
-+		}
-+		break;
-+	default:
-+		outfmt(out2, "%s not found\n", command);
-+		return 127;
-+	}
-+
-+	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;
-+	}
-+
-+	if (verify_only || verbose_verify_only) {
-+		return describe_command(*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;
-+}
-+
-+STATIC int
-+is_regular_builtin(name)
-+        const char *name;
-+{
-+        static const char *regular_builtins[] = {
-+        	"alias", "bg", "cd", "command", "false", "fc", "fg",
-+        	"getopts", "jobs", "kill", "newgrp", "read", "true",
-+        	"umask", "unalias", "wait", (char *)NULL
-+        };
-+        int i;
-+
-+        if (!name) return 0;
-+        for (i = 0; regular_builtins[i]; i++)
-+                if (equal(name, regular_builtins[i])) return 1;
-+        return 0;
-+}
-diff -Nur ash-0.4.0.orig/exec.h ash-0.4.0.fixed/exec.h
---- ash-0.4.0.orig/exec.h	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/exec.h	2003-10-01 21:08:15.000000000 -0500
-@@ -56,6 +56,8 @@
- 
- #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 */
-@@ -74,3 +76,4 @@
- void defun __P((char *, union node *));
- int unsetfunc __P((char *));
- int typecmd __P((int, char **));
-+int commandcmd __P((int, char **));
-diff -Nur ash-0.4.0.orig/expand.c ash-0.4.0.fixed/expand.c
---- ash-0.4.0.orig/expand.c	2000-03-14 06:03:45.000000000 -0600
-+++ ash-0.4.0.fixed/expand.c	2003-10-01 21:08:15.000000000 -0500
-@@ -54,6 +54,10 @@
- #include <pwd.h>
- #include <stdlib.h>
- #include <stdio.h>
-+#if defined(__GLIBC__) && !defined(GLOB_BROKEN)
-+#include <fnmatch.h>
-+#include <glob.h>
-+#endif
- 
- /*
-  * Routines to expand arguments to commands.  We have to deal with
-@@ -102,17 +106,30 @@
- STATIC int subevalvar __P((char *, char *, int, int, int, int));
- STATIC char *evalvar __P((char *, int));
- STATIC int varisset __P((char *, int));
-+STATIC char *strtodest __P((char *, int, 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(GLOB_BROKEN)
-+STATIC const char *preglob __P((const char *));
-+STATIC void addglob __P((const glob_t *));
-+#else
- STATIC void expmeta __P((char *, char *));
-+#endif
- STATIC void addfname __P((char *));
-+#if defined(__GLIBC__) && !defined(GLOB_BROKEN)
-+STATIC int patmatch __P((char *, char *, int));
-+STATIC int patmatch2 __P((char *, char *, int));
-+STATIC char * _rmescapes __P((char *, int));
-+#else
- STATIC struct strlist *expsort __P((struct strlist *));
- STATIC struct strlist *msort __P((struct strlist *, int));
- STATIC int pmatch __P((char *, char *, int));
-+#define patmatch2 patmatch
-+#endif
- STATIC char *cvtnum __P((int, char *));
- 
- /*
-@@ -371,7 +388,7 @@
- 	 * have to rescan starting from the beginning since CTLESC
- 	 * characters have to be processed left to right.
- 	 */
--	CHECKSTRSPACE(8, expdest);
-+	CHECKSTRSPACE(10, expdest);
- 	USTPUTC('\0', expdest);
- 	start = stackblock();
- 	p = expdest - 1;
-@@ -393,7 +410,7 @@
- 	if (quotes)
- 		rmescapes(p+2);
- 	result = arith(p+2);
--	fmtstr(p, 10, "%d", result);
-+	fmtstr(p, 12, "%d", result);
- 
- 	while (*p++)
- 		;
-@@ -503,7 +520,7 @@
- 	int amount;
- 
- 	herefd = -1;
--	argstr(p, 0);
-+	argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
- 	STACKSTRNUL(expdest);
- 	herefd = saveherefd;
- 	argbackq = saveargbackq;
-@@ -535,7 +552,7 @@
- 		for (loc = startp; loc < str; loc++) {
- 			c = *loc;
- 			*loc = '\0';
--			if (patmatch(str, startp, varflags & VSQUOTE))
-+			if (patmatch2(str, startp, varflags & VSQUOTE))
- 				goto recordleft;
- 			*loc = c;
- 			if ((varflags & VSQUOTE) && *loc == CTLESC)
-@@ -547,7 +564,7 @@
- 		for (loc = str - 1; loc >= startp;) {
- 			c = *loc;
- 			*loc = '\0';
--			if (patmatch(str, startp, varflags & VSQUOTE))
-+			if (patmatch2(str, startp, varflags & VSQUOTE))
- 				goto recordleft;
- 			*loc = c;
- 			loc--;
-@@ -564,7 +581,7 @@
- 
- 	case VSTRIMRIGHT:
- 	        for (loc = str - 1; loc >= startp;) {
--			if (patmatch(str, loc, varflags & VSQUOTE))
-+			if (patmatch2(str, loc, varflags & VSQUOTE))
- 				goto recordright;
- 			loc--;
- 			if ((varflags & VSQUOTE) && loc > startp &&
-@@ -580,7 +597,7 @@
- 
- 	case VSTRIMRIGHTMAX:
- 		for (loc = startp; loc < str - 1; loc++) {
--			if (patmatch(str, loc, varflags & VSQUOTE))
-+			if (patmatch2(str, loc, varflags & VSQUOTE))
- 				goto recordright;
- 			if ((varflags & VSQUOTE) && *loc == CTLESC)
- 			        loc++;
-@@ -819,6 +836,34 @@
- 
- 
- /*
-+ * Put a string on the stack.
-+ */
-+
-+STATIC char *
-+strtodest(p, quoted, allow_split)
-+	char *p;
-+	int quoted;
-+	int allow_split;
-+{
-+	char const *syntax;
-+
-+	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);
-+
-+	return p;
-+}
-+
-+
-+
-+/*
-  * Add the value of a specialized variable to the stack string.
-  */
- 
-@@ -834,22 +879,6 @@
- 	extern int oexitstatus;
- 	char sep;
- 	char **ap;
--	char const *syntax;
--
--#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)
--
- 
- 	switch (*name) {
- 	case '$':
-@@ -875,7 +904,7 @@
- 	case '@':
- 		if (allow_split && quoted) {
- 			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
--				STRTODEST(p);
-+				p = strtodest(p, quoted, allow_split);
- 				if (*ap)
- 					STPUTC('\0', expdest);
- 			}
-@@ -888,21 +917,20 @@
- 		else
- 			sep = ' ';
- 		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
--			STRTODEST(p);
-+			p = strtodest(p, quoted, allow_split);
- 			if (*ap && sep)
- 				STPUTC(sep, expdest);
- 		}
- 		break;
- 	case '0':
--		p = arg0;
--		STRTODEST(p);
-+		p = strtodest(arg0, quoted, allow_split);
- 		break;
- 	default:
- 		if (is_digit(*name)) {
- 			num = atoi(name);
- 			if (num > 0 && num <= shellparam.nparam) {
--				p = shellparam.p[num - 1];
--				STRTODEST(p);
-+				p = strtodest(shellparam.p[num - 1], quoted,
-+					      allow_split);
- 			}
- 		}
- 		break;
-@@ -1054,6 +1082,98 @@
-  * should be escapes.  The results are stored in the list exparg.
-  */
- 
-+#if defined(__GLIBC__) && !defined(GLOB_BROKEN)
-+STATIC void
-+expandmeta(str, flag)
-+	struct strlist *str;
-+	int flag;
-+{
-+	const char *p;
-+	glob_t pglob;
-+	/* TODO - EXP_REDIR */
-+
-+	while (str) {
-+		if (fflag)
-+			goto nometa;
-+		p = preglob(str->text);
-+		INTOFF;
-+		switch (glob(p, GLOB_NOMAGIC, 0, &pglob)) {
-+		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;
-+	}
-+}
-+
-+
-+/*
-+ * Prepare the string for glob(3).
-+ */
-+
-+STATIC const char *
-+preglob(str)
-+	const char *str;
-+{
-+	const char *p;
-+	char *q, *r;
-+	size_t len;
-+
-+	p = str;
-+	while (*p != CTLQUOTEMARK && *p != CTLESC) {
-+		if (*p++ == '\0')
-+			return str;
-+	}
-+	len = p - str;
-+	q = r = stalloc(strlen(str) + 1);
-+	if (len > 0) {
-+		memcpy(q, str, len);
-+		q += len;
-+	}
-+	do {
-+		if (*p == CTLQUOTEMARK)
-+			continue;
-+		if (*p == CTLESC) {
-+			if (*++p != '/')
-+				*q++ = '\\';
-+		}
-+		*q++ = *p;
-+	} while (*++p);
-+	*q = '\0';
-+	return r;
-+}
-+
-+
-+/*
-+ * 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
- char *expdir;
- 
- 
-@@ -1238,6 +1358,7 @@
- 	if (! atend)
- 		endname[-1] = '/';
- }
-+#endif
- 
- 
- /*
-@@ -1260,6 +1381,7 @@
- }
- 
- 
-+#if !(defined(__GLIBC__) && !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
-@@ -1321,6 +1443,7 @@
- 	}
- 	return list;
- }
-+#endif
- 
- 
- 
-@@ -1328,6 +1451,39 @@
-  * Returns true if the pattern matches the string.
-  */
- 
-+#if defined(__GLIBC__) && !defined(GLOB_BROKEN)
-+STATIC int
-+patmatch(pattern, string, squoted)
-+	char *pattern;
-+	char *string;
-+	int squoted;	/* string might have quote chars */
-+	{
-+	const char *p;
-+	char *q;
-+
-+	p = preglob(pattern);
-+	q = squoted ? _rmescapes(string, 1) : string;
-+
-+	return !fnmatch(p, q, 0);
-+}
-+
-+
-+STATIC int
-+patmatch2(pattern, string, squoted)
-+	char *pattern;
-+	char *string;
-+	int squoted;	/* string might have quote chars */
-+	{
-+	char *p;
-+	int res;
-+
-+	sstrnleft--;
-+	p = grabstackstr(expdest);
-+	res = patmatch(pattern, string, squoted);
-+	ungrabstackstr(p, expdest);
-+	return res;
-+}
-+#else
- int
- patmatch(pattern, string, squoted)
- 	char *pattern;
-@@ -1462,6 +1618,7 @@
- 		return 0;
- 	return 1;
- }
-+#endif
- 
- 
- 
-@@ -1469,6 +1626,50 @@
-  * Remove any CTLESC characters from a string.
-  */
- 
-+#if defined(__GLIBC__) && !defined(GLOB_BROKEN)
-+void
-+rmescapes(str)
-+	char *str;
-+{
-+	_rmescapes(str, 0);
-+}
-+
-+
-+STATIC char *
-+_rmescapes(str, flag)
-+	char *str;
-+	int flag;
-+{
-+	char *p, *q, *r;
-+
-+	p = str;
-+	while (*p != CTLESC && *p != CTLQUOTEMARK) {
-+		if (*p++ == '\0')
-+			return str;
-+	}
-+	q = p;
-+	r = str;
-+	if (flag) {
-+		size_t len = p - str;
-+		q = r = stalloc(strlen(p) + len + 1);
-+		if (len > 0) {
-+			memcpy(q, str, len);
-+			q += len;
-+		}
-+	}
-+	while (*p) {
-+		if (*p == CTLQUOTEMARK) {
-+			p++;
-+			continue;
-+		}
-+		if (*p == CTLESC)
-+			p++;
-+		*q++ = *p++;
-+	}
-+	*q = '\0';
-+	return r;
-+}
-+#else
- void
- rmescapes(str)
- 	char *str;
-@@ -1492,6 +1693,7 @@
- 	}
- 	*q = '\0';
- }
-+#endif
- 
- 
- 
-diff -Nur ash-0.4.0.orig/expand.h ash-0.4.0.fixed/expand.h
---- ash-0.4.0.orig/expand.h	1999-07-09 06:02:06.000000000 -0500
-+++ ash-0.4.0.fixed/expand.h	2003-10-01 21:08:15.000000000 -0500
-@@ -64,7 +64,9 @@
- void expandhere __P((union node *, int));
- void expandarg __P((union node *, struct arglist *, int));
- void expari __P((int));
-+#if !(defined(__GLIBC__) && !defined(GLOB_BROKEN))
- int patmatch __P((char *, char *, int));
-+#endif
- void rmescapes __P((char *));
- int casematch __P((union node *, char *));
- 
-diff -Nur ash-0.4.0.orig/hetio.c ash-0.4.0.fixed/hetio.c
---- ash-0.4.0.orig/hetio.c	1969-12-31 18:00:00.000000000 -0600
-+++ ash-0.4.0.fixed/hetio.c	2003-10-01 21:08:15.000000000 -0500
-@@ -0,0 +1,377 @@
-+/*
-+ * Termios command line History and Editting for NetBSD sh (ash)
-+ * Copyright (c) 1999
-+ *	Main code:	Adam Rogoyski <rogoyski at cs.utexas.edu> 
-+ *	Etc:		Dave Cinege <dcinege at 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. 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"
-+
-+#ifdef HETIO
-+
-+#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(&output);
-+}
-+
-+
-+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(&output);
-+}
-+
-+
-+void input_end(int *cursor, int len)
-+{
-+	while (*cursor < len) {
-+		out1str("\033[C");
-+		++*cursor;
-+	}
-+	flushout(&output);
-+}
-+
-+
-+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(&output);
-+	}
-+}
-+
-+int hetio_read_input(int fd)
-+{
-+	int nr = 0;
-+
-+	if (!hetio_inter) {		/* Are we an interactive shell? */
-+		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 */
-+#ifndef CTRL_D_DELETE
-+					return 0;
-+#else
-+					if (cursor != len) {
-+						input_delete(cursor);
-+						len--;
-+					}
-+					break;
-+#endif
-+				case '\b':	/* Backspace */
-+				case DEL:
-+					input_backspace(&cursor, &len);
-+					break;
-+				case '\n':	/* Enter */
-+					*(parsenextc + len++ + 1) = c;
-+					out1c(c);
-+					flushout(&output);
-+					break_out = 1;
-+					break;
-+				case ESC:	/* escape sequence follows */
-+					if ((ret = read(fd, &c, 1)) < 1)
-+						return ret;
-+										
-+					if (c == '[' || c == 'O' ) {    /* 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 = len; j > 0; j--)		/* return to begining of line */
-+									out1c('\b');
-+
-+								strcpy (parsenextc, hp->s);		/* write new command */
-+								len = strlen (hp->s);
-+								out1str(parsenextc);
-+								flushout(&output);
-+								cursor = len;
-+								break;
-+							case 'C':		/* Right */
-+      								if (cursor < len) {
-+									out1str("\033[C");
-+									cursor++;
-+									flushout(&output);
-+						 		}
-+								break;
-+							case 'D':		/* Left */
-+								if (cursor > 0) {
-+									out1str("\033[D");
-+									cursor--;
-+									flushout(&output);
-+								}
-+								break;
-+							case '3':		/* Delete */
-+								if (cursor != len) {
-+									input_delete(cursor);
-+									len--;
-+								}
-+								break;								
-+							case 'H':		/* Home (xterm) */
-+							case '1':		/* Home (Ctrl-A) */
-+      								input_home(&cursor);
-+								break;
-+							case 'F':		/* End (xterm_ */
-+							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 (~) */
-+					}
-+			
-+					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(&output);
-+					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;
-+}
-+#endif
-diff -Nur ash-0.4.0.orig/hetio.h ash-0.4.0.fixed/hetio.h
---- ash-0.4.0.orig/hetio.h	1969-12-31 18:00:00.000000000 -0600
-+++ ash-0.4.0.fixed/hetio.h	2003-10-01 21:08:15.000000000 -0500
-@@ -0,0 +1,22 @@
-+/*
-+ * Termios command line History and Editting for NetBSD sh (ash)
-+ * Copyright (c) 1999
-+ *	Main code:	Adam Rogoyski <rogoyski at cs.utexas.edu> 
-+ *	Etc:		Dave Cinege <dcinege at 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 -Nur ash-0.4.0.orig/histedit.c ash-0.4.0.fixed/histedit.c
---- ash-0.4.0.orig/histedit.c	2001-01-12 10:50:35.000000000 -0600
-+++ ash-0.4.0.fixed/histedit.c	2003-10-01 21:08:15.000000000 -0500
-@@ -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 = 1;
-+#else
- 	optreset = 1; optind = 1; /* initialize getopt */
-+#endif
- 	while (not_fcnumber(argv[optind]) &&
- 	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
- 		switch ((char)ch) {
-diff -Nur ash-0.4.0.orig/input.c ash-0.4.0.fixed/input.c
---- ash-0.4.0.orig/input.c	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/input.c	2003-10-01 21:08:15.000000000 -0500
-@@ -66,7 +66,13 @@
- #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 */
- 
-@@ -108,7 +114,9 @@
- 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));
-@@ -198,6 +206,11 @@
- 		}
- 	} else
- #endif
-+
-+#ifdef HETIO
-+		nr = hetio_read_input(parsefile->fd);
-+		if (nr == -255)
-+#endif
- 		nr = read(parsefile->fd, buf, BUFSIZ - 1);
- 
- 
-diff -Nur ash-0.4.0.orig/jobs.c ash-0.4.0.fixed/jobs.c
---- ash-0.4.0.orig/jobs.c	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/jobs.c	2003-10-01 21:08:15.000000000 -0500
-@@ -92,6 +92,7 @@
- int initialpgrp;		/* pgrp of shell on invocation */
- short curjob;			/* current job */
- #endif
-+STATIC int intreceived;
- 
- STATIC void restartjob __P((struct job *));
- STATIC void freejob __P((struct job *));
-@@ -101,8 +102,10 @@
- STATIC int waitproc __P((int, int *));
- STATIC void cmdtxt __P((union node *));
- STATIC void cmdputs __P((const char *));
-+STATIC void waitonint(int);
- 
- 
-+#if JOBS
- /*
-  * Turn job control on and off.
-  *
-@@ -126,9 +129,9 @@
- 	if (on) {
- 		do { /* while we are in the background */
- #ifdef OLD_TTY_DRIVER
--			if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
-+			if (ioctl(fd2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
- #else
--			initialpgrp = tcgetpgrp(2);
-+			initialpgrp = tcgetpgrp(fd2);
- 			if (initialpgrp < 0) {
- #endif
- 				out2str("sh: can't access tty; job control turned off\n");
-@@ -143,7 +146,7 @@
- 			}
- 		} while (0);
- #ifdef OLD_TTY_DRIVER
--		if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
-+		if (ioctl(fd2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
- 			out2str("sh: need new tty driver to run job control; job control turned off\n");
- 			mflag = 0;
- 			return;
-@@ -154,16 +157,16 @@
- 		setsignal(SIGTTIN);
- 		setpgid(0, rootpid);
- #ifdef OLD_TTY_DRIVER
--		ioctl(2, TIOCSPGRP, (char *)&rootpid);
-+		ioctl(fd2, TIOCSPGRP, (char *)&rootpid);
- #else
--		tcsetpgrp(2, rootpid);
-+		tcsetpgrp(fd2, rootpid);
- #endif
- 	} else { /* turning job control off */
- 		setpgid(0, initialpgrp);
- #ifdef OLD_TTY_DRIVER
--		ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
-+		ioctl(fd2, TIOCSPGRP, (char *)&initialpgrp);
- #else
--		tcsetpgrp(2, initialpgrp);
-+		tcsetpgrp(fd2, initialpgrp);
- #endif
- 		setsignal(SIGTSTP);
- 		setsignal(SIGTTOU);
-@@ -171,6 +174,7 @@
- 	}
- 	jobctl = on;
- }
-+#endif
- 
- 
- #ifdef mkinit
-@@ -189,6 +193,94 @@
- 
- #if JOBS
- 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) {
-+		error(
-+"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
-+"kill -l [exitstatus]"
-+		);
-+	}
-+
-+	if (*argv[1] == '-') {
-+		signo = decode_signal(argv[1]+1);
-+		if (signo < 0) {
-+			int c;
-+
-+			while ((c = nextopt("ls:")) != '\0')
-+				switch (c) {
-+				case 'l':
-+					list = 1;
-+					break;
-+				case 's':
-+					signo = decode_signal(optarg);
-+		                        break;
-+				default:
-+					error(
-+	"nextopt returned character code 0%o", c);
-+			}
-+		} else
-+			argptr++;
-+	}
-+
-+	if (!list && signo < 0)
-+		signo = SIGTERM;
-+
-+	if ((signo < 0 || !*argptr) ^ list) {
-+		error(
-+"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
-+"kill -l [exitstatus]"
-+		);
-+	}
-+
-+	if (list) {
-+		if (!*argptr) {
-+			out1fmt("0\n");
-+			for (i = 1; i < NSIG; i++) {
-+				if (strncmp(signal_names[i], "SIGJUNK(", 8)
-+				    == 0)
-+					continue;
-+				out1fmt("%s\n", signal_names[i] + 3);
-+			}
-+			return 0;
-+		}
-+		signo = atoi(*argptr);
-+		if (signo > 128)
-+			signo -= 128;
-+		if (0 < signo && signo < NSIG)
-+			out1fmt("%s\n", signal_names[signo] + 3);
-+		else
-+			error("invalid signal number or exit status: %s",
-+			      *argptr);
-+		return 0;
-+	}
-+
-+	do {
-+		if (**argptr == '%') {
-+			jp = getjob(*argptr);
-+			if (jp->jobctl == 0)
-+				error("job %s not created under job control",
-+				      *argptr);
-+			pid = -jp->ps[0].pid;
-+		} else
-+			pid = atoi(*argptr);
-+		if (kill(pid, signo) != 0)
-+			error("%s: %s", *argptr, strerror(errno));
-+	} while (*++argptr);
-+
-+	return 0;
-+}
-+
-+int
- fgcmd(argc, argv)
- 	int argc;
- 	char **argv;
-@@ -202,9 +294,9 @@
- 		error("job not created under job control");
- 	pgrp = jp->ps[0].pid;
- #ifdef OLD_TTY_DRIVER
--	ioctl(2, TIOCSPGRP, (char *)&pgrp);
-+	ioctl(fd2, TIOCSPGRP, (char *)&pgrp);
- #else
--	tcsetpgrp(2, pgrp);
-+	tcsetpgrp(fd2, pgrp);
- #endif
- 	restartjob(jp);
- 	INTOFF;
-@@ -594,9 +686,6 @@
- 		TRACE(("Child shell %d\n", getpid()));
- 		wasroot = rootshell;
- 		rootshell = 0;
--		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
--			if (p->used)
--				freejob(p);
- 		closescript();
- 		INTON;
- 		clear_traps();
-@@ -611,10 +700,10 @@
- 			if (mode == FORK_FG) {
- 				/*** this causes superfluous TIOCSPGRPS ***/
- #ifdef OLD_TTY_DRIVER
--				if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
-+				if (ioctl(fd2, TIOCSPGRP, (char *)&pgrp) < 0)
- 					error("TIOCSPGRP failed, errno=%d", errno);
- #else
--				if (tcsetpgrp(2, pgrp) < 0)
-+				if (tcsetpgrp(fd2, pgrp) < 0)
- 					error("tcsetpgrp failed, errno=%d", errno);
- #endif
- 			}
-@@ -623,6 +712,7 @@
- 		} else if (mode == FORK_BG) {
- 			ignoresig(SIGINT);
- 			ignoresig(SIGQUIT);
-+			ignoresig(SIGHUP);
- 			if ((jp == NULL || jp->nprocs == 0) &&
- 			    ! fd0_redirected_p ()) {
- 				close(0);
-@@ -634,6 +724,7 @@
- 		if (mode == FORK_BG) {
- 			ignoresig(SIGINT);
- 			ignoresig(SIGQUIT);
-+			ignoresig(SIGHUP);
- 			if ((jp == NULL || jp->nprocs == 0) &&
- 			    ! fd0_redirected_p ()) {
- 				close(0);
-@@ -642,6 +733,9 @@
- 			}
- 		}
- #endif
-+		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
-+			if (p->used)
-+				freejob(p);
- 		if (wasroot && iflag) {
- 			setsignal(SIGINT);
- 			setsignal(SIGQUIT);
-@@ -701,19 +795,39 @@
- #endif
- 	int status;
- 	int st;
-+	struct sigaction act, oact;
- 
- 	INTOFF;
-+	intreceived = 0;
-+#if JOBS
-+	if (!jobctl) {
-+#else
-+	if (!iflag) {
-+#endif
-+		sigaction(SIGINT, 0, &act);
-+		act.sa_handler = waitonint;
-+		sigaction(SIGINT, &act, &oact);
-+	}
- 	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
- 	while (jp->state == 0) {
- 		dowait(1, jp);
- 	}
- #if JOBS
-+	if (!jobctl) {
-+#else
-+	if (!iflag) {
-+#endif
-+		extern char *trap[];
-+		sigaction(SIGINT, &oact, 0);
-+		if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
-+	}
-+#if JOBS
- 	if (jp->jobctl) {
- #ifdef OLD_TTY_DRIVER
--		if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
-+		if (ioctl(fd2, TIOCSPGRP, (char *)&mypgrp) < 0)
- 			error("TIOCSPGRP failed, errno=%d\n", errno);
- #else
--		if (tcsetpgrp(2, mypgrp) < 0)
-+		if (tcsetpgrp(fd2, mypgrp) < 0)
- 			error("tcsetpgrp failed, errno=%d\n", errno);
- #endif
- 	}
-@@ -896,10 +1010,10 @@
- #ifdef BSD
- 	int flags;
- 
--#if JOBS
--	flags = WUNTRACED;
--#else
- 	flags = 0;
-+#if JOBS
-+	if (jobctl)
-+		flags |= WUNTRACED;
- #endif
- 	if (block == 0)
- 		flags |= WNOHANG;
-@@ -1068,6 +1182,8 @@
- 		p = ">>";  i = 1;  goto redir;
- 	case NTOFD:
- 		p = ">&";  i = 1;  goto redir;
-+	case NTOOV:
-+		p = ">|";  i = 1;  goto redir;
- 	case NFROM:
- 		p = "<";  i = 0;  goto redir;
- 	case NFROMFD:
-@@ -1140,3 +1256,8 @@
- 	}
- 	cmdnextc = q;
- }
-+
-+STATIC void waitonint(int sig) {
-+	intreceived = 1;
-+	return;
-+}
-diff -Nur ash-0.4.0.orig/jobs.h ash-0.4.0.fixed/jobs.h
---- ash-0.4.0.orig/jobs.h	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/jobs.h	2003-10-01 21:08:15.000000000 -0500
-@@ -80,6 +80,7 @@
- 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 -Nur ash-0.4.0.orig/main.c ash-0.4.0.fixed/main.c
---- ash-0.4.0.orig/main.c	2001-01-12 10:50:36.000000000 -0600
-+++ ash-0.4.0.fixed/main.c	2003-10-01 21:08:15.000000000 -0500
-@@ -79,6 +79,10 @@
- #include "exec.h"
- #include "cd.h"
- 
-+#ifdef HETIO
-+#include "hetio.h"
-+#endif
-+
- #define PROFILE 0
- 
- int rootpid;
-@@ -111,10 +115,16 @@
- 	struct stackmark smark;
- 	volatile int state;
- 	char *shinit;
-+	int priviliged;
-+
-+	priviliged = getuid() != geteuid() || getgid() != getegid();
- 
- #if PROFILE
- 	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
- #endif
-+#if defined(linux) || defined(__GNU__)
-+	signal(SIGCHLD, SIG_DFL);
-+#endif
- 	state = 0;
- 	if (setjmp(jmploc.loc)) {
- 		/*
-@@ -181,11 +191,14 @@
- 		read_profile("/etc/profile");
- state1:
- 		state = 2;
--		read_profile(".profile");
-+		if (priviliged == 0)
-+			read_profile(".profile");
-+		else
-+			read_profile("/etc/suid_profile");
- 	}
- state2:
- 	state = 3;
--	if (getuid() == geteuid() && getgid() == getegid()) {
-+	if (iflag && !priviliged) {
- 		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
- 			state = 3;
- 			read_profile(shinit);
-@@ -239,6 +252,10 @@
- 
- 	TRACE(("cmdloop(%d) called\n", top));
- 	setstackmark(&smark);
-+#ifdef HETIO
-+	if(iflag && top)
-+		hetio_init();
-+#endif
- 	for (;;) {
- 		if (pendingsigs)
- 			dotrap();
-diff -Nur ash-0.4.0.orig/miscbltin.c ash-0.4.0.fixed/miscbltin.c
---- ash-0.4.0.orig/miscbltin.c	2001-01-12 10:50:37.000000000 -0600
-+++ ash-0.4.0.fixed/miscbltin.c	2003-10-01 21:08:15.000000000 -0500
-@@ -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
-+
- extern char **argptr;		/* argument list for builtin command */
- 
- 
-diff -Nur ash-0.4.0.orig/mksignames.c ash-0.4.0.fixed/mksignames.c
---- ash-0.4.0.orig/mksignames.c	1969-12-31 18:00:00.000000000 -0600
-+++ ash-0.4.0.fixed/mksignames.c	2003-10-01 21:08:15.000000000 -0500
-@@ -0,0 +1,400 @@
-+/* 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
-+
-+char *signal_names[2 * NSIG];
-+
-+char *progname;
-+
-+#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 < sizeof(signal_names)/sizeof(signal_names[0]); 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] = "SIGRTMIN";
-+#endif
-+
-+#if defined (SIGRTMAX)
-+  rtmax = SIGRTMAX;
-+  signal_names[rtmax] = "SIGRTMAX";
-+#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);
-+	  sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
-+	  signal_names[rtmax-i] = (char *)malloc(RTLEN);
-+	  sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
-+	}
-+
-+      if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
-+	{
-+	  /* Need an extra RTMIN signal */
-+	  signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
-+	  sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
-+	}
-+    }
-+#endif /* SIGRTMIN && SIGRTMAX */
-+
-+/* AIX */
-+#if defined (SIGLOST)	/* resource lost (eg, record-lock lost) */
-+  signal_names[SIGLOST] = "SIGLOST";
-+#endif
-+
-+#if defined (SIGMSG)	/* HFT input data pending */
-+  signal_names[SIGMSG] = "SIGMSG";
-+#endif
-+
-+#if defined (SIGDANGER)	/* system crash imminent */
-+  signal_names[SIGDANGER] = "SIGDANGER";
-+#endif
-+
-+#if defined (SIGMIGRATE) /* migrate process to another CPU */
-+  signal_names[SIGMIGRATE] = "SIGMIGRATE";
-+#endif
-+
-+#if defined (SIGPRE)	/* programming error */
-+  signal_names[SIGPRE] = "SIGPRE";
-+#endif
-+
-+#if defined (SIGVIRT)	/* AIX virtual time alarm */
-+  signal_names[SIGVIRT] = "SIGVIRT";
-+#endif
-+
-+#if defined (SIGALRM1)	/* m:n condition variables */
-+  signal_names[SIGALRM1] = "SIGALRM1";
-+#endif
-+
-+#if defined (SIGWAITING)	/* m:n scheduling */
-+  signal_names[SIGWAITING] = "SIGWAITING";
-+#endif
-+
-+#if defined (SIGGRANT)	/* HFT monitor mode granted */
-+  signal_names[SIGGRANT] = "SIGGRANT";
-+#endif
-+
-+#if defined (SIGKAP)	/* keep alive poll from native keyboard */
-+  signal_names[SIGKAP] = "SIGKAP";
-+#endif
-+
-+#if defined (SIGRETRACT) /* HFT monitor mode retracted */
-+  signal_names[SIGRETRACT] = "SIGRETRACT";
-+#endif
-+
-+#if defined (SIGSOUND)	/* HFT sound sequence has completed */
-+  signal_names[SIGSOUND] = "SIGSOUND";
-+#endif
-+
-+#if defined (SIGSAK)	/* Secure Attention Key */
-+  signal_names[SIGSAK] = "SIGSAK";
-+#endif
-+
-+/* SunOS5 */
-+#if defined (SIGLWP)	/* special signal used by thread library */
-+  signal_names[SIGLWP] = "SIGLWP";
-+#endif
-+
-+#if defined (SIGFREEZE)	/* special signal used by CPR */
-+  signal_names[SIGFREEZE] = "SIGFREEZE";
-+#endif
-+
-+#if defined (SIGTHAW)	/* special signal used by CPR */
-+  signal_names[SIGTHAW] = "SIGTHAW";
-+#endif
-+
-+#if defined (SIGCANCEL)	/* thread cancellation signal used by libthread */
-+  signal_names[SIGCANCEL] = "SIGCANCEL";
-+#endif
-+
-+/* HP-UX */
-+#if defined (SIGDIL)	/* DIL signal (?) */
-+  signal_names[SIGDIL] = "SIGDIL";
-+#endif
-+
-+/* System V */
-+#if defined (SIGCLD)	/* Like SIGCHLD.  */
-+  signal_names[SIGCLD] = "SIGCLD";
-+#endif
-+
-+#if defined (SIGPWR)	/* power state indication */
-+  signal_names[SIGPWR] = "SIGPWR";
-+#endif
-+
-+#if defined (SIGPOLL)	/* Pollable event (for streams)  */
-+  signal_names[SIGPOLL] = "SIGPOLL";
-+#endif
-+
-+/* Unknown */
-+#if defined (SIGWINDOW)
-+  signal_names[SIGWINDOW] = "SIGWINDOW";
-+#endif
-+
-+/* Common */
-+#if defined (SIGHUP)	/* hangup */
-+  signal_names[SIGHUP] = "SIGHUP";
-+#endif
-+
-+#if defined (SIGINT)	/* interrupt */
-+  signal_names[SIGINT] = "SIGINT";
-+#endif
-+
-+#if defined (SIGQUIT)	/* quit */
-+  signal_names[SIGQUIT] = "SIGQUIT";
-+#endif
-+
-+#if defined (SIGILL)	/* illegal instruction (not reset when caught) */
-+  signal_names[SIGILL] = "SIGILL";
-+#endif
-+
-+#if defined (SIGTRAP)	/* trace trap (not reset when caught) */
-+  signal_names[SIGTRAP] = "SIGTRAP";
-+#endif
-+
-+#if defined (SIGIOT)	/* IOT instruction */
-+  signal_names[SIGIOT] = "SIGIOT";
-+#endif
-+
-+#if defined (SIGABRT)	/* Cause current process to dump core. */
-+  signal_names[SIGABRT] = "SIGABRT";
-+#endif
-+
-+#if defined (SIGEMT)	/* EMT instruction */
-+  signal_names[SIGEMT] = "SIGEMT";
-+#endif
-+
-+#if defined (SIGFPE)	/* floating point exception */
-+  signal_names[SIGFPE] = "SIGFPE";
-+#endif
-+
-+#if defined (SIGKILL)	/* kill (cannot be caught or ignored) */
-+  signal_names[SIGKILL] = "SIGKILL";
-+#endif
-+
-+#if defined (SIGBUS)	/* bus error */
-+  signal_names[SIGBUS] = "SIGBUS";
-+#endif
-+
-+#if defined (SIGSEGV)	/* segmentation violation */
-+  signal_names[SIGSEGV] = "SIGSEGV";
-+#endif
-+
-+#if defined (SIGSYS)	/* bad argument to system call */
-+  signal_names[SIGSYS] = "SIGSYS";
-+#endif
-+
-+#if defined (SIGPIPE)	/* write on a pipe with no one to read it */
-+  signal_names[SIGPIPE] = "SIGPIPE";
-+#endif
-+
-+#if defined (SIGALRM)	/* alarm clock */
-+  signal_names[SIGALRM] = "SIGALRM";
-+#endif
-+
-+#if defined (SIGTERM)	/* software termination signal from kill */
-+  signal_names[SIGTERM] = "SIGTERM";
-+#endif
-+
-+#if defined (SIGURG)	/* urgent condition on IO channel */
-+  signal_names[SIGURG] = "SIGURG";
-+#endif
-+
-+#if defined (SIGSTOP)	/* sendable stop signal not from tty */
-+  signal_names[SIGSTOP] = "SIGSTOP";
-+#endif
-+
-+#if defined (SIGTSTP)	/* stop signal from tty */
-+  signal_names[SIGTSTP] = "SIGTSTP";
-+#endif
-+
-+#if defined (SIGCONT)	/* continue a stopped process */
-+  signal_names[SIGCONT] = "SIGCONT";
-+#endif
-+
-+#if defined (SIGCHLD)	/* to parent on child stop or exit */
-+  signal_names[SIGCHLD] = "SIGCHLD";
-+#endif
-+
-+#if defined (SIGTTIN)	/* to readers pgrp upon background tty read */
-+  signal_names[SIGTTIN] = "SIGTTIN";
-+#endif
-+
-+#if defined (SIGTTOU)	/* like TTIN for output if (tp->t_local&LTOSTOP) */
-+  signal_names[SIGTTOU] = "SIGTTOU";
-+#endif
-+
-+#if defined (SIGIO)	/* input/output possible signal */
-+  signal_names[SIGIO] = "SIGIO";
-+#endif
-+
-+#if defined (SIGXCPU)	/* exceeded CPU time limit */
-+  signal_names[SIGXCPU] = "SIGXCPU";
-+#endif
-+
-+#if defined (SIGXFSZ)	/* exceeded file size limit */
-+  signal_names[SIGXFSZ] = "SIGXFSZ";
-+#endif
-+
-+#if defined (SIGVTALRM)	/* virtual time alarm */
-+  signal_names[SIGVTALRM] = "SIGVTALRM";
-+#endif
-+
-+#if defined (SIGPROF)	/* profiling time alarm */
-+  signal_names[SIGPROF] = "SIGPROF";
-+#endif
-+
-+#if defined (SIGWINCH)	/* window changed */
-+  signal_names[SIGWINCH] = "SIGWINCH";
-+#endif
-+
-+/* 4.4 BSD */
-+#if defined (SIGINFO) && !defined (_SEQUENT_)	/* information request */
-+  signal_names[SIGINFO] = "SIGINFO";
-+#endif
-+
-+#if defined (SIGUSR1)	/* user defined signal 1 */
-+  signal_names[SIGUSR1] = "SIGUSR1";
-+#endif
-+
-+#if defined (SIGUSR2)	/* user defined signal 2 */
-+  signal_names[SIGUSR2] = "SIGUSR2";
-+#endif
-+
-+#if defined (SIGKILLTHR)	/* BeOS: Kill Thread */
-+  signal_names[SIGKILLTHR] = "SIGKILLTHR";
-+#endif
-+
-+  for (i = 0; i < NSIG; i++)
-+    if (signal_names[i] == (char *)NULL)
-+      {
-+	signal_names[i] = (char *)malloc (18);
-+	sprintf (signal_names[i], "SIGJUNK(%d)", i);
-+      }
-+
-+  signal_names[NSIG] = "DEBUG";
-+}
-+
-+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, "char *signal_names[NSIG + 2] = {\n");
-+
-+  for (i = 0; i <= NSIG; 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 -Nur ash-0.4.0.orig/mksyntax.c ash-0.4.0.fixed/mksyntax.c
---- ash-0.4.0.orig/mksyntax.c	2001-01-12 10:50:38.000000000 -0600
-+++ ash-0.4.0.fixed/mksyntax.c	2003-10-01 21:08:15.000000000 -0500
-@@ -238,14 +238,14 @@
- 	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("'", "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);
-diff -Nur ash-0.4.0.orig/nodetypes ash-0.4.0.fixed/nodetypes
---- ash-0.4.0.orig/nodetypes	1999-02-05 06:04:52.000000000 -0600
-+++ ash-0.4.0.fixed/nodetypes	2003-10-01 21:08:15.000000000 -0500
-@@ -119,6 +119,7 @@
- NFROM nfile			# fd< fname
- NFROMTO nfile			# fd<> fname
- NAPPEND nfile			# fd>> fname
-+NTOOV nfile			# fd>| fname
- 	type	  int
- 	next	  nodeptr		# next redirection in list
- 	fd	  int			# file descriptor being redirected
-diff -Nur ash-0.4.0.orig/options.c ash-0.4.0.fixed/options.c
---- ash-0.4.0.orig/options.c	1999-07-09 06:02:07.000000000 -0500
-+++ ash-0.4.0.fixed/options.c	2003-10-01 21:08:15.000000000 -0500
-@@ -79,7 +79,7 @@
- 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 *));
- 
- 
- /*
-@@ -118,7 +118,8 @@
- 	        arg0 = *argptr++;
- 
- 	shellparam.p = argptr;
--	shellparam.reset = 1;
-+	shellparam.optind = 1;
-+	shellparam.optoff = -1;
- 	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
- 	while (*argptr) {
- 		shellparam.nparam++;
-@@ -282,7 +283,8 @@
- 	shellparam.malloc = 1;
- 	shellparam.nparam = nparam;
- 	shellparam.p = newparam;
--	shellparam.optnext = NULL;
-+	shellparam.optind = 1;
-+	shellparam.optoff = -1;
- }
- 
- 
-@@ -330,7 +332,8 @@
- 	}
- 	ap2 = shellparam.p;
- 	while ((*ap2++ = *ap1++) != NULL);
--	shellparam.optnext = NULL;
-+	shellparam.optind = 1;
-+	shellparam.optoff = -1;
- 	INTON;
- 	return 0;
- }
-@@ -363,10 +366,8 @@
- getoptsreset(value)
- 	const char *value;
- {
--	if (number(value) == 1) {
--		shellparam.optnext = NULL;
--		shellparam.reset = 1;
--	}
-+	shellparam.optind = number(value);
-+	shellparam.optoff = -1;
- }
- 
- /*
-@@ -385,50 +386,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;
- 	}
-@@ -453,7 +462,7 @@
- 	}
- 
- 	if (*++q == ':') {
--		if (*p == '\0' && (p = **optnext) == NULL) {
-+		if (*p == '\0' && (p = *optnext) == NULL) {
- 			if (optstr[0] == ':') {
- 				s[0] = c;
- 				s[1] = '\0';
-@@ -468,30 +477,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;
-+	*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 -Nur ash-0.4.0.orig/options.h ash-0.4.0.fixed/options.h
---- ash-0.4.0.orig/options.h	1999-07-09 06:02:07.000000000 -0500
-+++ ash-0.4.0.fixed/options.h	2003-10-01 21:08:15.000000000 -0500
-@@ -41,10 +41,9 @@
- 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 */
- };
- 
- 
-diff -Nur ash-0.4.0.orig/output.c ash-0.4.0.fixed/output.c
---- ash-0.4.0.orig/output.c	2001-01-12 10:50:39.000000000 -0600
-+++ ash-0.4.0.fixed/output.c	2003-10-01 21:08:15.000000000 -0500
-@@ -65,6 +65,10 @@
- #include <errno.h>
- #include <unistd.h>
- #include <stdlib.h>
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+#undef CEOF			/* get rid of the redefine warning */
-+#include <fcntl.h>
-+#endif
- 
- #include "shell.h"
- #include "syntax.h"
-@@ -79,9 +83,15 @@
- #define OUTPUT_ERR 01		/* error occurred on output */
- 
- 
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
-+struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
-+struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
-+#else
- 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};
-+#endif
- struct output *out1 = &output;
- struct output *out2 = &errout;
- 
-@@ -92,9 +102,19 @@
- INCLUDE "output.h"
- INCLUDE "memalloc.h"
- 
-+INIT {
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+	initstreams();
-+#endif
-+}
-+
- RESET {
- 	out1 = &output;
- 	out2 = &errout;
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+	if (memout.stream != NULL)
-+		closememout();
-+#endif
- 	if (memout.buf != NULL) {
- 		ckfree(memout.buf);
- 		memout.buf = NULL;
-@@ -124,33 +144,22 @@
- 
- 
- void
--out1str(p)
--	const char *p;
--	{
--	outstr(p, out1);
--}
--
--
--void
--out2str(p)
--	const char *p;
--	{
--	outstr(p, out2);
--}
--
--
--void
- outstr(p, file)
- 	const char *p;
- 	struct output *file;
- 	{
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+	fputs(p, file->stream);
-+#else
- 	while (*p)
- 		outc(*p++, file);
-+#endif
- 	if (file == out2)
- 		flushout(file);
- }
- 
- 
-+#if !defined(_GNU_SOURCE) || defined(__UCLIBC__)
- char out_junk[16];
- 
- 
-@@ -183,6 +192,7 @@
- 	}
- 	dest->nleft--;
- }
-+#endif
- 
- 
- void
-@@ -192,11 +202,11 @@
- }
- 
- 
-+#if !defined(_GNU_SOURCE) || defined(__UCLIBC__)
- void
- flushout(dest)
- 	struct output *dest;
- 	{
--
- 	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
- 		return;
- 	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
-@@ -204,6 +214,7 @@
- 	dest->nextc = dest->buf;
- 	dest->nleft = dest->bufsize;
- }
-+#endif
- 
- 
- void
-@@ -264,6 +275,7 @@
- 	va_end(ap);
- }
- 
-+#if !defined(__GLIBC__) && !defined(__UCLIBC__)
- void
- #ifdef __STDC__
- dprintf(const char *fmt, ...)
-@@ -285,6 +297,7 @@
- 	va_end(ap);
- 	flushout(out2);
- }
-+#endif
- 
- void
- #ifdef __STDC__
-@@ -295,7 +308,9 @@
- #endif
- {
- 	va_list ap;
-+#if !defined(_GNU_SOURCE) || defined(__UCLIBC__)
- 	struct output strout;
-+#endif
- #ifndef __STDC__
- 	char *outbuf;
- 	size_t length;
-@@ -308,6 +323,9 @@
- #else
- 	va_start(ap, fmt);
- #endif
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+	vsnprintf(outbuf, length, fmt, ap);
-+#else
- 	strout.nextc = outbuf;
- 	strout.nleft = length;
- 	strout.fd = BLOCK_OUT;
-@@ -316,8 +334,10 @@
- 	outc('\0', &strout);
- 	if (strout.flags & OUTPUT_ERR)
- 		outbuf[length - 1] = '\0';
-+#endif
- }
- 
-+#if !defined(_GNU_SOURCE) || defined(__UCLIBC__)
- /*
-  * Formatted output.  This routine handles a subset of the printf formats:
-  * - Formats supported: d, u, o, p, X, s, and c.
-@@ -534,7 +554,7 @@
- 	}
- #endif	/* !HAVE_VASPRINTF */
- }
--
-+#endif
- 
- 
- /*
-@@ -544,7 +564,7 @@
- int
- xwrite(fd, buf, nbytes)
- 	int fd;
--	char *buf;
-+	const char *buf;
- 	int nbytes;
- 	{
- 	int ntry;
-@@ -570,6 +590,8 @@
- }
- 
- 
-+
-+#ifdef notdef
- /*
-  * Version of ioctl that retries after a signal is caught.
-  * XXX unused function
-@@ -586,3 +608,27 @@
- 	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
- 	return i;
- }
-+#endif
-+
-+
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+void initstreams() {
-+	output.stream = stdout;
-+	errout.stream = stderr;
-+}
-+
-+
-+void
-+openmemout() {
-+	memout.stream = open_memstream(&memout.buf, &memout.bufsize);
-+}
-+
-+
-+void
-+closememout() {
-+	INTOFF;
-+	fclose(memout.stream);
-+	memout.stream = NULL;
-+	INTON;
-+}
-+#endif
-diff -Nur ash-0.4.0.orig/output.h ash-0.4.0.fixed/output.h
---- ash-0.4.0.orig/output.h	1998-01-31 12:28:11.000000000 -0600
-+++ ash-0.4.0.fixed/output.h	2003-10-01 21:08:15.000000000 -0500
-@@ -45,13 +45,19 @@
- #else
- #include <varargs.h>
- #endif
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+#include <stdio.h>
-+#endif
- 
- struct output {
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+	FILE *stream;
-+#endif
- 	char *nextc;
- 	int nleft;
- 	char *buf;
- 	int bufsize;
--	short fd;
-+	int fd;
- 	short flags;
- };
- 
-@@ -61,29 +67,44 @@
- 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 *));
-+#ifndef _GNU_SOURCE
- void emptyoutbuf __P((struct output *));
-+#endif
- void flushall __P((void));
-+#ifndef _GNU_SOURCE
- void flushout __P((struct output *));
-+#endif
- 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)));
-+#if !defined(__GLIBC__) && !defined(__UCLIBC__)
- void dprintf __P((const char *, ...))
-     __attribute__((__format__(__printf__,1,2)));
-+#endif
- void fmtstr __P((char *, size_t, const char *, ...))
-     __attribute__((__format__(__printf__,3,4)));
-+#ifndef _GNU_SOURCE
- 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 char *, int));
-+#if defined(_GNU_SOURCE) && !defined(__UCLIBC__)
-+void initstreams __P((void));
-+void openmemout __P((void));
-+void closememout __P((void));
- 
-+#define outc(c, o)	putc(c, (o)->stream)
-+#define flushout(o)	fflush((o)->stream)
-+#define doformat(d, f, a)	vfprintf((d)->stream, f, a)
-+#else
- #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);
-+#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 OUTPUT_INCL
- #endif
-diff -Nur ash-0.4.0.orig/parser.c ash-0.4.0.fixed/parser.c
---- ash-0.4.0.orig/parser.c	2001-01-12 10:50:39.000000000 -0600
-+++ ash-0.4.0.fixed/parser.c	2003-10-01 21:08:15.000000000 -0500
-@@ -221,6 +221,7 @@
- 	union node *n1, *n2, *n3;
- 	int t;
- 
-+	checkkwd = 1;
- 	n1 = pipeline();
- 	for (;;) {
- 		if ((t = readtoken()) == TAND) {
-@@ -231,6 +232,7 @@
- 			tokpushback++;
- 			return n1;
- 		}
-+		checkkwd = 2;
- 		n2 = pipeline();
- 		n3 = (union node *)stalloc(sizeof (struct nbinary));
- 		n3->type = t;
-@@ -250,9 +252,11 @@
- 
- 	negate = 0;
- 	TRACE(("pipeline: entered\n"));
--	while (readtoken() == TNOT)
-+	if (readtoken() == TNOT) {
- 		negate = !negate;
--	tokpushback++;
-+		checkkwd = 1;
-+	} else
-+		tokpushback++;
- 	n1 = command();
- 	if (readtoken() == TPIPE) {
- 		pipenode = (union node *)stalloc(sizeof (struct npipe));
-@@ -264,6 +268,7 @@
- 		do {
- 			prev = lp;
- 			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
-+			checkkwd = 2;
- 			lp->n = command();
- 			prev->next = lp;
- 		} while (readtoken() == TPIPE);
-@@ -288,9 +293,8 @@
- 	union node *ap, **app;
- 	union node *cp, **cpp;
- 	union node *redir, **rpp;
--	int t, negate = 0;
-+	int t;
- 
--	checkkwd = 2;
- 	redir = NULL;
- 	n1 = NULL;
- 	rpp = &redir;
-@@ -303,12 +307,6 @@
- 	}
- 	tokpushback++;
- 
--	while (readtoken() == TNOT) {
--		TRACE(("command: TNOT recognized\n"));
--		negate = !negate;
--	}
--	tokpushback++;
--
- 	switch (readtoken()) {
- 	case TIF:
- 		n1 = (union node *)stalloc(sizeof (struct nif));
-@@ -417,6 +415,8 @@
- 		cpp = &n1->ncase.cases;
- 		checkkwd = 2, readtoken();
- 		do {
-+			if (lasttoken == TLP)
-+				readtoken();
- 			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
- 			cp->type = NCLIST;
- 			app = &cp->nclist.pattern;
-@@ -464,21 +464,22 @@
- 		break;
- 	/* Handle an empty command like other simple commands.  */
- 	case TSEMI:
-+	case TAND:
-+	case TOR:
-+	case TNL:
-+	case TEOF:
-+	case TRP:
-+	case TBACKGND:
- 		/*
- 		 * 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:
- 		tokpushback++;
- 		n1 = simplecmd(rpp, redir);
--		goto checkneg;
-+		return n1;
- 	default:
- 		synexpect(-1);
- 		/* NOTREACHED */
-@@ -502,15 +503,7 @@
- 		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;
-+	return n1;
- }
- 
- 
-@@ -520,8 +513,7 @@
- 	{
- 	union node *args, **app;
- 	union node **orig_rpp = rpp;
--	union node *n = NULL, *n2;
--	int negate = 0;
-+	union node *n = NULL;
- 
- 	/* If we don't have any redirections already, then we must reset */
- 	/* rpp to be the address of the local redir variable.  */
-@@ -537,12 +529,6 @@
- 	 */
- 	orig_rpp = rpp;
- 
--	while (readtoken() == TNOT) {
--		TRACE(("command: TNOT recognized\n"));
--		negate = !negate;
--	}
--	tokpushback++;
--
- 	for (;;) {
- 		if (readtoken() == TWORD) {
- 			n = (union node *)stalloc(sizeof (struct narg));
-@@ -565,8 +551,9 @@
- 				synerror("Bad function name");
- #endif
- 			n->type = NDEFUN;
-+			checkkwd = 2;
- 			n->narg.next = command();
--			goto checkneg;
-+			return n;
- 		} else {
- 			tokpushback++;
- 			break;
-@@ -579,16 +566,7 @@
- 	n->ncmd.backgnd = 0;
- 	n->ncmd.args = args;
- 	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;
-+	return n;
- }
- 
- STATIC union node *
-@@ -743,7 +721,7 @@
- 			}
- 		}
- out:
--		checkkwd = (t == TNOT) ? savecheckkwd : 0;
-+		checkkwd = 0;
- 	}
- #ifdef DEBUG
- 	if (!alreadyseen)
-@@ -882,6 +860,7 @@
- 	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__
-@@ -892,6 +871,7 @@
- 	(void) &varnest;
- 	(void) &arinest;
- 	(void) &parenlevel;
-+	(void) &dqvarnest;
- 	(void) &oldstyle;
- 	(void) &prevsyntax;
- 	(void) &syntax;
-@@ -906,6 +886,7 @@
- 	varnest = 0;
- 	arinest = 0;
- 	parenlevel = 0;
-+	dqvarnest = 0;
- 
- 	STARTSTACKSTR(out);
- 	loop: {	/* for each line, until end of word */
-@@ -938,7 +919,8 @@
- 				USTPUTC(c, out);
- 				break;
- 			case CCTL:
--				if (eofmark == NULL || dblquote)
-+				if ((eofmark == NULL || dblquote) &&
-+				    dqvarnest == 0)
- 					USTPUTC(CTLESC, out);
- 				USTPUTC(c, out);
- 				break;
-@@ -983,7 +965,8 @@
- 					if (arinest) {
- 						syntax = ARISYNTAX;
- 						dblquote = 0;
--					} else if (eofmark == NULL) {
-+					} else if (eofmark == NULL &&
-+						   dqvarnest == 0) {
- 						syntax = BASESYNTAX;
- 						dblquote = 0;
- 					}
-@@ -996,6 +979,9 @@
- 			case CENDVAR:	/* '}' */
- 				if (varnest > 0) {
- 					varnest--;
-+					if (dqvarnest > 0) {
-+						dqvarnest--;
-+					}
- 					USTPUTC(CTLENDVAR, out);
- 				} else {
- 					USTPUTC(c, out);
-@@ -1125,6 +1111,8 @@
- 			np->type = NAPPEND;
- 		else if (c == '&')
- 			np->type = NTOFD;
-+		else if (c == '|')
-+			np->type = NTOOV;
- 		else {
- 			np->type = NTO;
- 			pungetc();
-@@ -1260,8 +1248,12 @@
- 		if (dblquote || arinest)
- 			flags |= VSQUOTE;
- 		*(stackblock() + typeloc) = subtype | flags;
--		if (subtype != VSNORMAL)
-+		if (subtype != VSNORMAL) {
- 			varnest++;
-+			if (dblquote) {
-+				dqvarnest++;
-+			}
-+		}
- 	}
- 	goto parsesub_return;
- }
-diff -Nur ash-0.4.0.orig/redir.c ash-0.4.0.fixed/redir.c
---- ash-0.4.0.orig/redir.c	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/redir.c	2003-10-01 21:08:15.000000000 -0500
-@@ -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>
-@@ -66,6 +67,7 @@
- #include "output.h"
- #include "memalloc.h"
- #include "error.h"
-+#include "options.h"
- 
- 
- #define EMPTY -2		/* marks an unused slot in redirtab */
-@@ -92,8 +94,15 @@
- */
- int fd0_redirected = 0;
- 
--STATIC void openredirect __P((union node *, char[10 ]));
-+/*
-+ * We also keep track of where fd2 goes.
-+ */
-+int fd2 = 2;
-+
-+STATIC int openredirect __P((union node *));
-+STATIC void dupredirect __P((union node *, int, char[10 ]));
- STATIC int openhere __P((union node *));
-+STATIC int noclobberopen __P((const char *));
- 
- 
- /*
-@@ -113,6 +122,7 @@
- 	struct redirtab *sv = NULL;
- 	int i;
- 	int fd;
-+	int newfd;
- 	int try;
- 	char memory[10];	/* file descriptors to write to memory */
- 
-@@ -133,36 +143,47 @@
- 		    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) {
-+		INTOFF;
-+		newfd = openredirect(n);
-+		if (((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) ||
-+		    (fd == fd2)) {
-+			if (newfd == fd) {
-+				try++;
-+			} else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
- 				switch (errno) {
- 				case EBADF:
- 					if (!try) {
--						openredirect(n, memory);
-+						dupredirect(n, newfd, memory);
- 						try++;
--						goto again;
-+						break;
- 					}
- 					/* FALLTHROUGH*/
- 				default:
-+					if (newfd >= 0) {
-+						close(newfd);
-+					}
- 					INTON;
- 					error("%d: %s", fd, strerror(errno));
- 					/* NOTREACHED */
- 				}
- 			}
- 			if (!try) {
--				sv->renamed[fd] = i;
- 				close(fd);
-+				if (flags & REDIR_PUSH) {
-+					sv->renamed[fd] = i;
-+				}
-+				if (fd == fd2) {
-+					fd2 = i;
-+				}
- 			}
--			INTON;
--		} else {
-+		} else if (fd != newfd) {
- 			close(fd);
- 		}
-                 if (fd == 0)
-                         fd0_redirected++;
- 		if (!try)
--			openredirect(n, memory);
-+			dupredirect(n, newfd, memory);
-+		INTON;
- 	}
- 	if (memory[1])
- 		out1 = &memout;
-@@ -171,22 +192,13 @@
- }
- 
- 
--STATIC void
--openredirect(redir, memory)
-+STATIC int
-+openredirect(redir)
- 	union node *redir;
--	char memory[10];
- 	{
--	int fd = redir->nfile.fd;
- 	char *fname;
- 	int f;
- 
--	/*
--	 * 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;
-@@ -199,6 +211,14 @@
- 			goto ecreate;
- 		break;
- 	case NTO:
-+		/* Take care of noclobber mode. */
-+		if (Cflag) {
-+			fname = redir->nfile.expfname;
-+			if ((f = noclobberopen(fname)) < 0)
-+				goto ecreate;
-+			break;
-+		}
-+	case NTOOV:
- 		fname = redir->nfile.expfname;
- #ifdef O_CREAT
- 		if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
-@@ -222,32 +242,48 @@
- 		break;
- 	case NTOFD:
- 	case NFROMFD:
-+		f = -1;
-+		break;
-+	case NHERE:
-+	case NXHERE:
-+		f = openhere(redir);
-+		break;
-+	default:
-+		abort();
-+	}
-+
-+	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
-+dupredirect(redir, f, memory)
-+	union node *redir;
-+	int f;
-+	char memory[10];
-+	{
-+	int fd = redir->nfile.fd;
-+
-+	memory[fd] = 0;
-+	if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
- 		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
- 			if (memory[redir->ndup.dupfd])
- 				memory[fd] = 1;
- 			else
- 				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));
- }
- 
- 
-@@ -304,6 +340,7 @@
- 	struct redirtab *rp = redirlist;
- 	int i;
- 
-+	INTOFF;
- 	for (i = 0 ; i < 10 ; i++) {
- 		if (rp->renamed[i] != EMPTY) {
-                         if (i == 0)
-@@ -313,9 +350,11 @@
- 				copyfd(rp->renamed[i], i);
- 				close(rp->renamed[i]);
- 			}
-+			if (rp->renamed[i] == fd2) {
-+				fd2 = i;
-+			}
- 		}
- 	}
--	INTOFF;
- 	redirlist = rp->next;
- 	ckfree(rp);
- 	INTON;
-@@ -359,6 +398,9 @@
- 		for (i = 0 ; i < 10 ; i++) {
- 			if (rp->renamed[i] >= 0) {
- 				close(rp->renamed[i]);
-+				if (rp->renamed[i] == fd2) {
-+					fd2 = -1;
-+				}
- 			}
- 			rp->renamed[i] = EMPTY;
- 		}
-@@ -389,3 +431,62 @@
- 	}
- 	return newfd;
- }
-+
-+/*
-+ * Open a file in noclobber mode.
-+ * The code was copied from bash.
-+ */
-+int
-+noclobberopen(fname)
-+	const char *fname;
-+{
-+	int r, fd;
-+	struct stat finfo, finfo2;
-+
-+	/*
-+	 * If the file exists and is a regular file, return an error
-+	 * immediately.
-+	 */
-+	r = stat(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 open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
-+	fd = open(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 (fstat(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;
-+}
-diff -Nur ash-0.4.0.orig/redir.h ash-0.4.0.fixed/redir.h
---- ash-0.4.0.orig/redir.h	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/redir.h	2003-10-01 21:08:15.000000000 -0500
-@@ -42,6 +42,8 @@
- #define REDIR_PUSH 01		/* save previous values of file descriptors */
- #define REDIR_BACKQ 02		/* save the command output in memory */
- 
-+extern int fd2;
-+
- union node;
- void redirect __P((union node *, int));
- void popredir __P((void));
-diff -Nur ash-0.4.0.orig/setmode.c ash-0.4.0.fixed/setmode.c
---- ash-0.4.0.orig/setmode.c	1969-12-31 18:00:00.000000000 -0600
-+++ ash-0.4.0.fixed/setmode.c	2003-10-01 21:08:15.000000000 -0500
-@@ -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 -Nur ash-0.4.0.orig/sh.1 ash-0.4.0.fixed/sh.1
---- ash-0.4.0.orig/sh.1	2001-01-12 10:50:40.000000000 -0600
-+++ ash-0.4.0.fixed/sh.1	2003-10-01 21:08:15.000000000 -0500
-@@ -649,7 +649,7 @@
- they were one program:
- .Pp
- .Bd -literal -offset indent
--{ echo -n \*q hello \*q ; echo \*q world" } > greeting
-+{ echo \*q hello \\c\*q ; echo \*q world" } > greeting
- .Ed
- .Pp
- .Ss Functions
-@@ -1306,14 +1306,16 @@
- will continue to print the old name for the directory.
- .It Xo read Op Fl p Ar prompt
- .Op Fl r
--.Op Ar variable...
-+.Ar variable...
- .Xc
- The prompt is printed if the
- .Fl p
- 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
-@@ -1394,6 +1396,9 @@
- by one. If there are zero positional parameters,
- .Ic shift
- does nothing.
-+.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...
-diff -Nur ash-0.4.0.orig/show.c ash-0.4.0.fixed/show.c
---- ash-0.4.0.orig/show.c	1999-10-09 06:02:09.000000000 -0500
-+++ ash-0.4.0.fixed/show.c	2003-10-01 21:08:15.000000000 -0500
-@@ -155,6 +155,7 @@
- 			case NTO:	s = ">";  dftfd = 1; break;
- 			case NAPPEND:	s = ">>"; dftfd = 1; break;
- 			case NTOFD:	s = ">&"; dftfd = 1; break;
-+			case NTOOV:	s = ">|"; dftfd = 1; break;
- 			case NFROM:	s = "<";  dftfd = 0; break;
- 			case NFROMFD:	s = "<&"; dftfd = 0; break;
- 			case NFROMTO:	s = "<>"; dftfd = 0; break;
-diff -Nur ash-0.4.0.orig/trap.c ash-0.4.0.fixed/trap.c
---- ash-0.4.0.orig/trap.c	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/trap.c	2003-10-01 21:08:15.000000000 -0500
-@@ -62,7 +62,11 @@
- #include "error.h"
- #include "trap.h"
- #include "mystring.h"
-+#include "mail.h"
- 
-+#ifdef HETIO
-+#include "hetio.h"
-+#endif
- 
- /*
-  * Sigmode records the current value of the signal handlers for the various
-@@ -84,7 +88,7 @@
- char gotsig[NSIG];		/* indicates specified signal received */
- int pendingsigs;			/* indicates some signal received */
- 
--static int getsigaction __P((int, sig_t *));
-+extern char *signal_names[];
- 
- /*
-  * The trap builtin.
-@@ -107,16 +111,20 @@
- 		return 0;
- 	}
- 	ap = argv + 1;
--	if (is_number(*ap))
-+	if (argc == 2)
- 		action = NULL;
- 	else
- 		action = *ap++;
- 	while (*ap) {
--		if ((signo = number(*ap)) < 0 || signo > NSIG)
-+		if ((signo = decode_signal(*ap)) < 0)
- 			error("%s: bad trap", *ap);
- 		INTOFF;
--		if (action)
--			action = savestr(action);
-+		if (action) {
-+			if (action[0] == '-' && action[1] == '\0')
-+				action = NULL;
-+			else
-+				action = savestr(action);
-+		}
- 		if (trap[signo])
- 			ckfree(trap[signo]);
- 		trap[signo] = action;
-@@ -157,13 +165,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;
-@@ -206,15 +214,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 */
-@@ -225,31 +233,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;
-+	sigemptyset(&act.sa_mask);
-+	sigaction(signo, &act, 0);
- }
- 
- /*
-@@ -347,6 +345,7 @@
- 	setsignal(SIGINT);
- 	setsignal(SIGQUIT);
- 	setsignal(SIGTERM);
-+	chkmail(1);
- 	is_interactive = on;
- }
- 
-@@ -364,6 +363,9 @@
- 	char *p;
- 
- 	TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
-+#ifdef HETIO
-+	hetio_reset_term();
-+#endif
- 	if (setjmp(loc1.loc)) {
- 		goto l1;
- 	}
-@@ -383,3 +385,17 @@
- l2:   _exit(status);
- 	/* NOTREACHED */
- }
-+
-+int decode_signal(const char *string)
-+{
-+	int signo;
-+
-+	if (is_number(string)) return atoi(string);
-+
-+	for (signo=0; signo < NSIG; signo++)
-+		if (strcasecmp(string, signal_names[signo]) == 0 ||
-+			strcasecmp(string, &(signal_names[signo])[3]) == 0)
-+			return signo;
-+
-+	return -1;
-+}
-diff -Nur ash-0.4.0.orig/trap.h ash-0.4.0.fixed/trap.h
---- ash-0.4.0.orig/trap.h	2000-05-23 05:03:19.000000000 -0500
-+++ ash-0.4.0.fixed/trap.h	2003-10-01 21:08:15.000000000 -0500
-@@ -42,9 +42,10 @@
- 
- 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));
-+int decode_signal __P((const char *));
-diff -Nur ash-0.4.0.orig/var.c ash-0.4.0.fixed/var.c
---- ash-0.4.0.orig/var.c	2001-01-12 10:50:40.000000000 -0600
-+++ ash-0.4.0.fixed/var.c	2003-10-01 21:08:15.000000000 -0500
-@@ -114,7 +114,7 @@
- 	  NULL },
- 	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
- 	  NULL },
--	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
-+ 	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- 	  changepath },
- 	/*
- 	 * vps1 depends on uid
-@@ -138,13 +138,16 @@
- 
- /*
-  * Initialize the varable symbol tables and import the environment
-+ * Setting PWD added by herbert
-  */
- 
- #ifdef mkinit
-+INCLUDE "cd.h"
- INCLUDE "var.h"
- INIT {
- 	char **envp;
- 	extern char **environ;
-+	extern char *curdir;
- 
- 	initvar();
- 	for (envp = environ ; *envp ; envp++) {
-@@ -152,6 +155,9 @@
- 			setvareq(*envp, VEXPORT|VTEXTFIXED);
- 		}
- 	}
-+
-+	getpwd();
-+	setvar("PWD", curdir, VEXPORT|VTEXTFIXED);
- }
- #endif
- 
-@@ -166,6 +172,7 @@
- 	const struct varinit *ip;
- 	struct var *vp;
- 	struct var **vpp;
-+	char ppid[30];
- 
- 	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
- 		if ((vp->flags & VEXPORT) == 0) {
-@@ -187,6 +194,9 @@
- 		vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
- 		vps1.flags = VSTRFIXED|VTEXTFIXED;
- 	}
-+	
-+	snprintf(ppid, 29, "%ld", (long)getppid());
-+	setvar("PPID", ppid, VREADONLY|VNOFUNC);
- }
- 
- /*
-@@ -283,6 +293,7 @@
- 	struct var *vp, **vpp;
- 
- 	vpp = hashvar(s);
-+	flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
- 	for (vp = *vpp ; vp ; vp = vp->next) {
- 		if (varequal(s, vp->text)) {
- 			if (vp->flags & VREADONLY) {
-@@ -305,7 +316,8 @@
- 			 * 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()))
-+			if (iflag &&
-+			    (vp == &vmpath || (vp == &vmail && ! mpathset())))
- 				chkmail(1);
- 			INTON;
- 			return;
rmfile ./source/apps/ash/ash-0.4.0.diff
}


More information about the Frugalware-darcs mailing list