mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
daemonization, io socket and file redirection
This commit is contained in:
parent
f11071cdd8
commit
864267f238
@ -23,9 +23,6 @@
|
||||
*/
|
||||
void board_init()
|
||||
{
|
||||
#ifdef MODULE_UART0
|
||||
_native_init_uart0();
|
||||
#endif
|
||||
LED_GREEN_OFF;
|
||||
LED_RED_ON;
|
||||
puts("RIOT native board initialized.");
|
||||
|
@ -19,6 +19,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.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>
|
||||
|
||||
@ -27,11 +36,15 @@
|
||||
#include "board_uart0.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;
|
||||
|
||||
/* uart API */
|
||||
|
||||
int uart0_puts(char *astring, int length)
|
||||
{
|
||||
int nwritten, offset;
|
||||
@ -60,28 +73,119 @@ int uart0_puts(char *astring, int 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];
|
||||
int nread;
|
||||
|
||||
if (!FD_ISSET(_native_uart_in, &_native_rfds)) {
|
||||
DEBUG("_native_handle_uart0_input - nothing to do\n");
|
||||
return;
|
||||
}
|
||||
DEBUG("_native_handle_uart0_input\n");
|
||||
DEBUG("handle_uart_in\n");
|
||||
|
||||
nread = read(_native_uart_in, buf, sizeof(buf));
|
||||
nread = read(STDIN_FILENO, buf, sizeof(buf));
|
||||
if (nread == -1) {
|
||||
err(1, "_native_handle_uart0_input(): read()");
|
||||
err(1, "handle_uart_in(): read()");
|
||||
}
|
||||
else if (nread == 0) {
|
||||
/* XXX:
|
||||
* preliminary resolution for this situation, will be coped
|
||||
* with properly in #161 */
|
||||
close(_native_uart_in);
|
||||
_native_uart_in = -1;
|
||||
printf("stdin closed");
|
||||
/* end of file / socket closed */
|
||||
if (_native_uart_conn != 0) {
|
||||
if (_native_null_out_file != -1) {
|
||||
if (dup2(_native_null_out_file, STDOUT_FILENO) == -1) {
|
||||
err(EXIT_FAILURE, "handle_uart_in: dup2(STDOUT_FILENO)");
|
||||
}
|
||||
}
|
||||
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++) {
|
||||
uart0_handle_incoming(buf[pos]);
|
||||
@ -91,18 +195,78 @@ void _native_handle_uart0_input()
|
||||
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)
|
||||
{
|
||||
DEBUG("_native_set_uart_fds");
|
||||
if (_native_uart_in != -1) {
|
||||
FD_SET(_native_uart_in, &_native_rfds);
|
||||
FD_SET(STDIN_FILENO, &_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.");
|
||||
}
|
||||
|
@ -1,8 +1,16 @@
|
||||
#ifdef MODULE_UART0
|
||||
#include <sys/select.h>
|
||||
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);
|
||||
#endif
|
||||
|
||||
extern int _native_null_out_file;
|
||||
extern int _native_null_in_pipe[2];
|
||||
void board_init(void);
|
||||
|
@ -79,3 +79,62 @@ restarting.
|
||||
Packet delivery under OSX only works with user assistance at the
|
||||
moment. run 'kill -SIGIO <RIOT process ID>' to deliver a packet to a
|
||||
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 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.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 "cpu.h"
|
||||
|
||||
#include "board_internal.h"
|
||||
#include "native_internal.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)
|
||||
{
|
||||
/* get system read/write */
|
||||
/* get system read/write/printf */
|
||||
*(void **)(&real_read) = dlsym(RTLD_NEXT, "read");
|
||||
*(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
|
||||
if (argc < 2) {
|
||||
printf("usage: %s <tap interface>\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
usage_exit();
|
||||
}
|
||||
#else /* args unused here */
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
_native_log_stderr(stderrtype);
|
||||
_native_log_stdout(stdouttype);
|
||||
_native_null_in(stdiotype);
|
||||
|
||||
#ifdef MODULE_UART0
|
||||
_native_init_uart0(stdiotype, ioparam);
|
||||
#endif
|
||||
|
||||
native_hwtimer_pre_init();
|
||||
|
Loading…
Reference in New Issue
Block a user