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