diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dumm/irdumm.c | 77 |
1 files changed, 73 insertions, 4 deletions
diff --git a/src/dumm/irdumm.c b/src/dumm/irdumm.c index 53443bf27..9b5e02109 100644 --- a/src/dumm/irdumm.c +++ b/src/dumm/irdumm.c @@ -20,6 +20,7 @@ #include <library.h> #include <dumm.h> +#include <debug.h> #undef PACKAGE_NAME #undef PACKAGE_TARNAME @@ -79,6 +80,23 @@ static void sigchld_handler(int signal, siginfo_t *info, void* ptr) } /** + * SIGINT/SEGV/TERM signal handler + */ +static void sigint_handler(int signal, siginfo_t *info, void* ptr) +{ + struct sigaction action; + + dumm->destroy(dumm); + + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + sigaction(SIGCHLD, &action, NULL); + + library_deinit(); + exit(0); +} + +/** * Guest bindings */ static VALUE guest_get(VALUE class, VALUE key) @@ -169,20 +187,66 @@ static VALUE guest_stop(VALUE self) return self; } -static void cb(void *data, char *buf, size_t len) +typedef struct { + char buf[1024]; + char *top; +} exec_t; + +static void exec_cb(exec_t *exec, char *buf, size_t len) { - printf("%.*s", len, buf); + size_t to_copy; + char *nl; + + while (len) + { + to_copy = min(len, sizeof(exec->buf) - (exec->top - exec->buf)); + memcpy(exec->top, buf, to_copy); + exec->top += to_copy; + len -= to_copy; + buf += to_copy; + + while (TRUE) + { + nl = memchr(exec->buf, '\n', exec->top - exec->buf); + if (!nl) + { + break; + } + if (nl > exec->buf) + { + rb_yield(rb_str_new(exec->buf, nl - exec->buf)); + } + nl++; + to_copy = exec->top - nl; + memmove(exec->buf, nl, to_copy); + exec->top = exec->buf + to_copy; + } + if (exec->top >= exec->buf + sizeof(exec->buf)) + { + rb_yield(rb_str_new(exec->buf, sizeof(exec->buf))); + exec->top = exec->buf; + } + } } static VALUE guest_exec(VALUE self, VALUE cmd) { guest_t *guest; + exec_t exec; + bool block; + block = rb_block_given_p(); + exec.top = exec.buf; Data_Get_Struct(self, guest_t, guest); - if (guest->exec(guest, cb, NULL, "%s", StringValuePtr(cmd)) != 0) + if (guest->exec(guest, block ? (void*)exec_cb : NULL, &exec, + "%s", StringValuePtr(cmd)) != 0) { rb_raise(rb_eRuntimeError, "executing command failed"); } + if (exec.top != exec.buf && block) + { + rb_yield(rb_str_new(exec.buf, exec.top - exec.buf)); + } return self; } @@ -521,9 +585,14 @@ int main(int argc, char *argv[]) iface_init(); sigemptyset(&action.sa_mask); - action.sa_sigaction = sigchld_handler; action.sa_flags = SA_SIGINFO; + action.sa_sigaction = sigchld_handler; sigaction(SIGCHLD, &action, NULL); + action.sa_sigaction = sigint_handler; + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); + sigaction(SIGSEGV, &action, NULL); + sigaction(SIGHUP, &action, NULL); rb_require("irb"); rb_eval_string_protect("include Dumm", &state); |