1
0
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:
Martine Lenders 2017-01-12 18:59:12 +01:00
parent 2f2624577b
commit e9d13d73bc

View File

@ -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