xref: /csrg-svn/contrib/emacs-18.57/etc/env.c (revision 60290)
159814Shibler /* env.c - manipulate environment and execute a program
259814Shibler    in that environment
359814Shibler    Mly 861126
459814Shibler 
559814Shibler    Copyright (C) 1986 Free Software Foundation, Inc.
659814Shibler 
759814Shibler     This program is free software; you can redistribute it and/or modify
859814Shibler     it under the terms of the GNU General Public License as published by
959814Shibler     the Free Software Foundation; either version 1, or (at your option)
1059814Shibler     any later version.
1159814Shibler 
1259814Shibler     This program is distributed in the hope that it will be useful,
1359814Shibler     but WITHOUT ANY WARRANTY; without even the implied warranty of
1459814Shibler     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1559814Shibler     GNU General Public License for more details.
1659814Shibler 
1759814Shibler     You should have received a copy of the GNU General Public License
1859814Shibler     along with this program; if not, write to the Free Software
1959814Shibler     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2059814Shibler 
2159814Shibler  In other words, you are welcome to use, share and improve this program.
2259814Shibler  You are forbidden to forbid anyone else to use, share and improve
2359814Shibler  what you give them.   Help stamp out software-hoarding!  */
2459814Shibler 
2559814Shibler /*
2659814Shibler 
2759814Shibler    If first argument is "-", then a new environment is constructed
2859814Shibler    from scratch; otherwise the environment is inherited from the parent
2959814Shibler    process, except as modified by other options.
3059814Shibler 
3159814Shibler    So, "env - foo" will invoke the "foo" program in a null environment,
3259814Shibler    whereas "env foo" would invoke "foo" in the same environment as that
3359814Shibler    passed to "env" itself.
3459814Shibler 
3559814Shibler    Subsequent arguments are interpreted as follows:
3659814Shibler 
3759814Shibler    * "variable=value" (ie an arg containing a "=" character)
3859814Shibler      means to set the specified environment variable to that value.
3959814Shibler      `value' may be of zero length ("variable=").  Note that setting
4059814Shibler      a variable to a zero-length value is different from unsetting it.
4159814Shibler 
4259814Shibler    * "-u variable" or "-unset variable"
4359814Shibler      means to unset that variable
4459814Shibler      If that variable isn't set, does nothing.
4559814Shibler 
4659814Shibler    * "-s variable value" or "-set variable value"
4759814Shibler      same as "variable=value"
4859814Shibler 
4959814Shibler    * "-" or "--"
5059814Shibler      are used to indicate that the following argument is the program
5159814Shibler      to invoke.  This is only necessary when the program's name
5259814Shibler      begins with "-" or contains a "="
5359814Shibler 
5459814Shibler    * anything else
5559814Shibler      The first remaining argument specifies a program to invoke
5659814Shibler      (it is searched for according to the specification of the PATH
5759814Shibler      environment variable) and any arguments following that are
5859814Shibler      passed as arguments to that program
5959814Shibler 
6059814Shibler      If no program-name is specified following the environment
6159814Shibler      specifications the the resulting environment is printed
6259814Shibler      (The is like specifying a program-name of "printenv")
6359814Shibler 
6459814Shibler    Examples:
6559814Shibler      If the environment passed to "env" is
6659814Shibler      { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks }
6759814Shibler 
6859814Shibler      * "env DISPLAY=gnu:0 nemacs"
6959814Shibler         calls "nemacs" in the envionment
7059814Shibler 	{ EDITOR=emacs USER=rms DISPLAY=gnu }
7159814Shibler 
7259814Shibler      * "env - USER=foo /hacks/hack bar baz"
7359814Shibler        will call the "hack" program on arguments "bar" and "baz"
7459814Shibler        in an environment in which the only variable is "USER"
7559814Shibler        Note that the "-" option will clear out the PATH variable,
7659814Shibler        so one should be careful to specify in which directory
7759814Shibler        to find the program to call
7859814Shibler 
7959814Shibler      * "env -u EDITOR USER=foo PATH=/energy -- e=mc2 bar baz"
8059814Shibler        The program "/energy/e=mc2" is called with environment
8159814Shibler        { USER=foo PATH=/energy }
8259814Shibler 
8359814Shibler */
8459814Shibler 
8559814Shibler #ifdef EMACS
8659814Shibler #define NO_SHORTNAMES
8759814Shibler #include "../src/config.h"
8859814Shibler #endif /* EMACS */
8959814Shibler 
9059814Shibler #include <stdio.h>
91*60290Shibler #include <errno.h>
9259814Shibler 
9359814Shibler extern int execvp ();
9459814Shibler extern char *index ();
9559814Shibler 
9659814Shibler char *xmalloc (), *xrealloc ();
9759814Shibler char *concat ();
9859814Shibler 
9959814Shibler extern char **environ;
10059814Shibler 
10159814Shibler char **nenv;
10259814Shibler int nenv_size;
10359814Shibler 
10459814Shibler char *progname;
10559814Shibler void setenv ();
10659814Shibler void fatal ();
10759814Shibler 
main(argc,argv,envp)10859814Shibler main (argc, argv, envp)
10959814Shibler      register int argc;
11059814Shibler      register char **argv;
11159814Shibler      char **envp;
11259814Shibler {
11359814Shibler   register char *tem;
11459814Shibler 
11559814Shibler   progname = argv[0];
11659814Shibler   argc--;
11759814Shibler   argv++;
11859814Shibler 
11959814Shibler   nenv_size = 100;
12059814Shibler   nenv = (char **) xmalloc (nenv_size * sizeof (char *));
12159814Shibler   *nenv = (char *) 0;
12259814Shibler 
12359814Shibler   /* "-" flag means to not inherit parent's environment */
12459814Shibler   if (argc && !strcmp (*argv, "-"))
12559814Shibler     {
12659814Shibler       argc--;
12759814Shibler       argv++;
12859814Shibler     }
12959814Shibler   else
13059814Shibler     /* Else pass on existing env vars. */
13159814Shibler     for (; *envp; envp++)
13259814Shibler       {
13359814Shibler 	tem = index (*envp, '=');
13459814Shibler 	if (tem)
13559814Shibler 	  {
13659814Shibler 	    *tem = '\000';
13759814Shibler 	    setenv (*envp, tem + 1);
13859814Shibler 	  }
13959814Shibler      }
14059814Shibler 
14159814Shibler   while (argc > 0)
14259814Shibler     {
14359814Shibler       tem = index (*argv, '=');
14459814Shibler       if (tem)
14559814Shibler 	/* If arg contains a "=" it specifies to set a variable */
14659814Shibler 	{
14759814Shibler 	  *tem = '\000';
14859814Shibler 	  setenv (*argv, tem + 1);
14959814Shibler 	  argc--; argv++;
15059814Shibler 	  continue;
15159814Shibler 	}
15259814Shibler 
15359814Shibler       if (**argv != '-')
15459814Shibler 	/* Remaining args are program name and args to pass it */
15559814Shibler 	break;
15659814Shibler 
15759814Shibler       if (argc < 2)
15859814Shibler 	fatal ("No argument following \"%s\" switch", *argv);
15959814Shibler        if (!strcmp (*argv, "-u") ||
16059814Shibler 	       !strcmp (*argv, "-unset"))
16159814Shibler 	/* Unset a variable */
16259814Shibler 	{
16359814Shibler 	  argc--; argv++;
16459814Shibler 	  setenv (*argv, 0);
16559814Shibler 	  argc--; argv++;
16659814Shibler 	}
16759814Shibler       else if (!strcmp (*argv, "-s") ||
16859814Shibler 	       !strcmp (*argv, "-set"))
16959814Shibler 	/* Set a variable */
17059814Shibler 	{
17159814Shibler 	  argc--; argv++;
17259814Shibler 	  tem = *argv;
17359814Shibler 	  if (argc < 2)
17459814Shibler 	    fatal ("No value specified for variable \"%s\"",
17559814Shibler 		   tem);
17659814Shibler 	  argc--; argv++;
17759814Shibler 	  setenv (tem, *argv);
17859814Shibler 	  argc--; argv++;
17959814Shibler 	}
18059814Shibler       else if (!strcmp (*argv, "-") || !strcmp (*argv, "--"))
18159814Shibler 	{
18259814Shibler 	  argc--; argv++;
18359814Shibler 	  break;
18459814Shibler 	}
18559814Shibler       else
18659814Shibler 	{
18759814Shibler 	  fatal ("unknown switch \"%s\"", *argv);
18859814Shibler 	}
18959814Shibler     }
19059814Shibler 
19159814Shibler   /* If no program specified print the environment and exit */
19259814Shibler   if (argc <= 0)
19359814Shibler     {
19459814Shibler       while (*nenv)
19559814Shibler 	printf ("%s\n", *nenv++);
19659814Shibler       exit (0);
19759814Shibler     }
19859814Shibler   else
19959814Shibler     {
200*60290Shibler #ifndef BSD4_4
20159814Shibler       extern int errno, sys_nerr;
20259814Shibler       extern char *sys_errlist[];
203*60290Shibler #endif
20459814Shibler 
20559814Shibler       environ = nenv;
20659814Shibler       (void) execvp (*argv, argv);
20759814Shibler 
20859814Shibler       fprintf (stderr, "%s: Cannot execute \"%s\"",
20959814Shibler 	       progname, *argv);
21059814Shibler       if (errno < sys_nerr)
21159814Shibler 	fprintf (stderr, ": %s\n" , sys_errlist[errno]);
21259814Shibler       else
21359814Shibler 	putc ('\n', stderr);
21459814Shibler       exit (errno != 0 ? errno : 1);
21559814Shibler     }
21659814Shibler }
21759814Shibler 
21859814Shibler void
setenv(var,val)21959814Shibler setenv (var, val)
22059814Shibler   register char *var, *val;
22159814Shibler {
22259814Shibler   register char **e;
22359814Shibler   int len = strlen (var);
22459814Shibler 
22559814Shibler   {
22659814Shibler     register char *tem = index (var, '=');
22759814Shibler     if (tem)
22859814Shibler       fatal ("Environment variable names may not contain \"=\": %s",
22959814Shibler 	     var);
23059814Shibler     else if (*var == '\000')
23159814Shibler       fatal ("Zero-length environment variable name specified.");
23259814Shibler   }
23359814Shibler 
23459814Shibler   for (e = nenv; *e; e++)
23559814Shibler     if (!strncmp (var, *e, len) &&
23659814Shibler 	(*e)[len] == '=')
23759814Shibler       {
23859814Shibler 	if (val)
23959814Shibler 	  goto set;
24059814Shibler 	else
24159814Shibler 	  do { *e = *(e + 1); } while (*e++);
24259814Shibler 	return;
24359814Shibler       }
24459814Shibler 
24559814Shibler   if (!val)
24659814Shibler     return; /* Nothing to unset */
24759814Shibler 
24859814Shibler   len = e - nenv;
24959814Shibler   if (len + 1 >= nenv_size)
25059814Shibler     {
25159814Shibler       nenv_size += 100;
25259814Shibler       nenv = (char **) xrealloc (nenv, nenv_size * sizeof (char *));
25359814Shibler       e = nenv + len;
25459814Shibler     }
25559814Shibler 
25659814Shibler  set:
25759814Shibler   val = concat (var, "=", val);
25859814Shibler   if (*e)
25959814Shibler     free (*e);
26059814Shibler   else
26159814Shibler     *(e + 1) = (char *) 0;
26259814Shibler   *e = val;
26359814Shibler   return;
26459814Shibler }
26559814Shibler 
26659814Shibler void
fatal(msg,arg1,arg2)26759814Shibler fatal (msg, arg1, arg2)
26859814Shibler      char *msg, *arg1, *arg2;
26959814Shibler {
27059814Shibler   fprintf (stderr, "%s: ", progname);
27159814Shibler   fprintf (stderr, msg, arg1, arg2);
27259814Shibler   putc ('\n', stderr);
27359814Shibler   exit (1);
27459814Shibler }
27559814Shibler 
27659814Shibler 
27759814Shibler extern char *malloc (), *realloc ();
27859814Shibler 
27959814Shibler void
memory_fatal()28059814Shibler memory_fatal ()
28159814Shibler {
28259814Shibler   fatal ("Out of memory");
28359814Shibler }
28459814Shibler 
28559814Shibler char *
xmalloc(size)28659814Shibler xmalloc (size)
28759814Shibler      int size;
28859814Shibler {
28959814Shibler   register char *value;
29059814Shibler   value = (char *) malloc (size);
29159814Shibler   if (!value) memory_fatal ();
29259814Shibler   return (value);
29359814Shibler }
29459814Shibler 
29559814Shibler char *
xrealloc(ptr,size)29659814Shibler xrealloc (ptr, size)
29759814Shibler      char *ptr;
29859814Shibler      int size;
29959814Shibler {
30059814Shibler   register char *value;
30159814Shibler   value = (char *) realloc (ptr, size);
30259814Shibler   if (!value) memory_fatal ();
30359814Shibler   return (value);
30459814Shibler }
30559814Shibler 
30659814Shibler /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
30759814Shibler 
30859814Shibler char *
concat(s1,s2,s3)30959814Shibler concat (s1, s2, s3)
31059814Shibler      char *s1, *s2, *s3;
31159814Shibler {
31259814Shibler   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
31359814Shibler   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
31459814Shibler 
31559814Shibler   strcpy (result, s1);
31659814Shibler   strcpy (result + len1, s2);
31759814Shibler   strcpy (result + len1 + len2, s3);
31859814Shibler   *(result + len1 + len2 + len3) = 0;
31959814Shibler 
32059814Shibler   return result;
32159814Shibler }
32259814Shibler 
32359814Shibler 
32459814Shibler /*
32559814Shibler  * Local variables:
32659814Shibler  * compile-command: "cc -g -o env env.c"
32759814Shibler  * end:
32859814Shibler  */
329