summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Blandy <jimb@redhat.com>1991-06-03 23:20:54 +0000
committerJim Blandy <jimb@redhat.com>1991-06-03 23:20:54 +0000
commit2075f660c0f4029d51592cd4ed96c418b0a01482 (patch)
tree13afc049bcb1b3585a2be5e459d296774b0bbf2a
parent16a87c44d76fa2481d6db2c0c7c9a7f1995ac079 (diff)
downloademacs-2075f660c0f4029d51592cd4ed96c418b0a01482.tar.gz
entered into RCS
-rw-r--r--lib-src/env.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/lib-src/env.c b/lib-src/env.c
new file mode 100644
index 00000000000..853cb5bfb22
--- /dev/null
+++ b/lib-src/env.c
@@ -0,0 +1,338 @@
+/* env - manipulate environment and execute a program in that environment
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Mly 861126 */
+
+/* If first argument is "-", then a new environment is constructed
+ from scratch; otherwise the environment is inherited from the parent
+ process, except as modified by other options.
+
+ So, "env - foo" will invoke the "foo" program in a null environment,
+ whereas "env foo" would invoke "foo" in the same environment as that
+ passed to "env" itself.
+
+ Subsequent arguments are interpreted as follows:
+
+ * "variable=value" (i.e., an arg containing a "=" character)
+ means to set the specified environment variable to that value.
+ `value' may be of zero length ("variable="). Note that setting
+ a variable to a zero-length value is different from unsetting it.
+
+ * "-u variable" or "-unset variable"
+ means to unset that variable.
+ If that variable isn't set, does nothing.
+
+ * "-s variable value" or "-set variable value"
+ same as "variable=value".
+
+ * "-" or "--"
+ are used to indicate that the following argument is the program
+ to invoke. This is only necessary when the program's name
+ begins with "-" or contains a "=".
+
+ * anything else
+ The first remaining argument specifies a program to invoke
+ (it is searched for according to the specification of the PATH
+ environment variable) and any arguments following that are
+ passed as arguments to that program.
+
+ If no program-name is specified following the environment
+ specifications, the resulting environment is printed.
+ This is like specifying a program-name of "printenv".
+
+ Examples:
+ If the environment passed to "env" is
+ { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks }
+
+ * "env DISPLAY=gnu:0 nemacs"
+ calls "nemacs" in the envionment
+ { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks DISPLAY=gnu:0 }
+
+ * "env - USER=foo /hacks/hack bar baz"
+ calls the "hack" program on arguments "bar" and "baz"
+ in an environment in which the only variable is "USER".
+ Note that the "-" option clears out the PATH variable,
+ so one should be careful to specify in which directory
+ to find the program to call.
+
+ * "env -u EDITOR USER=foo PATH=/energy -- e=mc2 bar baz"
+ The program "/energy/e=mc2" is called with environment
+ { USER=foo PATH=/energy }
+*/
+
+#ifdef EMACS
+#define NO_SHORTNAMES
+#include "../src/config.h"
+#endif /* EMACS */
+
+#include <stdio.h>
+
+extern int execvp ();
+
+char *xmalloc (), *xrealloc ();
+char *concat ();
+
+extern char **environ;
+
+char **nenv;
+int nenv_size;
+
+char *progname;
+void setenv ();
+void fatal ();
+char *myindex ();
+
+main (argc, argv, envp)
+ register int argc;
+ register char **argv;
+ char **envp;
+{
+ register char *tem;
+
+ progname = argv[0];
+ argc--;
+ argv++;
+
+ nenv_size = 100;
+ nenv = (char **) xmalloc (nenv_size * sizeof (char *));
+ *nenv = (char *) 0;
+
+ /* "-" flag means to not inherit parent's environment */
+ if (argc && !strcmp (*argv, "-"))
+ {
+ argc--;
+ argv++;
+ }
+ else
+ /* Else pass on existing env vars. */
+ for (; *envp; envp++)
+ {
+ tem = myindex (*envp, '=');
+ if (tem)
+ {
+ *tem = '\000';
+ setenv (*envp, tem + 1);
+ }
+ }
+
+ while (argc > 0)
+ {
+ tem = myindex (*argv, '=');
+ if (tem)
+ /* If arg contains a "=" it specifies to set a variable */
+ {
+ *tem = '\000';
+ setenv (*argv, tem + 1);
+ argc--;
+ argv++;
+ continue;
+ }
+
+ if (**argv != '-')
+ /* Remaining args are program name and args to pass it */
+ break;
+
+ if (argc < 2)
+ fatal ("no argument for `%s' option", *argv);
+ if (!strcmp (*argv, "-u")
+ || !strcmp (*argv, "-unset"))
+ /* Unset a variable */
+ {
+ argc--;
+ argv++;
+ setenv (*argv, (char *) 0);
+ argc--;
+ argv++;
+ }
+ else if (!strcmp (*argv, "-s") ||
+ !strcmp (*argv, "-set"))
+ /* Set a variable */
+ {
+ argc--;
+ argv++;
+ tem = *argv;
+ if (argc < 2)
+ fatal ("no value specified for variable \"%s\"", tem);
+ argc--;
+ argv++;
+ setenv (tem, *argv);
+ argc--;
+ argv++;
+ }
+ else if (!strcmp (*argv, "-") || !strcmp (*argv, "--"))
+ {
+ argc--;
+ argv++;
+ break;
+ }
+ else
+ {
+ fatal ("unrecognized option `%s'", *argv);
+ }
+ }
+
+ /* If no program specified print the environment and exit */
+ if (argc <= 0)
+ {
+ while (*nenv)
+ printf ("%s\n", *nenv++);
+ exit (0);
+ }
+ else
+ {
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+
+ environ = nenv;
+ (void) execvp (*argv, argv);
+
+ fprintf (stderr, "%s: cannot execute `%s'", progname, *argv);
+ if (errno < sys_nerr)
+ fprintf (stderr, ": %s\n", sys_errlist[errno]);
+ else
+ putc ('\n', stderr);
+ exit (errno != 0 ? errno : 1);
+ }
+}
+
+void
+setenv (var, val)
+ register char *var, *val;
+{
+ register char **e;
+ int len = strlen (var);
+
+ {
+ register char *tem = myindex (var, '=');
+ if (tem)
+ fatal ("environment variable names can not contain `=': %s", var);
+ else if (*var == '\000')
+ fatal ("zero-length environment variable name specified");
+ }
+
+ for (e = nenv; *e; e++)
+ if (!strncmp (var, *e, len) && (*e)[len] == '=')
+ {
+ if (val)
+ goto set;
+ else
+ do
+ {
+ *e = *(e + 1);
+ } while (*e++);
+ return;
+ }
+
+ if (!val)
+ return; /* Nothing to unset */
+
+ len = e - nenv;
+ if (len + 1 >= nenv_size)
+ {
+ nenv_size += 100;
+ nenv = (char **) xrealloc (nenv, nenv_size * sizeof (char *));
+ e = nenv + len;
+ }
+
+set:
+ val = concat (var, "=", val);
+ if (*e)
+ free (*e);
+ else
+ *(e + 1) = (char *) 0;
+ *e = val;
+ return;
+}
+
+void
+fatal (msg, arg1, arg2)
+ char *msg, *arg1, *arg2;
+{
+ fprintf (stderr, "%s: ", progname);
+ fprintf (stderr, msg, arg1, arg2);
+ putc ('\n', stderr);
+ exit (1);
+}
+
+
+extern char *malloc (), *realloc ();
+
+void
+memory_fatal ()
+{
+ fatal ("virtual memory exhausted");
+}
+
+char *
+xmalloc (size)
+ int size;
+{
+ register char *value;
+ value = (char *) malloc (size);
+ if (!value)
+ memory_fatal ();
+ return (value);
+}
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ int size;
+{
+ register char *value;
+ value = (char *) realloc (ptr, size);
+ if (!value)
+ memory_fatal ();
+ return (value);
+}
+
+/* Return a newly-allocated string whose contents concatenate
+ those of S1, S2, S3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ result[len1 + len2 + len3] = 0;
+
+ return result;
+}
+
+/* Return a pointer to the first occurrence in STR of C,
+ or 0 if C does not occur. */
+
+char *
+myindex (str, c)
+ char *str;
+ char c;
+{
+ char *s = str;
+
+ while (*s)
+ {
+ if (*s == c)
+ return s;
+ s++;
+ }
+ return 0;
+}