diff --git a/boards/native/drivers/native-uart0.c b/boards/native/drivers/native-uart0.c index d58139aa7a101af68ced16df0dfae80d01c84ac1..6ba53fc03c64001bdb1e72e89dc583ed2e85cc78 100644 --- a/boards/native/drivers/native-uart0.c +++ b/boards/native/drivers/native-uart0.c @@ -45,6 +45,9 @@ int _native_uart_sock; int _native_uart_conn; +int _native_replay_enabled; +FILE *_native_replay_buffer; + fd_set _native_uart_rfds; /* uart API */ @@ -227,6 +230,34 @@ void handle_uart_sock(void) if (real_dup2(s, STDIN_FILENO) == -1) { err(EXIT_FAILURE, "handle_uart_sock: dup2()"); } + + /* play back log from last position */ + if (_native_replay_enabled) { + warnx("handle_uart_sock: replaying buffer"); + size_t nread; + char buf[200]; + while ((nread = real_fread(buf, 1, sizeof(buf), _native_replay_buffer)) != 0) { + int nwritten; + int pos = 0; + while ((nwritten = real_write(STDOUT_FILENO, &buf[pos], nread)) != -1) { + nread -= nwritten; + pos += nwritten; + if (nread == 0) { + break; + } + } + if (nwritten == -1) { + err(EXIT_FAILURE, "handle_uart_sock: write"); + } + } + if (real_feof(_native_replay_buffer) != 0) { + real_clearerr(_native_replay_buffer); + } + else if (real_ferror(_native_replay_buffer) != 0) { + err(EXIT_FAILURE, "handle_uart_sock(): fread()"); + } + } + _native_syscall_leave(); _native_uart_conn = s; @@ -260,8 +291,18 @@ int _native_set_uart_fds(void) } #endif -void _native_init_uart0(char *stdiotype, char *ioparam) +void _native_init_uart0(char *stdiotype, char *ioparam, int replay) { + _native_replay_enabled = replay; + + if (_native_replay_enabled) { + char stdout_logname[255]; + snprintf(stdout_logname, sizeof(stdout_logname), "/tmp/riot.stdout.%d", _native_pid); + if ((_native_replay_buffer = real_fopen(stdout_logname, "r+")) == NULL) { + err(EXIT_FAILURE, "_native_init_uart0: fdopen(_native_null_out_file)"); + } + } + if (strcmp(stdiotype, "tcp") == 0) { _native_uart_sock = init_tcp_socket(ioparam); } diff --git a/boards/native/include/board_internal.h b/boards/native/include/board_internal.h index f2cac0bfb2b175c680a0455e3fc201ca272debf3..a364ed24cc34806d34b3617ff8934e3a4202b4c1 100644 --- a/boards/native/include/board_internal.h +++ b/boards/native/include/board_internal.h @@ -7,7 +7,7 @@ void _native_handle_uart0_input(void); * @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); +void _native_init_uart0(char *stdiotype, char *ioparam, int replay); int _native_set_uart_fds(void); #endif diff --git a/cpu/native/include/native_internal.h b/cpu/native/include/native_internal.h index 54c38e15d8c64929b48f032604314a41308ae4b4..585751604800899c24f4fd1b2cdb4aa484135a81 100644 --- a/cpu/native/include/native_internal.h +++ b/cpu/native/include/native_internal.h @@ -13,6 +13,7 @@ #define _NATIVE_INTERNAL_H #include <signal.h> +#include <stdio.h> /* enable signal handler register access on different platforms * check here for more: * http://sourceforge.net/p/predef/wiki/OperatingSystems/ @@ -54,18 +55,23 @@ void _native_syscall_enter(void); */ extern ssize_t (*real_read)(int fd, void *buf, size_t count); extern ssize_t (*real_write)(int fd, const void *buf, size_t count); +extern size_t (*real_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); extern void* (*real_malloc)(size_t size); +extern void (*real_clearerr)(FILE *stream); extern void (*real_free)(void *ptr); extern void* (*real_calloc)(size_t nmemb, size_t size); extern void* (*real_realloc)(void *ptr, size_t size); extern int (*real_getpid)(void); extern int (*real_pipe)(int[2]); extern int (*real_close)(int); +extern int (*real_feof)(FILE *stream); +extern int (*real_ferror)(FILE *stream); extern int (*real_fork)(void); extern int (*real_dup2)(int, int); extern int (*real_unlink)(const char *); extern int (*real_execve)(const char *, char *const[], char *const[]); extern int (*real_pause)(void); +extern FILE* (*real_fopen)(const char *path, const char *mode); /** * data structures diff --git a/cpu/native/startup.c b/cpu/native/startup.c index 9a70f3e3db41deddfafe417382993191c4c97e6d..bc0e894c0a0b31ed3e48583c81c15f3d13ba2652 100644 --- a/cpu/native/startup.c +++ b/cpu/native/startup.c @@ -161,7 +161,7 @@ void usage_exit(void) #endif #ifdef MODULE_UART0 - real_printf(" [-t <port>|-u [path]]"); + real_printf(" [-t <port>|-u [path]] [-r]"); #endif real_printf(" [-i <id>] [-d] [-e|-E] [-o]\n"); @@ -175,7 +175,9 @@ void usage_exit(void) real_printf("\ -t <port> redirect stdio to TCP socket listening on <port>\n\ -u <path> redirect stdio to UNIX socket (<path> if given,\n\ - /tmp/riot.tty.PID otherwise)\n"); + /tmp/riot.tty.PID otherwise)\n\ +-r replay missed output when (re-)attaching to socket\n\ + (implies -o)\n"); #endif real_printf("\ -i <id> specify instance id (set by config module)\n\ @@ -209,6 +211,11 @@ __attribute__((constructor)) static void startup(int argc, char **argv) *(void **)(&real_unlink) = dlsym(RTLD_NEXT, "unlink"); *(void **)(&real_execve) = dlsym(RTLD_NEXT, "execve"); *(void **)(&real_pause) = dlsym(RTLD_NEXT, "pause"); + *(void **)(&real_fopen) = dlsym(RTLD_NEXT, "fopen"); + *(void **)(&real_fread) = dlsym(RTLD_NEXT, "fread"); + *(void **)(&real_feof) = dlsym(RTLD_NEXT, "feof"); + *(void **)(&real_ferror) = dlsym(RTLD_NEXT, "ferror"); + *(void **)(&real_clearerr) = dlsym(RTLD_NEXT, "clearerr"); _native_argv = argv; _progname = argv[0]; @@ -223,6 +230,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv) char *stdiotype = "stdio"; #ifdef MODULE_UART0 char *ioparam = NULL; + int replay = 0; #endif #ifdef MODULE_NATIVENET @@ -274,6 +282,10 @@ __attribute__((constructor)) static void startup(int argc, char **argv) stdouttype = "file"; } #ifdef MODULE_UART0 + else if (strcmp("-r", arg) == 0) { + stdouttype = "file"; + replay = 1; + } else if (strcmp("-t", arg) == 0) { stdiotype = "tcp"; if (argp + 1 < argc) { @@ -314,7 +326,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv) _native_null_in(stdiotype); #ifdef MODULE_UART0 - _native_init_uart0(stdiotype, ioparam); + _native_init_uart0(stdiotype, ioparam, replay); #endif native_hwtimer_pre_init(); diff --git a/cpu/native/syscalls.c b/cpu/native/syscalls.c index f7aba006e6ff24bc12d130a0f8f28e7f38808cce..cc3abda816feea974fc1445b590ad3a447bcf53c 100644 --- a/cpu/native/syscalls.c +++ b/cpu/native/syscalls.c @@ -50,7 +50,9 @@ extern volatile tcb_t *sched_active_thread; ssize_t (*real_read)(int fd, void *buf, size_t count); ssize_t (*real_write)(int fd, const void *buf, size_t count); +size_t (*real_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); void* (*real_malloc)(size_t size); +void (*real_clearerr)(FILE *stream); void (*real_free)(void *ptr); void* (*real_calloc)(size_t nmemb, size_t size); void* (*real_realloc)(void *ptr, size_t size); @@ -60,7 +62,10 @@ int (*real_fork)(void); int (*real_dup2)(int, int); int (*real_unlink)(const char *); int (*real_execve)(const char *, char *const[], char *const[]); +int (*real_feof)(FILE *stream); +int (*real_ferror)(FILE *stream); int (*real_pause)(void); +FILE* (*real_fopen)(const char *path, const char *mode); void _native_syscall_enter(void) {