[net.sources] setenv

stephen@dcl-cs.UUCP (Stephen J. Muir) (10/23/85)

----------------------------------- 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@ucl-cs	| Post: University of Lancaster,
JANET:	stephen@uk.ac.lancs.comp	|	Department of Computing,
Phone:	+44 524 65201 Ext. 4599		|	Bailrigg, Lancaster, UK.
Project:Alvey ECLIPSE Distribution	|	LA1 4YR