Commit 7b2a7420 authored by Geoff Simmons's avatar Geoff Simmons

Add .setenv().

parent a4723917
......@@ -264,6 +264,17 @@ can be implemented more efficiently by using the ``-u`` argument with
sort.arg("-u");
}
.. _xvdp.setenv():
VOID xvdp.setenv(STRING var, STRING value, BOOL overwrite)
----------------------------------------------------------
::
VOID xvdp.setenv(STRING var, STRING value, BOOL overwrite=1)
XXX ...
.. _pipe.version():
STRING version()
......
......@@ -25,3 +25,55 @@ client c1 {
expect resp.status == 200
expect resp.bodylen > 0
} -run
varnish v1 -vcl+backend {
import ${vmod_pipe};
sub vcl_init {
new env = pipe.vdp("${env}");
env.setenv("FOO", "bar");
env.setenv("BAZ", "quux");
env.setenv("EMPTY", "");
}
sub vcl_deliver {
set resp.filters = "env";
}
}
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.body ~ {(?m)^\s*FOO\s*=\s*bar\s*$}
expect resp.body ~ {(?m)^\s*BAZ\s*=\s*quux\s*$}
expect resp.body ~ {(?m)^\s*EMPTY\s*=\s*$}
} -run
varnish v1 -errvcl {vdp pipe failure: env.setenv(): var is empty} {
import ${vmod_pipe};
backend b None;
sub vcl_init {
new env = pipe.vdp("${env}");
env.setenv("", "foo");
}
}
varnish v1 -errvcl {vdp pipe failure: env.setenv(): var may not contain '=': FOO=} {
import ${vmod_pipe};
backend b None;
sub vcl_init {
new env = pipe.vdp("${env}");
env.setenv("FOO=", "");
}
}
varnish v1 -vcl { backend b None; }
# Tests the object finalization with cleanup of env lists.
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.discard vcl2"
delay 1
varnish v1 -cli "vcl.list"
......@@ -62,16 +62,28 @@ extern char **environ;
#define DEFAULT_BUFSZ ((size_t)512)
#endif
struct setenv_entry {
unsigned magic;
#define PIPE_SETENV_MAGIC 0x1167db2e
VSLIST_ENTRY(setenv_entry) list;
char *var;
char *value;
VCL_BOOL overwrite;
};
VSLIST_HEAD(setenv_head, setenv_entry);
struct VPFX(pipe_vdp) {
unsigned magic;
unsigned magic;
#define PIPE_VDP_MAGIC 0xa887d6c3
char *name;
char *path;
struct vdp *vdp;
char **argv;
size_t bufsz;
int argc;
int tmo_ms;
char *name;
char *path;
struct vdp *vdp;
char **argv;
struct setenv_head *setenv_head;
size_t bufsz;
int argc;
int tmo_ms;
};
struct vdp_map {
......@@ -163,6 +175,7 @@ vdp_init(struct req *req, void **priv)
struct vrt_ctx fake_ctx[1];
struct vmod_priv *task_priv;
struct task_cfg *task;
struct setenv_head *setenv_head;
char **argv;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
......@@ -204,6 +217,8 @@ vdp_init(struct req *req, void **priv)
state->fds[STDERR_FILENO].events = POLLIN;
argv = obj->argv;
setenv_head = obj->setenv_head;
/* Hackishly using non-API knowledge of VRT_priv_task() */
INIT_OBJ(fake_ctx, VRT_CTX_MAGIC);
fake_ctx->req = req;
......@@ -234,6 +249,8 @@ vdp_init(struct req *req, void **priv)
}
if (state->chldpid == 0) {
struct setenv_entry *setenv_entry;
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
......@@ -247,6 +264,23 @@ vdp_init(struct req *req, void **priv)
if (mk_dup(out[1], STDOUT_FILENO) != 0)
exit(EXIT_FAILURE);
if (setenv_head != NULL)
VSLIST_FOREACH(setenv_entry, setenv_head, list) {
CHECK_OBJ_NOTNULL(setenv_entry,
PIPE_SETENV_MAGIC);
errno = 0;
if (setenv(setenv_entry->var,
setenv_entry->value,
setenv_entry->overwrite) != 0) {
fprintf(stderr, "Cannot set environment"
" variable %s=%s: %s",
setenv_entry->var,
setenv_entry->value,
vstrerror(errno));
exit(EXIT_FAILURE);
}
}
errno = 0;
if (execve(obj->path, argv, environ) == -1) {
fprintf(stderr, "cannot exec %s: %s", obj->path,
......@@ -602,6 +636,7 @@ vmod_vdp__init(VRT_CTX, struct VPFX(pipe_vdp) **vdpp, const char *obj_name,
vdp_obj->path = strdup(path);
vdp_obj->bufsz = bufsz;
vdp_obj->tmo_ms = timeout * 1000;
AZ(vdp_obj->setenv_head);
errno = 0;
vdp = malloc(sizeof(*vdp));
......@@ -649,6 +684,7 @@ VCL_VOID
vmod_vdp__fini(struct VPFX(pipe_vdp) **vdpp)
{
struct VPFX(pipe_vdp) *vdp_obj;
struct setenv_entry *setenv_entry;
if (vdpp == NULL || *vdpp == NULL)
return;
......@@ -662,6 +698,17 @@ vmod_vdp__fini(struct VPFX(pipe_vdp) **vdpp)
free(vdp_obj->argv[i]);
free(vdp_obj->argv);
}
if (vdp_obj->setenv_head != NULL)
while (!VSLIST_EMPTY(vdp_obj->setenv_head)) {
setenv_entry = VSLIST_FIRST(vdp_obj->setenv_head);
CHECK_OBJ_NOTNULL(setenv_entry, PIPE_SETENV_MAGIC);
if (setenv_entry->var != NULL)
free(setenv_entry->var);
if (setenv_entry->value != NULL)
free(setenv_entry->value);
VSLIST_REMOVE_HEAD(vdp_obj->setenv_head, list);
FREE_OBJ(setenv_entry);
}
FREE_OBJ(vdp_obj);
}
......@@ -765,6 +812,68 @@ vmod_vdp_arg(VRT_CTX, struct VPFX(pipe_vdp) *obj, VCL_STRING arg)
return;
}
VCL_VOID
vmod_vdp_setenv(VRT_CTX, struct VPFX(pipe_vdp) *obj, VCL_STRING var,
VCL_STRING value, VCL_BOOL overwrite)
{
struct setenv_entry *entry;
#if 0
struct vmod_priv *priv;
struct task_cfg *task;
#endif
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
CHECK_OBJ_NOTNULL(obj, PIPE_VDP_MAGIC);
if (!(ctx->method & (VCL_MET_INIT | VCL_MET_DELIVER))) {
VDPFAIL(ctx, "%s.setenv(): may only be called in vcl_init or "
"vcl_deliver", obj->name);
return;
}
if (var == NULL || *var == '\0') {
VDPFAIL(ctx, "%s.setenv(): var is empty", obj->name);
return;
}
if (strchr(var, '=') != NULL) {
VDPFAIL(ctx, "%s.setenv(): var may not contain '=': %s",
obj->name, var);
return;
}
if (value == NULL) {
VDPFAIL(ctx, "%s.setenv(): value is NULL", obj->name);
return;
}
/* XXX only vcl_init */
if (obj->setenv_head == NULL) {
errno = 0;
obj->setenv_head = malloc(sizeof(*obj->setenv_head));
if (obj->setenv_head == NULL) {
VDPFAIL(ctx,
"%s.setenv(): cannot allocate list head: %s",
obj->name, vstrerror(errno));
return;
}
VSLIST_INIT(obj->setenv_head);
}
errno = 0;
ALLOC_OBJ(entry, PIPE_SETENV_MAGIC);
if (entry == NULL) {
VDPFAIL(ctx, "%s.setenv(): cannot allocate list entry: %s",
obj->name, vstrerror(errno));
return;
}
entry->var = strdup(var);
entry->value = strdup(value);
entry->overwrite = overwrite;
VSLIST_INSERT_HEAD(obj->setenv_head, entry, list);
return;
}
VCL_STRING
vmod_version(VRT_CTX)
{
......
......@@ -245,6 +245,10 @@ can be implemented more efficiently by using the ``-u`` argument with
sort.arg("-u");
}
$Method VOID .setenv(STRING var, STRING value, BOOL overwrite=1)
XXX ...
$Function STRING version()
Return the version string for this library.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment