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 #include -#ifdef __rtems__ -#include -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 +#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 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 @@ -114,25 +114,6 @@ static struct afswtch *af_getbyname(const char *name); 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; @@ -182,12 +163,23 @@ usage(void) } #ifdef __rtems__ -int -main_ifconfig(int argc, char *argv[]) -#else +#include + +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 + +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 + +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 + +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 + * + * + * 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 +#include +#include + +__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 + * + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 #include #include +#include #include #include @@ -45,6 +46,10 @@ #include #include +#define RTEMS_BSD_PROGRAM_NO_EXIT_WRAP +#define RTEMS_BSD_PROGRAM_NO_PRINTF_WRAP +#include + #include #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); }