Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
04-21-2004, 04:35 PM
|
#1
|
LQ Newbie
Registered: Apr 2004
Location: Lake City, Florida, USA
Distribution: Red Hat and SuSE
Posts: 9
Rep:
|
setenv within a program doesn't last
I wrote a C++ program which calls setenv() to change
the "path" environment variable. Within the program
I can then call getenv("PATH") and see the new
value.
But after the program exits, if I list the environment
variables using the tcsh command: setenv | grep -i path
I see the old path, not the one newly set.
Apparently the program is run with a copy of the
environment, which is modified and then discarded.
Any ideas how to make this program work?
I want the path changed within the shell after the
program terminates.
Note: I am using the setenv() command described in
section 3 of the man pages (man 3 setenv).
I also tried system("setenv path=(/bin /sbin)");
but it failed the same way.
Thanks,
Mark
Red Hat Linux version 9
gcc compiler
tcsh shell used
|
|
|
04-21-2004, 04:55 PM
|
#2
|
Member
Registered: May 2002
Posts: 964
Rep:
|
When you run a program, it runs in it's own separate sub-process.
When the sub-process exits, then all of the environment variables exit with it.
You return to the parent process, which never saw those changes.
If you want to set envrionment variables that stick around, you probably want to try using a simple script -- then execute the script with dot notation like this:
|
|
|
04-21-2004, 05:24 PM
|
#3
|
LQ Newbie
Registered: Apr 2004
Location: west coast USA
Distribution: redhat 9, fedora core 2, Gentoo
Posts: 20
Rep:
|
Hi, I think what you are trying to do willl not work (if I'm wrong I'd love to know the answer!). Since your program is creating a child process which is then used to create the variable using setenv, then when this process exits the enviroment change is lost, it's said much better here:
"A script can export variables only to child processes, that is, only to commands or processes which that particular script initiates. A script invoked from the command line cannot export variables back to the command line environment. Child processes cannot export variables back to the parent processes that spawned them."
Advanced Bash Cripting Guide Ch 4.4
Cheers
|
|
|
04-21-2004, 05:26 PM
|
#4
|
Senior Member
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536
Rep:
|
Quote:
Apparently the program is run with a copy of the
environment, which is modified and then discarded.
|
Yes, that is exactly what happens. Only the program itself and its child processes (if the env. var. is exported) have the changed or added env. var. available.
What you could do to fix it is, instead of exiting your program, replacing it with a new shell process. For example: (C..., not C++. Sorry) :
Code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *shell;
/* Get the path of the current shell to start it later */
shell = getenv("SHELL");
if (shell == NULL) {
fprintf(stderr, "Error eding SHELL env. var.\n");
return 1;
}
/* Overwrite env. var. PATH */
if (setenv("PATH", "/usr/bin", 1) < 0) {
fprintf(stderr, "Error setting env. var.\n");
return 1;
}
/* Replace this program by a new instance of the shell */
execl(shell, shell, NULL);
/* We should never get here, so it's an error. */
fprintf(stderr, "Error starting shell\n");
return 2;
}
When you run this, the program will exit by starting a new shell that will have the changed PATH. However, the previous shell you started the program from is still running as well. (and the new one will have a different commandline history as well). So if you start the program more than once, there will be a stack of shells running. you can verify this byt running it a few times, and then run:
Code:
/usr/bin/pstree | /bin/grep -B1 pstree
To prevent this, (and keep the same command line history) you need to run the program with "exec", like this: If you run this a few times,and then check "/usr/bin/pstree | /bin/grep -B1 pstree", there will still be one shell running.
Hope this helps.
Last edited by Hko; 04-21-2004 at 05:29 PM.
|
|
|
04-21-2004, 05:32 PM
|
#5
|
Senior Member
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536
Rep:
|
P.S. If changing environment variables is the only thing your program does, stick with jim mcnamara's solution. Much easier and more apropriate for just changing env. vars.
|
|
|
04-22-2004, 12:24 AM
|
#6
|
Senior Member
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246
Rep:
|
You could just do this: system("VAR=setting; export VAR");
|
|
|
04-22-2004, 11:58 AM
|
#7
|
Member
Registered: May 2002
Posts: 964
Rep:
|
itsme - wont'work because system() forks (using exec) and creates a subprocess.
"export" only creates the variable for that process and any of it's children - not the parent process.
If a child could alter parent environments by using export, unix would have zero security.
Last edited by jim mcnamara; 04-22-2004 at 12:00 PM.
|
|
|
04-22-2004, 07:00 PM
|
#8
|
Member
Registered: Mar 2004
Location: Massachusetts
Distribution: Debian
Posts: 557
Rep:
|
Another way to handle this is to just have your program output shell commands to set the environment the way it wants it. e.g. ssh-agent is meant to be called like "eval `ssh-agent`"
The tricky part of this is that you need to output command appropriate to the shell you're using: csh and sh are a little different. You can check the SHELL environment variable of course.
|
|
|
04-26-2004, 04:39 PM
|
#9
|
LQ Newbie
Registered: Apr 2004
Location: Lake City, Florida, USA
Distribution: Red Hat and SuSE
Posts: 9
Original Poster
Rep:
|
Thanks for all the replies.
It looks like my original plan is simply not possible.
For closure, I finally used a method like that
proposed by "aluser":
eval `fixpath`
(recall that I am using tcsh)
where the name of my program is: fixpath
and the program writes a string like this to stdout:
set path=(/sbin /usr/bin)
It is not as clean as I had hoped for, but not too ugly.
Thanks 'aluser', for I didn't know about the eval
command.
Mark
|
|
|
All times are GMT -5. The time now is 10:15 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|