passing a block to guest.exec() processes output lines
This commit is contained in:
+73
-4
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <dumm.h>
|
#include <dumm.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#undef PACKAGE_NAME
|
#undef PACKAGE_NAME
|
||||||
#undef PACKAGE_TARNAME
|
#undef PACKAGE_TARNAME
|
||||||
@@ -78,6 +79,23 @@ static void sigchld_handler(int signal, siginfo_t *info, void* ptr)
|
|||||||
enumerator->destroy(enumerator);
|
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
|
* Guest bindings
|
||||||
*/
|
*/
|
||||||
@@ -169,20 +187,66 @@ static VALUE guest_stop(VALUE self)
|
|||||||
return 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)
|
static VALUE guest_exec(VALUE self, VALUE cmd)
|
||||||
{
|
{
|
||||||
guest_t *guest;
|
guest_t *guest;
|
||||||
|
exec_t exec;
|
||||||
|
bool block;
|
||||||
|
|
||||||
|
block = rb_block_given_p();
|
||||||
|
exec.top = exec.buf;
|
||||||
Data_Get_Struct(self, guest_t, guest);
|
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");
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,9 +585,14 @@ int main(int argc, char *argv[])
|
|||||||
iface_init();
|
iface_init();
|
||||||
|
|
||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
action.sa_sigaction = sigchld_handler;
|
|
||||||
action.sa_flags = SA_SIGINFO;
|
action.sa_flags = SA_SIGINFO;
|
||||||
|
action.sa_sigaction = sigchld_handler;
|
||||||
sigaction(SIGCHLD, &action, NULL);
|
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_require("irb");
|
||||||
rb_eval_string_protect("include Dumm", &state);
|
rb_eval_string_protect("include Dumm", &state);
|
||||||
|
|||||||
Reference in New Issue
Block a user