summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-10-17 10:38:34 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-10-31 13:18:48 +0100
commitd01564c473842adfd93148bb367fa0679f99e6b8 (patch)
treec838d184a92e6df21f32950392190e9b1842adf1
parentSimplify getopt() to getopt_r() translation (diff)
downloadrtems-libbsd-d01564c473842adfd93148bb367fa0679f99e6b8.tar.bz2
Move program control to thread structure
-rw-r--r--Makefile3
-rwxr-xr-xfreebsd-to-rtems.py3
-rw-r--r--freebsd/include/err.h15
-rw-r--r--freebsd/lib/libc/gen/err.c12
-rw-r--r--freebsd/sbin/ifconfig/ifconfig.c38
-rw-r--r--freebsd/sbin/ping/ping.c57
-rw-r--r--freebsd/sbin/route/route.c30
-rw-r--r--freebsd/sys/sys/proc.h1
-rw-r--r--freebsd/sys/sys/systm.h2
-rw-r--r--freebsd/usr.bin/netstat/main.c21
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-program.h85
-rw-r--r--rtemsbsd/rtems/rtems-bsd-program.c202
-rw-r--r--rtemsbsd/rtems/rtems-getprogname.c8
-rw-r--r--testsuite/syscalls01/test_main.c196
14 files changed, 558 insertions, 115 deletions
diff --git a/Makefile b/Makefile
index 2d5107ae..c2534a96 100644
--- a/Makefile
+++ b/Makefile
@@ -70,6 +70,7 @@ LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-page.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-panic.c
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
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-signal.c
@@ -86,10 +87,8 @@ LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-taskqueue.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-thread.c
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
LIB_C_FILES += rtemsbsd/rtems/rtems-uthread_kevent.c
diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py
index 73e6a5ea..1fadb58b 100755
--- a/freebsd-to-rtems.py
+++ b/freebsd-to-rtems.py
@@ -627,6 +627,7 @@ rtems.addRTEMSSourceFiles(
'rtems/rtems-bsd-panic.c',
'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',
'rtems/rtems-bsd-signal.c',
@@ -643,10 +644,8 @@ rtems.addRTEMSSourceFiles(
'rtems/rtems-bsd-thread.c',
'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',
'rtems/rtems-uthread_kevent.c',
diff --git a/freebsd/include/err.h b/freebsd/include/err.h
index 772d654f..65aff6f2 100644
--- a/freebsd/include/err.h
+++ b/freebsd/include/err.h
@@ -47,19 +47,6 @@
#include <sys/cdefs.h>
#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);
void verr(int, const char *, __va_list) __dead2 __printf0like(2, 0);
@@ -74,8 +61,10 @@ void warnc(int, const char *, ...) __printf0like(2, 3);
void vwarnc(int, const char *, __va_list) __printf0like(2, 0);
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
#endif /* !_ERR_H_ */
diff --git a/freebsd/lib/libc/gen/err.c b/freebsd/lib/libc/gen/err.c
index bbd5bffc..d2956c81 100644
--- a/freebsd/lib/libc/gen/err.c
+++ b/freebsd/lib/libc/gen/err.c
@@ -46,9 +46,16 @@ __FBSDID("$FreeBSD$");
#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
* to include <stdio.h> first. However, it is really a `FILE *', and the
@@ -68,6 +75,7 @@ err_set_exit(void (*ef)(int))
{
err_exit = ef;
}
+#endif /* __rtems__ */
__weak_reference(_err, err);
@@ -109,8 +117,10 @@ verrc(int eval, int code, const char *fmt, va_list ap)
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(code));
+#ifndef __rtems__
if (err_exit)
err_exit(eval);
+#endif /* __rtems__ */
exit(eval);
}
@@ -132,8 +142,10 @@ verrx(int eval, const char *fmt, va_list ap)
if (fmt != NULL)
vfprintf(err_file, fmt, ap);
fprintf(err_file, "\n");
+#ifndef __rtems__
if (err_exit)
err_exit(eval);
+#endif /* __rtems__ */
exit(eval);
}
diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c
index c8a296ee..d983862d 100644
--- a/freebsd/sbin/ifconfig/ifconfig.c
+++ b/freebsd/sbin/ifconfig/ifconfig.c
@@ -115,25 +115,6 @@ static struct afswtch *af_getbyfamily(int af);
static void af_other_status(int);
#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;
void
@@ -182,12 +163,23 @@ usage(void)
}
#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;
const struct afswtch *afp = NULL;
diff --git a/freebsd/sbin/ping/ping.c b/freebsd/sbin/ping/ping.c
index 5adb9d5b..f1b4b912 100644
--- a/freebsd/sbin/ping/ping.c
+++ b/freebsd/sbin/ping/ping.c
@@ -218,44 +218,39 @@ static void tvsub(struct timeval *, struct timeval *);
static void usage(void) __dead2;
#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;
struct in_addr ifaddr;
diff --git a/freebsd/sbin/route/route.c b/freebsd/sbin/route/route.c
index 509c5952..964188ff 100644
--- a/freebsd/sbin/route/route.c
+++ b/freebsd/sbin/route/route.c
@@ -116,24 +116,6 @@ extern char *iso_ntoa();
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)
const char *cp;
@@ -147,11 +129,17 @@ usage(cp)
}
#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;
{
diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h
index 5cd7b64c..6dbc88c5 100644
--- a/freebsd/sys/sys/proc.h
+++ b/freebsd/sys/sys/proc.h
@@ -201,6 +201,7 @@ struct thread {
#ifdef __rtems__
rtems_chain_node td_node;
Thread_Control *td_thread;
+ struct rtems_bsd_program_control *td_prog_ctrl;
char td_name [16];
#endif /* __rtems__ */
#ifndef __rtems__
diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h
index 1349e6d0..e464356a 100644
--- a/freebsd/sys/sys/systm.h
+++ b/freebsd/sys/sys/systm.h
@@ -153,8 +153,10 @@ struct ucred;
struct uio;
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);
int eopnotsupp(void);
diff --git a/freebsd/usr.bin/netstat/main.c b/freebsd/usr.bin/netstat/main.c
index d1714b6d..dc413942 100644
--- a/freebsd/usr.bin/netstat/main.c
+++ b/freebsd/usr.bin/netstat/main.c
@@ -361,15 +361,14 @@ int unit; /* unit number for above */
int af; /* address family */
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;
protox[i].pr_index = N_TCBINFO;
@@ -728,19 +727,11 @@ static int rtems_shell_main_netstat(int argc, char *argv[])
#endif
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 */
int ch;
diff --git a/rtemsbsd/include/machine/rtems-bsd-program.h b/rtemsbsd/include/machine/rtems-bsd-program.h
new file mode 100644
index 00000000..b2e542e0
--- /dev/null
+++ b/rtemsbsd/include/machine/rtems-bsd-program.h
@@ -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_ */
diff --git a/rtemsbsd/rtems/rtems-bsd-program.c b/rtemsbsd/rtems/rtems-bsd-program.c
new file mode 100644
index 00000000..f6a63ff7
--- /dev/null
+++ b/rtemsbsd/rtems/rtems-bsd-program.c
@@ -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);
+}
diff --git a/rtemsbsd/rtems/rtems-getprogname.c b/rtemsbsd/rtems/rtems-getprogname.c
deleted file mode 100644
index 1a075df8..00000000
--- a/rtemsbsd/rtems/rtems-getprogname.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * RTEMS version of
- */
-
-const char *getprogname(void)
-{
- return "RTEMS";
-}
diff --git a/testsuite/syscalls01/test_main.c b/testsuite/syscalls01/test_main.c
index cfac1354..6f64c21e 100644
--- a/testsuite/syscalls01/test_main.c
+++ b/testsuite/syscalls01/test_main.c
@@ -36,6 +36,7 @@
#include <sys/filio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <err.h>
#include <assert.h>
#include <errno.h>
@@ -45,6 +46,10 @@
#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>
#define TEST_NAME "LIBBSD SYSCALLS 1"
@@ -1201,6 +1206,193 @@ test_socket_recv_and_recvfrom_and_recvmsg(void)
assert(rtems_resource_snapshot_check(&snapshot));
}
+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)
{
@@ -1221,6 +1413,10 @@ test_main(void)
test_socket_send_and_sendto_and_sendmsg();
test_socket_recv_and_recvfrom_and_recvmsg();
+ test_bsd_program();
+ test_warn();
+ test_err();
+
puts("*** END OF " TEST_NAME " TEST ***");
exit(0);
}