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