passing a block to guest.exec() processes output lines

This commit is contained in:
Martin Willi
2008-07-09 10:51:10 +00:00
parent bf44108019
commit ee70c94835
+73 -4
View File
@@ -20,6 +20,7 @@
#include <library.h>
#include <dumm.h>
#include <debug.h>
#undef PACKAGE_NAME
#undef PACKAGE_TARNAME
@@ -78,6 +79,23 @@ static void sigchld_handler(int signal, siginfo_t *info, void* ptr)
enumerator->destroy(enumerator);
}
/**
* 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
*/
@@ -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);