home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume6
/
setenv
< prev
next >
Wrap
Text File
|
1989-03-07
|
7KB
|
345 lines
Newsgroups: comp.sources.misc
From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Subject: v06i056: setenv.c - a sorted environment package
Message-Id: <8902222357.aa04304@solo9.cs.vu.nl>
Reply-To: Maarten Litmaath <maart@cs.vu.nl>
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