[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]
Summary
env - run a command in a modified environment
Lines of code: 662
Principal syscalls: putenv(), unsetenv()
Support syscall: execvp()
Options: 14 (6 short, 8 long)
Descended from env as originated in System III (1982)
Added to Shellutils in November 1992 [First version]
Number of revisions: 117 [Code Evolution]
append_unset_var()
- Adds a new variable to the unset listbuild_argv()
- Constructs an array vector from a stringescape_char()
- Converts a text escape code in to the actual code valueextract_varname()
- Finds a pointer to the desired variableparse_split_string()
- Breaks an input string in to the argument vectorscan_varname()
- Finds a pointer to the end of a variable nameunset_envvars()
- Removes desired variables from the environmentvalidate_escape_sequence()
- Tests if an input escape sequence is validvalidate_split_str()
- Separates a string based on the FreeBSD syntax, if possible
die()
- Exit with mandatory non-zero error and message to stderrerror()
- Outputs error message to standard error with possible process termination
Setup
env prepares some data at global to support execution: A list of variables that need to be removed from the environment and details about the environment string to set. Variables include:
dev_debug
- Flag to use verbose debug information**usvars
- Pointer to the list of variables to unsetusvars_alloc
- The number of unset variables allocatedusvars_used
- The number of unset variables defined*varname
- The list of variables to setvnlen
- The number of variables to set
main() initializes the following:
ignore_environment
- Flag for providing a blank environment (-i)newdir
- The user provided working directory for the target commend (-C)opt_nul_terminate_output
- Flag for null terminating output (-0)optc
- The current command line option letter
Parsing
Parsing for env is more complicated than most utilities because user-provided arguments must be parsed for the environment -- either building a new argv, or building a list of variables to remove (-S and -u respectively).
Several questions answered by parsing:
- What new environment variables should be added?
- Should nay environment variables be removed?
- Shuld we use a completely blank environment?
- Should test output be null-terminated rather than newlined?
- How much feedback should be give the user?
- Should the target command execute in a different directory?
Parsing failures
These failure cases are explicitly checked:
- User-specified string has invalid formats
- Using null-term output with an executable command
- Providing a working directory without a command
- An unknown option is used
All parsing failures result in a short error message followed by the usage instructions.
Execution
As execution begins, most of the prep work has already been accomplished. All that's left is to change the environment and execute the desired command
The exact process is:
- Remove any (or all) environment variables if requested
- Set environment variables, with possible debug messages
- If this was a test run, output the final environment state
- Change directory to the new target if requested
- Debug output the target command and arguments
- Call
execvp()
- Handle any
execvp()
failure cases (return status)
Failure cases:
- Setting or unsetting any environment fails
execvp()
fails for any reason
All failures at this stage output an error message to STDERR and return without displaying usage help