aboutsummaryrefslogtreecommitdiff
path: root/capture.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-07-21 13:25:07 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-07-21 13:33:04 +0300
commitec78df167efca7feba360b29700ef052eccf4b69 (patch)
tree1bcad85c0bc4696c0d87b45faefb9f00daef01cb /capture.c
parent9565c4d075158f27b5bfd6eab500f0e3f6d8c9ed (diff)
downloadposixruncapture-ec78df167efca7feba360b29700ef052eccf4b69.tar.gz
posixruncapture-ec78df167efca7feba360b29700ef052eccf4b69.tar.bz2
Improve constructor calling convention; implement timeout and line monitoring
* Capture.xs: Rewrite constructor to optionally take named arguments. * Makefile.PL: Remove 'subdirs-test_.*' rules. * capture.h (capture): New structure. All capture_ functions operate on it. * capture.c (capture_new): Change signature. Set line monitoring features if required. (capture_DESTROY): Free line buffers and dereference callback references. * lib/POSIX/Run/Capture.pm: Fix trivial error (get_lines): New method.
Diffstat (limited to 'capture.c')
-rw-r--r--capture.c123
1 files changed, 103 insertions, 20 deletions
diff --git a/capture.c b/capture.c
index 11fbc17..61398de 100644
--- a/capture.c
+++ b/capture.c
@@ -1,20 +1,64 @@
#include "capture.h"
#include <stdlib.h>
-struct runcap *
-capture_new(AV *av)
+static void
+call_monitor(SV *cv, const char *ptr, size_t sz)
{
- struct runcap *rc;
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(newSVpv(ptr, sz)));
+ PUTBACK;
+
+ call_sv(cv, G_DISCARD);
+
+ FREETMPS;
+ LEAVE;
+}
+
+static void
+line_monitor(const char *ptr, size_t sz, void *closure)
+{
+ struct line_closure *lc = closure;
+
+ if (lc->len || ptr[sz-1] != '\n') {
+ size_t newsz = lc->len + sz + 1;
+
+ if (newsz > lc->size) {
+ lc->str = realloc(lc->str, newsz);
+ if (!lc->str)
+ croak("Out of memory");
+ lc->size = newsz;
+ }
+ memcpy(lc->str + lc->len, ptr, sz);
+ lc->len += sz;
+ lc->str[lc->len] = 0;
+
+ if (lc->str[lc->len - 1] == '\n') {
+ call_monitor(lc->cv, lc->str, lc->len);
+ lc->len = 0;
+ }
+ } else
+ call_monitor(lc->cv, ptr, sz);
+}
+
+struct capture *
+capture_new(AV *av, unsigned timeout, SV *cb[2])
+{
+ struct capture *cp;
I32 i, n;
char **argv;
-
- rc = malloc(sizeof *rc);
- if (!rc)
+
+ cp = malloc(sizeof *cp);
+ if (!cp)
goto nomem;
- memset(rc, 0, sizeof *rc);
+ memset(cp, 0, sizeof *cp);
n = av_len(av);
if (n == -1)
- return rc;
+ return cp;
argv = calloc(n + 2, sizeof *argv);
if (!argv)
goto nomem;
@@ -31,30 +75,60 @@ capture_new(AV *av)
}
argv[i] = NULL;
- rc->rc_argv = argv;
-
- return rc;
+ cp->rc.rc_argv = argv;
+
+ if (timeout) {
+ cp->rc.rc_timeout = timeout;
+ cp->flags |= RCF_TIMEOUT;
+ }
+
+ cp->closure[0].cv = cb[0];
+ if (cb[0] != &PL_sv_undef) {
+ SvREFCNT_inc(cb[0]);
+ cp->rc.rc_cap[RUNCAP_STDOUT].sc_linemon = line_monitor;
+ cp->rc.rc_cap[RUNCAP_STDOUT].sc_monarg = &cp->closure[0];
+ cp->flags |= RCF_STDOUT_LINEMON;
+ }
+
+ cp->closure[1].cv = cb[1];
+ if (cb[1] != &PL_sv_undef) {
+ SvREFCNT_inc(cb[1]);
+ cp->closure[1].cv = cb[1];
+ cp->rc.rc_cap[RUNCAP_STDERR].sc_linemon = line_monitor;
+ cp->rc.rc_cap[RUNCAP_STDERR].sc_monarg = &cp->closure[1];
+ cp->flags |= RCF_STDOUT_LINEMON;
+ }
+
+ return cp;
nomem:
return NULL;
}
void
-capture_DESTROY(struct runcap *rc)
+capture_DESTROY(struct capture *cp)
{
// printf("DESTROY\n");
- if (rc->rc_argv) {
+ if (cp->rc.rc_argv) {
size_t i;
- for (i = 0; rc->rc_argv[i]; i++) {
- free(rc->rc_argv[i]);
+ for (i = 0; cp->rc.rc_argv[i]; i++) {
+ free(cp->rc.rc_argv[i]);
}
- free(rc->rc_argv);
+ free(cp->rc.rc_argv);
}
- runcap_free(rc);
- free(rc);
+ runcap_free(&cp->rc);
+
+ free(cp->closure[0].str);
+ if (cp->closure[0].cv != &PL_sv_undef)
+ SvREFCNT_dec(cp->closure[0].cv);
+
+ free(cp->closure[1].str);
+ if (cp->closure[1].cv != &PL_sv_undef)
+ SvREFCNT_dec(cp->closure[1].cv);
+ free(cp);
}
char *
-capture_next_line(struct runcap *rc, int fd)
+capture_next_line(struct capture *cp, int fd)
{
char *buf = NULL;
size_t sz = 0;
@@ -63,7 +137,7 @@ capture_next_line(struct runcap *rc, int fd)
if (fd != RUNCAP_STDOUT && fd != RUNCAP_STDERR) {
croak("invalid stream number: %d", fd);
}
- n = runcap_getline(rc, fd, &buf, &sz);
+ n = runcap_getline(&cp->rc, fd, &buf, &sz);
if (n == -1)
croak("error getting line: %s", strerror(errno));
if (n == 0)
@@ -71,6 +145,15 @@ capture_next_line(struct runcap *rc, int fd)
return realloc(buf, n + 1);
}
+int
+capture_run(struct capture *cp)
+{
+ if (!cp->rc.rc_argv)
+ croak("no command line given");
+
+ return runcap(&cp->rc, cp->flags);
+}
+
void
capture_wd()
{

Return to:

Send suggestions and report system problems to the System administrator.