setenv(3)/delenv(3) - add/change/delete environment variables
Stephen J. Muir
stephen at dcl-cs.UUCP
Wed Oct 23 08:33:50 AEST 1985
----------------------------------- Cut Here ----------------------------------
#!/bin/sh
echo 'Start of pack.out, part 01 of 01:'
echo 'x - setenv.3'
sed 's/^X//' > setenv.3 << '/'
X.TH SETENV 3 "22 October 1985"
X.SH NAME
Xsetenv, delenv \- add/change/delete environment variables
X.SH SYNOPSIS
X.nf
X.B setenv (name, value)
X.B char *name, *value;
X
X.B delenv (name)
X.B char *name;
X.fi
X.SH DESCRIPTION
X.I Setenv
Xallows a program to set environment variables.
X.I Delenv
Xallows a program to delete them.
XThese routines follow on logically from
X.IR getenv (3).
X.SH EXAMPLES
X.nf
Xsetenv ("EDITOR", "/usr/ucb/ex");
Xdelenv ("EDITOR");
X.fi
X.SH NOTES
XThe third argument to routine
X.B main
Xstill points to the original environment after execution of these routines.
XThe flag
X.I \-lsjm
Xneeds to be given to
X.IR cc (1)
Xor
X.IR ld (1).
X.SH "RETURN VALUES"
X.I Setenv
Xand
X.I delenv
Xboth return 0 on success and -1 if enough memory couldn't be allocated.
X.I Delenv
Xcan also return 1 meaning that the
X.B name
Xwasn't found in the current environment.
XThe first call to
X.I setenv
Xor
X.I delenv
Xinitialises both routines.
XAfter that,
X.I delenv
Xcannot return -1.
X.SH "SEE ALSO"
Xgetenv (3), execve (2)
X.SH AUTHOR
XStephen J. Muir, Lancaster University.
/
echo 'x - setenv.c'
sed 's/^X//' > setenv.c << '/'
X/* Written by Stephen J. Muir, Computing Dept., Lancaster University */
X
X# include <strings.h>
X
X/* This is the number of extra array elements to allocate each time it becomes
X * necessary.
X */
X# define INC 10
X
Xextern char **environ, *malloc ();
Xextern int free ();
X
Xstatic char **original, **current, **limit;
X
X/* This routine should be called only once (when either "setenv" or "delenv" is
X * called for the first time). It would only be called again if it fails due
X * to lack of memory. It makes a copy of the original environment because the
X * original environment array and its elements were not obtained from "malloc"
X * and the "free" routine cannot, therefore, be called with any of its
X * elements.
X *
X * return values:
X * 0: success
X * -1: out of memory - nothing has changed
X */
Xstatic /* this is a private routine */
Xinitialise ()
X { register char **old, **new_ptr, *tmp, **new_env;
X
X /* count number of existing strings */
X for (old = environ; *old; ++old)
X ;
X
X /* make space for extra strings */
X if ((new_ptr =
X new_env =
X (char **)malloc (sizeof (char **) * ((old - environ) + INC + 1))
X )
X == 0
X )
X return (-1);
X
X /* "limit" points to the last element of the array -- it is used to
X * decide when to recreate it
X */
X limit = new_env + (old - environ) + INC;
X
X /* copy across old strings */
X for (old = environ; *old; ++old)
X { if ((tmp = malloc (strlen (*old) + 1)) == 0)
X { /* out of memory -- undo everything */
X while (new_ptr != new_env)
X free (*--new_ptr);
X free ((char *)new_ptr);
X return (-1);
X }
X strcpy (tmp, *old);
X *new_ptr++ = tmp;
X }
X /* "current" points to the null pointer at the end of the array */
X *(current = new_ptr) = 0;
X
X /* this is really just a flag to say it's initialised */
X original = environ;
X /* overwrite old environment with new */
X environ = new_env;
X return (0);
X }
X
X/* This is a special routine to compare a string "name" of the form "NAME" with
X * a string "name_value" of the form "NAME=VALUE". It returns zero if the
X * comparison is successful
X */
Xstatic /* this is a private routine */
Xdiffer (name, name_value)
X char *name, *name_value;
X { while (*name && *name_value)
X if (*name++ != *name_value++)
X return (1);
X return (*name_value != '=');
X }
X
X/* This routine deletes an environment variable, e.g. delenv ("SHELL");
X *
X * return values:
X * 0: success
X * 1: environment variable not found
X * -1: out of memory - nothing has changed
X */
Xdelenv (name)
X char *name;
X { register char **ptr;
X
X /* initialise if necessary */
X if (original == 0 && initialise ())
X return (-1);
X
X /* attempt to find it */
X for (ptr = environ; *ptr && differ (name, *ptr); ++ptr)
X ;
X if (*ptr == 0)
X return (1); /* not found */
X
X /* delete it */
X free (*ptr);
X *ptr = *--current;
X *current = 0;
X return (0);
X }
X
X/* This routine sets a new environment variable, replacing an existing one
X * where appropriate, e.g. setenv ("SHELL", "/bin/csh");
X *
X * return values:
X * 0: success
X * -1: out of memory - nothing has changed
X */
Xsetenv (name, value)
X char *name, *value;
X { register char **old, **new_ptr, *cp, *tmp, **new_env;
X
X /* initialise if necessary */
X if (original == 0 && initialise ())
X return (-1);
X
X /* allocate space for the new string */
X if ((cp = tmp = malloc (strlen (name) + strlen (value) + 2)) == 0)
X return (-1);
X
X /* find an existing one if we can - we do this now as we will lose
X * the original "name" pointer in the while loop following
X */
X for (old = environ; *old && differ (name, *old); ++old)
X ;
X
X /* make the new entry */
X while (*name)
X *cp++ = *name++;
X *cp++ = '=';
X while (*value)
X *cp++ = *value++;
X *cp = '\0';
X
X /* case 1: overwrite previous value */
X if (*old)
X { free (*old);
X *old = tmp;
X }
X
X /* case 2: no previous value and no space left - allocate more */
X else if (current == limit)
X { if ((new_ptr =
X new_env =
X (char **)malloc (sizeof (char **) *
X ((old - environ) + INC + 1)
X )
X ) == 0
X )
X { free (tmp);
X return (-1);
X }
X limit = new_env + (old - environ) + INC;
X for (old = environ; *old; )
X *new_ptr++ = *old++;
X *new_ptr++ = tmp;
X *(current = new_ptr) = 0;
X free ((char *)environ);
X environ = new_env;
X }
X
X /* case 3: no previous value and there is enough space */
X else
X { *current++ = tmp;
X *current = 0;
X }
X return (0);
X }
/
echo 'Part 01 of pack.out complete.'
exit
--
UUCP: ...!seismo!mcvax!ukc!dcl-cs!stephen
DARPA: stephen%lancs.comp at ucl-cs | Post: University of Lancaster,
JANET: stephen at uk.ac.lancs.comp | Department of Computing,
Phone: +44 524 65201 Ext. 4599 | Bailrigg, Lancaster, UK.
Project:Alvey ECLIPSE Distribution | LA1 4YR
More information about the Comp.sources.unix
mailing list