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