xref: /original-bsd/contrib/emacs-18.57/etc/env.c (revision 30928eff)
1 /* env.c - manipulate environment and execute a program
2    in that environment
3    Mly 861126
4 
5    Copyright (C) 1986 Free Software Foundation, Inc.
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 1, or (at your option)
10     any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21  In other words, you are welcome to use, share and improve this program.
22  You are forbidden to forbid anyone else to use, share and improve
23  what you give them.   Help stamp out software-hoarding!  */
24 
25 /*
26 
27    If first argument is "-", then a new environment is constructed
28    from scratch; otherwise the environment is inherited from the parent
29    process, except as modified by other options.
30 
31    So, "env - foo" will invoke the "foo" program in a null environment,
32    whereas "env foo" would invoke "foo" in the same environment as that
33    passed to "env" itself.
34 
35    Subsequent arguments are interpreted as follows:
36 
37    * "variable=value" (ie an arg containing a "=" character)
38      means to set the specified environment variable to that value.
39      `value' may be of zero length ("variable=").  Note that setting
40      a variable to a zero-length value is different from unsetting it.
41 
42    * "-u variable" or "-unset variable"
43      means to unset that variable
44      If that variable isn't set, does nothing.
45 
46    * "-s variable value" or "-set variable value"
47      same as "variable=value"
48 
49    * "-" or "--"
50      are used to indicate that the following argument is the program
51      to invoke.  This is only necessary when the program's name
52      begins with "-" or contains a "="
53 
54    * anything else
55      The first remaining argument specifies a program to invoke
56      (it is searched for according to the specification of the PATH
57      environment variable) and any arguments following that are
58      passed as arguments to that program
59 
60      If no program-name is specified following the environment
61      specifications the the resulting environment is printed
62      (The is like specifying a program-name of "printenv")
63 
64    Examples:
65      If the environment passed to "env" is
66      { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks }
67 
68      * "env DISPLAY=gnu:0 nemacs"
69         calls "nemacs" in the envionment
70 	{ EDITOR=emacs USER=rms DISPLAY=gnu }
71 
72      * "env - USER=foo /hacks/hack bar baz"
73        will call the "hack" program on arguments "bar" and "baz"
74        in an environment in which the only variable is "USER"
75        Note that the "-" option will clear out the PATH variable,
76        so one should be careful to specify in which directory
77        to find the program to call
78 
79      * "env -u EDITOR USER=foo PATH=/energy -- e=mc2 bar baz"
80        The program "/energy/e=mc2" is called with environment
81        { USER=foo PATH=/energy }
82 
83 */
84 
85 #ifdef EMACS
86 #define NO_SHORTNAMES
87 #include "../src/config.h"
88 #endif /* EMACS */
89 
90 #include <stdio.h>
91 #include <errno.h>
92 
93 extern int execvp ();
94 extern char *index ();
95 
96 char *xmalloc (), *xrealloc ();
97 char *concat ();
98 
99 extern char **environ;
100 
101 char **nenv;
102 int nenv_size;
103 
104 char *progname;
105 void setenv ();
106 void fatal ();
107 
108 main (argc, argv, envp)
109      register int argc;
110      register char **argv;
111      char **envp;
112 {
113   register char *tem;
114 
115   progname = argv[0];
116   argc--;
117   argv++;
118 
119   nenv_size = 100;
120   nenv = (char **) xmalloc (nenv_size * sizeof (char *));
121   *nenv = (char *) 0;
122 
123   /* "-" flag means to not inherit parent's environment */
124   if (argc && !strcmp (*argv, "-"))
125     {
126       argc--;
127       argv++;
128     }
129   else
130     /* Else pass on existing env vars. */
131     for (; *envp; envp++)
132       {
133 	tem = index (*envp, '=');
134 	if (tem)
135 	  {
136 	    *tem = '\000';
137 	    setenv (*envp, tem + 1);
138 	  }
139      }
140 
141   while (argc > 0)
142     {
143       tem = index (*argv, '=');
144       if (tem)
145 	/* If arg contains a "=" it specifies to set a variable */
146 	{
147 	  *tem = '\000';
148 	  setenv (*argv, tem + 1);
149 	  argc--; argv++;
150 	  continue;
151 	}
152 
153       if (**argv != '-')
154 	/* Remaining args are program name and args to pass it */
155 	break;
156 
157       if (argc < 2)
158 	fatal ("No argument following \"%s\" switch", *argv);
159        if (!strcmp (*argv, "-u") ||
160 	       !strcmp (*argv, "-unset"))
161 	/* Unset a variable */
162 	{
163 	  argc--; argv++;
164 	  setenv (*argv, 0);
165 	  argc--; argv++;
166 	}
167       else if (!strcmp (*argv, "-s") ||
168 	       !strcmp (*argv, "-set"))
169 	/* Set a variable */
170 	{
171 	  argc--; argv++;
172 	  tem = *argv;
173 	  if (argc < 2)
174 	    fatal ("No value specified for variable \"%s\"",
175 		   tem);
176 	  argc--; argv++;
177 	  setenv (tem, *argv);
178 	  argc--; argv++;
179 	}
180       else if (!strcmp (*argv, "-") || !strcmp (*argv, "--"))
181 	{
182 	  argc--; argv++;
183 	  break;
184 	}
185       else
186 	{
187 	  fatal ("unknown switch \"%s\"", *argv);
188 	}
189     }
190 
191   /* If no program specified print the environment and exit */
192   if (argc <= 0)
193     {
194       while (*nenv)
195 	printf ("%s\n", *nenv++);
196       exit (0);
197     }
198   else
199     {
200 #ifndef BSD4_4
201       extern int errno, sys_nerr;
202       extern char *sys_errlist[];
203 #endif
204 
205       environ = nenv;
206       (void) execvp (*argv, argv);
207 
208       fprintf (stderr, "%s: Cannot execute \"%s\"",
209 	       progname, *argv);
210       if (errno < sys_nerr)
211 	fprintf (stderr, ": %s\n" , sys_errlist[errno]);
212       else
213 	putc ('\n', stderr);
214       exit (errno != 0 ? errno : 1);
215     }
216 }
217 
218 void
219 setenv (var, val)
220   register char *var, *val;
221 {
222   register char **e;
223   int len = strlen (var);
224 
225   {
226     register char *tem = index (var, '=');
227     if (tem)
228       fatal ("Environment variable names may not contain \"=\": %s",
229 	     var);
230     else if (*var == '\000')
231       fatal ("Zero-length environment variable name specified.");
232   }
233 
234   for (e = nenv; *e; e++)
235     if (!strncmp (var, *e, len) &&
236 	(*e)[len] == '=')
237       {
238 	if (val)
239 	  goto set;
240 	else
241 	  do { *e = *(e + 1); } while (*e++);
242 	return;
243       }
244 
245   if (!val)
246     return; /* Nothing to unset */
247 
248   len = e - nenv;
249   if (len + 1 >= nenv_size)
250     {
251       nenv_size += 100;
252       nenv = (char **) xrealloc (nenv, nenv_size * sizeof (char *));
253       e = nenv + len;
254     }
255 
256  set:
257   val = concat (var, "=", val);
258   if (*e)
259     free (*e);
260   else
261     *(e + 1) = (char *) 0;
262   *e = val;
263   return;
264 }
265 
266 void
267 fatal (msg, arg1, arg2)
268      char *msg, *arg1, *arg2;
269 {
270   fprintf (stderr, "%s: ", progname);
271   fprintf (stderr, msg, arg1, arg2);
272   putc ('\n', stderr);
273   exit (1);
274 }
275 
276 
277 extern char *malloc (), *realloc ();
278 
279 void
280 memory_fatal ()
281 {
282   fatal ("Out of memory");
283 }
284 
285 char *
286 xmalloc (size)
287      int size;
288 {
289   register char *value;
290   value = (char *) malloc (size);
291   if (!value) memory_fatal ();
292   return (value);
293 }
294 
295 char *
296 xrealloc (ptr, size)
297      char *ptr;
298      int size;
299 {
300   register char *value;
301   value = (char *) realloc (ptr, size);
302   if (!value) memory_fatal ();
303   return (value);
304 }
305 
306 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
307 
308 char *
309 concat (s1, s2, s3)
310      char *s1, *s2, *s3;
311 {
312   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
313   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
314 
315   strcpy (result, s1);
316   strcpy (result + len1, s2);
317   strcpy (result + len1 + len2, s3);
318   *(result + len1 + len2 + len3) = 0;
319 
320   return result;
321 }
322 
323 
324 /*
325  * Local variables:
326  * compile-command: "cc -g -o env env.c"
327  * end:
328  */
329