Commits

Jarkko Kniivilä committed 1102c6a

A port of ash to Plan9 with parts taken from dash and bash.

  • Participants
  • Parent commits 4a3fa7a

Comments (0)

Files changed (57)

 
 WARNS=2
 YHEADER=1
-PROG=	sh
+PROG=	ash
 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
+	test.c siglist.c system.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
 SRCS=	${SHSRCS} ${GENSRCS}
 
-LDADD+=	-ll -ledit -ltermcap
+LDADD+=	-ll -lbsd -lintl
 DPADD+=	${LIBL} ${LIBEDIT} ${LIBTERMCAP}
 
 LFLAGS= -8	# 8-bit lex scanner for arithmetic
 YFLAGS=	-d
 
-CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
+CPPFLAGS+=-D_POSIX_SOURCE -D_BSD_EXTENSION -D_SUSV2_SOURCE -D_PLAN9_SOURCE -D_RESEARCH_SOURCE \
+	-DSHELL -DSMALL -DHAVE_STRTOD -DHAVE_BSEARCH -DHAVE_SYSCONF -DHAVE_ISALPHA \
+	-I. -I${.CURDIR}
 
 .PATH:	${.CURDIR}/bltin ${.CURDIR}/../../usr.bin/printf ${.CURDIR}/../test
 
 CLEANFILES+= mkinit mknodes mksyntax
 CLEANFILES+= ${GENSRCS} y.tab.h
 
+arith.c arith.h: arith.y
+	byacc -d ${.ALLSRC}
+	mv y.tab.c arith.c
+	mv y.tab.h arith.h
+
 token.h: mktokens
 	sh ${.ALLSRC}
 
 	./${.ALLSRC}
 
 mkinit: mkinit.c
-	${HOST_LINK.c} -o mkinit ${.IMPSRC}
+	${LINK.c} -o mkinit ${.IMPSRC}
 
 mknodes: mknodes.c
-	${HOST_LINK.c} -o mknodes ${.IMPSRC}
+	${LINK.c} -o mknodes ${.IMPSRC}
 
-.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
+#.if	(${MACHINE_ARCH} == "powerpc") || \
+#	(${MACHINE_ARCH} == "arm32") || \
+#	(${MACHINE_ARCH} == "arm26")
+#TARGET_CHARFLAG= -DTARGET_CHAR="u_int8_t"
+#.else
+TARGET_CHARFLAG= -DTARGET_CHAR="char"
+#.endif
 
 mksyntax: mksyntax.c
-	${HOST_LINK.c} ${TARGET_CHARFLAG} -o mksyntax ${.IMPSRC}
+	${LINK.c} ${TARGET_CHARFLAG} -o mksyntax ${.IMPSRC}
 
-.include <bsd.prog.mk>
+.include <prog.mk>
 
 ${OBJS}: builtins.h nodes.h syntax.h token.h
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+/*
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
 #else
 __RCSID("$NetBSD: alias.c,v 1.10 1998/05/20 00:27:56 christos Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <stdlib.h>
-#include "shell.h"
+/* #include "shell.h" */
 #include "input.h"
 #include "output.h"
 #include "error.h"
 
 struct alias *atab[ATABSIZE];
 
-STATIC void setalias __P((char *, char *));
-STATIC int unalias __P((char *));
-STATIC struct alias **hashalias __P((char *));
+STATIC void setalias(char *, char *);
+STATIC int unalias(char *);
+STATIC struct alias **hashalias(char *);
 
 STATIC
 void
 }
 
 #ifdef mkinit
-MKINIT void rmaliases __P((void));
+MKINIT void rmaliases(void);
 
 SHELLPROC {
 	rmaliases();
 	int flag;
 };
 
-struct alias *lookupalias __P((char *, int));
-int aliascmd __P((int, char **));
-int unaliascmd __P((int, char **));
-void rmaliases __P((void));
+struct alias *lookupalias(char *, int);
+int aliascmd(int, char **);
+int unaliascmd(int, char **);
+void rmaliases(void);
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: arith.y,v 1.13 1999/07/09 03:05:49 christos Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <stdlib.h>
 #include "expand.h"
 
 const char *arith_buf, *arith_startbuf;
 
-void yyerror __P((const char *));
-int yyparse __P((void));
+void yyerror(const char *);
+int yyparse(void);
 #ifdef TESTARITH
-int main __P((int , char *[]));
-int error __P((char *));
+int main(int , char *[]);
+int error(char *);
 #endif
 
 int
 yyerror(s)
 	const char *s;
 {
-
 	yyerrok;
 	yyclearin;
 	arith_lex_reset();	/* reprime lex */
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: arith_lex.l,v 1.10 1999/02/05 07:52:52 christos Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <unistd.h>
 #include "arith.h"

File bltin/bltin.h

 #define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
 #endif
 
-pointer stalloc __P((int));
-void error __P((char *, ...));
-int	echocmd __P((int, char **));
+pointer stalloc(int);
+void error(char *, ...);
+int	echocmd(int, char **);
 
 
 extern char *commandname;

File bltin/test.c

+/*
+ * 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/stat.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include "bltin.h"
+
+/* test(1) accepts the following grammar:
+	oexpr	::= aexpr | aexpr "-o" oexpr ;
+	aexpr	::= nexpr | nexpr "-a" aexpr ;
+	nexpr	::= primary | "!" primary
+	primary	::= unary-operator operand
+		| operand binary-operator operand
+		| operand
+		| "(" oexpr ")"
+		;
+	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+	binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+			"-nt"|"-ot"|"-ef";
+	operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+	EOI,
+	FILRD,
+	FILWR,
+	FILEX,
+	FILEXIST,
+	FILREG,
+	FILDIR,
+	FILCDEV,
+	FILBDEV,
+	FILFIFO,
+	FILSOCK,
+	FILSYM,
+	FILGZ,
+	FILTT,
+	FILSUID,
+	FILSGID,
+	FILSTCK,
+	FILNT,
+	FILOT,
+	FILEQ,
+	FILUID,
+	FILGID,
+	STREZ,
+	STRNZ,
+	STREQ,
+	STRNE,
+	STRLT,
+	STRGT,
+	INTEQ,
+	INTNE,
+	INTGE,
+	INTGT,
+	INTLE,
+	INTLT,
+	UNOT,
+	BAND,
+	BOR,
+	LPAREN,
+	RPAREN,
+	OPERAND
+};
+
+enum token_types {
+	UNOP,
+	BINOP,
+	BUNOP,
+	BBINOP,
+	PAREN
+};
+
+static struct t_op {
+	const char *op_text;
+	short op_num, op_type;
+} const ops [] = {
+	{"-r",	FILRD,	UNOP},
+	{"-w",	FILWR,	UNOP},
+	{"-x",	FILEX,	UNOP},
+	{"-e",	FILEXIST,UNOP},
+	{"-f",	FILREG,	UNOP},
+	{"-d",	FILDIR,	UNOP},
+	{"-c",	FILCDEV,UNOP},
+	{"-b",	FILBDEV,UNOP},
+	{"-p",	FILFIFO,UNOP},
+	{"-u",	FILSUID,UNOP},
+	{"-g",	FILSGID,UNOP},
+	{"-k",	FILSTCK,UNOP},
+	{"-s",	FILGZ,	UNOP},
+	{"-t",	FILTT,	UNOP},
+	{"-z",	STREZ,	UNOP},
+	{"-n",	STRNZ,	UNOP},
+	{"-h",	FILSYM,	UNOP},		/* for backwards compat */
+	{"-O",	FILUID,	UNOP},
+	{"-G",	FILGID,	UNOP},
+	{"-L",	FILSYM,	UNOP},
+	{"-S",	FILSOCK,UNOP},
+	{"=",	STREQ,	BINOP},
+	{"!=",	STRNE,	BINOP},
+	{"<",	STRLT,	BINOP},
+	{">",	STRGT,	BINOP},
+	{"-eq",	INTEQ,	BINOP},
+	{"-ne",	INTNE,	BINOP},
+	{"-ge",	INTGE,	BINOP},
+	{"-gt",	INTGT,	BINOP},
+	{"-le",	INTLE,	BINOP},
+	{"-lt",	INTLT,	BINOP},
+	{"-nt",	FILNT,	BINOP},
+	{"-ot",	FILOT,	BINOP},
+	{"-ef",	FILEQ,	BINOP},
+	{"!",	UNOT,	BUNOP},
+	{"-a",	BAND,	BBINOP},
+	{"-o",	BOR,	BBINOP},
+	{"(",	LPAREN,	PAREN},
+	{")",	RPAREN,	PAREN},
+	{0,	0,	0}
+};
+
+static char **t_wp;
+static struct t_op const *t_wp_op;
+
+static void syntax(const char *, const char *);
+static int oexpr(enum token);
+static int aexpr(enum token);
+static int nexpr(enum token);
+static int primary(enum token);
+static int binop(void);
+static int filstat(char *, enum token);
+static enum token t_lex(char **);
+static int isoperand(char **);
+static int newerf(const char *, const char *);
+static int olderf(const char *, const char *);
+static int equalf(const char *, const char *);
+#ifdef HAVE_FACCESSAT
+static int test_file_access(const char *, int);
+#else
+static int test_st_mode(const struct stat *, int);
+static int bash_group_member(gid_t);
+#endif
+
+static inline intmax_t getn(const char *s)
+{
+	return atomax10(s);
+}
+
+static const struct t_op *getop(const char *s)
+{
+	const struct t_op *op;
+
+	for (op = ops; op->op_text; op++) {
+		if (strcmp(s, op->op_text) == 0)
+			return op;
+	}
+
+	return NULL;
+}
+
+int
+testcmd(int argc, char **argv)
+{
+	const struct t_op *op;
+	enum token n;
+	int res;
+
+	if (*argv[0] == '[') {
+		if (*argv[--argc] != ']')
+			error("missing ]");
+		argv[argc] = NULL;
+	}
+
+	argv++;
+	argc--;
+
+	if (argc < 1)
+		return 1;
+
+	/*
+	 * POSIX prescriptions: he who wrote this deserves the Nobel
+	 * peace prize.
+	 */
+	switch (argc) {
+	case 3:
+		op = getop(argv[1]);
+		if (op && op->op_type == BINOP) {
+			n = OPERAND;
+			goto eval;
+		}
+		/* fall through */
+
+	case 4:
+		if (!strcmp(argv[0], "(") && !strcmp(argv[argc - 1], ")")) {
+			argv[--argc] = NULL;
+			argv++;
+			argc--;
+		}
+	}
+
+	n = t_lex(argv);
+
+eval:
+	t_wp = argv;
+	res = !oexpr(n);
+	argv = t_wp;
+
+	if (argv[0] != NULL && argv[1] != NULL)
+		syntax(argv[0], "unexpected operator");
+
+	return res;
+}
+
+static void
+syntax(const char *op, const char *msg)
+{
+	if (op && *op)
+		error("%s: %s", op, msg);
+	else
+		error("%s", msg);
+}
+
+static int
+oexpr(enum token n)
+{
+	int res = 0;
+
+	for (;;) {
+		res |= aexpr(n);
+		n = t_lex(t_wp + 1);
+		if (n != BOR)
+			break;
+		n = t_lex(t_wp += 2);
+	}
+	return res;
+}
+
+static int
+aexpr(enum token n)
+{
+	int res = 1;
+
+	for (;;) {
+		if (!nexpr(n))
+			res = 0;
+		n = t_lex(t_wp + 1);
+		if (n != BAND)
+			break;
+		n = t_lex(t_wp += 2);
+	}
+	return res;
+}
+
+static int
+nexpr(enum token n)
+{
+	if (n == UNOT)
+		return !nexpr(t_lex(++t_wp));
+	return primary(n);
+}
+
+static int
+primary(enum token n)
+{
+	enum token nn;
+	int res;
+
+	if (n == EOI)
+		return 0;		/* missing expression */
+	if (n == LPAREN) {
+		if ((nn = t_lex(++t_wp)) == RPAREN)
+			return 0;	/* missing expression */
+		res = oexpr(nn);
+		if (t_lex(++t_wp) != RPAREN)
+			syntax(NULL, "closing paren expected");
+		return res;
+	}
+	if (t_wp_op && t_wp_op->op_type == UNOP) {
+		/* unary expression */
+		if (*++t_wp == NULL)
+			syntax(t_wp_op->op_text, "argument expected");
+		switch (n) {
+		case STREZ:
+			return strlen(*t_wp) == 0;
+		case STRNZ:
+			return strlen(*t_wp) != 0;
+		case FILTT:
+			return isatty(getn(*t_wp));
+#ifdef HAVE_FACCESSAT
+		case FILRD:
+			return test_file_access(*t_wp, R_OK);
+		case FILWR:
+			return test_file_access(*t_wp, W_OK);
+		case FILEX:
+			return test_file_access(*t_wp, X_OK);
+#endif
+		default:
+			return filstat(*t_wp, n);
+		}
+	}
+
+	if (t_lex(t_wp + 1), t_wp_op && t_wp_op->op_type == BINOP) {
+		return binop();
+	}
+
+	return strlen(*t_wp) > 0;
+}
+
+static int
+binop(void)
+{
+	const char *opnd1, *opnd2;
+	struct t_op const *op;
+
+	opnd1 = *t_wp;
+	(void) t_lex(++t_wp);
+	op = t_wp_op;
+
+	if ((opnd2 = *++t_wp) == (char *)0)
+		syntax(op->op_text, "argument expected");
+
+	switch (op->op_num) {
+	default:
+#ifdef DEBUG
+		abort();
+		/* NOTREACHED */
+#endif
+	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);
+	}
+}
+
+static int
+filstat(char *nm, enum token mode)
+{
+	struct stat s;
+
+	if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s))
+		return 0;
+
+	switch (mode) {
+#ifndef HAVE_FACCESSAT
+	case FILRD:
+		return test_st_mode(&s, R_OK);
+	case FILWR:
+		return test_st_mode(&s, W_OK);
+	case FILEX:
+		return test_st_mode(&s, X_OK);
+#endif
+	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);
+#if 0
+	case FILSOCK:
+		return S_ISSOCK(s.st_mode);
+#endif
+	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;
+#if 0
+	case FILSTCK:
+		return (s.st_mode & S_ISVTX) != 0;
+#endif
+	case FILGZ:
+		return !!s.st_size;
+	case FILUID:
+		return s.st_uid == geteuid();
+	case FILGID:
+		return s.st_gid == getegid();
+	default:
+		return 1;
+	}
+}
+
+static enum token t_lex(char **tp)
+{
+	struct t_op const *op;
+	char *s = *tp;
+
+	if (s == 0) {
+		t_wp_op = (struct t_op *)0;
+		return EOI;
+	}
+
+	op = getop(s);
+	if (op && !(op->op_type == UNOP && isoperand(tp)) &&
+	    !(op->op_num == LPAREN && !tp[1])) {
+		t_wp_op = op;
+		return op->op_num;
+	}
+
+	t_wp_op = (struct t_op *)0;
+	return OPERAND;
+}
+
+static int isoperand(char **tp)
+{
+	struct t_op const *op;
+	char *s;
+
+	if (!(s = tp[1]))
+		return 1;
+	if (!tp[2])
+		return 0;
+
+	op = getop(s);
+	return op && op->op_type == BINOP;
+}
+
+static int
+newerf (const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat (f1, &b1) == 0 &&
+		stat (f2, &b2) == 0 &&
+		b1.st_mtime > b2.st_mtime);
+}
+
+static int
+olderf (const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat (f1, &b1) == 0 &&
+		stat (f2, &b2) == 0 &&
+		b1.st_mtime < b2.st_mtime);
+}
+
+static int
+equalf (const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat (f1, &b1) == 0 &&
+		stat (f2, &b2) == 0 &&
+		b1.st_dev == b2.st_dev &&
+		b1.st_ino == b2.st_ino);
+}
+
+#ifdef HAVE_FACCESSAT
+static int test_file_access(const char *path, int mode)
+{
+	return !faccessat(AT_FDCWD, path, mode, AT_EACCESS);
+}
+#else	/* HAVE_FACCESSAT */
+/*
+ * Similar to what access(2) does, but uses the effective uid and gid.
+ * Doesn't make the mistake of telling root that any file is executable.
+ * Returns non-zero if the file is accessible.
+ */
+static int
+test_st_mode(const struct stat *st, int mode)
+{
+	int euid = geteuid();
+
+	if (euid == 0) {
+		/* Root can read or write any file. */
+		if (mode != X_OK)
+			return 1;
+
+		/* Root can execute any file that has any one of the execute
+		   bits set. */
+		mode = S_IXUSR | S_IXGRP | S_IXOTH;
+	} else if (st->st_uid == euid)
+		mode <<= 6;
+	else if (bash_group_member(st->st_gid))
+		mode <<= 3;
+
+	return st->st_mode & mode;
+}
+
+/* Return non-zero if GID is one that we have in our groups list. */
+static int
+bash_group_member(gid_t gid)
+{
+	register int i;
+	gid_t *group_array;
+	int ngroups;
+
+	/* Short-circuit if possible, maybe saving a call to getgroups(). */
+	if (gid == getgid() || gid == getegid())
+		return (1);
+
+	ngroups = getgroups(0, NULL);
+	group_array = stalloc(ngroups * sizeof(gid_t));
+	if ((getgroups(ngroups, group_array)) != ngroups)
+		return (0);
+
+	/* Search through the list looking for GID. */
+	for (i = 0; i < ngroups; i++)
+		if (gid == group_array[i])
+			return (1);
+
+	return (0);
+}
+#endif	/* HAVE_FACCESSAT */
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+/* #include <sys/cdefs.h> 
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)cd.c	8.2 (Berkeley) 5/4/95";
 #else
 __RCSID("$NetBSD: cd.c,v 1.27 1999/07/09 03:05:49 christos Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <sys/types.h>
 #include <sys/stat.h>
  * The cd and pwd commands.
  */
 
-#include "shell.h"
+#include <sys/stat.h>
+/* #include "shell.h" */
 #include "var.h"
 #include "nodes.h"	/* for jobs.h */
 #include "jobs.h"
 #include "show.h"
 #include "cd.h"
 
-STATIC int docd __P((char *, int));
-STATIC char *getcomponent __P((void));
-STATIC void updatepwd __P((char *));
+STATIC int docd(char *, int);
+STATIC char *getcomponent(void);
+STATIC void updatepwd(char *);
 
 char *curdir = NULL;		/* current working directory */
 char *prevdir;			/* previous working directory */
  *
  */
 
-void	getpwd __P((void));
-int	cdcmd __P((int, char **));
-int	pwdcmd __P((int, char **));
+void	getpwd(void);
+int	cdcmd(int, char **);
+int	pwdcmd(int, char **);
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+/* #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
 #else
 __RCSID("$NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 /*
  * Errors and exceptions.
 char *commandname;
 
 
-static void exverror __P((int, const char *, va_list))
+static void exverror(int, const char *, va_list)
     __attribute__((__noreturn__));
 
 /*
 #endif
 	{ ENXIO,	ALL,	"no such device or address" },
 	{ EROFS,	ALL,	"read-only file system" },
+#ifdef ETXTBSY
 	{ ETXTBSY,	ALL,	"text busy" },
+#endif
 #ifdef SYSV
 	{ EAGAIN,	E_EXEC,	"not enough memory" },
 #endif
 #define CLEAR_PENDING_INT intpending = 0
 #define int_pending() intpending
 
-void exraise __P((int)) __attribute__((__noreturn__));
-void onint __P((void));
-void error __P((const char *, ...)) __attribute__((__noreturn__));
-void exerror __P((int, const char *, ...)) __attribute__((__noreturn__));
-const char *errmsg __P((int, int));
+void exraise(int)  __attribute__((__noreturn__));
+void onint(void) ;
+void error(const char *, ...)  __attribute__((__noreturn__));
+void exerror(int, const char *, ...)  __attribute__((__noreturn__));
+const char *errmsg(int, int) ;
 
 
 /*
  * so we use _setjmp instead.
  */
 
-#if defined(BSD) && !defined(__SVR4)
+#if 0
 #define setjmp(jmploc)	_setjmp(jmploc)
 #define longjmp(jmploc, val)	_longjmp(jmploc, val)
 #endif
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+/* #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
 #else
 __RCSID("$NetBSD: eval.c,v 1.56 2000/05/22 10:18:46 elric Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <signal.h>
 #include <unistd.h>
  * Evaluate a command.
  */
 
-#include "shell.h"
+/* #include "shell.h" */
 #include "nodes.h"
 #include "syntax.h"
 #include "expand.h"
 int oexitstatus;		/* saved exit status */
 
 
-STATIC void evalloop __P((union node *, int));
-STATIC void evalfor __P((union node *, int));
-STATIC void evalcase __P((union node *, int));
-STATIC void evalsubshell __P((union node *, int));
-STATIC void expredir __P((union node *));
-STATIC void evalpipe __P((union node *));
-STATIC void evalcommand __P((union node *, int, struct backcmd *));
-STATIC void prehash __P((union node *));
+STATIC void evalloop(union node *, int);
+STATIC void evalfor(union node *, int);
+STATIC void evalcase(union node *, int);
+STATIC void evalsubshell(union node *, int);
+STATIC void expredir(union node *);
+STATIC void evalpipe(union node *);
+STATIC void evalcommand(union node *, int, struct backcmd *);
+STATIC void prehash(union node *);
 
 
 /*
 	struct job *jp;		/* job structure for command */
 };
 
-int evalcmd __P((int, char **));
-void evalstring __P((char *, int));
+int evalcmd(int, char **);
+void evalstring(char *, int);
 union node;	/* BLETCH for ansi C */
-void evaltree __P((union node *, int));
-void evalbackcmd __P((union node *, struct backcmd *));
-int bltincmd __P((int, char **));
-int breakcmd __P((int, char **));
-int returncmd __P((int, char **));
-int falsecmd __P((int, char **));
-int truecmd __P((int, char **));
-int execcmd __P((int, char **));
+void evaltree(union node *, int);
+void evalbackcmd(union node *, struct backcmd *);
+int bltincmd(int, char **);
+int breakcmd(int, char **);
+int returncmd(int, char **);
+int falsecmd(int, char **);
+int truecmd(int, char **);
+int execcmd(int, char **);
 
 /* in_function returns nonzero if we are currently evaluating a function */
 #define in_function()	funcnest
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: exec.c,v 1.31 2000/11/01 19:21:41 christos Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <sys/types.h>
 #include <sys/stat.h>
  * would make the command name "hash" a misnomer.
  */
 
-#include "shell.h"
+/* #include "shell.h" */
 #include "main.h"
 #include "nodes.h"
 #include "parser.h"
 int exerrno = 0;			/* Last exec error */
 
 
-STATIC void tryexec __P((char *, char **, char **));
-STATIC void execinterp __P((char **, char **));
-STATIC void printentry __P((struct tblentry *, int));
-STATIC void clearcmdentry __P((int));
-STATIC struct tblentry *cmdlookup __P((char *, int));
-STATIC void delete_cmd_entry __P((void));
+STATIC void tryexec(char *, char **, char **);
+STATIC void execinterp(char **, char **);
+STATIC void printentry(struct tblentry *, int);
+STATIC void clearcmdentry(int);
+STATIC struct tblentry *cmdlookup(char *, int);
+STATIC void delete_cmd_entry(void);
 
 
 
  */
 
 #ifdef mkinit
-MKINIT void deletefuncs __P((void));
+MKINIT void deletefuncs(void);
 
 SHELLPROC {
 	deletefuncs();
 extern const char *pathopt;	/* set by padvance */
 extern int exerrno;		/* last exec error */
 
-void shellexec __P((char **, char **, const char *, int))
+void shellexec(char **, char **, const char *, int)
     __attribute__((noreturn));
-char *padvance __P((const char **, const char *));
-int hashcmd __P((int, char **));
-void find_command __P((char *, struct cmdentry *, int, const char *));
-int find_builtin __P((char *));
-void hashcd __P((void));
-void changepath __P((const char *));
-void deletefuncs __P((void));
-void getcmdentry __P((char *, struct cmdentry *));
-void addcmdentry __P((char *, struct cmdentry *));
-void defun __P((char *, union node *));
-int unsetfunc __P((char *));
-int typecmd __P((int, char **));
+char *padvance(const char **, const char *);
+int hashcmd(int, char **);
+void find_command(char *, struct cmdentry *, int, const char *);
+int find_builtin(char *);
+void hashcd(void);
+void changepath(const char *);
+void deletefuncs(void);
+void getcmdentry(char *, struct cmdentry *);
+void addcmdentry(char *, struct cmdentry *);
+void defun(char *, union node *);
+int unsetfunc(char *);
+int typecmd(int, char **);
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: expand.c,v 1.49 2000/03/13 22:47:19 soren Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <sys/types.h>
 #include <sys/time.h>
  * backquotes, shell variables, and file metacharacters.
  */
 
-#include "shell.h"
+/* #include "shell.h" */
 #include "main.h"
 #include "nodes.h"
 #include "eval.h"
 struct ifsregion *ifslastp;	/* last struct in list */
 struct arglist exparg;		/* holds expanded arg list */
 
-STATIC void argstr __P((char *, int));
-STATIC char *exptilde __P((char *, int));
-STATIC void expbackq __P((union node *, int, int));
-STATIC int subevalvar __P((char *, char *, int, int, int, int));
-STATIC char *evalvar __P((char *, int));
-STATIC int varisset __P((char *, int));
-STATIC void varvalue __P((char *, int, int));
-STATIC void recordregion __P((int, int, int));
-STATIC void removerecordregions __P((int)); 
-STATIC void ifsbreakup __P((char *, struct arglist *));
-STATIC void ifsfree __P((void));
-STATIC void expandmeta __P((struct strlist *, int));
-STATIC void expmeta __P((char *, char *));
-STATIC void addfname __P((char *));
-STATIC struct strlist *expsort __P((struct strlist *));
-STATIC struct strlist *msort __P((struct strlist *, int));
-STATIC int pmatch __P((char *, char *, int));
-STATIC char *cvtnum __P((int, char *));
+STATIC void argstr(char *, int);
+STATIC char *exptilde(char *, int);
+STATIC void expbackq(union node *, int, int);
+STATIC int subevalvar(char *, char *, int, int, int, int);
+STATIC char *evalvar(char *, int);
+STATIC int varisset(char *, int);
+STATIC void varvalue(char *, int, int);
+STATIC void recordregion(int, int, int);
+STATIC void removerecordregions(int); 
+STATIC void ifsbreakup(char *, struct arglist *);
+STATIC void ifsfree(void);
+STATIC void expandmeta(struct strlist *, int);
+STATIC void expmeta(char *, char *);
+STATIC void addfname(char *);
+STATIC struct strlist *expsort(struct strlist *);
+STATIC struct strlist *msort(struct strlist *, int);
+STATIC int pmatch(char *, char *, int);
+STATIC char *cvtnum(int, char *);
 
 /*
  * Expand shell variables and backquotes inside a here document.
 	union node *arg;	/* the document */
 	int fd;			/* where to write the expanded version */
 	{
-	herefd = fd;
-	expandarg(arg, (struct arglist *)NULL, 0);
-	xwrite(fd, stackblock(), expdest - stackblock());
-}
+		herefd = fd;
+		expandarg(arg, (struct arglist *)NULL, 0);
+		xwrite(fd, stackblock(), expdest - (char *)stackblock());
+	}
 
 
 /*
 	struct ifsregion saveifs, *savelastp;
 	struct nodelist *saveargbackq;
 	char lastc;
-	int startloc = dest - stackblock();
+	int startloc = dest - (char *)stackblock();
 	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
 	int saveherefd;
 	int quotes = flag & (EXP_FULL | EXP_CASE);
 	if (in.jp)
 		exitstatus = waitforjob(in.jp);
 	if (quoted == 0)
-		recordregion(startloc, dest - stackblock(), 0);
+		recordregion(startloc, dest - (char *)stackblock(), 0);
 	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
 		(dest - stackblock()) - startloc,
 		(dest - stackblock()) - startloc,
 			set = 1;
 	}
 	varlen = 0;
-	startloc = expdest - stackblock();
+	startloc = expdest - (char *)stackblock();
 	if (set && subtype != VSPLUS) {
 		/* insert the value of the variable */
 		if (special) {
 			varvalue(var, varflags & VSQUOTE, flag & EXP_FULL);
 			if (subtype == VSLENGTH) {
-				varlen = expdest - stackblock() - startloc;
+				varlen = expdest - (char *)stackblock() - startloc;
 				STADJUST(-varlen, expdest);
 			}
 		} else {
 		if (!easy)
 			break;
 record:
-		recordregion(startloc, expdest - stackblock(),
+		recordregion(startloc, expdest - (char *)stackblock(),
 			     varflags & VSQUOTE);
 		break;
 
 		 * right after it
 		 */
 		STPUTC('\0', expdest);
-		patloc = expdest - stackblock();
+		patloc = expdest - (char *)stackblock();
 		if (subevalvar(p, NULL, patloc, subtype,
 			       startloc, varflags) == 0) {
-			int amount = (expdest - stackblock() - patloc) + 1;
+			int amount = (expdest - (char *)stackblock() - patloc) + 1;
 			STADJUST(-amount, expdest);
 		}
 		/* Remove any recorded regions beyond start of variable */
 
 
 union node;
-void expandhere __P((union node *, int));
-void expandarg __P((union node *, struct arglist *, int));
-void expari __P((int));
-int patmatch __P((char *, char *, int));
-void rmescapes __P((char *));
-int casematch __P((union node *, char *));
+void expandhere(union node *, int);
+void expandarg(union node *, struct arglist *, int);
+void expari(int);
+int patmatch(char *, char *, int);
+void rmescapes(char *);
+int casematch(union node *, char *);
 
 /* From arith.y */
-int arith __P((const char *));
-int expcmd __P((int , char **));
-void arith_lex_reset __P((void));
-int yylex __P((void));
+int arith(const char *);
+int expcmd(int , char **);
+void arith_lex_reset(void);
+int yylex(void);
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: histedit.c,v 1.24 2000/11/06 04:21:14 mycroft Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
+
+#ifndef SMALL
 
 #include <sys/param.h>
-#include <paths.h>
+/* #include <paths.h> */
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include "mystring.h"
 #include "myhistedit.h"
 #include "error.h"
-#ifndef SMALL
 #include "eval.h"
 #include "memalloc.h"
 
  *	@(#)init.h	8.2 (Berkeley) 5/4/95
  */
 
-void init __P((void));
-void reset __P((void));
-void initshellproc __P((void));
+void init(void);
+void reset(void);
+void initshellproc(void);
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: input.c,v 1.34 2000/05/22 10:18:47 elric Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <stdio.h>	/* defines BUFSIZ */
 #include <fcntl.h>
  * This file implements the input routines used by the parser.
  */
 
-#include "shell.h"
+/* #include "shell.h" */
 #include "redir.h"
 #include "syntax.h"
 #include "input.h"
 #include "error.h"
 #include "alias.h"
 #include "parser.h"
+#ifndef SMALL
 #include "myhistedit.h"
+#endif
 
 #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
 
 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));
+STATIC void pushfile(void);
+static int preadfd(void);
 
 #ifdef mkinit
 INCLUDE "input.h"
                 if (nr < 0) {
                         if (errno == EINTR)
                                 goto retry;
-                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
+                        if (parsefile->fd == 0 && errno == EAGAIN) {
                                 int flags = fcntl(0, F_GETFL, 0);
                                 if (flags >= 0 && flags & O_NONBLOCK) {
                                         flags &=~ O_NONBLOCK;
 extern char *parsenextc;	/* next character in input buffer */
 extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
 
-char *pfgets __P((char *, int));
-int pgetc __P((void));
-int preadbuffer __P((void));
-void pungetc __P((void));
-void pushstring __P((char *, int, void *));
-void popstring __P((void));
-void setinputfile __P((const char *, int));
-void setinputfd __P((int, int));
-void setinputstring __P((char *, int));
-void popfile __P((void));
-void popallfiles __P((void));
-void closescript __P((void));
+char *pfgets(char *, int);
+int pgetc(void);
+int preadbuffer(void);
+void pungetc(void);
+void pushstring(char *, int, void *);
+void popstring(void);
+void setinputfile(const char *, int);
+void setinputfd(int, int);
+void setinputstring(char *, int);
+void popfile(void);
+void popallfiles(void);
+void closescript(void);
 
 #define pgetc_macro()	(--parsenleft >= 0? *parsenextc++ : preadbuffer())
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: jobs.c,v 1.36 2000/05/22 10:18:47 elric Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <fcntl.h>
 #include <signal.h>
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <paths.h>
+/* #include <paths.h> */
 #include <sys/types.h>
 #include <sys/param.h>
-#ifdef BSD
+#if defined(BSD) || defined(_BSD_EXTENSION)
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
 #include <sys/ioctl.h>
 
+#define _PATH_DEVNULL "/dev/null"
+
 #include "shell.h"
 #if JOBS
 #if OLD_TTY_DRIVER
 #include "memalloc.h"
 #include "error.h"
 #include "mystring.h"
+#include "siglist.h"
 
+#define KILLPG(pid, sig) kill(-(pid), (sig))
 
 struct job *jobtab;		/* array of jobs */
 int njobs;			/* size of array */
 short curjob;			/* current job */
 #endif
 
-STATIC void restartjob __P((struct job *));
-STATIC void freejob __P((struct job *));
-STATIC struct job *getjob __P((char *));
-STATIC int dowait __P((int, struct job *));
-STATIC int onsigchild __P((void));
-STATIC int waitproc __P((int, int *));
-STATIC void cmdtxt __P((union node *));
-STATIC void cmdputs __P((const char *));
+STATIC void restartjob(struct job *);
+STATIC void freejob(struct job *);
+STATIC struct job *getjob(char *);
+STATIC int dowait(int, struct job *);
+STATIC int onsigchild(void);
+STATIC int waitproc(int, int *);
+STATIC void cmdtxt(union node *);
+STATIC void cmdputs(const char *);
 
 
 /*
 MKINIT int jobctl;
 
 void
-setjobctl(on)
-	int on;
+setjobctl(int on)
 {
 #ifdef OLD_TTY_DRIVER
 	int ldisc;
 			if (initialpgrp == -1)
 				initialpgrp = getpgrp();
 			else if (initialpgrp != getpgrp()) {
-				killpg(initialpgrp, SIGTTIN);
+				KILLPG(initialpgrp, SIGTTIN);
 				continue;
 			}
 		} while (0);
 	if (jp->state == JOBDONE)
 		return;
 	INTOFF;
-	killpg(jp->ps[0].pid, SIGCONT);
+	KILLPG(jp->ps[0].pid, SIGCONT);
 	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
 		if (WIFSTOPPED(ps->status)) {
 			ps->status = -1;
 					scopy(sys_siglist[i & 0x7F], s);
 				else
 					fmtstr(s, 64, "Signal %d", i & 0x7F);
+#if 0
 				if (WCOREDUMP(ps->status))
 					strcat(s, " (core dumped)");
+#endif
 			}
 			out1str(s);
 			col += strlen(s);
 	}
 	INTON;
 	if (! rootshell || ! iflag || (job && thisjob == job)) {
+#if 0
 		core = WCOREDUMP(status);
+#endif
 #if JOBS
 		if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
 		else
 				out2str(sys_siglist[sig]);
 			else
 				outfmt(out2, "Signal %d", sig);
+#if 0
 			if (core)
 				out2str(" - core dumped");
+#endif
 			out2c('\n');
 			flushout(&errout);
 		} else {
 #endif
 	if (block == 0)
 		flags |= WNOHANG;
-	return wait3(status, flags, (struct rusage *)NULL);
+	return waitpid(-1, status, flags);
 #else
 #ifdef SYSV
 	int (*save)();
 #define FORK_BG 1
 #define FORK_NOJOB 2
 
+#include <sys/types.h>
 
 /*
  * A job structure contains information about a job.  A job is either a
 extern short backgndpid;	/* pid of last background process */
 extern int job_warning;		/* user was warned about stopped jobs */
 
-void setjobctl __P((int));
-int fgcmd __P((int, char **));
-int bgcmd __P((int, char **));
-int jobscmd __P((int, char **));
-void showjobs __P((int));
-int waitcmd __P((int, char **));
-int jobidcmd __P((int, char **));
-struct job *makejob __P((union node *, int));
-int forkshell __P((struct job *, union node *, int));
-int waitforjob __P((struct job *));
-int stoppedjobs __P((void));
-char *commandtext __P((union node *));
+void setjobctl(int);
+int fgcmd(int, char **);
+int bgcmd(int, char **);
+int jobscmd(int, char **);
+void showjobs(int);
+int waitcmd(int, char **);
+int jobidcmd(int, char **);
+struct job *makejob(union node *, int);
+int forkshell(struct job *, union node *, int);
+int waitforjob(struct job *);
+int stoppedjobs(void);
+char *commandtext(union node *);
 
 #if ! JOBS
 #define setjobctl(on)	/* do nothing */
-/*	$NetBSD: machdep.h,v 1.8 1995/05/11 21:29:21 christos Exp $	*/
-
 /*-
  * Copyright (c) 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
  * 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
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * in some way.  The following macro will get this right on many machines.
  */
 
-#ifndef ALIGN
-union align {
-	int i;
-	char *cp;
-};
-
-#define ALIGN(nbytes)	(((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
-#endif
+#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
+/*
+ * It appears that grabstackstr() will barf with such alignments
+ * because stalloc() will return a string allocated in a new stackblock.
+ */
+#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: mail.c,v 1.14 2000/07/03 03:26:19 matt Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 /*
  * Routines to check for mail.  (Perhaps make part of main.c?)
  *	@(#)mail.h	8.2 (Berkeley) 5/4/95
  */
 
-void chkmail __P((int));
+void chkmail(int);
  * SUCH DAMAGE.
  */
 
+/*
 #include <sys/cdefs.h>
 #ifndef lint
 __COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
 	The Regents of the University of California.  All rights reserved.\n");
-#endif /* not lint */
+#endif
 
 #ifndef lint
 #if 0
 #else
 __RCSID("$NetBSD: main.c,v 1.39 2000/11/01 19:56:01 christos Exp $");
 #endif
-#endif /* not lint */
+#endif
+*/
 
 #include <errno.h>
 #include <stdio.h>
 extern int etext();
 #endif
 
-STATIC void read_profile __P((const char *));
-STATIC char *find_dot_file __P((char *));
-int main __P((int, char **));
+STATIC void read_profile(const char *);
+STATIC char *find_dot_file(char *);
+int main(int, char **);
 
 /*
  * Main routine.  We initialize things, parse the arguments, execute
 extern int rootpid;	/* pid of main shell */
 extern int rootshell;	/* true if we aren't a child of the main shell */
 
-void readcmdfile __P((char *));
-void cmdloop __P((int));
-int dotcmd __P((int, char **));
-int exitcmd __P((int, char **));
+void readcmdfile(char *);
+void cmdloop(int);
+int dotcmd(int, char **);
+int exitcmd(int, char **);
-/*	$NetBSD: memalloc.c,v 1.23 2000/11/01 19:56:01 christos Exp $	*/
-
 /*-
  * Copyright (c) 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
  * 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
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)memalloc.c	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: memalloc.c,v 1.23 2000/11/01 19:56:01 christos Exp $");
-#endif
-#endif /* not lint */
-
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "error.h"
 #include "machdep.h"
 #include "mystring.h"
+#include "system.h"
 
 /*
  * Like malloc, but returns an error when out of space.
  */
 
 pointer
-ckmalloc(nbytes)
-	int nbytes;
+ckmalloc(size_t nbytes)
 {
 	pointer p;
 
-	INTOFF;
 	p = malloc(nbytes);
-	INTON;
 	if (p == NULL)
 		error("Out of space");
 	return p;
  */
 
 pointer
-ckrealloc(p, nbytes)
-	pointer p;
-	int nbytes;
+ckrealloc(pointer p, size_t nbytes)
 {
-
-	if ((p = realloc(p, nbytes)) == NULL)
+	p = realloc(p, nbytes);
+	if (p == NULL)
 		error("Out of space");
 	return p;
 }
  */
 
 char *
-savestr(s)
-	char *s;
-	{
-	char *p;
-
-	p = ckmalloc(strlen(s) + 1);
-	scopy(s, p);
+savestr(const char *s)
+{
+	char *p = strdup(s);
+	if (!p)
+		error("Out of space");
 	return p;
 }
 
  * well.
  */
 
-#define MINSIZE 504		/* minimum size of a block */
-
+/* minimum size of a block */
+#define MINSIZE SHELL_ALIGN(504)
 
 struct stack_block {
 	struct stack_block *prev;
 
 struct stack_block stackbase;
 struct stack_block *stackp = &stackbase;
-struct stackmark *markp;
 char *stacknxt = stackbase.space;
-int stacknleft = MINSIZE;
-int sstrnleft;
+size_t stacknleft = MINSIZE;
+char *sstrend = stackbase.space + MINSIZE;
 int herefd = -1;
 
-
-
 pointer
-stalloc(nbytes)
-	int nbytes;
+stalloc(size_t nbytes)
 {
 	char *p;
+	size_t aligned;
 
-	nbytes = ALIGN(nbytes);
-	if (nbytes > stacknleft) {
-		int blocksize;
+	aligned = SHELL_ALIGN(nbytes);
+	if (aligned > stacknleft) {
+		size_t len;
+		size_t blocksize;
 		struct stack_block *sp;
 
-		blocksize = nbytes;
+		blocksize = aligned;
 		if (blocksize < MINSIZE)
 			blocksize = MINSIZE;
+		len = sizeof(struct stack_block) - MINSIZE + blocksize;
+		if (len < blocksize)
+			error("Out of space");
 		INTOFF;
-		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
+		sp = ckmalloc(len);
 		sp->prev = stackp;
 		stacknxt = sp->space;
 		stacknleft = blocksize;
+		sstrend = stacknxt + blocksize;
 		stackp = sp;
 		INTON;
 	}
 	p = stacknxt;
-	stacknxt += nbytes;
-	stacknleft -= nbytes;
+	stacknxt += aligned;
+	stacknleft -= aligned;
 	return p;
 }
 
 
 void
-stunalloc(p)
-	pointer p;
-	{
-	if (p == NULL) {		/*DEBUG */
+stunalloc(pointer p)
+{
+#ifdef DEBUG
+	if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
 		write(2, "stunalloc\n", 10);
 		abort();
 	}
+#endif
 	stacknleft += stacknxt - (char *)p;
 	stacknxt = p;
 }
 
 
 
-void
-setstackmark(mark)
-	struct stackmark *mark;
-	{
+void pushstackmark(struct stackmark *mark, size_t len)
+{
 	mark->stackp = stackp;
 	mark->stacknxt = stacknxt;
 	mark->stacknleft = stacknleft;
-	mark->marknext = markp;
-	markp = mark;
+	grabstackblock(len);
 }
 
+void setstackmark(struct stackmark *mark)
+{
+	pushstackmark(mark, stacknxt == stackp->space && stackp != &stackbase);
+}
+
 
 void
-popstackmark(mark)
-	struct stackmark *mark;
-	{
+popstackmark(struct stackmark *mark)
+{
 	struct stack_block *sp;
 
 	INTOFF;
-	markp = mark->marknext;
 	while (stackp != mark->stackp) {
 		sp = stackp;
 		stackp = sp->prev;
 	}
 	stacknxt = mark->stacknxt;
 	stacknleft = mark->stacknleft;
+	sstrend = mark->stacknxt + mark->stacknleft;
 	INTON;
 }
 
  */
 
 void
-growstackblock() {
-	char *p;
-	int newlen = ALIGN(stacknleft * 2 + 100);
-	char *oldspace = stacknxt;
-	int oldlen = stacknleft;
-	struct stack_block *sp;
-	struct stack_block *oldstackp;
+growstackblock(void)
+{
+	size_t newlen;
+
+	newlen = stacknleft * 2;
+	if (newlen < stacknleft)
+		error("Out of space");
+	if (newlen < 128)
+		newlen += 128;
 
 	if (stacknxt == stackp->space && stackp != &stackbase) {
+		struct stack_block *sp;
+		struct stack_block *prevstackp;
+		size_t grosslen;
+
 		INTOFF;
-		oldstackp = stackp;
 		sp = stackp;
-		stackp = sp->prev;
-		sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
-		sp->prev = stackp;
+		prevstackp = sp->prev;
+		grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
+		sp = ckrealloc((pointer)sp, grosslen);
+		sp->prev = prevstackp;
 		stackp = sp;
 		stacknxt = sp->space;
 		stacknleft = newlen;
-		{
-		  /* Stack marks pointing to the start of the old block
-		   * must be relocated to point to the new block 
-		   */
-		  struct stackmark *xmark;
-		  xmark = markp;
-		  while (xmark != NULL && xmark->stackp == oldstackp) {
-		    xmark->stackp = stackp;
-		    xmark->stacknxt = stacknxt;
-		    xmark->stacknleft = stacknleft;
-		    xmark = xmark->marknext;
-		  }
-		}
+		sstrend = sp->space + newlen;
 		INTON;
 	} else {
-		p = stalloc(newlen);
-		memcpy(p, oldspace, oldlen);
-		stacknxt = p;			/* free the space */
-		stacknleft += newlen;		/* we just allocated */
+		char *oldspace = stacknxt;
+		int oldlen = stacknleft;
+		char *p = stalloc(newlen);
+
+		/* free the space we just allocated */
+		stacknxt = memcpy(p, oldspace, oldlen);
+		stacknleft += newlen;
 	}
 }
 
-
-
-void
-grabstackblock(len)
-	int len;
-{
-	len = ALIGN(len);
-	stacknxt += len;
-	stacknleft -= len;
-}
-
-
-
 /*
- * The following routines are somewhat easier to use that the above.
+ * The following routines are somewhat easier to use than the above.
  * The user declares a variable of type STACKSTR, which may be declared
  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
  * the user uses the macro STPUTC to add characters to the string.  In
  * is space for at least one character.
  */
 
-
-char *
-growstackstr() {
-	int len = stackblocksize();
-	if (herefd >= 0 && len >= 1024) {
-		xwrite(herefd, stackblock(), len);
-		sstrnleft = len - 1;
-		return stackblock();
-	}
+void *
+growstackstr(void)
+{
+	size_t len = stackblocksize();
 	growstackblock();
-	sstrnleft = stackblocksize() - len - 1;
 	return stackblock() + len;
 }
 
-
 /*
  * Called from CHECKSTRSPACE.
  */
 
 char *
-makestrspace() {
-	int len = stackblocksize() - sstrnleft;
-	growstackblock();
-	sstrnleft = stackblocksize() - len;
+makestrspace(size_t newlen, char *p)
+{
+	size_t len = p - stacknxt;
+	size_t size;
+
+	for (;;) {
+		size_t nleft;
+
+		size = stackblocksize();
+		nleft = size - len;
+		if (nleft >= newlen)
+			break;
+		growstackblock();
+	}
 	return stackblock() + len;
 }
 
+char *
+stnputs(const char *s, size_t n, char *p)
+{
+	p = makestrspace(n, p);
+	p = mempcpy(p, s, n);
+	return p;
+}
 
-
-void
-ungrabstackstr(s, p)
-	char *s;
-	char *p;
-	{
-	stacknleft += stacknxt - s;
-	stacknxt = s;
-	sstrnleft = stacknleft - (p - s);
+char *
+stputs(const char *s, char *p)
+{
+	return stnputs(s, strlen(s), p);
 }
-/*	$NetBSD: memalloc.h,v 1.11 2000/11/01 19:56:01 christos Exp $	*/
-
 /*-
  * Copyright (c) 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
  * 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
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
  */
 
+#ifndef MEMALLOC_H
+#define MEMALLOC_H
+
+#include <stddef.h>
+#include "shell.h"
+
 struct stackmark {
 	struct stack_block *stackp;
 	char *stacknxt;
-	int stacknleft;
-	struct stackmark *marknext;
+	size_t stacknleft;
 };
 
 
 extern char *stacknxt;
-extern int stacknleft;
-extern int sstrnleft;
+extern size_t stacknleft;
+extern char *sstrend;
 extern int herefd;
 
-pointer ckmalloc __P((int));
-pointer ckrealloc __P((pointer, int));
-char *savestr __P((char *));
-pointer stalloc __P((int));
-void stunalloc __P((pointer));
-void setstackmark __P((struct stackmark *));
-void popstackmark __P((struct stackmark *));
-void growstackblock __P((void));
-void grabstackblock __P((int));
-char *growstackstr __P((void));
-char *makestrspace __P((void));
-void ungrabstackstr __P((char *, char *));
+pointer ckmalloc(size_t);
+pointer ckrealloc(pointer, size_t);
+char *savestr(const char *);
+pointer stalloc(size_t);
+void stunalloc(pointer);
+void pushstackmark(struct stackmark *mark, size_t len);
+void setstackmark(struct stackmark *);
+void popstackmark(struct stackmark *);
+void growstackblock(void);
+void *growstackstr(void);
+char *makestrspace(size_t, char *);
+char *stnputs(const char *, size_t, char *);
+char *stputs(const char *, char *);
 
 
+static inline void grabstackblock(size_t len)
+{
+	stalloc(len);
+}
 
-#define stackblock() stacknxt
+static inline char *_STPUTC(int c, char *p) {
+	if (p == sstrend)
+		p = growstackstr();
+	*p++ = c;
+	return p;
+}
+
+#define stackblock() ((void *)stacknxt)
 #define stackblocksize() stacknleft
-#define STARTSTACKSTR(p)	p = stackblock(), sstrnleft = stackblocksize()
-#define STPUTC(c, p)	(--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
-#define CHECKSTRSPACE(n, p)	{ if (sstrnleft < n) p = makestrspace(); }
-#define USTPUTC(c, p)	(--sstrnleft, *p++ = (c))
-#define STACKSTRNUL(p)	(sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
-#define STUNPUTC(p)	(++sstrnleft, --p)
+#define STARTSTACKSTR(p) ((p) = stackblock())
+#define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
+#define CHECKSTRSPACE(n, p) \
+	({ \
+		char *q = (p); \
+		size_t l = (n); \
+		size_t m = sstrend - q; \
+		if (l > m) \
+			(p) = makestrspace(l, q); \
+		0; \
+	})
+#define USTPUTC(c, p)	(*p++ = (c))
+#define STACKSTRNUL(p)	((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(p)	(--p)
 #define STTOPC(p)	p[-1]
-#define STADJUST(amount, p)	(p += (amount), sstrnleft -= (amount))
-#define grabstackstr(p)	stalloc(stackblocksize() - sstrnleft)
+#define STADJUST(amount, p)	(p += (amount))
+
+#define grabstackstr(p)	stalloc((char *)(p) - (char *)stackblock())
+#define ungrabstackstr(s, p) stunalloc((s))
+#define stackstrend() ((void *)sstrend)
 
 #define ckfree(p)	free((pointer)(p))
+
+#endif