mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-27 15:31:17 +01:00
native: prettify argument parsing
This commit is contained in:
parent
2f2624577b
commit
e9d13d73bc
@ -2,6 +2,7 @@
|
||||
* Native CPU entry code
|
||||
*
|
||||
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||
* 2017 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -11,6 +12,7 @@
|
||||
* @{
|
||||
* @file
|
||||
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -21,6 +23,9 @@
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -38,6 +43,12 @@
|
||||
#include "native_internal.h"
|
||||
#include "tty_uart.h"
|
||||
|
||||
typedef enum {
|
||||
_STDIOTYPE_STDIO = 0, /**< leave intact */
|
||||
_STDIOTYPE_NULL, /**< redirect to "/dev/null" */
|
||||
_STDIOTYPE_FILE, /**< redirect to file */
|
||||
} _stdiotype_t;
|
||||
|
||||
int _native_null_in_pipe[2];
|
||||
int _native_null_out_file;
|
||||
const char *_progname;
|
||||
@ -53,18 +64,32 @@ const char *_native_unix_socket_path = NULL;
|
||||
extern netdev2_tap_t netdev2_tap;
|
||||
#endif
|
||||
|
||||
static const char short_opts[] = ":hi:s:deEoc:";
|
||||
static const struct option long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "id", required_argument, NULL, 'i' },
|
||||
{ "seed", required_argument, NULL, 's' },
|
||||
{ "daemonize", no_argument, NULL, 'd' },
|
||||
{ "stderr-pipe", no_argument, NULL, 'e' },
|
||||
{ "stderr-noredirect", no_argument, NULL, 'E' },
|
||||
{ "stdout-pipe", no_argument, NULL, 'o' },
|
||||
{ "uart-tty", required_argument, NULL, 'c' },
|
||||
{ NULL, 0, NULL, '\0' },
|
||||
};
|
||||
|
||||
/**
|
||||
* initialize _native_null_in_pipe to allow for reading from stdin
|
||||
* @param stdiotype: "stdio" (only initialize pipe) or any string
|
||||
* (redirect stdin to _native_null_in_pipe)
|
||||
* @brief initialize _native_null_in_pipe to allow for reading from stdin
|
||||
*
|
||||
* @param[in] stdiotype _STDIOTYPE_STDIO to to just initialize pipe, any other
|
||||
* value to also redirect stdin to that pipe
|
||||
*/
|
||||
void _native_null_in(char *stdiotype)
|
||||
void _native_input(_stdiotype_t stdintype)
|
||||
{
|
||||
if (real_pipe(_native_null_in_pipe) == -1) {
|
||||
err(EXIT_FAILURE, "_native_null_in(): pipe()");
|
||||
}
|
||||
|
||||
if (strcmp(stdiotype, "stdio") == 0) {
|
||||
if (stdintype == _STDIOTYPE_STDIO) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,73 +99,48 @@ void _native_null_in(char *stdiotype)
|
||||
}
|
||||
|
||||
/**
|
||||
* set up stdout redirection
|
||||
* @brief set up output redirection
|
||||
*
|
||||
* @param stdouttype: "stdio" (leave intact), "null" (redirect to
|
||||
* /dev/null) or "file" (redirect to /tmp/riot.stdout.PID)
|
||||
*/
|
||||
void _native_log_stdout(char *stdouttype)
|
||||
{
|
||||
int stdout_outfile;
|
||||
|
||||
if (strcmp(stdouttype, "stdio") == 0) {
|
||||
_native_null_out_file = -1;
|
||||
return;
|
||||
}
|
||||
else if (strcmp(stdouttype, "null") == 0) {
|
||||
if ((stdout_outfile = real_open("/dev/null", O_WRONLY)) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_stdout: open");
|
||||
}
|
||||
}
|
||||
else if (strcmp(stdouttype, "file") == 0) {
|
||||
char stdout_logname[255];
|
||||
snprintf(stdout_logname, sizeof(stdout_logname), "/tmp/riot.stdout.%d", _native_pid);
|
||||
if ((stdout_outfile = real_creat(stdout_logname, 0666)) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_stdout: open");
|
||||
}
|
||||
}
|
||||
else {
|
||||
errx(EXIT_FAILURE, "_native_log_stdout: unknown log type");
|
||||
}
|
||||
|
||||
if (real_dup2(stdout_outfile, STDOUT_FILENO) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_stdout: dup2(STDOUT_FILENO)");
|
||||
}
|
||||
_native_null_out_file = stdout_outfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* set up stderr redirection
|
||||
* @param[in] stdiotype The type of redirection
|
||||
* @param[in] output Output file. May be either `STDOUT_FILENO` for stdout or
|
||||
* `STDERR_FILENO` for stderr
|
||||
*
|
||||
* @param stderrtype: "stdio" (leave intact), "null" (redirect to
|
||||
* /dev/null) or "file" (redirect to /tmp/riot.stdout.PID)
|
||||
* @return The new file descriptor of the redirection
|
||||
* @return -1 if the file descriptor did not change from the standard one
|
||||
*/
|
||||
void _native_log_stderr(char *stderrtype)
|
||||
int _native_log_output(_stdiotype_t stdiotype, int output)
|
||||
{
|
||||
int stderr_outfile;
|
||||
int outfile;
|
||||
|
||||
if (strcmp(stderrtype, "stdio") == 0) {
|
||||
return;
|
||||
}
|
||||
else if (strcmp(stderrtype, "null") == 0) {
|
||||
if ((stderr_outfile = real_open("/dev/null", O_WRONLY)) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_stderr: open");
|
||||
}
|
||||
}
|
||||
else if (strcmp(stderrtype, "file") == 0) {
|
||||
char stderr_logname[255];
|
||||
snprintf(stderr_logname, sizeof(stderr_logname), "/tmp/riot.stderr.%d", _native_pid);
|
||||
if ((stderr_outfile = real_creat(stderr_logname, 0666)) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_stderr: open");
|
||||
}
|
||||
}
|
||||
else {
|
||||
errx(EXIT_FAILURE, "_native_log_stderr: unknown log type");
|
||||
}
|
||||
assert((output == STDERR_FILENO) || (output == STDOUT_FILENO));
|
||||
|
||||
if (real_dup2(stderr_outfile, STDERR_FILENO) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_stderr: dup2(STDERR_FILENO)");
|
||||
switch (stdiotype) {
|
||||
case _STDIOTYPE_STDIO:
|
||||
return -1;
|
||||
case _STDIOTYPE_NULL:
|
||||
if ((outfile = real_open("/dev/null", O_WRONLY)) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_output: open");
|
||||
}
|
||||
break;
|
||||
case _STDIOTYPE_FILE: {
|
||||
/* 20 should suffice for 64-bit PIDs ;-) */
|
||||
char logname[sizeof("/tmp/riot.stderr.") + 20];
|
||||
|
||||
snprintf(logname, sizeof(logname), "/tmp/riot.std%s.%d",
|
||||
(output == STDOUT_FILENO) ? "out": "err", _native_pid);
|
||||
if ((outfile = real_creat(logname, 0666)) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_output: open");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
errx(EXIT_FAILURE, "_native_log_output: unknown log type");
|
||||
break;
|
||||
}
|
||||
if (real_dup2(outfile, output) == -1) {
|
||||
err(EXIT_FAILURE, "_native_log_output: dup2(output)");
|
||||
}
|
||||
return outfile;
|
||||
}
|
||||
|
||||
void daemonize(void)
|
||||
@ -175,26 +175,26 @@ void daemonize(void)
|
||||
* Remove any -d options from an argument vector.
|
||||
*
|
||||
* @param[in][out] argv an argument vector
|
||||
*
|
||||
* @return 1 if "-d" was found, 0 otherwise
|
||||
*/
|
||||
static int filter_daemonize_argv(char **argv)
|
||||
static void filter_daemonize_argv(char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
for (char **narg = argv; *narg != NULL; narg++) {
|
||||
int idx = 0;
|
||||
for (char **narg = argv; *narg != NULL; narg++, idx++) {
|
||||
if (strcmp("-d", narg[0]) == 0) {
|
||||
ret = 1;
|
||||
char **xarg = narg;
|
||||
do {
|
||||
xarg[0] = xarg[1];
|
||||
} while (*xarg++ != NULL);
|
||||
if (optind > 1) {
|
||||
/* adapt optind if changed */
|
||||
optind--;
|
||||
}
|
||||
narg--; /* rescan current item to filter out double args */
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usage_exit(void)
|
||||
void usage_exit(int status)
|
||||
{
|
||||
real_printf("usage: %s", _progname);
|
||||
|
||||
@ -202,29 +202,32 @@ void usage_exit(void)
|
||||
real_printf(" <tap interface>");
|
||||
#endif
|
||||
|
||||
real_printf(" [-i <id>] [-d] [-e|-E] [-o] [-c <tty device>]\n");
|
||||
real_printf(" [-i <id>] [-d] [-e|-E] [-o] [-c <tty>]\n");
|
||||
|
||||
real_printf(" help: %s -h\n", _progname);
|
||||
|
||||
real_printf("\nOptions:\n\
|
||||
-h help\n");
|
||||
|
||||
real_printf("\
|
||||
-i <id> specify instance id (set by config module)\n\
|
||||
-s <seed> specify srandom(3) seed (/dev/random is used instead of\n\
|
||||
random(3) if the option is omitted)\n\
|
||||
-d daemonize\n\
|
||||
-e redirect stderr to file\n\
|
||||
-E do not redirect stderr (i.e. leave sterr unchanged despite\n\
|
||||
daemon/socket io)\n\
|
||||
-o redirect stdout to file (/tmp/riot.stdout.PID) when not attached\n\
|
||||
to socket\n\
|
||||
-c specify TTY device for UART\n");
|
||||
|
||||
real_printf("\n\
|
||||
The order of command line arguments matters.\n");
|
||||
real_exit(EXIT_FAILURE);
|
||||
real_printf(" help: %s -h\n\n", _progname);
|
||||
|
||||
real_printf("\nOptions:\n"
|
||||
" -h, --help\n"
|
||||
" print this help message\n"
|
||||
" -i <id>, --id=<id>\n"
|
||||
" specify instance id (set by config module)\n"
|
||||
" -s <seed>, --seed=<seed>\n"
|
||||
" specify srandom(3) seed (/dev/random is used instead of random(3) if\n"
|
||||
" the option is omitted)\n"
|
||||
" -d, --daemonize\n"
|
||||
" daemonize native instance\n"
|
||||
" -e, --stderr-pipe\n"
|
||||
" redirect stderr to file\n"
|
||||
" -E, --stderr-noredirect\n"
|
||||
" do not redirect stderr (i.e. leave sterr unchanged despite\n"
|
||||
" daemon/socket io)\n"
|
||||
" -o, --stdout-pipe\n"
|
||||
" redirect stdout to file (/tmp/riot.stdout.PID) when not attached\n"
|
||||
" to socket\n"
|
||||
" -c <tty>, --uart-tty=<tty>\n"
|
||||
" specify TTY device for UART. This argument can be used multiple\n"
|
||||
" times (up to UART_NUMOF)\n");
|
||||
real_exit(status);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) static void startup(int argc, char **argv)
|
||||
@ -238,97 +241,84 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
|
||||
/* will possibly be overridden via option below: */
|
||||
_native_id = _native_pid;
|
||||
|
||||
int argp = 1;
|
||||
char *stderrtype = "stdio";
|
||||
char *stdouttype = "stdio";
|
||||
char *stdiotype = "stdio";
|
||||
int uart = 0;
|
||||
int c, opt_idx = 0, uart = 0;
|
||||
bool dmn = false, force_stderr = false;
|
||||
_stdiotype_t stderrtype = _STDIOTYPE_STDIO;
|
||||
_stdiotype_t stdouttype = _STDIOTYPE_STDIO;
|
||||
_stdiotype_t stdintype = _STDIOTYPE_STDIO;
|
||||
|
||||
#if defined(MODULE_NETDEV2_TAP)
|
||||
if (
|
||||
(argc < 2)
|
||||
|| (
|
||||
(strcmp("-h", argv[argp]) == 0)
|
||||
|| (strcmp("--help", argv[argp]) == 0)
|
||||
)
|
||||
) {
|
||||
usage_exit();
|
||||
while ((c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx)) >= 0) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
case 'h':
|
||||
usage_exit(EXIT_SUCCESS);
|
||||
case 'i':
|
||||
_native_id = atol(optarg);
|
||||
break;
|
||||
case 's':
|
||||
_native_rng_seed = atol(optarg);
|
||||
_native_rng_mode = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dmn = true;
|
||||
break;
|
||||
case 'e':
|
||||
if (force_stderr) {
|
||||
/* -e and -E are mutually exclusive */
|
||||
usage_exit(EXIT_FAILURE);
|
||||
}
|
||||
stderrtype = _STDIOTYPE_FILE;
|
||||
break;
|
||||
case 'E':
|
||||
if (stderrtype == _STDIOTYPE_FILE) {
|
||||
/* -e and -E are mutually exclusive */
|
||||
usage_exit(EXIT_FAILURE);
|
||||
}
|
||||
force_stderr = true;
|
||||
break;
|
||||
case 'o':
|
||||
stdouttype = _STDIOTYPE_FILE;
|
||||
break;
|
||||
case 'c':
|
||||
tty_uart_setup(uart++, optarg);
|
||||
break;
|
||||
default:
|
||||
usage_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#ifdef MODULE_NETDEV2_TAP
|
||||
if (argv[optind] == NULL) {
|
||||
/* no tap parameter left */
|
||||
usage_exit(EXIT_FAILURE);
|
||||
}
|
||||
argp++;
|
||||
#endif
|
||||
|
||||
for (; argp < argc; argp++) {
|
||||
char *arg = argv[argp];
|
||||
if ((strcmp("-h", arg) == 0) || (strcmp("--help", arg) == 0)) {
|
||||
usage_exit();
|
||||
if (dmn) {
|
||||
filter_daemonize_argv(_native_argv);
|
||||
if (stderrtype == _STDIOTYPE_STDIO) {
|
||||
stderrtype = _STDIOTYPE_NULL;
|
||||
}
|
||||
else if (strcmp("-i", arg) == 0) {
|
||||
if (argp + 1 < argc) {
|
||||
argp++;
|
||||
}
|
||||
else {
|
||||
usage_exit();
|
||||
}
|
||||
_native_id = atol(argv[argp]);
|
||||
if (stdouttype == _STDIOTYPE_STDIO) {
|
||||
stdouttype = _STDIOTYPE_NULL;
|
||||
}
|
||||
else if (strcmp("-s", arg) == 0) {
|
||||
if (argp + 1 < argc) {
|
||||
argp++;
|
||||
}
|
||||
else {
|
||||
usage_exit();
|
||||
}
|
||||
_native_rng_seed = atol(argv[argp]);
|
||||
_native_rng_mode = 1;
|
||||
if (stdintype == _STDIOTYPE_STDIO) {
|
||||
stdintype = _STDIOTYPE_NULL;
|
||||
}
|
||||
else if (strcmp("-d", arg) == 0) {
|
||||
if (strcmp(stdiotype, "stdio") == 0) {
|
||||
stdiotype = "null";
|
||||
}
|
||||
if (strcmp(stdouttype, "stdio") == 0) {
|
||||
stdouttype = "null";
|
||||
}
|
||||
if (strcmp(stderrtype, "stdio") == 0) {
|
||||
stderrtype = "null";
|
||||
}
|
||||
}
|
||||
else if (strcmp("-e", arg) == 0) {
|
||||
stderrtype = "file";
|
||||
}
|
||||
else if (strcmp("-E", arg) == 0) {
|
||||
stderrtype = "stdio";
|
||||
}
|
||||
else if (strcmp("-o", arg) == 0) {
|
||||
stdouttype = "file";
|
||||
}
|
||||
else if (strcmp("-c", arg) == 0) {
|
||||
if (argp + 1 < argc) {
|
||||
argp++;
|
||||
}
|
||||
else {
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
tty_uart_setup(uart++, argv[argp]);
|
||||
}
|
||||
else {
|
||||
usage_exit();
|
||||
}
|
||||
}
|
||||
|
||||
if (filter_daemonize_argv(_native_argv)) {
|
||||
daemonize();
|
||||
}
|
||||
if (force_stderr) {
|
||||
stderrtype = _STDIOTYPE_STDIO;
|
||||
}
|
||||
|
||||
_native_log_stderr(stderrtype);
|
||||
_native_log_stdout(stdouttype);
|
||||
_native_null_in(stdiotype);
|
||||
_native_log_output(stderrtype, STDERR_FILENO);
|
||||
_native_null_out_file = _native_log_output(stdouttype, STDOUT_FILENO);
|
||||
_native_input(stdintype);
|
||||
|
||||
native_cpu_init();
|
||||
native_interrupt_init();
|
||||
#ifdef MODULE_NETDEV2_TAP
|
||||
netdev2_tap_params_t p;
|
||||
p.tap_name = &(argv[1]);
|
||||
p.tap_name = &(argv[optind]);
|
||||
netdev2_tap_setup(&netdev2_tap, &p);
|
||||
#endif
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user