[comp.lang.c] setenv

jph@ais.org (Joseph Hillenburg) (02/17/91)

Do any of you know of a way to impliment a setenv() system call on 4.3BSD?
I'd like to use a call like that in a program I have, but everyone I've talked
to said it's impossible or hard to do. I saw an article on putenv(), would
that be in any way like this? It doesn't seem to exit on our system.


-- 
   //   Joseph Hillenburg, Secretary, Bloomington Amiga Users Group
 \X/  joseph@valnet.UUCP     jph@irie.ais.org       jph@albert.ai.mit.edu
       "Only Apple could slow down a 68030 chip" --Computer Shopper

jik@athena.mit.edu (Jonathan I. Kamens) (02/18/91)

In article <JB--AP*@irie.ais.org>, jph@ais.org (Joseph Hillenburg) writes:
|> Do any of you know of a way to impliment a setenv() system call on 4.3BSD?
|> I'd like to use a call like that in a program I have, but everyone I've talked
|> to said it's impossible or hard to do. I saw an article on putenv(), would
|> that be in any way like this? It doesn't seem to exit on our system.

  I'd say that "everyone you've talked to" is wrong.

  The 4.3reno BSD contains implementation of putenv, setenv and unsetenv. 
4.3taho contains implementations of setenv and unsetenv, but no putenv (as far
as I can tell at first glance.

  The tahoe source code says that it's redistributable as long as the
copyright remains intact, and it compiles fine on a 4.3 system (the reno code
doesn't, because it uses <stddef.h> and <stdlib.h>, which don't exist in stock
4.3), so I've included the tahoe code in a shar below.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  setenv.c
# Wrapped by jik@pit-manager on Sun Feb 17 15:57:16 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'setenv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'setenv.c'\"
else
echo shar: Extracting \"'setenv.c'\" \(2838 characters\)
sed "s/^X//" >'setenv.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)setenv.c	5.2 (Berkeley) 6/27/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X#include <stdio.h>
X
X/*
X * setenv --
X *	Set the value of the environmental variable "name" to be
X *	"value".  If rewrite is set, replace any current value.
X */
Xsetenv(name, value, rewrite)
X	register char *name, *value;
X	int rewrite;
X{
X	extern char **environ;
X	static int alloced;			/* if allocated space before */
X	register char *C;
X	int l_value, offset;
X	char *malloc(), *realloc(), *_findenv();
X
X	if (*value == '=')			/* no `=' in value */
X		++value;
X	l_value = strlen(value);
X	if ((C = _findenv(name, &offset))) {	/* find if already exists */
X		if (!rewrite)
X			return(0);
X		if (strlen(C) >= l_value) {	/* old larger; copy over */
X			while (*C++ = *value++);
X			return(0);
X		}
X	}
X	else {					/* create new slot */
X		register int	cnt;
X		register char	**P;
X
X		for (P = environ, cnt = 0; *P; ++P, ++cnt);
X		if (alloced) {			/* just increase size */
X			environ = (char **)realloc((char *)environ,
X			    (u_int)(sizeof(char *) * (cnt + 2)));
X			if (!environ)
X				return(-1);
X		}
X		else {				/* get new space */
X			alloced = 1;		/* copy old entries into it */
X			P = (char **)malloc((u_int)(sizeof(char *) *
X			    (cnt + 2)));
X			if (!P)
X				return(-1);
X			bcopy(environ, P, cnt * sizeof(char *));
X			environ = P;
X		}
X		environ[cnt + 1] = NULL;
X		offset = cnt;
X	}
X	for (C = name; *C && *C != '='; ++C);	/* no `=' in name */
X	if (!(environ[offset] =			/* name + `=' + value */
X	    malloc((u_int)((int)(C - name) + l_value + 2))))
X		return(-1);
X	for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
X	for (*C++ = '='; *C++ = *value++;);
X	return(0);
X}
X
X/*
X * unsetenv(name) --
X *	Delete environmental variable "name".
X */
Xvoid
Xunsetenv(name)
X	char	*name;
X{
X	extern	char	**environ;
X	register char	**P;
X	int	offset;
X
X	while (_findenv(name, &offset))		/* if set multiple times */
X		for (P = &environ[offset];; ++P)
X			if (!(*P = *(P + 1)))
X				break;
X}
END_OF_FILE
if test 2838 -ne `wc -c <'setenv.c'`; then
    echo shar: \"'setenv.c'\" unpacked with wrong size!
fi
# end of 'setenv.c'
fi
echo shar: End of shell archive.
exit 0

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (02/18/91)

In article <1991Feb17.205749.27681@athena.mit.edu>, jik@athena.mit.edu (Jonathan I. Kamens) writes:
> In article <JB--AP*@irie.ais.org>, jph@ais.org (Joseph Hillenburg) writes:
> |> Do any of you know of a way to implement a setenv() system call on 4.3BSD?

>   I'd say that "everyone you've talked to" is wrong.
> 
>   The 4.3reno BSD contains implementation of putenv, setenv and unsetenv. 

The question is not whether it is possible to have a function called
setenv() that does something to a copy of the environment.  The question
is whether there is a way to do what the original poster has in mind,
which he unfortunately forgot to tell us.  If Joseph Hillenburg wants a
function which will set variables in the environment of the parent shell
(which is what people are usually looking for, and what "can't do it" is
usually referring to), then the BSD functions are irrelevant, because
they don't do that.

In UNIX, getenv() and putenv() -- and setenv() and unsetenv() if you
have them -- work on a COPY of the parent's environment.  In other
operating systems, it varies.  See "logical names" in VMS documentation.
putenv() -- if you have it -- is _likely_ to affect commands executed
via system(), but not the parent CLI.

-- 
Professional programming is paranoid programming