Date: Wed, 19 Apr 2000 23:30:02 -0700 (PDT) From: Anatoly Vorobey <mellon@pobox.com> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/6577: /bin/sh environment variables not set in simple commands Message-ID: <200004200630.XAA07459@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/6577; it has been noted by GNATS. From: Anatoly Vorobey <mellon@pobox.com> To: freebsd-gnats-submit@freebsd.org Cc: Subject: Re: bin/6577: /bin/sh environment variables not set in simple commands Date: Thu, 20 Apr 2000 09:27:28 +0000 >Gambit-C version 3 depends upon >FOO=bar eval echo \$FOO >outputting "bar" to build. It outputs nothing. This is contrary to >the documented behaviour (for Simple Commands) and to observed >behaviour on AiX, Digital Unix and on bash. I have a fix for this. It's a "I know what I'm doing" fix rather than "this seems to work" fix; so here's a bit of explanation which hopefully will make it easier for someone to review and commit ;) Basically, our sh(1) keeps internal environment, defined by FOO=bar pairs before the command, pointed to by variable cmdenviron defined in eval.c . It merges it with the global environment only when executing external commands. The builtin commands, on the other hands, are expected to use bltinlookup() which will look both into cmdenviron and the global environment, instead of vanilla lookupvar() which only looks into the latter. The simple builtin commands which are affected by variables all do that (a good example is 'cd' checking $HOME). However, "eval" itself is implemented as a builtin command, which will call evalstr -- the "real" eval used also by the command loop. When this "real" eval which parses and executes all commands needs to look into a variable, it happens in codepath evalstr->evalcommand->expandarg->argstr->evalvar->lookupvar. Because of this last lookupvar() call, the builtin eval effectively ignores its internal environment, even though it's there in "cmdenviron" while it executes. I have changed that call from lookupvar() to bltinlookup(). Since the whole codepath basically only ever comes from inside eval processing, it's okay as we do want eval to always remember about internal environment just in case it's being executed as a builtin. An additional gotcha is that earlier evalcommand() never bothered to clear cmdenviron, and it could hold internal environment of some builtin command long after it's done executing, which was okay since all builtin commands were executed from evalcommand() and it would reset cmdenviron before launching one. This is no more acceptable since now evalcommand() will consult cmdenviron just to parse its arguments, and when this evalcommand() does *not* execute as a result of a builtin call, cmdenviron may contain remains of a previous builtin's environment. Thus I clear cmdenviron upon a builtin's exit now. Testing: well, I've played with it. I've tested that things like FOO=bar eval echo \$FOO now work correctly. I've built a few worlds. I've run a few configures. Index: eval.c =================================================================== RCS file: /freebsd/cvs/src/bin/sh/eval.c,v retrieving revision 1.27 diff -u -r1.27 eval.c --- eval.c 1999/12/20 13:42:59 1.27 +++ eval.c 2000/04/20 08:45:47 @@ -850,6 +850,7 @@ exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); flushall(); cmddone: + cmdenviron = NULL; out1 = &output; out2 = &errout; freestdout(); Index: expand.c =================================================================== RCS file: /freebsd/cvs/src/bin/sh/expand.c,v retrieving revision 1.31 diff -u -r1.31 expand.c --- expand.c 1999/12/15 11:46:32 1.31 +++ expand.c 2000/04/20 08:47:23 @@ -667,7 +667,7 @@ set = varisset(var, varflags & VSNUL); val = NULL; } else { - val = lookupvar(var); + val = bltinlookup(var, 1); if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { val = NULL; set = 0; -- Anatoly Vorobey, mellon@pobox.com http://pobox.com/~mellon/ "Angels can fly because they take themselves lightly" - G.K.Chesterton To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200004200630.XAA07459>