diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-22 09:26:47 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-22 09:32:47 +0300 |
commit | 4da9775f1d88787517e54f5c1fe1c43f1e023480 (patch) | |
tree | a214263c46aea4199cdf32ee0763f53e1e80a05a /capture.c | |
parent | 5ea83707e0b082687b59469fa422611e18e812bc (diff) | |
download | posixruncapture-4da9775f1d88787517e54f5c1fe1c43f1e023480.tar.gz posixruncapture-4da9775f1d88787517e54f5c1fe1c43f1e023480.tar.bz2 |
Add new methods for manipulating argv and program pathname
* Capture.xs (capture_new): Use new ARGV typedef. Handle the new
"program" keyword.
(capture_set_argv_ref, capture_set_program)
(capture_argv, capture_program): New methods.
* capture.c: Handle out of memory errors.
(XS_pack_ARGV, XS_unpack_ARGV): New functions.
(capture_new): Change signature. Set the rc_program field.
(capture_DESTROY): Destroy cp->program
(capture_set_argv_ref): New function.
* capture.h (capture) <program>: New member.
(ARGV): New typedef.
(capture_new): Change signature.
(XS_unpack_ARGV, XS_pack_ARGV)
(capture_set_argv_ref): New protos.
* lib/POSIX/Run/Capture.pm (set_argv): New method.
* typemap: Hande ARGV conversions.
* runcap: Update.
Diffstat (limited to 'capture.c')
-rw-r--r-- | capture.c | 125 |
1 files changed, 91 insertions, 34 deletions
@@ -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) { |