aboutsummaryrefslogtreecommitdiff
path: root/capture.c
diff options
context:
space:
mode:
Diffstat (limited to 'capture.c')
-rw-r--r--capture.c125
1 files changed, 91 insertions, 34 deletions
diff --git a/capture.c b/capture.c
index 4d2c04c..471b2bf 100644
--- a/capture.c
+++ b/capture.c
@@ -1,6 +1,12 @@
#include "capture.h"
#include <stdlib.h>
+static inline void
+croak_nomem(void)
+{
+ croak("Out of memory");
+}
+
static void
call_monitor(SV *cv, const char *ptr, size_t sz)
{
@@ -30,7 +36,7 @@ line_monitor(const char *ptr, size_t sz, void *closure)
if (newsz > lc->size) {
lc->str = realloc(lc->str, newsz);
if (!lc->str)
- croak("Out of memory");
+ croak_nomem();
lc->size = newsz;
}
memcpy(lc->str + lc->len, ptr, sz);
@@ -44,41 +50,90 @@ line_monitor(const char *ptr, size_t sz, void *closure)
} else
call_monitor(lc->cv, ptr, sz);
}
+
+void
+XS_pack_ARGV(SV *const sv, ARGV argv)
+{
+ AV *av = newAV();
+
+ if (argv) {
+ int i;
+ for (i = 0; argv[i]; i++)
+ av_push(av, newSVpv(argv[i], 0));
+ }
+ sv_setsv(sv, newRV_inc((SV*)av));
+}
+
+ARGV
+XS_unpack_ARGV(SV *sv)
+{
+ AV *av;
+ I32 i, n;
+ char **argv;
+ if (!sv || !SvOK(sv) || !SvROK(sv) || (SvTYPE(SvRV(sv)) != SVt_PVAV))
+ croak ("array reference expected");
+
+ av = (AV *)SvRV(sv);
+
+ n = av_len(av);
+ if (n == -1) {
+ argv = NULL;
+ } else {
+ argv = calloc(n + 2, sizeof *argv);
+ if (!argv)
+ croak_nomem();
+ for (i = 0; i <= n; i++) {
+ SV *sv, **psv = av_fetch(av, i, 0);
+ if (!psv)
+ croak("element %d doesn't exist", i);
+ sv = *psv;
+ if (SvROK(sv)) {
+ croak("argument #%d is not a scalar", i);
+ } else {
+ char *s = SvPV_nolen(sv);
+ if ((argv[i] = strdup(s)) == NULL)
+ croak_nomem();
+ }
+ }
+ argv[i] = NULL;
+ }
+ return argv;
+}
+
+static void
+free_argv(struct capture *cp)
+{
+ if (cp->rc.rc_argv) {
+ size_t i;
+ for (i = 0; cp->rc.rc_argv[i]; i++) {
+ free(cp->rc.rc_argv[i]);
+ }
+ free(cp->rc.rc_argv);
+ cp->rc.rc_argv = NULL;
+ }
+}
+
struct capture *
-capture_new(AV *av, unsigned timeout, SV *cb[2])
+capture_new(SV *program, ARGV argv, unsigned timeout, SV *cb[2])
{
struct capture *cp;
I32 i, n;
- char **argv;
cp = malloc(sizeof *cp);
if (!cp)
- goto nomem;
+ croak_nomem();
memset(cp, 0, sizeof *cp);
- n = av_len(av);
- if (n == -1)
- return cp;
- argv = calloc(n + 2, sizeof *argv);
- if (!argv)
- goto nomem;
- for (i = 0; i <= n; i++) {
- SV *sv, **psv = av_fetch(av, i, 0);
- if (!psv)
- croak("element %d doesn't exist", i);
- sv = *psv;
- if (SvROK(sv)) {
- croak("argument #%d is not a scalar", i);
- } else {
- char *s = SvPV_nolen(sv);
- if ((argv[i] = strdup(s)) == NULL)
- goto nomem;
- }
- }
- argv[i] = NULL;
cp->rc.rc_argv = argv;
+ cp->program = program;
+ if (program != &PL_sv_undef) {
+ SvREFCNT_inc(program);
+ cp->rc.rc_program = SvPV_nolen(program);
+ cp->flags |= RCF_PROGRAM;
+ }
+
if (timeout) {
cp->rc.rc_timeout = timeout;
cp->flags |= RCF_TIMEOUT;
@@ -102,24 +157,19 @@ capture_new(AV *av, unsigned timeout, SV *cb[2])
}
return cp;
- nomem:
- return NULL;
}
void
capture_DESTROY(struct capture *cp)
{
-// printf("DESTROY\n");
- if (cp->rc.rc_argv) {
- size_t i;
- for (i = 0; cp->rc.rc_argv[i]; i++) {
- free(cp->rc.rc_argv[i]);
- }
- free(cp->rc.rc_argv);
- }
+ free_argv(cp);
runcap_free(&cp->rc);
free(cp->closure[0].str);
+
+ if (cp->program != &PL_sv_undef)
+ SvREFCNT_dec(cp->program);
+
if (cp->closure[0].cv != &PL_sv_undef)
SvREFCNT_dec(cp->closure[0].cv);
@@ -129,6 +179,13 @@ capture_DESTROY(struct capture *cp)
free(cp);
}
+void
+capture_set_argv_ref(struct capture *cp, ARGV argv)
+{
+ free_argv(cp);
+ cp->rc.rc_argv = argv;
+}
+
char *
capture_next_line(struct capture *cp, int fd)
{

Return to:

Send suggestions and report system problems to the System administrator.