ports/115094: [PATCH] shells/zsh: fix for using *env()
Sean C. Farley
scf at FreeBSD.org
Tue Jul 31 19:30:02 UTC 2007
>Number: 115094
>Category: ports
>Synopsis: [PATCH] shells/zsh: fix for using *env()
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Tue Jul 31 19:30:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Sean C. Farley
>Release: FreeBSD 6.2-STABLE i386
>Organization:
>Environment:
System: FreeBSD thor.farley.org 6.2-STABLE FreeBSD 6.2-STABLE #0: Sun Jul 29 21:02:21 CDT 2007
>Description:
This patch by Peter Stephenson adds (un)setenv() detection to zsh. This
fixes the issue on 7-CURRENT where zsh was manipulating environ directly
in conflict with the new *env() functions. 6-STABLE continues to works
correctly.
See "zsh oddities with recent -current" for the initial report:
http://lists.freebsd.org/pipermail/freebsd-current/2007-July/075538.html
Here is the thread about the patch:
http://www.zsh.org/mla/workers/2007/msg00619.html
Notes:
- With the recent autoconf changes, I am not sure if the patches to both
configure and configure.ac are needed.
- The patch to the test case is not really needed.
- The next version of zsh should have this fix in it.
Added file(s):
- files/patch-environ
Port maintainer (sergei at FreeBSD.org) is cc'd.
Generated with FreeBSD Port Tools 0.77
>How-To-Repeat:
>Fix:
--- zsh-4.3.4_1.patch begins here ---
Index: files/patch-environ
===================================================================
RCS file: files/patch-environ
diff -N files/patch-environ
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ files/patch-environ 31 Jul 2007 14:21:36 -0000
@@ -0,0 +1,253 @@
+diff -u Src/exec.c Src/exec.c
+--- Src/exec.c 2007-02-14 10:11:19.000000000 -0600
++++ Src/exec.c 2007-07-31 08:49:13.000000000 -0500
+@@ -501,7 +501,16 @@
+ * that as argv[0] for this external command */
+ if (unset(RESTRICTED) && (z = zgetenv("ARGV0"))) {
+ setdata(firstnode(args), (void *) ztrdup(z));
++ /*
++ * Note we don't do anything with the parameter structure
++ * for ARGV0: that's OK since we're about to exec or exit
++ * on failure.
++ */
++#ifdef USE_SET_UNSET_ENV
++ unsetenv("ARGV0");
++#else
+ delenvvalue(z - 6);
++#endif
+ } else if (dash) {
+ /* Else if the pre-command `-' was given, we add `-' *
+ * to the front of argv[0] for this command. */
+diff -u Src/params.c Src/params.c
+--- Src/params.c 2007-04-13 06:40:27.000000000 -0500
++++ Src/params.c 2007-07-31 08:49:13.000000000 -0500
+@@ -606,7 +606,7 @@
+ createparamtable(void)
+ {
+ Param ip, pm;
+-#ifndef HAVE_PUTENV
++#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV)
+ char **new_environ;
+ int envsize;
+ #endif
+@@ -661,7 +661,7 @@
+
+ setsparam("LOGNAME", ztrdup((str = getlogin()) && *str ? str :
cached_username));
+
+-#ifndef HAVE_PUTENV
++#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV)
+ /* Copy the environment variables we are inheriting to dynamic *
+ * memory, so we can do mallocs and frees on it. */
+ envsize = sizeof(char *)*(1 + arrlen(environ));
+@@ -3727,6 +3727,30 @@
+ int
+ zputenv(char *str)
+ {
++#ifdef USE_SET_UNSET_ENV
++ /*
++ * If we are using unsetenv() to remove values from the
++ * environment, which is the safe thing to do, we
++ * need to use setenv() to put them there in the first place.
++ * Unfortunately this is a slightly different interface
++ * from what zputenv() assumes.
++ */
++ char *ptr;
++ int ret;
++
++ for (ptr = str; *ptr && *ptr != '='; ptr++)
++ ;
++ if (*ptr) {
++ *ptr = '\0';
++ ret = setenv(str, ptr+1, 1);
++ *ptr = '=';
++ } else {
++ /* safety first */
++ DPUTS(1, "bad environment string");
++ ret = setenv(str, ptr, 1);
++ }
++ return ret;
++#else
+ #ifdef HAVE_PUTENV
+ return putenv(str);
+ #else
+@@ -3750,9 +3774,12 @@
+ }
+ return 0;
+ #endif
++#endif
+ }
+
+ /**/
++#ifndef USE_SET_UNSET_ENV
++/**/
+ static int
+ findenv(char *name, int *pos)
+ {
+@@ -3771,6 +3798,8 @@
+
+ return 0;
+ }
++/**/
++#endif
+
+ /* Given *name = "foo", it searches the environment for string *
+ * "foo=bar", and returns a pointer to the beginning of "bar" */
+@@ -3811,14 +3840,18 @@
+ void
+ addenv(Param pm, char *value)
+ {
+- char *oldenv = 0, *newenv = 0, *env = 0;
++ char *newenv = 0;
++#ifndef USE_SET_UNSET_ENV
++ char *oldenv = 0, *env = 0;
+ int pos;
+
+- /* First check if there is already an environment *
+- * variable matching string `name'. If not, and *
+- * we are not requested to add new, return */
++ /*
++ * First check if there is already an environment
++ * variable matching string `name'.
++ */
+ if (findenv(pm->node.nam, &pos))
+ oldenv = environ[pos];
++#endif
+
+ newenv = mkenvstr(pm->node.nam, value, pm->node.flags);
+ if (zputenv(newenv)) {
+@@ -3826,6 +3859,19 @@
+ pm->env = NULL;
+ return;
+ }
++#ifdef USE_SET_UNSET_ENV
++ /*
++ * If we are using setenv/unsetenv to manage the environment,
++ * we simply store the string we created in pm->env since
++ * memory management of the environment is handled entirely
++ * by the system.
++ *
++ * TODO: is this good enough to fix problem cases from
++ * the other branch? If so, we don't actually need to
++ * store pm->env at all, just a flag that the value was set.
++ */
++ pm->env = newenv;
++#else
+ /*
+ * Under Cygwin we must use putenv() to maintain consistency.
+ * Unfortunately, current version (1.1.2) copies argument and may
+@@ -3845,6 +3891,7 @@
+
+ DPUTS(1, "addenv should never reach the end");
+ pm->env = NULL;
++#endif
+ }
+
+
+@@ -3875,6 +3922,7 @@
+ * string. */
+
+
++#ifndef USE_SET_UNSET_ENV
+ /**/
+ void
+ delenvvalue(char *x)
+@@ -3890,6 +3938,8 @@
+ }
+ zsfree(x);
+ }
++#endif
++
+
+ /* Delete a pointer from the list of pointers to environment *
+ * variables by shifting all the other pointers up one slot. */
+@@ -3898,7 +3948,12 @@
+ void
+ delenv(Param pm)
+ {
++#ifdef USE_SET_UNSET_ENV
++ unsetenv(pm->node.nam);
++ zsfree(pm->env);
++#else
+ delenvvalue(pm->env);
++#endif
+ pm->env = NULL;
+ /*
+ * Note we don't remove PM_EXPORT from the flags. This
+diff -u Src/system.h Src/system.h
+--- Src/system.h 2007-04-13 05:11:31.000000000 -0500
++++ Src/system.h 2007-07-31 08:49:13.000000000 -0500
+@@ -693,6 +693,15 @@
+
+ extern char **environ;
+
++/*
++ * We always need setenv and unsetenv in pairs, because
++ * we don't know how to do memory management on the values set.
++ */
++#if defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
++# define USE_SET_UNSET_ENV
++#endif
++
++
+ /* These variables are sometimes defined in, *
+ * and needed by, the termcap library. */
+ #if MUST_DEFINE_OSPEED
+diff -u Test/B02typeset.ztst Test/B02typeset.ztst
+--- Test/B02typeset.ztst 2006-06-26 13:17:32.000000000 -0500
++++ Test/B02typeset.ztst 2007-07-31 08:49:13.000000000 -0500
+@@ -379,3 +379,31 @@
+ >integer local i
+ >local tagged scalar
+ >preserved
++
++ export ENVFOO=bar
++ print ENVFOO in environment
++ env | grep '^ENVFOO'
++ print Changing ENVFOO
++ ENVFOO="not bar any more"
++ env | grep '^ENVFOO'
++ unset ENVFOO
++ print ENVFOO no longer in environment
++ env | grep '^ENVFOO'
++1:Adding and removing values to and from the environment
++>ENVFOO in environment
++>ENVFOO=bar
++>Changing ENVFOO
++>ENVFOO=not bar any more
++>ENVFOO no longer in environment
++
++ (export FOOENV=BAR
++ env | grep '^FOOENV'
++ print Exec
++ exec $ZTST_testdir/../Src/zsh -c '
++ print Unset
++ unset FOOENV
++ env | grep "^FOOENV"')
++1:Can unset environment variables after exec
++>FOOENV=BAR
++>Exec
++>Unset
+diff -u configure configure
+--- configure 2007-01-18 10:33:17.000000000 -0600
++++ configure 2007-07-31 08:49:06.000000000 -0500
+@@ -10263,7 +10263,7 @@
+ setlocale \
+ uname \
+ signgam \
+- putenv getenv \
++ putenv getenv setenv unsetenv xw \
+ brk sbrk \
+ pathconf sysconf \
+ tgetent tigetflag tigetnum tigetstr setupterm \
+diff -u configure.ac configure.ac
+--- configure.ac 2007-01-05 07:58:04.000000000 -0600
++++ configure.ac 2007-07-31 08:49:06.000000000 -0500
+@@ -1126,7 +1126,7 @@
+ setlocale \
+ uname \
+ signgam \
+- putenv getenv \
++ putenv getenv setenv unsetenv xw\
+ brk sbrk \
+ pathconf sysconf \
+ tgetent tigetflag tigetnum tigetstr setupterm \
--- zsh-4.3.4_1.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list