I am hoping someone here can help me with a little bit of trouble using the execve() call. I have some code that needs to call an external script under CNL (Compute Node Linux, i.e. - Cray XT4/XT5). CNL is extremely lean and is missing enough libraries to make using something as common as /usr/bin/env impossible. I'm trying to use execve() to pass the arguments to the script and a custom (read stripped-down) set of environmental variables as we want very tight control over these. (Many of the paths in $PATH are not available to the file system on the compute nodes.)
Here's what I have:
char *cmdstr; // This will hold a string with the name of the script
char **my_args = NULL; // these next two should be self-explanatory
char **my_env = NULL;
I have a simple little function to append a string to the array of strings that looks something like this:
void add_strtoarray(char ***str_array, int *num_elements,
const char *my_string)
{
(*num_elements)++;
*str_array = (char **) realloc(*str_array,
(*num_elements)*sizeof(char *));
(*str_array)[(*num_elements) - 1] = strdup(my_string);
So ... in my code I do the following:
// Set up the info for execve
char *cmdstr;
char **my_env = NULL;
char **my_args = NULL;
int num_my_env = 0;
int num_my_args = 0;
pid_t pid;
// Populate my environment
add_strtoarray(&my_env,&num_my_env,env_ROOT);
add_strtoarray(&my_env,&num_my_env,env_EXTRALIBS);
add_strtoarray(&my_env,&num_my_env,env_EXTRAINCLUDE);
.
.
.
add_strtoarray(&my_env,&num_my_env,env_PYTHONHOME);
add_strtoarray(&my_env,&num_my_env,env_PYTHONPATH);
add_strtoarray(&my_env,&num_my_env,env_PATH);
// Generate the argument list
add_strtoarray(&my_args,&num_my_args,"-i");
add_strtoarray(&my_args,&num_my_args,inputdeck);
.
.
.
add_strtoarray(&my_args,&num_my_args,"-o");
add_strtoarray(&my_args,&num_my_args,outputdeck);
// UTILPATH is in a site-specific header file
// script_name is supplied on the command line
sprintf(cmdstr,"%s/%s",UTILPATH,script_name);
pid = vfork();
if (pid == -1) {
// fork error code here
}
if (pid == 0) {
exeve(cmdstr,my_args,my_env);
}
else {
wait(NULL);
}
According the the man pages, the native environment variable const char **environ is of the same type as my declarations. However, if I modify the script referred to in cmdstr to print out its argv[] list I see that only the first of my strings in my_args is passed in. That is ... for the example above the script thinks that it has a single element in argv (ignoring the name of the executable), namely "-i". Similarly, the environment doesn't seem to be getting passed properly to the script.
I'm completely baffled by this! Any suggestions would be helpful.