oksh-noxz

[fork] Portable OpenBSD ksh, based on the Public Domain Korn Shell (pdksh).
git clone https://noxz.tech/git/oksh-noxz.git
oksh-noxz

commit: f2c5d6627169cbe3912fe62366ae76c8704e415e
parent: 97bf44c1dc82e5a11e67b496462ee76ab5643421
author: Brian Callahan <dodonpachi-github@mailinator.com>
date:   Mon, 8 Jun 2015 12:08:13 -0400
Update to latest OpenBSD ksh code.
Redo portability work in the style of how I did mg-portable, which will be easier to maintain in the long run.
ACVS/Entries55+++++++++++++++++
ACVS/Entries.Log1+
ACVS/Repository1+
ACVS/Root1+
AGNUmakefile55+++++++++++++++++
MMakefile38++++--------
DMakefile.bsd18------
DMakefile.linux17-----
MREADME.md22+------
Mc_sh.c8---
Memacs.c7---
Mexec.c9++-
Mhistory.c7---
Mjobs.c21++++---
Mlex.c1-
Mmain.c10+--
Mmisc.c14++---
Rcharclass.hportable/common/charclass.hportable/common/charclass.h|
Rreallocarray.cportable/common/reallocarray.cportable/common/reallocarray.c|
Aportable/freebsd/freebsd.h11++++
Aportable/linux/linux.h20++++++
Rqueue.hportable/linux/queue.hportable/linux/queue.h|
Rsetmode.cportable/linux/setmode.cportable/linux/setmode.c|
Rsigname.cportable/linux/signame.cportable/linux/signame.c|
Rstrlcat.cportable/linux/strlcat.cportable/linux/strlcat.c|
Rstrlcpy.cportable/linux/strlcpy.cportable/linux/strlcpy.c|
Aportable/linux/strtonum.c65++++++++++++++++++++
Aportable/netbsd/netbsd.h8+++
R.profileprofileprofile|
Msh.142++++++++-----
Msh.h17+++--
Mtrap.c7---
Mvar.c23++++---
33 files changed, 307 insertions(+), 215 deletions(-)
diff --git a/CVS/Entries b/CVS/Entries
@@ -0,0 +1,55 @@
+/BUG-REPORTS/1.19/Thu Nov 28 10:33:37 2013//
+/CONTRIBUTORS/1.10/Mon Feb  6 16:47:07 2006//
+/ChangeLog/1.16/Thu Nov 28 10:33:37 2013//
+/ChangeLog.0/1.5/Thu Nov 28 10:33:37 2013//
+/IAFA-PACKAGE/1.7/Wed Jul 14 13:37:23 1999//
+/INSTALL/1.1.1.1/Wed Aug 14 06:19:10 1996//
+/LEGAL/1.2/Thu Jul 17 20:59:43 2003//
+/Makefile/1.29/Mon Dec  2 20:41:01 2013//
+/NEWS/1.15/Thu Aug  2 11:05:54 2007//
+/NOTES/1.12/Thu Nov 28 10:33:37 2013//
+/PROJECTS/1.7/Thu Nov 28 10:33:37 2013//
+/README/1.10/Mon Mar 10 03:48:16 2003//
+/alloc.c/1.8/Mon Jul 21 17:30:08 2008//
+/c_ksh.c/1.34/Tue Dec 17 16:37:05 2013//
+/c_sh.c/1.45/Wed Aug 27 08:26:04 2014//
+/c_test.c/1.18/Sun Mar  1 20:11:06 2009//
+/c_test.h/1.4/Mon Dec 20 11:34:26 2004//
+/c_ulimit.c/1.19/Thu Nov 28 10:33:37 2013//
+/config.h/1.14/Mon Mar 14 21:20:00 2011//
+/edit.c/1.40/Thu Mar 12 10:20:30 2015//
+/edit.h/1.9/Mon May 30 17:14:35 2011//
+/emacs.c/1.50/Wed Mar 25 12:10:52 2015//
+/eval.c/1.40/Sat Sep 14 20:09:30 2013//
+/exec.c/1.51/Sat Apr 18 18:28:36 2015//
+/expand.h/1.6/Wed Mar 30 17:16:37 2005//
+/expr.c/1.24/Mon Dec  8 14:26:31 2014//
+/history.c/1.40/Thu Nov 20 15:22:39 2014//
+/io.c/1.25/Mon Aug 11 20:28:47 2014//
+/jobs.c/1.41/Sat Apr 18 18:28:36 2015//
+/ksh.1/1.159/Wed Mar 25 12:10:52 2015//
+/ksh_limval.h/1.2/Sat Dec 18 20:55:52 2004//
+/lex.c/1.49/Tue Dec 17 16:37:06 2013//
+/lex.h/1.13/Sun Mar  3 19:11:34 2013//
+/mail.c/1.17/Thu Nov 28 10:33:37 2013//
+/main.c/1.55/Mon Feb  9 09:09:30 2015//
+/misc.c/1.40/Wed Mar 18 15:12:36 2015//
+/mknod.c/1.2/Tue Oct 27 23:59:21 2009//
+/path.c/1.12/Wed Mar 30 17:16:37 2005//
+/proto.h/1.35/Wed Sep  4 15:49:19 2013//
+/sh.1/1.128/Mon May  4 19:34:13 2015//
+/sh.h/1.33/Wed Dec 18 13:53:12 2013//
+/shf.c/1.16/Fri Apr 19 17:36:09 2013//
+/shf.h/1.6/Sun Dec 11 18:53:51 2005//
+/syn.c/1.29/Mon Jun  3 18:40:05 2013//
+/table.c/1.15/Sun Feb 19 07:52:30 2012//
+/table.h/1.8/Sun Feb 19 07:52:30 2012//
+/trap.c/1.23/Wed May 19 17:36:08 2010//
+/tree.c/1.20/Wed Jun 27 07:17:19 2012//
+/tree.h/1.10/Mon Mar 28 21:28:22 2005//
+/tty.c/1.10/Sun Aug 10 02:44:26 2014//
+/tty.h/1.5/Mon Dec 20 11:34:26 2004//
+/var.c/1.41/Fri Apr 17 17:20:41 2015//
+/version.c/1.12/Wed Jul 14 13:37:24 1999//
+/vi.c/1.28/Wed Dec 18 16:45:46 2013//
+D/tests////
diff --git a/CVS/Entries.Log b/CVS/Entries.Log
@@ -0,0 +1 @@
+R D/tests////
diff --git a/CVS/Repository b/CVS/Repository
@@ -0,0 +1 @@
+src/bin/ksh
diff --git a/CVS/Root b/CVS/Root
@@ -0,0 +1 @@
+anoncvs@anoncvs.comstyle.com:/cvs
diff --git a/GNUmakefile b/GNUmakefile
@@ -0,0 +1,55 @@
+# oksh portable GNUmakefile
+# This file written by Brian Callahan <bcallah@openbsd.org>
+# and released into the Public Domain.
+
+PROG = oksh
+
+PREFIX ?= /usr/local
+MANDIR ?= ${PREFIX}/man
+DOCDIR ?= ${PREFIX}/share/doc/oksh
+INSTALL = /usr/bin/install
+
+CFLAGS ?= -O2 -pipe
+CFLAGS += -Wall
+
+OBJS =	alloc.o c_ksh.o c_sh.o c_test.o c_ulimit.o edit.o emacs.o eval.o \
+	exec.o expr.o history.o io.o jobs.o lex.o mail.o main.o mknod.o \
+	misc.o path.o shf.o syn.o table.o trap.o tree.o tty.o var.o \
+	version.o vi.o
+
+#
+# Portability stuff.
+#
+UNAME_S := $(shell uname -s)
+ifeq ($(UNAME_S),Linux)
+GROUP =	root
+OBJS +=	portable/common/reallocarray.o portable/linux/setmode.o \
+	portable/linux/signame.o portable/linux/strlcat.o \
+	portable/linux/strlcpy.o portable/linux/strtonum.o
+else ifeq ($(UNAME_S),FreeBSD)
+GROUP =	bin
+OBJS +=	portable/common/reallocarray.o
+else ifeq ($(UNAME_S),DragonFly)
+GROUP =	bin
+OBJS += portable/common/reallocarray.o
+else ifeq ($(UNAME_S),NetBSD)
+GROUP =	bin
+OBJS += portable/common/reallocarray.o
+endif
+
+#
+# Only update /etc/shells at install time, not during update
+#
+UPDATE := `grep -w ${PREFIX}/bin/${PROG} /etc/shells > /dev/null;\
+	[ $$? -ne 0] && echo "${PREFIX}/bin/${PROG}" >> /etc/shells`
+
+all: ${OBJS}
+	${CC} -o ${PROG} ${OBJS}
+
+install: all
+	${INSTALL} -c -s -o root -g ${GROUP} -m 555 ${PROG} ${PREFIX}/bin
+	${INSTALL} -c -s -o root -g ${GROUP} -m 444 oksh.1 ${MANDIR}/man1/${PROG}.1
+	echo ${UPDATE}
+
+clean:
+	rm -f ${PROG} ${OBJS}
diff --git a/Makefile b/Makefile
@@ -1,29 +1,17 @@
-# oksh Makefile
+#	$OpenBSD: Makefile,v 1.29 2013/12/02 20:41:01 millert Exp $
 
-# OpenBSD defaults
-CC ?= cc
-CFLAGS ?= -O2 -pipe
-PREFIX ?= /usr/local
+PROG=	ksh
+SRCS=	alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c eval.c \
+	exec.c expr.c history.c io.c jobs.c lex.c mail.c main.c mknod.c \
+	misc.c path.c shf.c syn.c table.c trap.c tree.c tty.c var.c \
+	version.c vi.c
 
-CFLAGS += -Wall
-LDFLAGS += -static
+DEFS=	-Wall
+CFLAGS+=${DEFS} -I. -I${.CURDIR} -I${.CURDIR}/../../lib/libc/gen
+MAN=	ksh.1 sh.1
 
-PROG =	oksh
-OBJS =	alloc.o c_ksh.o c_sh.o c_test.o c_ulimit.o edit.o emacs.o \
-	eval.o exec.o expr.o history.o io.o jobs.o lex.o mail.o main.o \
-	mknod.o misc.o path.o shf.o syn.o table.o trap.o tree.o tty.o \
-	var.o version.o vi.o setmode.o signame.o strlcat.o strlcpy.o \
-	reallocarray.o
+LINKS=	${BINDIR}/ksh ${BINDIR}/rksh
+LINKS+=	${BINDIR}/ksh ${BINDIR}/sh
+MLINKS=	ksh.1 rksh.1
 
-# set OS platform (HACKITY HACK for gmake/bsd make compat)
-OS != echo `uname 2>/dev/null` | tr 'A-Z' 'a-z' | sed -E 's/.*(bsd|linux)/\1/'
-OS ?= linux
-
-all:	${OBJS}
-	${CC} ${LDFLAGS} -o ${PROG} ${OBJS}
-
-install: os
-include Makefile.${OS}
-
-clean:
-	rm -f ${PROG} *.o *~
+.include <bsd.prog.mk>
diff --git a/Makefile.bsd b/Makefile.bsd
@@ -1,18 +0,0 @@
-# group in BSD is wheel
-GROUP = wheel
-SEARCH=	grep -cw "oksh" /etc/shells
-
-# only install if root
-os: all
-	@if [ "`id -un`" != "root" ]; then \
-		echo ERROR: \'make install\' requires root, su, or sudo; \
-		exit 1; \
-	fi
-
-	install -c -s -o root -g ${GROUP} -m 555 oksh ${PREFIX}/bin
-	install -c -o root -g ${GROUP} -m 444 oksh.1 ${PREFIX}/man/man1
-
-# update /etc/shells at install time only, not during upgrade
-.if	${SEARCH:sh} == 0
-	echo "${PREFIX}/bin/oksh" >> /etc/shells
-.endif
diff --git a/Makefile.linux b/Makefile.linux
@@ -1,17 +0,0 @@
-# group in Linux is root
-GROUP = root
-
-# only update /etc/shells at install time, not during update
-UPDATE:= `grep -w oksh /etc/shells > /dev/null;\
-	[ $$? -ne 0 ] && echo "${PREFIX}/bin/oksh" >> /etc/shells`
-
-# make install can only be run by root
-os: all
-ifneq ($(shell id -un),root)
-	@echo ERROR: \'make install\' requires root, su, or sudo
-	@exit 1
-endif
-
-	install -c -s -o root -g ${GROUP} -m 555 oksh ${PREFIX}/bin
-	install -c -o root -g ${GROUP} -m 444 oksh.1 ${PREFIX}/man/man1
-	echo ${UPDATE}
diff --git a/README.md b/README.md
@@ -8,27 +8,9 @@ Because other operating systems deserve a good shell to use.
 Originally a port of ksh to FreeBSD. The default FreeBSD shell is tcsh.
 No one likes tcsh. DragonFly BSD should also just work.
 Later NetBSD support was added. NetBSD also has a ksh variant so it might be less useful there.
-Linux support, tested on Slackware, exists.
+Linux support, tested on Slackware and Ubuntu, exists.
 Other operating system support welcome and appreciated.
 
-Changes
--------
-* Added #include &lt;time.h&gt; in lex.c
-* Added #include &lt;sys/param.h&gt; and changed _PW_NAME_LEN to MAXLOGNAME in main.c
-* Added #define srand_deterministic block in var.c
-* Added charclass.h from OpenBSD libc
-* NetBSD does not have setresgid and setresuid so provide compatability calls in misc.c
-* Added LDFLAGS+=-static line in Makefile
-* Renamed README to README.pdksh
-* Added README.md (this file)
-
-Linux-specific changes
-----------------------
-Adding Linux support was invasive.
-* Added OpenBSD vesions of reallocarray.c, setmode.c, signame.c, strlcat.c, and strlcpy.c, all under #ifdef __linux__
-* Added defines, externs, and includes where needed, under #ifdef __linux__
-* Added OpenBSD &lt;sys/queue.h&gt; header as "queue.h" under #ifdef __linux__ and force Linux to use it
-
 License
 -------
 Most files are public domain (see LEGAL).
@@ -36,4 +18,4 @@ The rest are BSD or ISC licensed.
 
 Get a tarball
 -------------
-http://homepages.rpi.edu/~callab3/oksh-4.tar.gz
+http://devio.us/~bcallah/oksh/oksh-5.tar.gz
diff --git a/c_sh.c b/c_sh.c
@@ -11,14 +11,6 @@
 
 static void p_time(struct shf *, int, struct timeval *, int, char *, char *);
 
-/*
- * Linux does not have getmode() or setmode().
- */
-#ifdef __linux__
-extern mode_t getmode(const void *, mode_t);
-extern void *setmode(const char *);
-#endif
-
 /* :, false and true */
 int
 c_label(char **wp)
diff --git a/emacs.c b/emacs.c
@@ -21,13 +21,6 @@
 #include <locale.h>
 #include "edit.h"
 
-/*
- * Linux sucks.
- */
-#ifdef __linux__
-#include "queue.h"
-#endif
-
 static	Area	aedit;
 #define	AEDIT	&aedit		/* area for kill ring and macro defns */
 
diff --git a/exec.c b/exec.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: exec.c,v 1.50 2013/06/10 21:09:27 millert Exp $	*/
+/*	$OpenBSD: exec.c,v 1.51 2015/04/18 18:28:36 deraadt Exp $	*/
 
 /*
  * execute command tree
@@ -1234,6 +1234,7 @@ do_selectargs(char **ap, bool print_menu)
 	static const char *const read_args[] = {
 		"read", "-r", "REPLY", (char *) 0
 	};
+	const char *errstr;
 	char *s;
 	int i, argct;
 
@@ -1252,8 +1253,10 @@ do_selectargs(char **ap, bool print_menu)
 			return (char *) 0;
 		s = str_val(global("REPLY"));
 		if (*s) {
-			i = atoi(s);
-			return (i >= 1 && i <= argct) ? ap[i - 1] : null;
+			i = strtonum(s, 1, argct, &errstr);
+			if (errstr)
+				return null;
+			return ap[i - 1];
 		}
 		print_menu = 1;
 	}
diff --git a/history.c b/history.c
@@ -21,13 +21,6 @@
 #ifdef HISTORY
 # include <sys/mman.h>
 
-/*
- * Linux...
- */
-#ifdef __linux__
-#include <sys/file.h>
-#endif
-
 /*
  *	variables for handling the data file
  */
diff --git a/jobs.c b/jobs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: jobs.c,v 1.40 2013/09/04 15:49:18 millert Exp $	*/
+/*	$OpenBSD: jobs.c,v 1.41 2015/04/18 18:28:36 deraadt Exp $	*/
 
 /*
  * Process and job control
@@ -22,13 +22,6 @@
 #include <sys/resource.h>
 #include "tty.h"
 
-/*
- * Linux...
- */
-#ifdef __linux__
-#define CHILD_MAX 80
-#endif
-
 /* Order important! */
 #define PRUNNING	0
 #define PEXITED		1
@@ -1435,11 +1428,17 @@ static Job *
 j_lookup(const char *cp, int *ecodep)
 {
 	Job		*j, *last_match;
+	const char	*errstr;
 	Proc		*p;
 	int		len, job = 0;
 
 	if (digit(*cp)) {
-		job = atoi(cp);
+		job = strtonum(cp, 1, INT_MAX, &errstr);
+		if (errstr) {
+			if (ecodep)
+				*ecodep = JL_NOSUCH;
+			return (Job *) 0;
+		}
 		/* Look for last_proc->pid (what $! returns) first... */
 		for (j = job_list; j != (Job *) 0; j = j->next)
 			if (j->last_proc && j->last_proc->pid == job)
@@ -1474,7 +1473,9 @@ j_lookup(const char *cp, int *ecodep)
 
 	case '0': case '1': case '2': case '3': case '4':
 	case '5': case '6': case '7': case '8': case '9':
-		job = atoi(cp);
+		job = strtonum(cp, 1, INT_MAX, &errstr);
+		if (errstr)
+			break;
 		for (j = job_list; j != (Job *) 0; j = j->next)
 			if (j->job == job)
 				return j;
diff --git a/lex.c b/lex.c
@@ -5,7 +5,6 @@
  */
 
 #include "sh.h"
-#include <time.h>
 #include <libgen.h>
 #include <ctype.h>
 
diff --git a/main.c b/main.c
@@ -7,19 +7,11 @@
 #define	EXTERN				/* define EXTERNs in sh.h */
 
 #include "sh.h"
-#include <sys/param.h>
 #include <sys/stat.h>
 #include <pwd.h>
 
 extern char **environ;
 
-/*
- * Linux...
- */
-#ifdef __linux__
-#define MAXLOGNAME LOGIN_NAME_MAX
-#endif
-
 /*
  * global data
  */
@@ -70,7 +62,7 @@ static const char *initcoms [] = {
 	NULL
 };
 
-char username[MAXLOGNAME];
+char username[_PW_NAME_LEN + 1];
 
 #define version_param  (initcoms[2])
 
diff --git a/misc.c b/misc.c
@@ -6,7 +6,11 @@
 
 #include "sh.h"
 #include <ctype.h>
+#ifdef __OpenBSD__
 #include "charclass.h"
+#else
+#include "portable/common/charclass.h"
+#endif
 
 short ctypes [UCHAR_MAX+1];	/* type bits for unsigned char */
 
@@ -295,19 +299,9 @@ change_flag(enum sh_flag f,
 	if (f == FPRIVILEGED && oldval && !newval) {
 		gid_t gid = getgid();
 
-#ifdef __NetBSD__
-		setgid(gid);
-		setegid(gid);
-#else
 		setresgid(gid, gid, gid);
-#endif
 		setgroups(1, &gid);
-#ifdef __NetBSD__
-		setuid(ksheuid);
-		seteuid(ksheuid);
-#else
 		setresuid(ksheuid, ksheuid, ksheuid);
-#endif
 	} else if (f == FPOSIX && newval) {
 #ifdef BRACE_EXPAND
 		Flag(FBRACEEXPAND) = 0
diff --git a/charclass.h b/portable/common/charclass.h
rename charclass.h → portable/common/charclass.h
diff --git a/reallocarray.c b/portable/common/reallocarray.c
rename reallocarray.c → portable/common/reallocarray.c
@@ -15,11 +15,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * Linux still sucks.
- */
-#ifdef __linux__
-
 #include <sys/types.h>
 #include <errno.h>
 #include <stdint.h>
@@ -41,5 +36,3 @@ reallocarray(void *optr, size_t nmemb, size_t size)
 	}
 	return realloc(optr, size * nmemb);
 }
-
-#endif /* #ifdef __linux__ */
diff --git a/portable/freebsd/freebsd.h b/portable/freebsd/freebsd.h
@@ -0,0 +1,11 @@
+/*
+ * FreeBSD and DragonFly BSD support.
+ */
+
+/* Includes */
+#include <sys/param.h>
+#include <time.h>
+
+/* Defines */
+#define _PW_NAME_LEN	MAXLOGNAME
+#define srand_deterministic(x)	srand(x)
diff --git a/portable/linux/linux.h b/portable/linux/linux.h
@@ -0,0 +1,20 @@
+/*
+ * Linux support.
+ */
+
+/* Includes */
+#include <sys/file.h>
+#include <sys/param.h>
+#include <time.h>
+
+/* Defines */
+#define _PW_NAME_LEN	LOGIN_NAME_MAX
+#define CHILD_MAX	80
+#define srand_deterministic(x)	srand(x)
+
+/* Functions */
+const char *const sys_signame;
+mode_t	getmode(const void *, mode_t);
+void   *setmode(const char *);
+size_t	strlcat(char *, const char *, size_t);
+size_t	strlcpy(char *, const char *, size_t);
diff --git a/queue.h b/portable/linux/queue.h
rename queue.h → portable/linux/queue.h
@@ -32,11 +32,6 @@
  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
  */
 
-/*
- * Linux sucks.
- */
-#ifdef __linux__
-
 /*
  * This file defines five types of data structures: singly-linked lists, 
  * lists, simple queues, tail queues, and circular queues.
@@ -646,5 +641,3 @@ struct {								\
 	_Q_INVALIDATE((elm)->field.cqe_prev);				\
 	_Q_INVALIDATE((elm)->field.cqe_next);				\
 } while (0)
-
-#endif /* #ifdef __linux__ */
diff --git a/setmode.c b/portable/linux/setmode.c
rename setmode.c → portable/linux/setmode.c
@@ -33,12 +33,6 @@
  * SUCH DAMAGE.
  */
 
-/*
- * Linux does not have these functions.
- */
-
-#ifdef __linux__
-
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -459,5 +453,3 @@ compress_mode(BITCMD *set)
 		}
 	}
 }
-
-#endif /* #ifdef __linux__ */
diff --git a/signame.c b/portable/linux/signame.c
rename signame.c → portable/linux/signame.c
@@ -28,11 +28,6 @@
  * SUCH DAMAGE.
  */
 
-/*
- * Linux sucks.
- */
-#ifdef __linux__
-
 #include <signal.h>
 #include <unistd.h>
 
@@ -71,5 +66,3 @@ const char *const sys_signame[NSIG] = {
 	"USR2",		/* SIGUSR2 */
 	"THR",		/* SIGTHR */
 };
-
-#endif /* #ifdef __linux__ */
diff --git a/strlcat.c b/portable/linux/strlcat.c
rename strlcat.c → portable/linux/strlcat.c
@@ -16,11 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * glibc sucks.
- */
-#ifdef __linux__
-
 #include <sys/types.h>
 #include <string.h>
 
@@ -58,5 +53,3 @@ strlcat(char *dst, const char *src, size_t dsize)
 
 	return(dlen + (src - osrc));	/* count does not include NUL */
 }
-
-#endif /* #ifdef __linux__ */
diff --git a/strlcpy.c b/portable/linux/strlcpy.c
rename strlcpy.c → portable/linux/strlcpy.c
@@ -16,11 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * Linux sucks.
- */
-#ifdef __linux__
-
 #include <sys/types.h>
 #include <string.h>
 
@@ -53,5 +48,3 @@ strlcpy(char *dst, const char *src, size_t dsize)
 
 	return(src - osrc - 1);	/* count does not include NUL */
 }
-
-#endif /* #ifdef __linux__ */
diff --git a/portable/linux/strtonum.c b/portable/linux/strtonum.c
@@ -0,0 +1,65 @@
+/*	$OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $	*/
+
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define	INVALID		1
+#define	TOOSMALL	2
+#define	TOOLARGE	3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+    const char **errstrp)
+{
+	long long ll = 0;
+	int error = 0;
+	char *ep;
+	struct errval {
+		const char *errstr;
+		int err;
+	} ev[4] = {
+		{ NULL,		0 },
+		{ "invalid",	EINVAL },
+		{ "too small",	ERANGE },
+		{ "too large",	ERANGE },
+	};
+
+	ev[0].err = errno;
+	errno = 0;
+	if (minval > maxval) {
+		error = INVALID;
+	} else {
+		ll = strtoll(numstr, &ep, 10);
+		if (numstr == ep || *ep != '\0')
+			error = INVALID;
+		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+			error = TOOSMALL;
+		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+			error = TOOLARGE;
+	}
+	if (errstrp != NULL)
+		*errstrp = ev[error].errstr;
+	errno = ev[error].err;
+	if (error)
+		ll = 0;
+
+	return (ll);
+}
diff --git a/portable/netbsd/netbsd.h b/portable/netbsd/netbsd.h
@@ -0,0 +1,8 @@
+/*
+ * NetBSD support.
+ */
+
+/* Defines */
+#define setresgid(x, x, x)	setgid(x); setegid(x)
+#define setresuid(x, x, x)	setuid(x); seteuid(x)
+#define srand_deterministic(x)	srand(x)
diff --git a/.profile b/profile
rename .profile → profile
@@ -1,4 +1,5 @@
 # oksh initialization
+# Sample .profile
 
 PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games
 export PATH HOME TERM
diff --git a/sh.1 b/sh.1
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: sh.1,v 1.126 2015/03/31 21:23:34 jmc Exp $
+.\"	$OpenBSD: sh.1,v 1.128 2015/05/04 19:34:13 jmc Exp $
 .\"
 .\" Copyright (c) 2015 Jason McIntyre <jmc@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: March 31 2015 $
+.Dd $Mdocdate: May 4 2015 $
 .Dt SH 1
 .Os
 .Sh NAME
@@ -80,7 +80,7 @@ which can be used with the
 option.
 .Bl -tag -width Ds
 .It Fl a
-allexport.
+Allexport.
 Variable assignments are exported to all child processes
 of the running shell.
 If the assignment precedes a command it does not persist
@@ -92,22 +92,22 @@ or
 .Ic read
 makes the assignment.
 .It Fl b
-notify.
+Notify.
 The user is given notice asynchronously when background jobs complete.
 .It Fl C
-noclobber.
+Noclobber.
 Do not permit the redirection operator
 .Pq Sq >
 to clobber (overwrite) existing files.
 .It Fl e
-errexit.
+Errexit.
 Exit the shell immediately should an error occur or a command fail.
 For pipelines and
 .Cm &&
 and
 .Cm ||
 constructs, only exit if the last component fails.
-errexit is ignored for
+Errexit is ignored for
 .Ic while ,
 .Ic until ,
 .Ic if ,
@@ -116,7 +116,7 @@ and
 lists and pipelines beginning
 .Sq !\& .
 .It Fl f
-noglob.
+Noglob.
 Do not expand file name patterns.
 .It Fl h
 When a utility is first executed,
@@ -129,7 +129,7 @@ Enable behaviour convenient for an interactive shell.
 This option is set by default
 if the session is attached to a terminal.
 .It Fl m
-monitor.
+Monitor.
 Fully enable job control:
 enable the
 .Ic bg
@@ -142,7 +142,7 @@ and report when a job changes status.
 The processes of a job share their own process group.
 This option is set by default for interactive shells.
 .It Fl n
-noexec.
+Noexec.
 Read commands but do not execute them \(en
 useful for checking syntax errors in scripts.
 This option is ignored for interactive shells.
@@ -161,13 +161,17 @@ so setting this can prevent accidental logouts
 command).
 .It nolog
 Do not enter function definitions into command history.
+.It posix
+Enable POSIX mode
+(see
+.Sx STANDARDS ) .
 .It vi
 Enable
 .Xr vi 1
 command line editing.
 .El
 .It Fl u
-nounset.
+Nounset.
 If a command references an unset parameter,
 write an error to standard output instead of executing the command.
 This option is ignored for the special parameters
@@ -177,10 +181,10 @@ and
 If the shell is not interactive,
 immediately exit.
 .It Fl v
-verbose.
+Verbose.
 Write input to standard error after reading it.
 .It Fl x
-xtrace.
+Xtrace.
 Write a trace for each command to standard error after expanding it,
 and before executing it.
 .El
@@ -1970,7 +1974,7 @@ The process ID of the most recent background command.
 .Sh ENVIRONMENT
 The following environment variables affect the execution of
 .Nm :
-.Bl -tag -width "MAILCHECKXXX"
+.Bl -tag -width "POSIXLY_CORRECT"
 .It Ev CDPATH
 Colon separated list of directories used by the
 .Ic cd
@@ -2061,6 +2065,10 @@ is:
 .Bd -literal -offset 2n
 /usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin
 .Ed
+.It Ev POSIXLY_CORRECT
+Enable POSIX mode
+(see
+.Sx STANDARDS ) .
 .It Ev PPID
 The shell's parent process ID.
 Subshells have the same
@@ -2202,3 +2210,9 @@ built-ins should exit/return from the outermost loop if the argument
 .Ar n
 is greater than the level of loops.
 .El
+.Pp
+Enabling POSIX mode changes some behaviour to make
+.Nm
+adhere more strictly to the
+.St -p1003.1-2008
+specification.
diff --git a/sh.h b/sh.h
@@ -28,6 +28,17 @@
 
 #include <paths.h>
 
+/* oksh portable: system-specific headers */
+#ifdef __linux__
+#include "portable/linux/linux.h"
+#endif
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include "portable/freebsd/freebsd.h"
+#endif
+#ifdef __NetBSD__
+#include "portable/netbsd/netbsd.h"
+#endif
+
 /* Find a integer type that is at least 32 bits (or die) - SIZEOF_* defined
  * by autoconf (assumes an 8 bit byte, but I'm not concerned).
  * NOTE: INT32 may end up being more than 32 bits.
@@ -418,9 +429,3 @@ EXTERN	int	x_cols I__(80);	/* tty columns */
 # undef EXTERN
 #endif
 #undef I__
-
-/* Linux-specific additions */
-#ifdef __linux__
-extern size_t strlcat(char *, const char *, size_t);
-extern size_t strlcpy(char *, const char *, size_t);
-#endif
diff --git a/trap.c b/trap.c
@@ -6,13 +6,6 @@
 
 #include "sh.h"
 
-/*
- * Linux again...
- */
-#ifdef __linux__
-extern const char *const sys_signame;
-#endif
-
 Trap sigtraps[NSIG + 1];
 
 static struct sigaction Sigact_ign, Sigact_trap;
diff --git a/var.c b/var.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: var.c,v 1.40 2014/12/12 05:00:55 jsg Exp $	*/
+/*	$OpenBSD: var.c,v 1.41 2015/04/17 17:20:41 deraadt Exp $	*/
 
 #include "sh.h"
 #include <time.h>
@@ -8,13 +8,6 @@
 #include <limits.h>
 #include <stdlib.h>
 
-/*
- * Since no one else has this...
- */
-#ifndef __OpenBSD__
-#define srand_deterministic(x) srand(x)
-#endif
-
 /*
  * Variables
  *
@@ -1014,8 +1007,18 @@ setspec(struct tbl *vp)
 			set_editmode(str_val(vp));
 		break;
 	case V_COLUMNS:
-		if ((x_cols = intval(vp)) <= MIN_COLS)
-			x_cols = MIN_COLS;
+		{
+			long l;
+
+			if (getint(vp, &l, false) == -1) {
+				x_cols = MIN_COLS;
+				break;
+			}
+			if (l <= MIN_COLS || l > INT_MAX)
+				x_cols = MIN_COLS;
+			else
+				x_cols = l;
+		}
 		break;
 #endif /* EDIT */
 	case V_MAIL: