home *** CD-ROM | disk | FTP | other *** search
- From decwrl!ucbvax!tut.cis.ohio-state.edu!mailrus!ames!amdahl!uunet!allbery Fri Mar 24 22:24:47 PST 1989
- Article 821 of comp.sources.misc:
- Path: decwrl!ucbvax!tut.cis.ohio-state.edu!mailrus!ames!amdahl!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v06i056: setenv.c - a sorted environment package
- Message-ID: <8902222357.aa04304@solo9.cs.vu.nl>
- Date: 8 Mar 89 01:19:54 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: Maarten Litmaath <maart@cs.vu.nl>
- Lines: 338
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 6, Issue 56
- Submitted-by: Maarten Litmaath <maart@cs.vu.nl>
- Archive-name: setenv
-
- setenv() is better than putenv() in 3 ways:
-
- 1) the call is setenv(var, value), which is both easier and more
- natural than putenv(string)
- compare
- setenv("HOME", home);
- with
- strcpy(buf, "HOME=");
- strcat(buf, home);
- putenv(buf);
-
- 2) it isn't an error to invoke setenv() with a local (automatic)
- variable, because setenv() uses a malloc() + copy scheme (it needn't
- be blistering fast, you know)
-
- 3) it keeps the environment sorted, both for its own purposes and as a
- service to the user
-
- Regards & thanks for your attention,
- Maarten Litmaath @ VU Amsterdam:
- maart@cs.vu.nl, mcvax!botter!maart
-
- : This is a shar archive. Extract with sh, not csh.
- : This archive ends with exit, so do not worry about trailing junk.
- : --------------------------- cut here --------------------------
- PATH=/bin:/usr/bin:/usr/ucb
- echo Extracting 'setenv.c'
- sed 's/^X//' > 'setenv.c' << '+ END-OF-FILE ''setenv.c'
- Xstatic char id[] = "@(#)setenv.c 2.1 89/02/22 Maarten Litmaath";
- X
- X/*
- X * setenv.c
- X *
- X * Sorted environment package.
- X *
- X * char *setenv(char *var, char *value);
- X * Returns a pointer to the new "var=value" string if `value' has been
- X * assigned to `var', (char *) NULL if the number of environment variables
- X * exceeds MAX_ENV, or `var' is a NULL pointer or a malloc error occurred.
- X * If `value' is a NULL pointer, the empty string is assigned to `var'.
- X *
- X * int unsetenv(char *var);
- X * If `var' is the NULL pointer, the complete environment is unset.
- X * Returns -1 if the initial number of environment variables exceeds MAX_ENV
- X * or a malloc error occurred, else 0.
- X *
- X * int _envc;
- X * The current number of environment variables.
- X */
- X
- X#include "setenv.h"
- X#include <stdio.h>
- X
- Xstatic char *envbuf[MAX_ENV] = { 0 };
- Xstatic int initialized = 0, initenv(), envsearch();
- Xint _envc = 0;
- Xextern void free();
- X
- X
- Xchar *setenv(var, value)
- Xchar *var, *value;
- X{
- X extern char *malloc();
- X char **env, *buf;
- X int n;
- X
- X
- X if (!initialized && initenv() == -1)
- X return NULL;
- X
- X if (!var)
- X return NULL;
- X
- X if (!value)
- X value = "";
- X
- X n = strlen(var);
- X
- X if (!(buf = malloc(n + strlen(value) + 2)))
- X return NULL;
- X
- X (void) sprintf(buf, "%s=%s", var, value);
- X
- X if (envsearch(var, n, &env) == 0) {
- X free(*env); /* unsetenv old value */
- X *env = buf; /* setenv new value */
- X } else
- X if (_envc == MAX_ENV)
- X return NULL;
- X else
- X if (env == envbuf + _envc++) {
- X *env++ = buf;
- X *env = 0;
- X }
- X else { /* *env > var */
- X register char **p, **q;
- X
- X
- X p = envbuf + _envc;
- X q = p++;
- X while (q > env)
- X *--p = *--q; /* shift down */
- X *env = buf; /* insert new var */
- X }
- X
- X return buf;
- X}
- X
- X
- Xint unsetenv(var)
- Xchar *var;
- X{
- X register char **p, **q;
- X char **env;
- X
- X
- X if (!var)
- X if (!initialized) {
- X environ = envbuf;
- X return 0;
- X } else {
- X for (p = envbuf; *p; )
- X free(*p++);
- X *envbuf = 0;
- X _envc = 0;
- X return 0;
- X }
- X
- X if (!initialized && initenv() == -1)
- X return -1;
- X
- X if (envsearch(var, strlen(var), &env) == 1)
- X return 0;
- X
- X free(*env); /* unsetenv var */
- X
- X p = env++;
- X q = env;
- X while (*p++ = *q++) /* shift up rest of environment */
- X ;
- X --_envc;
- X
- X return 0;
- X}
- X
- X
- X/*
- X * int initenv();
- X * Copy environment to private area, sort the copy, set environ to copy,
- X * initialize _envc.
- X * Return -1 if the environment exceeds MAX_ENV or a malloc error occurred,
- X * else 0.
- X */
- X
- Xstatic int initenv()
- X{
- X register char **p = environ, **env = envbuf;
- X extern char *malloc(), *strcpy();
- X extern void qsort();
- X static int error = 0;
- X int istrcmp();
- X
- X
- X if (error == -1)
- X return -1;
- X
- X if (p)
- X while (*p && p < environ + MAX_ENV)
- X if (!(*env = malloc(strlen(*p) + 1)))
- X return error = -1;
- X else
- X (void) strcpy(*env++, *p++);
- X
- X if (p >= environ + MAX_ENV)
- X return error = -1;
- X
- X *env = 0;
- X _envc = env - envbuf;
- X qsort((char *) envbuf, _envc, sizeof *envbuf, istrcmp);
- X environ = envbuf;
- X initialized = 1;
- X return 0;
- X}
- X
- X
- X/*
- X * int envsearch(char *var, int n, char ***pos);
- X * Binarily search environment for `var', whose length is `n'.
- X * If it is present, `*pos' is set to the address of `var' in the environment
- X * and 0 is returned, else `*pos' is set to the address of the first variable
- X * lexicographically greater than `var', or to the end of the environment,
- X * and 1 is returned.
- X */
- X
- Xstatic int envsearch(var, n, pos)
- Xregister char *var;
- Xregister int n;
- Xchar ***pos;
- X{
- X register char **env, **first = envbuf, **last = envbuf + _envc;
- X register int m;
- X extern int strncmp();
- X
- X
- X while (first < last) {
- X env = first + ((last - first) >> 1);
- X if ((m = strncmp(*env, var, n)) < 0) {
- X first = env + 1;
- X continue;
- X }
- X if (m > 0) {
- X last = env;
- X continue;
- X }
- X if ((m = (*env)[n] - '=') == 0) {
- X *pos = env;
- X return 0;
- X }
- X if (m < 0) {
- X first = env + 1;
- X continue;
- X }
- X last = env;
- X }
- X
- X *pos = last;
- X return 1;
- X}
- X
- X
- Xstatic int istrcmp(p, q) /* indirect strcmp */
- Xchar **p, **q;
- X{
- X register char *s1 = *p, *s2 = *q;
- X
- X while (*s1 == *s2++)
- X if (!*s1++)
- X return 0;
- X return *s1 - *--s2;
- X}
- X
- X
- X#ifdef STANDALONE
- X
- Xmain(argc)
- Xint argc;
- X{
- X void set(), unset(), printenv();
- X
- X
- X printenv();
- X
- X if (argc > 1)
- X unset((char *) 0);
- X
- X unset("SHELL");
- X unset("PATH");
- X set("SHELL", "/foo/bar/baz");
- X set("FOO", "BAR");
- X unset("FOOO");
- X unset("FO");
- X unset((char *) 0);
- X set("ZORK", (char *) 0);
- X set("TMP", "/tmp");
- X}
- X
- X
- Xvoid set(p, q)
- Xchar *p, *q;
- X{
- X void printenv();
- X
- X
- X printf("%s -> %s\n\n", p ? p : "(null)", (q = setenv(p, q)) ? q : "?");
- X printenv();
- X}
- X
- X
- Xvoid unset(p)
- Xchar *p;
- X{
- X void printenv();
- X
- X
- X printf("%s: %d\n\n", p ? p : "(null)", unsetenv(p));
- X printenv();
- X}
- X
- X
- Xvoid printenv()
- X{
- X register char **env;
- X
- X
- X for (env = environ; *env; ++env)
- X printf("%s\n", *env);
- X printf("\n_envc=%d\n\n", _envc);
- X}
- X
- X#endif STANDALONE
- + END-OF-FILE setenv.c
- chmod 'u=rw,g=r,o=r' 'setenv.c'
- set `wc -c 'setenv.c'`
- count=$1
- case $count in
- 4740) :;;
- *) echo 'Bad character count in ''setenv.c' >&2
- echo 'Count should be 4740' >&2
- esac
- echo Extracting 'setenv.h'
- sed 's/^X//' > 'setenv.h' << '+ END-OF-FILE ''setenv.h'
- X/*
- X * setenv.h
- X */
- X
- X#ifndef SETENV_H
- X#define SETENV_H
- X
- X#define MAX_ENV 256
- X
- Xextern char **environ, *setenv();
- Xextern int unsetenv(), _envc;
- X
- X#endif !SETENV_H
- + END-OF-FILE setenv.h
- chmod 'u=rw,g=r,o=r' 'setenv.h'
- set `wc -c 'setenv.h'`
- count=$1
- case $count in
- 161) :;;
- *) echo 'Bad character count in ''setenv.h' >&2
- echo 'Count should be 161' >&2
- esac
- exit 0
-
-
-