Skip to content
Snippets Groups Projects
Commit 864267f2 authored by Ludwig Knüpfer's avatar Ludwig Knüpfer
Browse files

daemonization, io socket and file redirection

parent f11071cd
No related branches found
No related tags found
No related merge requests found
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
*/ */
void board_init() void board_init()
{ {
#ifdef MODULE_UART0
_native_init_uart0();
#endif
LED_GREEN_OFF; LED_GREEN_OFF;
LED_RED_ON; LED_RED_ON;
puts("RIOT native board initialized."); puts("RIOT native board initialized.");
......
...@@ -19,6 +19,15 @@ ...@@ -19,6 +19,15 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h> #include <sys/select.h>
...@@ -27,11 +36,15 @@ ...@@ -27,11 +36,15 @@
#include "board_uart0.h" #include "board_uart0.h"
#include "native_internal.h" #include "native_internal.h"
#include "board_internal.h"
static int _native_uart_in; int _native_uart_sock;
int _native_uart_conn;
fd_set _native_uart_rfds; fd_set _native_uart_rfds;
/* uart API */
int uart0_puts(char *astring, int length) int uart0_puts(char *astring, int length)
{ {
int nwritten, offset; int nwritten, offset;
...@@ -60,28 +73,119 @@ int uart0_puts(char *astring, int length) ...@@ -60,28 +73,119 @@ int uart0_puts(char *astring, int length)
return length; return length;
} }
void _native_handle_uart0_input() /* internal */
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
#ifndef UART_TCPPORT
#define UART_TCPPORT "4711"
#endif
int init_tcp_socket(char *tcpport)
{
struct addrinfo hints, *info, *p;
int i, s;
if (tcpport == NULL) {
tcpport = UART_TCPPORT;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((i = getaddrinfo(NULL, tcpport, &hints, &info)) != 0) {
errx(EXIT_FAILURE,
"init_uart_socket: getaddrinfo: %s", gai_strerror(i));
}
for (p = info; p != NULL; p = p->ai_next) {
if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
warn("init_uart_socket: socket");
continue;
}
i = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)) == -1) {
err(EXIT_FAILURE, "init_uart_socket: setsockopt");
}
if (bind(s, p->ai_addr, p->ai_addrlen) == -1) {
close(s);
warn("init_uart_socket: bind");
continue;
}
break;
}
if (p == NULL) {
errx(EXIT_FAILURE, "init_uart_socket: failed to bind\n");
}
freeaddrinfo(info);
if (listen(s, 1) == -1) {
err(EXIT_FAILURE, "init_uart_socket: listen");
}
return s;
}
int init_unix_socket()
{
int s;
struct sockaddr_un sa;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
err(EXIT_FAILURE, "init_unix_socket: socket");
}
sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, sizeof(sa.sun_path), "/tmp/riot.tty.%d", getpid());
unlink(sa.sun_path); /* remove stale socket */
if (bind(s, (struct sockaddr *)&sa, SUN_LEN(&sa)) == -1) {
err(EXIT_FAILURE, "init_unix_socket: bind");
}
if (listen(s, 5) == -1) {
err(EXIT_FAILURE, "init_unix_socket: listen");
}
return s;
}
void handle_uart_in()
{ {
char buf[42]; char buf[42];
int nread; int nread;
if (!FD_ISSET(_native_uart_in, &_native_rfds)) { DEBUG("handle_uart_in\n");
DEBUG("_native_handle_uart0_input - nothing to do\n");
return;
}
DEBUG("_native_handle_uart0_input\n");
nread = read(_native_uart_in, buf, sizeof(buf)); nread = read(STDIN_FILENO, buf, sizeof(buf));
if (nread == -1) { if (nread == -1) {
err(1, "_native_handle_uart0_input(): read()"); err(1, "handle_uart_in(): read()");
} }
else if (nread == 0) { else if (nread == 0) {
/* XXX: /* end of file / socket closed */
* preliminary resolution for this situation, will be coped if (_native_uart_conn != 0) {
* with properly in #161 */ if (_native_null_out_file != -1) {
close(_native_uart_in); if (dup2(_native_null_out_file, STDOUT_FILENO) == -1) {
_native_uart_in = -1; err(EXIT_FAILURE, "handle_uart_in: dup2(STDOUT_FILENO)");
printf("stdin closed"); }
}
if (dup2(_native_null_in_pipe[0], STDIN_FILENO) == -1) {
err(EXIT_FAILURE, "handle_uart_in: dup2(STDIN_FILENO)");
}
_native_uart_conn = 0;
warnx("closed stdio");
}
else {
errx(EXIT_FAILURE, "handle_uart_in: unhandled situation!");
}
} }
for(int pos = 0; pos < nread; pos++) { for(int pos = 0; pos < nread; pos++) {
uart0_handle_incoming(buf[pos]); uart0_handle_incoming(buf[pos]);
...@@ -91,18 +195,78 @@ void _native_handle_uart0_input() ...@@ -91,18 +195,78 @@ void _native_handle_uart0_input()
thread_yield(); thread_yield();
} }
void handle_uart_sock()
{
int s;
socklen_t t;
struct sockaddr remote;
t = sizeof(remote);
_native_syscall_enter();
if ((s = accept(_native_uart_sock, &remote, &t)) == -1) {
err(EXIT_FAILURE, "handle_uart_sock: accept");
}
else {
warnx("handle_uart_sock: successfully accepted socket");
}
if (dup2(s, STDOUT_FILENO) == -1) {
err(EXIT_FAILURE, "handle_uart_sock: dup2()");
}
if (dup2(s, STDIN_FILENO) == -1) {
err(EXIT_FAILURE, "handle_uart_sock: dup2()");
}
_native_syscall_leave();
_native_uart_conn = s;
}
void _native_handle_uart0_input()
{
if (FD_ISSET(STDIN_FILENO, &_native_rfds)) {
handle_uart_in();
}
else if ((_native_uart_sock != -1) && (FD_ISSET(_native_uart_sock, &_native_rfds))) {
handle_uart_sock();
}
else {
DEBUG("_native_handle_uart0_input - nothing to do\n");
}
}
int _native_set_uart_fds(void) int _native_set_uart_fds(void)
{ {
DEBUG("_native_set_uart_fds"); DEBUG("_native_set_uart_fds");
if (_native_uart_in != -1) { FD_SET(STDIN_FILENO, &_native_rfds);
FD_SET(_native_uart_in, &_native_rfds); if (_native_uart_sock == -1) {
return (STDIN_FILENO);
}
else {
FD_SET(_native_uart_sock, &_native_rfds);
return ((STDIN_FILENO > _native_uart_sock) ? STDIN_FILENO : _native_uart_sock);
} }
return _native_uart_in;
} }
void _native_init_uart0() void _native_init_uart0(char *stdiotype, char *ioparam)
{ {
_native_uart_in = STDIN_FILENO; if (strcmp(stdiotype, "tcp") == 0) {
_native_uart_sock = init_tcp_socket(ioparam);
}
else if (strcmp(stdiotype, "unix") == 0) {
_native_uart_sock = init_unix_socket();
}
else if (strcmp(stdiotype, "stdio") == 0) {
_native_uart_sock = -1;
_native_uart_conn = 1;
}
else if (strcmp(stdiotype, "null") == 0) {
_native_uart_sock = -1;
_native_uart_conn = 0;
}
else {
errx(EXIT_FAILURE, "_native_init_uart0: unknown stdio type");
}
puts("RIOT native uart0 initialized."); puts("RIOT native uart0 initialized.");
} }
#ifdef MODULE_UART0 #ifdef MODULE_UART0
#include <sys/select.h> #include <sys/select.h>
void _native_handle_uart0_input(void); void _native_handle_uart0_input(void);
void _native_init_uart0(void); /**
* @brief: initialize uart0
*
* @param stdiotype: "stdio", "tcp", "udp" io redirection
* @param ioparam: a string containing a port number if stdiotype is tcp
*/
void _native_init_uart0(char *stdiotype, char *ioparam);
int _native_set_uart_fds(void); int _native_set_uart_fds(void);
#endif #endif
extern int _native_null_out_file;
extern int _native_null_in_pipe[2];
void board_init(void); void board_init(void);
...@@ -79,3 +79,62 @@ restarting. ...@@ -79,3 +79,62 @@ restarting.
Packet delivery under OSX only works with user assistance at the Packet delivery under OSX only works with user assistance at the
moment. run 'kill -SIGIO <RIOT process ID>' to deliver a packet to a moment. run 'kill -SIGIO <RIOT process ID>' to deliver a packet to a
specific RIOT instance. specific RIOT instance.
DAEMONIZATION
=============
You can daemonize a riot process. This is useful for larger networks.
Valgrind will fork along with the riot process and dump its output in
the terminal.
Usage:
./bin/default.elf -d
Use uart redirection if you want to use a shell or get stderr/stdout
output with/from a daemonized process.
UART REDIRECTION
================
You can redirect the processes stdin/stdout/stderr by specifying
options.
Usage:
To redirect stdio to a UNIX socket run:
./bin/default.elf -u -d
RIOT pid: 18663
Attach this UNIX socket:
nc -U /tmp/riot.tty.18663
To redirect stdio to a TCP socket:
./bin/default.elf -t 4711 -d
RIOT pid: 18663
Attach this TCP socket:
nc localhost 4711
Stop the process:
kill 18663
To redirect stderr to a file:
./bin/default.elf -d -e
RIOT pid: 18663
Read from it:
tail -f /tmp/riot.stderr.18663
To redirect stdout to a file:
./bin/default.elf -d -o
RIOT pid: 18663
Read from it:
tail -f /tmp/riot.stdout.18663
The stdout redirection only writes to file while no socket connection
is established.
Socket redirection is only available when the uart module has been
compiled in.
...@@ -23,29 +23,248 @@ ...@@ -23,29 +23,248 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <err.h> #include <err.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <kernel_internal.h>
#include <cpu.h>
#include "kernel_internal.h" #include "kernel_internal.h"
#include "cpu.h" #include "cpu.h"
#include "board_internal.h"
#include "native_internal.h" #include "native_internal.h"
#include "tap.h" #include "tap.h"
int (*real_printf)(const char *format, ...);
char *argv0;
int _native_null_in_pipe[2];
int _native_null_out_file;
/**
* 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)
*/
void _native_null_in(char *stdiotype)
{
if (pipe(_native_null_in_pipe) == -1) {
err(1, "_native_null_in(): pipe()");
}
if (strcmp(stdiotype, "stdio") == 0) {
return;
}
if (dup2(_native_null_in_pipe[0], STDIN_FILENO) == -1) {
err(EXIT_FAILURE, "_native_null_in: dup2(STDIN_FILENO)");
}
}
/**
* set up stdout 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 = 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", getpid());
if ((stdout_outfile = creat(stdout_logname, 0666)) == -1) {
err(EXIT_FAILURE, "_native_log_stdout: open");
}
}
else {
errx(EXIT_FAILURE, "_native_log_stdout: unknown log type");
}
if (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 stderrtype: "stdio" (leave intact), "null" (redirect to
* /dev/null) or "file" (redirect to /tmp/riot.stdout.PID)
*/
void _native_log_stderr(char *stderrtype)
{
int stderr_outfile;
if (strcmp(stderrtype, "stdio") == 0) {
return;
}
else if (strcmp(stderrtype, "null") == 0) {
if ((stderr_outfile = 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", getpid());
if ((stderr_outfile = creat(stderr_logname, 0666)) == -1) {
err(EXIT_FAILURE, "_native_log_stderr: open");
}
}
else {
errx(EXIT_FAILURE, "_native_log_stderr: unknown log type");
}
if (dup2(stderr_outfile, STDERR_FILENO) == -1) {
err(EXIT_FAILURE, "_native_log_stderr: dup2(STDERR_FILENO)");
}
}
void daemonize()
{
pid_t pid;
if ((pid = fork()) == -1) {
err(EXIT_FAILURE, "daemonize: fork");
}
if (pid > 0) {
real_printf("RIOT pid: %d\n", pid);
exit(EXIT_SUCCESS);
}
}
void usage_exit()
{
real_printf("usage: %s", argv0);
#ifdef MODULE_NATIVENET
real_printf(" <tap interface>");
#endif
#ifdef MODULE_UART0
real_printf(" [-t <port>|-u]");
#endif
real_printf(" [-d] [-e|-E] [-o]\n");
real_printf("\nOptions:\n\
-d daemonize\n\
-e redirect stderr to file\n\
-E do not redirect stderr (i.e. leave sterr unchanged despite socket/daemon io)\n\
-o redirect stdout to file when not attached to socket\n");
#ifdef MODULE_UART0
real_printf("\
-u redirect stdio to UNIX socket\n\
-t redirect stdio to TCP socket\n");
#endif
real_printf("\n\
The order of command line arguments matters.\n");
exit(EXIT_FAILURE);
}
__attribute__((constructor)) static void startup(int argc, char **argv) __attribute__((constructor)) static void startup(int argc, char **argv)
{ {
/* get system read/write */ /* get system read/write/printf */
*(void **)(&real_read) = dlsym(RTLD_NEXT, "read"); *(void **)(&real_read) = dlsym(RTLD_NEXT, "read");
*(void **)(&real_write) = dlsym(RTLD_NEXT, "write"); *(void **)(&real_write) = dlsym(RTLD_NEXT, "write");
*(void **)(&real_printf) = dlsym(RTLD_NEXT, "printf");
argv0 = argv[0];
int argp = 1;
char *stderrtype = "stdio";
char *stdouttype = "stdio";
char *stdiotype = "stdio";
#ifdef MODULE_UART0
char *ioparam = NULL;
#endif
#ifdef MODULE_NATIVENET #ifdef MODULE_NATIVENET
if (argc < 2) { if (argc < 2) {
printf("usage: %s <tap interface>\n", argv[0]); usage_exit();
exit(EXIT_FAILURE); }
argp++;
#endif
for (; argp < argc; argp++) {
char *arg = argv[argp];
if (strcmp("-d", arg) == 0) {
daemonize();
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";
}
#ifdef MODULE_UART0
else if (strcmp("-t", arg) == 0) {
stdiotype = "tcp";
if (argp+1 < argc) {
ioparam = argv[++argp];
}
else {
usage_exit();
}
if (strcmp(stdouttype, "stdio") == 0) {
stdouttype = "null";
}
if (strcmp(stderrtype, "stdio") == 0) {
stderrtype = "null";
}
}
else if (strcmp("-u", arg) == 0) {
stdiotype = "unix";
if (strcmp(stdouttype, "stdio") == 0) {
stdouttype = "null";
}
if (strcmp(stderrtype, "stdio") == 0) {
stderrtype = "null";
}
}
#endif
else {
usage_exit();
}
} }
#else /* args unused here */
(void) argc; _native_log_stderr(stderrtype);
(void) argv; _native_log_stdout(stdouttype);
_native_null_in(stdiotype);
#ifdef MODULE_UART0
_native_init_uart0(stdiotype, ioparam);
#endif #endif
native_hwtimer_pre_init(); native_hwtimer_pre_init();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment