(add_tabstop): Give correct size when reallocating tab_list buffer.
[platform/upstream/coreutils.git] / src / env.c
1 /* env - run a program in a modified environment
2    Copyright (C) 86, 91, 92, 93, 94, 1995 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
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 "version.h"
87 #include "system.h"
88 #include "error.h"
89
90 int putenv ();
91
92 static void usage ();
93
94 extern char **environ;
95
96 /* The name by which this program was run. */
97 char *program_name;
98
99 /* If non-zero, display usage information and exit.  */
100 static int show_help;
101
102 /* If non-zero, print the version on standard output and exit.  */
103 static int show_version;
104
105 static struct option const longopts[] =
106 {
107   {"help", no_argument, &show_help, 1},
108   {"ignore-environment", no_argument, NULL, 'i'},
109   {"unset", required_argument, NULL, 'u'},
110   {"version", no_argument, &show_version, 1},
111   {NULL, 0, NULL, 0}
112 };
113
114 void
115 main (argc, argv, envp)
116      register int argc;
117      register char **argv;
118      char **envp;
119 {
120   char *dummy_environ[1];
121   int optc;
122   int ignore_environment = 0;
123
124   program_name = argv[0];
125
126   while ((optc = getopt_long (argc, argv, "+iu:", longopts, (int *) 0)) != EOF)
127     {
128       switch (optc)
129         {
130         case 0:
131           break;
132         case 'i':
133           ignore_environment = 1;
134           break;
135         case 'u':
136           break;
137         default:
138           usage (2);
139         }
140     }
141
142   if (show_version)
143     {
144       printf ("env - %s\n", version_string);
145       exit (0);
146     }
147
148   if (show_help)
149     usage (0);
150
151   if (optind != argc && !strcmp (argv[optind], "-"))
152     ignore_environment = 1;
153   
154   environ = dummy_environ;
155   environ[0] = NULL;
156
157   if (!ignore_environment)
158     for (; *envp; envp++)
159       putenv (*envp);
160
161   optind = 0;                   /* Force GNU getopt to re-initialize. */
162   while ((optc = getopt_long (argc, argv, "+iu:", longopts, (int *) 0)) != EOF)
163     if (optc == 'u')
164       putenv (optarg);          /* Requires GNU putenv. */
165
166   if (optind != argc && !strcmp (argv[optind], "-"))
167     ++optind;
168
169   while (optind < argc && strchr (argv[optind], '='))
170     putenv (argv[optind++]);
171
172   /* If no program is specified, print the environment and exit. */
173   if (optind == argc)
174     {
175       while (*environ)
176         puts (*environ++);
177       exit (0);
178     }
179
180   execvp (argv[optind], &argv[optind]);
181   error (errno == ENOENT ? 127 : 126, errno, "%s", argv[optind]);
182 }
183
184 static void
185 usage (status)
186      int status;
187 {
188   if (status != 0)
189     fprintf (stderr, "Try `%s --help' for more information.\n",
190              program_name);
191   else
192     {
193       printf ("Usage: %s [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]\n",
194               program_name);
195       printf ("\
196 \n\
197   -u, --unset=NAME           remove variable from the environment\n\
198   -i, --ignore-environment   start with an empty environment\n\
199       --help                 display this help and exit\n\
200       --version              output version information and exit\n\
201 \n\
202 A mere - implies -i.  If no COMMAND, print the resulting environment.\n\
203 ");
204     }
205   exit (status);
206 }