From 685786b3715e984fb37929dfac9891924f60d811 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 8 Mar 2016 06:16:41 -0800 Subject: Allow nil value in setenv. * sysif.c (setenv_wrap): If value is nil, and overwrite is missing or t, call unsetenv. * txr.1: Documented. --- sysif.c | 8 ++++++-- txr.1 | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/sysif.c b/sysif.c index 3b8341cc..d0a06ca0 100644 --- a/sysif.c +++ b/sysif.c @@ -703,8 +703,12 @@ val getenv_wrap(val name) static val setenv_wrap(val name, val value, val overwrite) { char *nameu8 = utf8_dup_to(c_str(name)); - char *valu8 = utf8_dup_to(c_str(value)); - setenv(nameu8, valu8, default_arg(overwrite, t) != nil); + char *valu8 = value ? utf8_dup_to(c_str(value)) : 0; + int ovw = default_arg(overwrite, t) != nil; + if (valu8) + setenv(nameu8, valu8, ovw); + else if (ovw) + unsetenv(nameu8); free(valu8); free(nameu8); return value; diff --git a/txr.1 b/txr.1 index fd4dd621..5d817140 100644 --- a/txr.1 +++ b/txr.1 @@ -35353,6 +35353,19 @@ function creates or modifies the environment variable indicated by The .meta value string argument specifies the new value for the variable. +If +.meta value +is +.codn nil , +then +.code setenv +behaves like +.codn unsetenv , +except that it observes the +.meta overwrite-p +argument. That is to say, the meaning of a null +.meta value +is that the variable is to be removed. If the .meta overwrite-p @@ -35366,11 +35379,22 @@ effectively giving rise to a two-argument form of .code setenv which creates or overwrites environment variables. +A variable removal is deemed to be an overwrite. +Thus if both +.meta value +and +.meta overwrite-p +are +.codn nil , +then +.code setenv +does nothing. + The .code setenv function unconditionally returns .meta value -regardless of whether or not it overwrites an existing variable. +regardless of whether or not it overwrites or removes an existing variable. The .code unsetenv @@ -35380,6 +35404,26 @@ specified by if it exists. On some platforms, it instead sets the environment variable to the empty string. +Note: supporting removal semantics in +.code setenv +allows for the following simple save/modify/restore pattern: + +.cblk + (let* ((old-val (getenv "SOME-VAR"))) + (unwind-protect + (progn (setenv "SOME-VAR" new-val) + ...) + (setenv "SOME-VAR" old-val))) +.cble + +This works in the case when +.code SOME-VAR +exists, as well as in the case that it doesn't exist. +In both cases, its previous value or, respectively, non-existence, +is restored by the +.code unwind-protect +cleanup form. + .SS* System Programming .coNP Accessor @ errno .synb -- cgit v1.2.3