#include <library.h>
#include <dumm.h>
+#include <debug.h>
#undef PACKAGE_NAME
#undef PACKAGE_TARNAME
}
/**
+ * 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)
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;
}
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);