• Tags
  • C

system() call not inheriting shell environment?

Latest response

Hi,

We have a piece of 'C' code that we've been using on our Oracle Linux servers for sometime without issue however, we're now trying to use it on our new Redhat Server and it's not working.
The code simply makes a system call to move a file between two directories.

Following is our original code that works on Oracle Linux:

command = "mv /home/useraccount/temp/filename.txt /home/useraccount/archive/newfilename.txt"
if (system(command) == 0) 
    log_output("File %s has been moved", filepntr->d_name);

However to get this to work on Redhat Linux we have to include the full path to the mv command thus:

command = "/usr/bin/mv /home/useraccount/temp/filename.txt /home/useraccount/archive/newfilename.txt"
if (system(command) == 0) 
    log_output("File %s has been moved", filepntr->d_name);

Can anyone please advise as to why on Redhat the PATH environment variable isn't inherited when we make the system() call as it is under Oracle Linux?

Thanks,

MikeT.

Responses

Hi Mike,

What is the PATH variable set to when running your C program on RHEL server? Test with something like this:

printf("PATH : %s\n", getenv("PATH"));

Or

const char* s = getenv("PATH");
printf("PATH :%s\n",(s!=NULL)? s : "getenv returned NULL");

By the way, system() can be quite dangerous and care should be taken. Nice writeup about it:

https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152177

Regards,

Dusan Baljevic (amateur radio VK2COT)

Hi Dusan,

Thanks for your reply. My understanding of the system() call is that it actually calls

/bin/sh -c $command

Since /bin/sh is a soft link to /bin/bash it actually calls bash but in "sh" mode. When Bash is called via /bin/sh in non-interactive mode it doesn't read any of the setup files, so the .bash_profile & .profile in the users home directory are not loaded and thus there is no PATH inherited.

This is what is causing our problem and I cannot find a way around it.

This all works fine on an Oracle Linux server but not a Redhat server, so there is a difference somewhere in the implementation of system() or how the shell is called.

Thanks for the reminder about the dangers of using the system() call, I am aware of the issues and it is something we are addressing however, this is some legacy code that we need to get working for the moment.

Any ideas gratefully received!

Thanks,

MikeT.

There likely is something else in play; the claim on PATH (or environment overall) not being inherited through system(..) did not sound credible, and is easy enough to test, so I tested.

Code:

#include <stdlib.h>
int main(char **argv, char **envp) {
        system("env");
        return 0;
}

So, running "env" command through system(..) in order to see what is set in the environment. Testing this by running the above (compiled as ./t) with explicitly set and very minimal environment (in order not to be drowned by all regular environment contents):

$ env -i PATH=/usr/bin:/whatever1 ./t
PATH=/usr/bin:/whatever1
PWD=/tmp
SHLVL=1
_=/usr/bin/env
$ env -i PATH=/usr/bin:/whatever2 ./t
PATH=/usr/bin:/whatever2
PWD=/tmp
SHLVL=1
_=/usr/bin/env

So, the PATH is very much inherited through system(..) here, on a RHEL7 server. This is such piece of functionality that I would be very surprised on having it to behave differently on any even near-POSIX system.

Please really do check (by printing to a log file or stderr or somewhere) the value of PATH right before your call to system(..), as already suggested above.

HTH, Juha

Hi Juha,

Did you run this code from your shell that you already had open? If so then this will indeed work and does for us however, the code I have copied in above is being called from a stored procedure in our Oracle database and thus /bin/sh doesn't inherit the environment.

We're looking at moving away from the system() call completely now as execve() will inherit even when called from a stored procedure.

How about using stdio routine rename()?

Hi Siem,

That Sir, is so simple it's brilliant! Thanks for your advice, we're looking at this now ....

MikeT.

Hi, Mike,

yes, that was run from a shell. But that does not change the fact that it is not the "system(..)" call that loses the environment. The issue was that whereever you did run that code of yours did not have the environment to provide to the /bin/sh invocation. So it appears that in your old system, the surrounding system (Oracle DB?) behaved differently with respect to passing the environment to this code of yours.

But the suggestion to use "rename(..)" is a very good proposal here, with the possible exception of cases where the source and target locations are on separate file systems; there rename(..) will fail even though "mv" will work.

Br, Juha

Hi juha,

Thanks for your reply. Fortunately we are moving files on the same filesystem and so the rename() is certainly the best solution for us.

Thanks to you all for your help, it's very much appreciated.

MikeT.

Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.