Index: Makefile
===================================================================
--- Makefile	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ Makefile	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -71,4 +71,5 @@
 LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-pci_bus.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-pci_cfgreg.c
+LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-program.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-rwlock.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-shell.c
@@ -87,8 +88,6 @@
 LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-timesupport.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-vm_glue.c
-LIB_C_FILES += rtemsbsd/rtems/rtems-getprogname.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-kvm.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-net-setup.c
-LIB_C_FILES += rtemsbsd/rtems/rtems-shell.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-syslog-initialize.c
 LIB_C_FILES += rtemsbsd/rtems/rtems-syspoll.c
Index: freebsd-to-rtems.py
===================================================================
--- freebsd-to-rtems.py	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd-to-rtems.py	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -628,4 +628,5 @@
 		'rtems/rtems-bsd-pci_bus.c',
 		'rtems/rtems-bsd-pci_cfgreg.c',
+		'rtems/rtems-bsd-program.c',
 		'rtems/rtems-bsd-rwlock.c',
 		'rtems/rtems-bsd-shell.c',
@@ -644,8 +645,6 @@
 		'rtems/rtems-bsd-timesupport.c',
 		'rtems/rtems-bsd-vm_glue.c',
-		'rtems/rtems-getprogname.c',
 		'rtems/rtems-kvm.c',
 		'rtems/rtems-net-setup.c',
-		'rtems/rtems-shell.c',
 		'rtems/rtems-syslog-initialize.c',
 		'rtems/rtems-syspoll.c',
Index: freebsd/include/err.h
===================================================================
--- freebsd/include/err.h	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/include/err.h	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -48,17 +48,4 @@
 #include <rtems/bsd/sys/_types.h>
 
-#ifdef __rtems__
-#include <setjmp.h>
-typedef struct  rtems_shell_globals_s {
-  jmp_buf exit_jmp;
-  int     exit_code;
-} rtems_shell_globals_t;
-extern rtems_shell_globals_t *rtems_shell_globals;
-void rtems_shell_exit (int code);
-
-#define exit rtems_shell_exit
-#endif
-
-
 __BEGIN_DECLS
 void	err(int, const char *, ...) __dead2 __printf0like(2, 3);
@@ -75,6 +62,8 @@
 void	warnx(const char *, ...) __printflike(1, 2);
 void	vwarnx(const char *, __va_list) __printflike(1, 0);
+#ifndef __rtems__
 void	err_set_file(void *);
 void	err_set_exit(void (*)(int));
+#endif /* __rtems__ */
 __END_DECLS
 
Index: freebsd/lib/libc/gen/err.c
===================================================================
--- freebsd/lib/libc/gen/err.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/lib/libc/gen/err.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -47,7 +47,14 @@
 #include "libc_private.h"
 
+#ifndef __rtems__
 static FILE *err_file; /* file to use for error output */
 static void (*err_exit)(int);
-
+#else /* __rtems__ */
+#include <machine/rtems-bsd-program.h>
+#define err_file stderr
+#define err_set_file(x) do { } while (0)
+#endif /* __rtems__ */
+
+#ifndef __rtems__
 /*
  * This is declared to take a `void *' so that the caller is not required
@@ -69,4 +76,5 @@
 	err_exit = ef;
 }
+#endif /* __rtems__ */
 
 __weak_reference(_err, err);
@@ -110,6 +118,8 @@
 	}
 	fprintf(err_file, "%s\n", strerror(code));
+#ifndef __rtems__
 	if (err_exit)
 		err_exit(eval);
+#endif /* __rtems__ */
 	exit(eval);
 }
@@ -133,6 +143,8 @@
 		vfprintf(err_file, fmt, ap);
 	fprintf(err_file, "\n");
+#ifndef __rtems__
 	if (err_exit)
 		err_exit(eval);
+#endif /* __rtems__ */
 	exit(eval);
 }
Index: freebsd/sbin/ifconfig/ifconfig.c
===================================================================
--- freebsd/sbin/ifconfig/ifconfig.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/sbin/ifconfig/ifconfig.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -116,23 +116,4 @@
 
 #ifdef __rtems__
-static int main_ifconfig(int argc, char *argv[]);
-static int rtems_shell_main_ifconfig(int argc, char *argv[])
-{
-  rtems_shell_globals_t  ifconfig_globals;
-  rtems_shell_globals = &ifconfig_globals;
-  memset (rtems_shell_globals, 0, sizeof (ifconfig_globals));
-  descr = NULL;
-  descrlen = 64;
-  newaddr = 1;
-  supmedia = 0;
-  printkeys = 0;	
-  ifconfig_globals.exit_code = 1;
-  if (setjmp (ifconfig_globals.exit_jmp) == 0)
-    return main_ifconfig ( argc, argv);
-  return ifconfig_globals.exit_code;
-}
-#endif
-
-#ifdef __rtems__
 static struct ifconfig_option *opts = NULL;
 
@@ -183,10 +164,21 @@
 
 #ifdef __rtems__
-int
-main_ifconfig(int argc, char *argv[])
-#else
+#include <machine/rtems-bsd-program.h>
+
+static int main(int argc, char *argv[]);
+
+static int rtems_shell_main_ifconfig(int argc, char *argv[])
+{
+	descr = NULL;
+	descrlen = 64;
+	newaddr = 1;
+	supmedia = 0;
+	printkeys = 0;
+
+	return rtems_bsd_program_call_main("ifconfig", main, argc, argv);
+}
+#endif /* __rtems__ */
 int
 main(int argc, char *argv[])
-#endif
 {
 	int c, all, namesonly, downonly, uponly;
Index: freebsd/sbin/ping/ping.c
===================================================================
--- freebsd/sbin/ping/ping.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/sbin/ping/ping.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -219,42 +219,37 @@
 
 #ifdef __rtems__
-static int main_ping(int argc, char *const *argv);
+#include <machine/rtems-bsd-program.h>
+
+static int main(int argc, char **argv);
+
 static int rtems_shell_main_ping(int argc, char *argv[])
 {
-  rtems_shell_globals_t  ping_globals;
-  rtems_shell_globals = &ping_globals;
-  memset (rtems_shell_globals, 0, sizeof (ping_globals));
-  BBELL = '\a';
-  BSPACE = '\b';
-  DOT = '.';
-  icmp_type = ICMP_ECHO;
-  icmp_type_rsp = ICMP_ECHOREPLY;
-  phdr_len = 0;
-  sweepmin = 0;
-  sweepincr = 1;
-  interval = 1000;
-  waittime = MAXWAIT;
-  nrcvtimeout = 0;
-  tmin = 999999999.0;
-  tmax = 0.0;
-  tsum = 0.0;
-  tsumsq = 0.0;
-  ping_globals.exit_code = 1;
-  if (setjmp (ping_globals.exit_jmp) == 0)
-    return main_ping (argc, argv);
-  return ping_globals.exit_code;
+	BBELL = '\a';
+	BSPACE = '\b';
+	DOT = '.';
+	icmp_type = ICMP_ECHO;
+	icmp_type_rsp = ICMP_ECHOREPLY;
+	phdr_len = 0;
+	sweepmin = 0;
+	sweepincr = 1;
+	interval = 1000;
+	waittime = MAXWAIT;
+	nrcvtimeout = 0;
+	tmin = 999999999.0;
+	tmax = 0.0;
+	tsum = 0.0;
+	tsumsq = 0.0;
+
+	return rtems_bsd_program_call_main("ping", main, argc, argv);
 }
-#endif
-
-
-
+#endif /* __rtems__ */
 int
-#ifdef __rtems__
-main_ping(argc, argv)
-#else
 main(argc, argv)
-#endif
 	int argc;
+#ifndef __rtems__
 	char *const *argv;
+#else /* __rtems__ */
+	char **argv;
+#endif /* __rtems__ */
 {
 	struct sockaddr_in from, sock_in;
Index: freebsd/sbin/route/route.c
===================================================================
--- freebsd/sbin/route/route.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/sbin/route/route.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -117,22 +117,4 @@
 void usage(const char *) __dead2;
 
-#ifdef __rtems__
-
-static int main_route(int argc, char **argv);
-
-static int rtems_shell_main_route(int argc, char *argv[])
-{
-  rtems_shell_globals_t  route_globals;
-  rtems_shell_globals = &route_globals;
-  memset (rtems_shell_globals, 0, sizeof (route_globals));
-  route_globals.exit_code = 1;
-  if (setjmp (route_globals.exit_jmp) == 0)
-    return main_route ( argc, argv);
-  return route_globals.exit_code;
-}
-
-#endif
-
-
 void
 usage(cp)
@@ -148,9 +130,15 @@
 
 #ifdef __rtems__
+#include <machine/rtems-bsd-program.h>
+
+static int main(int argc, char **argv);
+
+static int rtems_shell_main_route(int argc, char *argv[])
+{
+	return rtems_bsd_program_call_main("route", main, argc, argv);
+}
+#endif /* __rtems__ */
 int
-main_route(argc, argv)
-#else
 main(argc, argv)
-#endif
 	int argc;
 	char **argv;
Index: freebsd/sys/sys/proc.h
===================================================================
--- freebsd/sys/sys/proc.h	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/sys/sys/proc.h	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -202,4 +202,5 @@
 	rtems_chain_node td_node;
 	Thread_Control *td_thread;
+	struct rtems_bsd_program_control *td_prog_ctrl;
 	char td_name [16];
 #endif /* __rtems__ */
Index: freebsd/sys/sys/systm.h
===================================================================
--- freebsd/sys/sys/systm.h	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/sys/sys/systm.h	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -154,6 +154,8 @@
 struct _jmp_buf;
 
+#ifndef __rtems__
 int	setjmp(struct _jmp_buf *);
 void	longjmp(struct _jmp_buf *, int) __dead2;
+#endif /* __rtems__ */
 int	dumpstatus(vm_offset_t addr, off_t count);
 int	nullop(void);
Index: freebsd/usr.bin/netstat/main.c
===================================================================
--- freebsd/usr.bin/netstat/main.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ freebsd/usr.bin/netstat/main.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -362,13 +362,12 @@
 int	live;		/* true if we are examining a live system */
 
-
 #ifdef __rtems__
-static int main_netstat(int argc, char *argv[]);
+#include <machine/rtems-bsd-program.h>
+
+static int main(int argc, char *argv[]);
+
 static int rtems_shell_main_netstat(int argc, char *argv[])
 {
   int i;
-  rtems_shell_globals_t  netstat_globals;
-  rtems_shell_globals = &netstat_globals;
-  memset (rtems_shell_globals, 0, sizeof (netstat_globals));
 
   i = 0;
@@ -729,17 +728,9 @@
   noutputs = 0;
 
-  netstat_globals.exit_code = 1;
-  if (setjmp (netstat_globals.exit_jmp) == 0)
-    return main_netstat (argc, argv);
-  return netstat_globals.exit_code;
+  return rtems_bsd_program_call_main("netstat", main, argc, argv);
 }
-#endif
-
+#endif /* __rtems__ */
 int
-#ifdef __rtems__
-main_netstat(int argc, char *argv[])
-#else
 main(int argc, char *argv[])
-#endif
 {
 	struct protox *tp = NULL;  /* for printing cblocks & stats */
Index: rtemsbsd/include/machine/rtems-bsd-program.h
===================================================================
--- rtemsbsd/include/machine/rtems-bsd-program.h	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
+++ rtemsbsd/include/machine/rtems-bsd-program.h	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -0,0 +1,85 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_machine
+ *
+ * @brief TODO.
+ */
+
+/*
+ * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_PROGRAM_H_
+#define _RTEMS_BSD_MACHINE_RTEMS_BSD_PROGRAM_H_
+
+#include <sys/cdefs.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+__BEGIN_DECLS
+
+int
+rtems_bsd_program_call(const char *name, int (*prog)(void *), void *context);
+
+int
+rtems_bsd_program_call_main(const char *name, int (*main)(int, char **),
+    int argc, char **argv);
+
+void
+rtems_bsd_program_exit(int exit_code) __dead2;
+
+const char *
+rtems_bsd_program_get_name(void);
+
+void *
+rtems_bsd_program_get_context(void) __pure2;
+
+void
+rtems_bsd_program_lock(void);
+
+void
+rtems_bsd_program_unlock(void);
+
+#ifndef RTEMS_BSD_PROGRAM_NO_EXIT_WRAP
+  #define exit(code) rtems_bsd_program_exit(code)
+#endif
+
+#ifndef RTEMS_BSD_PROGRAM_NO_GETPROGNAME_WRAP
+  #define getprogname() rtems_bsd_program_get_name()
+#endif
+
+#ifndef RTEMS_BSD_PROGRAM_NO_PRINTF_WRAP
+  #define printf(...) fprintf(stdout, __VA_ARGS__)
+#endif
+
+__END_DECLS
+
+#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_PROGRAM_H_ */
Index: rtemsbsd/rtems/rtems-bsd-program.c
===================================================================
--- rtemsbsd/rtems/rtems-bsd-program.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
+++ rtemsbsd/rtems/rtems-bsd-program.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -0,0 +1,202 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_rtems
+ *
+ * @brief TODO.
+ */
+
+/*
+ * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
+
+#include <rtems/bsd/sys/param.h>
+#include <rtems/bsd/sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/mutex.h>
+
+#include <setjmp.h>
+#include <stdlib.h>
+
+struct rtems_bsd_program_control {
+	void *context;
+	int exit_code;
+	const char *name;
+	jmp_buf return_context;
+};
+
+int
+rtems_bsd_program_call(const char *name, int (*prog)(void *), void *context)
+{
+	struct thread *td = rtems_bsd_get_curthread_or_null();
+	int exit_code = EXIT_FAILURE;
+
+	if (td != NULL) {
+		struct rtems_bsd_program_control *prog_ctrl = td->td_prog_ctrl;
+
+		if (prog_ctrl == NULL) {
+			prog_ctrl = malloc(sizeof(*prog_ctrl), M_TEMP, 0);
+
+			if (prog_ctrl != NULL) {
+				td->td_prog_ctrl = prog_ctrl;
+
+				prog_ctrl->context = context;
+				prog_ctrl->name = name;
+				prog_ctrl->exit_code = exit_code;
+
+				if (setjmp(prog_ctrl->return_context) == 0) {
+					exit_code = (*prog)(context);
+				} else {
+					exit_code = prog_ctrl->exit_code;
+				}
+
+				td->td_prog_ctrl = NULL;
+				free(prog_ctrl, M_TEMP);
+			} else {
+				errno = ENOMEM;
+			}
+		} else {
+			panic("unexpected BSD program state");
+		}
+	} else {
+		errno = ENOMEM;
+	}
+
+	return exit_code;
+}
+
+void
+rtems_bsd_program_exit(int exit_code)
+{
+	struct thread *td = rtems_bsd_get_curthread_or_null();
+
+	if (td != NULL) {
+		struct rtems_bsd_program_control *prog_ctrl = td->td_prog_ctrl;
+
+		if (prog_ctrl != NULL) {
+			prog_ctrl->exit_code = exit_code;
+			longjmp(prog_ctrl->return_context, 1);
+		}
+	}
+
+	panic("unexpected BSD program exit");
+}
+
+const char *
+rtems_bsd_program_get_name(void)
+{
+	struct thread *td = rtems_bsd_get_curthread_or_null();
+	const char *name = "?";
+
+	if (td != NULL) {
+		struct rtems_bsd_program_control *prog_ctrl = td->td_prog_ctrl;
+
+		if (prog_ctrl != NULL) {
+			name = prog_ctrl->name;
+		}
+	}
+
+	return name;
+}
+
+void *
+rtems_bsd_program_get_context(void)
+{
+	struct thread *td = rtems_bsd_get_curthread_or_null();
+	void *context = NULL;
+
+	if (td != NULL) {
+		struct rtems_bsd_program_control *prog_ctrl = td->td_prog_ctrl;
+
+		if (prog_ctrl != NULL) {
+			context = prog_ctrl->context;
+		}
+	}
+
+	return context;
+}
+
+struct main_context {
+	int argc;
+	char **argv;
+	int (*main)(int, char **);
+};
+
+static int
+call_main(void *ctx)
+{
+	const struct main_context *mc = ctx;
+
+	return (*mc->main)(mc->argc, mc->argv);
+}
+
+int
+rtems_bsd_program_call_main(const char *name, int (*main)(int, char **),
+    int argc, char **argv)
+{
+	struct main_context mc = {
+		.argc = argc,
+		.argv = argv,
+		.main = main
+	};
+	int exit_code;
+
+	if (argv[argc] == NULL) {
+		exit_code = rtems_bsd_program_call(name, call_main, &mc);
+	} else {
+		errno = EFAULT;
+		exit_code = EXIT_FAILURE;
+	}
+
+	return exit_code;
+}
+
+static struct mtx program_mtx;
+
+MTX_SYSINIT(rtems_bsd_program, &program_mtx, "BSD program", MTX_DEF);
+
+void
+rtems_bsd_program_lock(void)
+{
+	mtx_lock(&program_mtx);
+}
+
+void
+rtems_bsd_program_unlock(void)
+{
+	mtx_unlock(&program_mtx);
+}
Index: emsbsd/rtems/rtems-getprogname.c
===================================================================
--- rtemsbsd/rtems/rtems-getprogname.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ 	(revision )
@@ -1,8 +1,0 @@
-/*
- * RTEMS version of 
- */
-
-const char *getprogname(void)
-{
-  return "RTEMS";
-}
Index: testsuite/syscalls01/test_main.c
===================================================================
--- testsuite/syscalls01/test_main.c	(revision c333babc98347dd8b49def957ed93f5bba55cdd8)
+++ testsuite/syscalls01/test_main.c	(revision d01564c473842adfd93148bb367fa0679f99e6b8)
@@ -37,4 +37,5 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <err.h>
 
 #include <assert.h>
@@ -45,4 +46,8 @@
 #include <string.h>
 #include <unistd.h>
+
+#define RTEMS_BSD_PROGRAM_NO_EXIT_WRAP
+#define RTEMS_BSD_PROGRAM_NO_PRINTF_WRAP
+#include <machine/rtems-bsd-program.h>
 
 #include <rtems/libcsupport.h>
@@ -1202,4 +1207,191 @@
 }
 
+static const char prog_name[] = "prog";
+
+static int
+invalid_prog(void *ctx)
+{
+	(void) ctx;
+
+	assert(0);
+}
+
+static int
+invalid_main(int argc, char **argv)
+{
+	(void) argc;
+	(void) argv;
+
+	assert(0);
+}
+
+static void *const some_context = (void *) 0xcafe;
+
+static int
+some_prog(void *ctx)
+{
+	assert(ctx == some_context);
+	assert(strcmp(rtems_bsd_program_get_name(), prog_name) == 0);
+	assert(rtems_bsd_program_get_context() == some_context);
+	errno = 0;
+	rtems_bsd_program_exit(456);
+}
+
+static const int some_argc = 1;
+
+static char *some_argv[] = { "a", NULL };
+
+static int
+some_main(int argc, char **argv)
+{
+	assert(argc == some_argc);
+	assert(argv == some_argv);
+	assert(strcmp(rtems_bsd_program_get_name(), prog_name) == 0);
+	errno = 0;
+	rtems_bsd_program_exit(789);
+}
+
+static void
+no_mem_bsd_program(int fd)
+{
+	(void) fd;
+
+	assert(rtems_bsd_program_call(prog_name, invalid_prog, NULL)
+	    == EXIT_FAILURE);
+	assert(rtems_bsd_program_call_main(prog_name, invalid_main, some_argc,
+	    some_argv) == EXIT_FAILURE);
+	assert(strcmp(rtems_bsd_program_get_name(), "?") == 0);
+	assert(rtems_bsd_program_get_context() == NULL);
+}
+
+static void
+test_bsd_program(void)
+{
+	rtems_resource_snapshot snapshot;
+	int exit_code;
+	void *greedy;
+	char *invalid_argv[2] = { "a", "b" };
+
+	assert(rtems_configuration_get_unified_work_area());
+
+	puts("test BSD program");
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	do_no_mem_test(no_mem_bsd_program, -1);
+
+	greedy = rtems_workspace_greedy_allocate(NULL, 0);
+	no_mem_bsd_program(-1);
+	rtems_workspace_greedy_free(greedy);
+
+	errno = 0;
+	exit_code = rtems_bsd_program_call_main(prog_name, NULL, 1, invalid_argv);
+	assert(errno == EFAULT);
+	assert(exit_code == EXIT_FAILURE);
+
+	errno = EINVAL;
+	exit_code = rtems_bsd_program_call(prog_name, some_prog, some_context);
+	assert(errno == 0);
+	assert(exit_code == 456);
+	assert(strcmp(rtems_bsd_program_get_name(), "?") == 0);
+	assert(rtems_bsd_program_get_context() == NULL);
+
+	errno = EINVAL;
+	exit_code = rtems_bsd_program_call_main(prog_name, some_main,
+	    some_argc, some_argv);
+	assert(errno == 0);
+	assert(exit_code == 789);
+	assert(strcmp(rtems_bsd_program_get_name(), "?") == 0);
+	assert(rtems_bsd_program_get_context() == NULL);
+
+	assert(rtems_resource_snapshot_check(&snapshot));
+}
+
+static void
+test_warn(void)
+{
+	puts("test warn");
+
+	errno = EAGAIN;
+	warn("%s", "warn");
+
+	errno = ENAMETOOLONG;
+	warn(NULL);
+
+	errno = 0;
+	warnc(EDOM, "%s", "warnc");
+
+	errno = 0;
+	warnc(ERANGE, NULL);
+
+	warnx("%s", "warnx");
+
+	warnx(NULL);
+}
+
+static int
+call_err(void *ctx)
+{
+	errno = EAGAIN;
+	err(10, "%s", "call_err");
+}
+
+static int
+call_err_null(void *ctx)
+{
+	errno = ENAMETOOLONG;
+	err(11, NULL);
+}
+
+static int
+call_errc(void *ctx)
+{
+	errc(12, EDOM, "%s", "call_errc");
+}
+
+static int
+call_errc_null(void *ctx)
+{
+	errc(13, ERANGE, NULL);
+}
+
+static int
+call_errx(void *ctx)
+{
+	errx(14, "%s", "call_errx");
+}
+
+static int
+call_errx_null(void *ctx)
+{
+	errx(15, NULL);
+}
+
+static void
+test_err(void)
+{
+	int exit_code;
+
+	puts("test err");
+
+	exit_code = rtems_bsd_program_call("err", call_err, NULL);
+	assert(exit_code == 10);
+
+	exit_code = rtems_bsd_program_call("err", call_err_null, NULL);
+	assert(exit_code == 11);
+
+	exit_code = rtems_bsd_program_call("errc", call_errc, NULL);
+	assert(exit_code == 12);
+
+	exit_code = rtems_bsd_program_call("errc", call_errc_null, NULL);
+	assert(exit_code == 13);
+
+	exit_code = rtems_bsd_program_call("errx", call_errx, NULL);
+	assert(exit_code == 14);
+
+	exit_code = rtems_bsd_program_call("errx", call_errx_null, NULL);
+	assert(exit_code == 15);
+}
+
 static void
 test_main(void)
@@ -1222,4 +1414,8 @@
 	test_socket_recv_and_recvfrom_and_recvmsg();
 
+	test_bsd_program();
+	test_warn();
+	test_err();
+
 	puts("*** END OF " TEST_NAME " TEST ***");
 	exit(0);
