Line data Source code
1 : /* env - run a program in a modified environment
2 : Copyright (C) 1986, 1991-2005, 2007 Free Software Foundation, Inc.
3 :
4 : This program is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation, either version 3 of the License, or
7 : (at your option) any later version.
8 :
9 : This program is distributed in the hope that it will be useful,
10 : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : GNU General Public License for more details.
13 :
14 : You should have received a copy of the GNU General Public License
15 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
16 :
17 : /* Richard Mlynarik and David MacKenzie */
18 :
19 : /* Options:
20 : -
21 : -i
22 : --ignore-environment
23 : Construct a new environment from scratch; normally the
24 : environment is inherited from the parent process, except as
25 : modified by other options.
26 :
27 : -u variable
28 : --unset=variable
29 : Unset variable VARIABLE (remove it from the environment).
30 : If VARIABLE was not set, does nothing.
31 :
32 : variable=value (an arg containing a "=" character)
33 : Set the environment variable VARIABLE to value VALUE. VALUE
34 : may be of zero length ("variable="). Setting a variable to a
35 : zero-length value is different from unsetting it.
36 :
37 : --
38 : Indicate that the following argument is the program
39 : to invoke. This is necessary when the program's name
40 : begins with "-" or contains a "=".
41 :
42 : The first remaining argument specifies a program to invoke;
43 : it is searched for according to the specification of the PATH
44 : environment variable. Any arguments following that are
45 : passed as arguments to that program.
46 :
47 : If no command name is specified following the environment
48 : specifications, the resulting environment is printed.
49 : This is like specifying a command name of "printenv".
50 :
51 : Examples:
52 :
53 : If the environment passed to "env" is
54 : { LOGNAME=rms EDITOR=emacs PATH=.:/gnubin:/hacks }
55 :
56 : env - foo
57 : runs "foo" in a null environment.
58 :
59 : env foo
60 : runs "foo" in the environment
61 : { LOGNAME=rms EDITOR=emacs PATH=.:/gnubin:/hacks }
62 :
63 : env DISPLAY=gnu:0 nemacs
64 : runs "nemacs" in the environment
65 : { LOGNAME=rms EDITOR=emacs PATH=.:/gnubin:/hacks DISPLAY=gnu:0 }
66 :
67 : env - LOGNAME=foo /hacks/hack bar baz
68 : runs the "hack" program on arguments "bar" and "baz" in an
69 : environment in which the only variable is "LOGNAME". Note that
70 : the "-" option clears out the PATH variable, so one should be
71 : careful to specify in which directory to find the program to
72 : call.
73 :
74 : env -u EDITOR LOGNAME=foo PATH=/energy -- e=mc2 bar baz
75 : runs the program "/energy/e=mc2" with environment
76 : { LOGNAME=foo PATH=/energy }
77 : */
78 :
79 : #include <config.h>
80 : #include <stdio.h>
81 : #include <getopt.h>
82 : #include <sys/types.h>
83 : #include <getopt.h>
84 :
85 : #include "system.h"
86 : #include "error.h"
87 :
88 : /* The official name of this program (e.g., no `g' prefix). */
89 : #define PROGRAM_NAME "env"
90 :
91 : #define AUTHORS "Richard Mlynarik", "David MacKenzie"
92 :
93 : int putenv ();
94 :
95 : extern char **environ;
96 :
97 : /* The name by which this program was run. */
98 : char *program_name;
99 :
100 : static struct option const longopts[] =
101 : {
102 : {"ignore-environment", no_argument, NULL, 'i'},
103 : {"unset", required_argument, NULL, 'u'},
104 : {GETOPT_HELP_OPTION_DECL},
105 : {GETOPT_VERSION_OPTION_DECL},
106 : {NULL, 0, NULL, 0}
107 : };
108 :
109 : void
110 9 : usage (int status)
111 : {
112 9 : if (status != EXIT_SUCCESS)
113 7 : fprintf (stderr, _("Try `%s --help' for more information.\n"),
114 : program_name);
115 : else
116 : {
117 2 : printf (_("\
118 : Usage: %s [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]\n"),
119 : program_name);
120 2 : fputs (_("\
121 : Set each NAME to VALUE in the environment and run COMMAND.\n\
122 : \n\
123 : -i, --ignore-environment start with an empty environment\n\
124 : -u, --unset=NAME remove variable from the environment\n\
125 : "), stdout);
126 2 : fputs (HELP_OPTION_DESCRIPTION, stdout);
127 2 : fputs (VERSION_OPTION_DESCRIPTION, stdout);
128 2 : fputs (_("\
129 : \n\
130 : A mere - implies -i. If no COMMAND, print the resulting environment.\n\
131 : "), stdout);
132 2 : emit_bug_reporting_address ();
133 : }
134 9 : exit (status);
135 : }
136 :
137 : int
138 39 : main (int argc, char **argv)
139 : {
140 : int optc;
141 39 : bool ignore_environment = false;
142 :
143 : initialize_main (&argc, &argv);
144 39 : program_name = argv[0];
145 39 : setlocale (LC_ALL, "");
146 : bindtextdomain (PACKAGE, LOCALEDIR);
147 : textdomain (PACKAGE);
148 :
149 39 : initialize_exit_failure (EXIT_FAILURE);
150 39 : atexit (close_stdout);
151 :
152 95 : while ((optc = getopt_long (argc, argv, "+iu:", longopts, NULL)) != -1)
153 : {
154 27 : switch (optc)
155 : {
156 7 : case 'i':
157 7 : ignore_environment = true;
158 7 : break;
159 10 : case 'u':
160 10 : break;
161 2 : case_GETOPT_HELP_CHAR;
162 1 : case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
163 7 : default:
164 7 : usage (EXIT_FAILURE);
165 : }
166 : }
167 :
168 29 : if (optind < argc && STREQ (argv[optind], "-"))
169 7 : ignore_environment = true;
170 :
171 29 : if (ignore_environment)
172 : {
173 : static char *dummy_environ[] = { NULL };
174 13 : environ = dummy_environ;
175 : }
176 :
177 29 : optind = 0; /* Force GNU getopt to re-initialize. */
178 74 : while ((optc = getopt_long (argc, argv, "+iu:", longopts, NULL)) != -1)
179 16 : if (optc == 'u')
180 10 : putenv (optarg); /* Requires GNU putenv. */
181 :
182 29 : if (optind < argc && STREQ (argv[optind], "-"))
183 7 : ++optind;
184 :
185 73 : while (optind < argc && strchr (argv[optind], '='))
186 15 : putenv (argv[optind++]);
187 :
188 : /* If no program is specified, print the environment and exit. */
189 29 : if (argc <= optind)
190 : {
191 23 : char *const *e = environ;
192 407 : while (*e)
193 361 : puts (*e++);
194 23 : exit (EXIT_SUCCESS);
195 : }
196 :
197 6 : execvp (argv[optind], &argv[optind]);
198 :
199 : {
200 6 : int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
201 6 : error (0, errno, "%s", argv[optind]);
202 6 : exit (exit_status);
203 : }
204 : }
|