Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!seismo!mcvax!ukc!reading!onion!minster!forsyth From: forsyth@minster.UUCP Newsgroups: comp.unix.questions,comp.unix.wizards Subject: exported functions Message-ID: <543354613.21303@minster.UUCP> Date: Sat, 21-Mar-87 14:50:13 EST Article-I.D.: minster.543354613.21303 Posted: Sat Mar 21 14:50:13 1987 Date-Received: Wed, 25-Mar-87 04:41:51 EST References: <580@csun.UUCP> <5680@brl-smoke.ARPA> <2201@ptsfa.UUCP> <730@hoqax.UUCP> <15224@sun.uucp> <339@its63b.ed.ac.uk> Organization: Department of Computer Science, University of York, England Lines: 120 Xref: utgpu comp.unix.questions:1478 comp.unix.wizards:1506 I was most disappointed when I discovered that the system V shell could not export functions. That was the second thing I tried! The code to print functions out for the `type' built-in command is pretty much what one requires to do exported functions. It can be changed to take the parse tree for a function and accumulate the function text as a string on the heap instead of printing it (the Bourne shell has a special storage manager that makes this trivial). I chose to represent each exported function as a separate string in the environment, with the form f(){...body...} Of course, getenv was changed to watch for ( as well as =, so that in my current implementation there are three possibilities for the parameter to getenv: name fetches the value of either a variable or function name=v fetches the value of a variable only name() fetches the value of a function only The ``value'' of a function includes the ``()''. Putenv accepts ``name=value'' or ``name()...''. There might be better conventions, but these work well enough. I think it is important for programs to be able to access or change the definition of functions individually, just as for variables like PATH; this makes exporting all functions in one environment variable unattractive. I also thought it made sense for execlp(name, arg...) to look for functions. At the ``as-is'' part of the PATH variable, if it finds that name is a simple name (no /'s) and there is a function with that name in the environment, it executes: sh -c 'name ${@+"$@"}' name arg ... This allows commands such as time, nohup, find, and overwrite, all of which execute other commands, to execute functions as well. If functions were exported only from shell to shell, using files, it would be much more expensive to do this. It is quite useful to allow these and other programs using execlp/execvp to execute functions. A function can contain arbitrary Shell commands, including loops and pipelines, and the quoting and ${} expansion is applied when the function is called, not while it is being defined. By naming uninterpreted Shell text in this way and passing it to other commands to execute, one can defer the interpretation until an ``ordinary'' command has prepared the desired environment. I can do this using sh -c directly, but it can be hard to get the quoting right first time in difficult cases, which is just when I need most help. For instance, I can type blotto() sed "s/^[^ ]* /`uuname -l` /" export blotto overwrite file blotto