There are three sides to using penv - configuration files, defining environment settings for a particular directory and invoking programs with those settings. For a description of the penv command-line options and the commands that may be specified with the -c option, please see the penv manual page. You may also want to look at some examples of using penv.
penv stores the environment settings for each directory into files located in the corresponding ``environment directory''. Each environment variable is stored in its own file, according to the directory layout format used by the envdir program. By default, the environment directories reside under a common ``base directory'' - /var/db/penv/ by default. The name of the environment directory is formed by taking the last components of the name of the current working directory and appending those to the base directory name. By default, the last two components are used. Thus, if the current working directory is /usr/ports/databases/mysql323-server/, then the directory where penv will store its settings will be /var/db/penv/databases/mysql323-server/. Both the base directory name and the number of path components used to construct the environment directory name may be overridden in the penv.conf file - see the global configuration section.
For its operation, penv needs some information that may be defined on the command line, in environment variables or in configuration files. There are two types of files: a global configuration file named penv.conf, residing in /usr/local/etc/ by default, and a per-user one, named .penvrc, in each user's home directory. The order in which configuration options are looked for is command line, environment settings, per-user configuration file, global configuration file. A sample configuration file is included with the penv distribution.
The syntax of the penv configuration files is simple - each line is either a blank line, a comment starting with the # character, or a variable definition. A variable definition line is of the form varname=value and the variables that may be defined are:
basedir (string) - the base for forming the environment directory name. This variable may be overridden by the -D command-line option or the PENV_BASEDIR environment variable. The default value is /var/db/penv/.
depth (integer) - the number of components to be taken from the name of the current working directory to obtain the environment directory name. This variable may be overridden by the -d command-line option or the PENV_DEPTH environment variable. The default value is 2.
envdir_p (string) - the name (full path) of the environment processor to use. This option may be overridden by the PENV_ENVDIR_P environment variable. The default value is /usr/local/bin/envdir.
So, you want to define some environment variables that will be used every time some command is run in a certain directory. Nothing easier than that! :)
Change to the directory in question
While using penv, keep in mind that it only affects the environment settings of your current working directory. Thus, both while defining settings and running commands, you need to ``be'' in the directory for which you want those settings to pertain.
Create the penv configuration directory
penv keeps every environment variable you define in a separate file in a configuration directory. Thus, for each directory that you want to define settings for, you need to create a configuration directory. This is done by the command:
% penv -c mkdir
Note: You may use the -D basedir or -d depth command-line options to specify the location and name of the penv configuration directory; see the penv manual page for more information. In general, though, the above command will be just enough.
Define the environment variables
With penv, you may specify two kinds of environment changes: defining a variable with a certain value and undefining a variable (removing it from the environment).
To define a variable and give it a certain value, use:
% penv -S varname=value
To specify that a variable should be removed from the environment, use:
% penv -S varname
This may raise a question: how is a variable defined to an empty value? Well, the answer is:
% penv -S varname=''
And that is all - your environment is all set up!
To run a program with an environment modified by the settings you have defined for a directory, simply run penv and tell it which program to execute:
% penv program args..
Yes, it really is as simple as that :)
Keep in mind, though, that penv runs only once, in your current directory, and only uses the settings for this directory. If you want to use it ``recursively'', e.g. for building a FreeBSD port's dependencies with specific settings for each dependency, you may want to have a look at the compatibility section for some patches to FreeBSD's make(1) command allowing it to invoke penv for each directory it recurses into.
The main reason penv was developed was the author's annoyance with having to specify the same variables over and over again when building FreeBSD ports. How does penv help with that? Well, judge for yourself. First, run the following sequence of commands just once:
% cd /usr/ports/mail/vpopmail % penv -c mkdir % penv -S WITH_MYSQL=yes WITH_MYSQL_USER=vpopmail WITH_MYSQL_PASS=unguessable WITH_MYSQL_DB=mail % penv -S WITH_HARDQUOTA=n WITH_QMAIL_EXT=yes
Of course, the two penv -S invocations could have been done in a single command, but those are broken down for clarity.
Now, every time you want to rebuild the mail/vpopmail port, instead of typing all those variables on the make(1) command line, never really certain whether you have not forgotten a couple of them, all you need to do is:
# cd /usr/ports/mail/vpopmail # penv make clean all install
..and penv will take care of passing all the necessary variables to the port build!
FreeBSD ports are not the only area when the same environment settings may have to be specified repeatedly. I, personally, like to build my FreeBSD base system with debug information, yet install it with stripped binaries to save space. So, instead of doing the following:
% cd /usr/src % make -DNOCLEAN DEBUG_FLAGS=-g3 buildworld buildkernel % sudo make TMPDIR=/home/roam/tmp STRIP=-s installkernel installworld
..I have set things up as:
% cd /usr/src % penv -c mkdir % penv -S NOCLEAN=yes DEBUG_FLAGS=-g3 TMPDIR=/home/roam/tmp STRIP=-s
..which allows me to later do simply:
% cd /usr/src % penv make buildworld buildkernel && sudo penv make installkernel installworld
..and be done with it.
Another FreeBSD-related example :) The documentation for many Ringlet software projects uses the build infrastructure of The FreeBSD Documentation Project. Some projects require tweaking some environment variables to get things right. Again, specifying those variables on the make(1) command line at every invocation may be tiresome; specifying them in the global make.conf configuration file would not do, because they would conflict with the settings for other projects. And again, penv comes to the rescue! :)
% cd /home/roam/doc/fbsd-bg % penv -c mkdir % penv -S DOCDIR=/home/roam/doc/fbsd-bg DOC_PREFIX_NAME=fbsd-bg
After doing this, building the documentation with the correct settings is a breeze :)
This, and other documents, can be downloaded from http://devel.ringlet.net/.
For questions about this documentation, e-mail <roam@ringlet.net>.