[comp.unix.wizards] Adding to Environment Pointers

drears@ARDEC.arpa (FSAC) (06/16/87)

    We are running Ultrik 2.0 on a vax 8600.  Is there a way to
change environmental pointers (PATH,PS1,HOME,etc) in a C program?
After I change the environmental pointers and add a few, I would
like to exec a different program while keeping the new values for
the pointers.  ANy suggestions?

Dennis

francus@cheshire.columbia.edu (Yoseff Francus) (06/17/87)

In article <7875@brl-adm.ARPA> drears@ARDEC.arpa (FSAC) writes:
>
>    We are running Ultrik 2.0 on a vax 8600.  Is there a way to
>change environmental pointers (PATH,PS1,HOME,etc) in a C program?
>After I change the environmental pointers and add a few, I would
>like to exec a different program while keeping the new values for
>the pointers.  ANy suggestions?
>
>Dennis

Dennis,
 What about the setenv command. If I'm not mistaken when you do an exec
 the new process retains the environment of the old one. If you look
 at login.c thats what happens every time the login command is run.
 Hope this is what you're lloking for.

******************************************************************
yf
In Xanadu did Kubla Khan a stately pleasure dome decree
But only if the NFL to a franchise would agree.


******************************************************************
yf
In Xanadu did Kubla Khan a stately pleasure dome decree
But only if the NFL to a franchise would agree.

franco@MIKEY.BBN.COM (Frank A. Lonigro) (06/18/87)

Dennis:
	I did a similar thing for a customized 'su' program.  This new
'su' program not only changed existing shell variables but added new ones
as well before exec'ing the shell.

	What I did was to steal that part of the code that creates shell
variables from the 'csh' source code.  If you don't have access to source
code then I would suggest learning how to manipulate the 'environ' variable
which is defined as 'extern char **environ'.  The documentation should
explain how to at least get access to environmental variables and should
get you on your way.

CSNET: franco%bbn.com@relay.cs.net
UUCP: Through harvard.

drears@ARDEC.arpa (FSAC) (06/22/87)

  I am trying to write a program that sets up a environment and then
execs a shell.  I am trying to build my environmental poingters one
by one but when I run the compiled program I get the error message:
"Trace/BPT trap".  I am running ULtrik 2.0 on a VAX 8600.  ANy
comments would be appreciated.  I have tried using the putenv(3)
command put it doesn't always work right. He is the code that matters:



#include <stdio.h>
#include <pwd.h>
#include <errno.h>

#define	PATH	"/usr/pica/bin:/bin:/usr/ucb:/usr/usg:/usr/brl/bin:/local/bin"

extern int	errno;

main(argc,argv,envp)
int	argc;
char	*argv[], *envp[];
{
	FILE	*fopen(), *fp;
	int result;
	int	uid, auid, agid;
	char	*identity, username[15];
	char	command[300], userfile[50], *fgets(), line[15], *ret;
	char	*home, *malloc(); 
	char	*newarg[], *newenvp[]; 
	struct	passwd *pwp, *getpwnam(), *getpwuid();

	identity=argv[0];

	/*  rest of code is deleted for space consideration reason
	    i get home define from the password entry */

	if (chdir(home)){
		fprintf(stderr,"ERRNO=%d",errno);
		fprintf(stderr,"%s: Could not cd to %s\n",identity,home);
		fprintf(stderr,"ERRNO=%d",errno);
		exit(-1);
	}

	/*  set up the envirnoment    */

	newarg[0]="/bin/sh";
	newenvp[0]=PATH;
	sprintf(newenvp[1],"HOME=%s",home);
	sprintf(newenvp[2],"PS1=%s>",identity);
	sprintf(newenvp[3],"MAIL=%s/mailbox",home);
	sprintf(newenvp[4],"USER=%s",identity);
	system("/bin/sh");

	/*  exec the shell with the new identity */

	exect("bin/sh",newarg,newenvp);


}


Dennis

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/22/87)

In article <7950@brl-adm.ARPA> drears@ARDEC.arpa (FSAC) writes:
>... when I run the compiled program I get the error message: "Trace/BPT trap".
>	system("/bin/sh");
No need for this.
>	exect("bin/sh",newarg,newenvp);
Of course you get a trap, that's what exect() is all about.
Use execve() instead.

ron@topaz.rutgers.edu (Ron Natalie) (06/23/87)

This one is simple so I'll just include the code:

/*
 *  Environment diddlers
 *
 *  Ron Natalie.
 */
extern char **environ;		    /*  Pointer to environment, set by crt0
				     *  used by execv, execl
				     */
static	int	_set_env = 0;	    /*  When zero, indicates that the environ
				     *  points to the original stack resident
				     *  environment.  We set it to one so that
				     *  we can free memory we malloc'd on
				     *  subsequent calls to setenv.
				     */

/*
 *  setenv - add an element to the environment
 *
 *  var is added to the environment.  It should be a string of
 *  the form "NAME=value".  Note, that the actual string is not
 *  copied, but a pointer is used, so be careful not to overwrite
 *  it before the exec.  Also, this does not check to make sure
 *  one doesn't already exist, so delenv first if you're not sure.
 */
setenv(var)
	char	*var;
{
	char	**e, **n;
	int	count;
 	char	**new;

	/*
         *  Count the number of items in the environment and malloc
	 *  room for all those plus the one we are adding.
	 */
	for(e = environ, count = 0; *e; e++) count++;
	new = (char **)malloc( (count+2)*sizeof (char *));
	/*
	 *  Copy over the points from the old to the new, and add the
	 *  new one.
	 */
	for(e = environ, n = new; count; count--)
		*n++ = *e++;
	*n++ = var;
	*n = 0;
	/*
	 *  If we had allocated this environ from a previous call,
	 *  free it now.
	 */
	if(_set_env) free(environ);
	else _set_env = 1;
	environ = new;
}

/*
 *  delenv - delete an environment variable.
 *
 *  Var should be the name of an environment variable such as "PATH"
 *  Note, that the space is not reclaimed, but this doesn't happen all
 *  that much.
 */
delenv(var)
	char	*var;
{
	char	**e;
	int	len = strlen(var);

	/*
	 *  Look for the entry in the environment.
	 */
	e = environ;
	while(*e)  {
		if(strncmp(var, *e, len) == 0)
			break;
		e++;
	}
	/*
	 *  Move everything after it, including the null terminator
	 *  down one, obliterating the deleted pointer.
	while(*e)  {
		*e = e[1];
		e++;
	}
}