问题
I am trying to use execve to run the ls command. Currently I'm running it with the following arguments:
execve(args[0], args, env_args)
//args looks like {"ls", "-l", "-a", NULL}
//env_args looks like {"PATH=/bin", "USER=me", NULL}
What I expected this to do was run the ls command using my new env_args meaning that it would look up ls in my PATH. However, this code actually doesn't do anything and when I run the code it just returns to my command prompt without output.
Using the same args[] I was using execvp and ls worked and searched my current path.
Can you tell me what I am doing wrong?
What I am trying to do is write my own shell program where I can create and export my own environment and have exec use the environment I have defined in a char**. Essentially I am writing my own functions to operate on env_args to add and remove vars and when I call exec i want to be able to call exec on {"ls", "-l", NULL} and have it look down my new environments path variable for a valid program called ls. I hope this explains what I am doing a little better. I don't think the extern environ var will work for me in this case.
回答1:
execve()
does not look at PATH; for that, you need execvp()
. Your program was failing to execute ls
, and apparently you don't report failures to execute a program after the execve()
. Note that members of the exec*()
family of functions only return on error.
You'd get the result you expected (more or less) if you ran the program with /bin
as your current directory (because ./ls
- aka ls
- would then exist).
You need to provide the pathname of the executable in the first argument to execve()
, after finding it using an appropriate PATH setting.
Or continue to use execvp()
, but set the variable environ
to your new environment. Note that environ
is now (POSIX 2008) declared in <unistd.h>
, but previously was not declared anywhere.
extern char **environ;
environ = env_args;
execvp(args[0], &args[0]);
You don't need to save the old value and restore it; you're in the child process and switching its environment won't affect the main program (shell).
This seems to work as I'd expect - and demonstrates that the original code behaves as I'd expect.
#include <stdio.h>
#include <unistd.h>
extern char **environ;
int main(void)
{
char *args[] = { "ls", "-l", "-a", NULL };
char *env_args[] = { "PATH=/bin", "USER=me", NULL };
execve(args[0], args, env_args);
fprintf(stderr, "Oops!\n");
environ = env_args;
execvp(args[0], &args[0]);
fprintf(stderr, "Oops again!\n");
return -1;
}
I get an 'Oops!' followed by the listing of my directory. When I create an executable ls
in my current directory:
#!/bin/sh
echo "Haha!"
then I don't get the 'Oops!' and do get the 'Haha!'.
来源:https://stackoverflow.com/questions/7630551/using-a-new-path-with-execve-to-run-ls-command