However, I have to parse out what I mean by the terms above.
Remember: I am talking about scripting, in shell and Perl, etc.
"Calling a function" in a shell script usually means executing a child process. And, by definition, a child process dos not pass environment variables back to its parent.
Now, of course, in every scripting language worth its salt, it is possible to write a function that sets environment variables. But that's a function in the language you are running in. It's a lot harder to have, e.g. perl or bash call a csh function, and have that child csh set environment variables in the parent perl or bash.
Similarly, you can source a file in csh, or "." it in bash, and hae some degree of modularization. But again it is same language.
Why do I care? Mainly because I am writing stuff in bash or perl or python, and I want to get whatever environment variables legacy csh scripts set up.
But, in general, you lose abstraction if you are constrained to call functions only written in your current language. Or, even then, if only callable via a special syntax, eg. csh's "source file" rather than just executing file.
Loss of abstraction. But, requiring a special syntax provides a but of security.You can tell who is side effectful, and who is not. Pure vs impure functions.
My clear-env script does things oppositely - it allows me to call a script in a subshell with a clean environment, but I don't necessarily see what it set up in the environment.
Similarly, my friends trick where bash can get a csh script's environment by doing something like
csh -c "source module; exec bashis NOT a "function call". It's more like continuations.
Part of the trouble is that the whole point of processes is to isolate the parent from the child.
Except that here, the whole point is to get access tyo the child's side effects.
I think that I may need to create a family of scripts in various languages that execute or source or whatever, and then, at the end, printenv into a file or stdout - so that the parent can parse the printenv.
A better way would be to do something like stop the child process in a debugger - and then have the parent look through the child's environment with the debugger.
I haven't even touched on other side effects. Not just the environment, but file descriptors.
E.g. "I have a bash script that wants to call a csh script that redirects stdout and stderr - and then have the parent bash script use those settings".
Linux /proc/PROCESSID/environ gives a way of getting at a child's environment.
Now, how can I stop it just as it is about to exit?
And how unportable this will be. Cygwin? Nah.
The way this is usually done is to have the child output some commands the parent evals. For example try running ssh-agent. The usage is then eval `ssh-agent`.
It autodetects the shell to generate the correct syntax (can be overridden).
You can also make both senses work (as does ssh-agent). If you do "ssh-agent foo bar" then it executes "foo bar" with the appropriately configured environment. If given no args then it outputs the shell commands the parent evals.
"... stop it just before it exits..."
What if the environment setting tool is itself wrapperized?
One would have to know whether to look at the environment of the child, or grandchild, or ...
This is a hack. It may make things better, but not perfect.
Post a Comment