xref: /original-bsd/contrib/emacs-18.57/etc/env.c (revision cda5c60b)
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 
92 extern int execvp ();
93 extern char *index ();
94 
95 char *xmalloc (), *xrealloc ();
96 char *concat ();
97 
98 extern char **environ;
99 
100 char **nenv;
101 int nenv_size;
102 
103 char *progname;
104 void setenv ();
105 void fatal ();
106 
107 main (argc, argv, envp)
108      register int argc;
109      register char **argv;
110      char **envp;
111 {
112   register char *tem;
113 
114   progname = argv[0];
115   argc--;
116   argv++;
117 
118   nenv_size = 100;
119   nenv = (char **) xmalloc (nenv_size * sizeof (char *));
120   *nenv = (char *) 0;
121 
122   /* "-" flag means to not inherit parent's environment */
123   if (argc && !strcmp (*argv, "-"))
124     {
125       argc--;
126       argv++;
127     }
128   else
129     /* Else pass on existing env vars. */
130     for (; *envp; envp++)
131       {
132 	tem = index (*envp, '=');
133 	if (tem)
134 	  {
135 	    *tem = '\000';
136 	    setenv (*envp, tem + 1);
137 	  }
138      }
139 
140   while (argc > 0)
141     {
142       tem = index (*argv, '=');
143       if (tem)
144 	/* If arg contains a "=" it specifies to set a variable */
145 	{
146 	  *tem = '\000';
147 	  setenv (*argv, tem + 1);
148 	  argc--; argv++;
149 	  continue;
150 	}
151 
152       if (**argv != '-')
153 	/* Remaining args are program name and args to pass it */
154 	break;
155 
156       if (argc < 2)
157 	fatal ("No argument following \"%s\" switch", *argv);
158        if (!strcmp (*argv, "-u") ||
159 	       !strcmp (*argv, "-unset"))
160 	/* Unset a variable */
161 	{
162 	  argc--; argv++;
163 	  setenv (*argv, 0);
164 	  argc--; argv++;
165 	}
166       else if (!strcmp (*argv, "-s") ||
167 	       !strcmp (*argv, "-set"))
168 	/* Set a variable */
169 	{
170 	  argc--; argv++;
171 	  tem = *argv;
172 	  if (argc < 2)
173 	    fatal ("No value specified for variable \"%s\"",
174 		   tem);
175 	  argc--; argv++;
176 	  setenv (tem, *argv);
177 	  argc--; argv++;
178 	}
179       else if (!strcmp (*argv, "-") || !strcmp (*argv, "--"))
180 	{
181 	  argc--; argv++;
182 	  break;
183 	}
184       else
185 	{
186 	  fatal ("unknown switch \"%s\"", *argv);
187 	}
188     }
189 
190   /* If no program specified print the environment and exit */
191   if (argc <= 0)
192     {
193       while (*nenv)
194 	printf ("%s\n", *nenv++);
195       exit (0);
196     }
197   else
198     {
199       extern int errno, sys_nerr;
200       extern char *sys_errlist[];
201 
202       environ = nenv;
203       (void) execvp (*argv, argv);
204 
205       fprintf (stderr, "%s: Cannot execute \"%s\"",
206 	       progname, *argv);
207       if (errno < sys_nerr)
208 	fprintf (stderr, ": %s\n" , sys_errlist[errno]);
209       else
210 	putc ('\n', stderr);
211       exit (errno != 0 ? errno : 1);
212     }
213 }
214 
215 void
216 setenv (var, val)
217   register char *var, *val;
218 {
219   register char **e;
220   int len = strlen (var);
221 
222   {
223     register char *tem = index (var, '=');
224     if (tem)
225       fatal ("Environment variable names may not contain \"=\": %s",
226 	     var);
227     else if (*var == '\000')
228       fatal ("Zero-length environment variable name specified.");
229   }
230 
231   for (e = nenv; *e; e++)
232     if (!strncmp (var, *e, len) &&
233 	(*e)[len] == '=')
234       {
235 	if (val)
236 	  goto set;
237 	else
238 	  do { *e = *(e + 1); } while (*e++);
239 	return;
240       }
241 
242   if (!val)
243     return; /* Nothing to unset */
244 
245   len = e - nenv;
246   if (len + 1 >= nenv_size)
247     {
248       nenv_size += 100;
249       nenv = (char **) xrealloc (nenv, nenv_size * sizeof (char *));
250       e = nenv + len;
251     }
252 
253  set:
254   val = concat (var, "=", val);
255   if (*e)
256     free (*e);
257   else
258     *(e + 1) = (char *) 0;
259   *e = val;
260   return;
261 }
262 
263 void
264 fatal (msg, arg1, arg2)
265      char *msg, *arg1, *arg2;
266 {
267   fprintf (stderr, "%s: ", progname);
268   fprintf (stderr, msg, arg1, arg2);
269   putc ('\n', stderr);
270   exit (1);
271 }
272 
273 
274 extern char *malloc (), *realloc ();
275 
276 void
277 memory_fatal ()
278 {
279   fatal ("Out of memory");
280 }
281 
282 char *
283 xmalloc (size)
284      int size;
285 {
286   register char *value;
287   value = (char *) malloc (size);
288   if (!value) memory_fatal ();
289   return (value);
290 }
291 
292 char *
293 xrealloc (ptr, size)
294      char *ptr;
295      int size;
296 {
297   register char *value;
298   value = (char *) realloc (ptr, size);
299   if (!value) memory_fatal ();
300   return (value);
301 }
302 
303 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
304 
305 char *
306 concat (s1, s2, s3)
307      char *s1, *s2, *s3;
308 {
309   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
310   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
311 
312   strcpy (result, s1);
313   strcpy (result + len1, s2);
314   strcpy (result + len1 + len2, s3);
315   *(result + len1 + len2 + len3) = 0;
316 
317   return result;
318 }
319 
320 
321 /*
322  * Local variables:
323  * compile-command: "cc -g -o env env.c"
324  * end:
325  */
326