aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dumm/irdumm.c77
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);