简体   繁体   中英

pathname vs arguments for execve parameters

I am trying to implement a simple shell program that runs user input commands. I want the user to enter "ls" or "dir" and have the shell run /bin/ls or /bin/dir. For the execve argument what would be correct:

char *args[] ={"/bin/", "ls", NULL};
//Fork, pid, etc...then
execve(args[0], args+1, NULL);

Or would it be something different?? I've see some people using /bin/ls as the pathname and then no arguments or ls as the pathname and \bin for the environment? I tried what I had above and it didn't work so I want to know if it is the arguments I am sending it or whether I should be looking elsewhere in my code for the problem. Note I am not interested in other variations of execve such as execvp. I am on a Linux system. Thanks

PATHNAME

The pathname in execve() must be the full path to the executable, such as /bin/ls . If using execvpe() , you could use ls alone as the pathname, but as you already specified, you don't want to use that.

ARGUMENTS

The arguments should be an array of strings, one for each space-separated argument specified on the command line. The last one should be NULL. The first argument should be the pathname itself. For example:

char* args[] = {"/bin/ls", "-la", "foo/bar", NULL};

ENVIRONMENT

The environment variables cannot be omitted when using execve() . In some implementations , NULL can be passed as the last argument to execve() , but this is not standard . Instead, you should pass a pointer to a null pointer; essentially an empty array of environment variables.

Putting it together

char *args[] ={"/bin/ls", "-foo", "bar", NULL};
//Fork, pid, etc...then
char* nullstr = NULL;
execve(args[0], args, &nullstr);

From execve [emphasis added] :

 int execve(const char *pathname, char *const argv[], char *const envp[]);

execve() executes the program referred to by pathname. This causes the program that is currently being run by the calling process to be replaced with a new program, with newly initialized stack, heap, and (initialized and uninitialized) data segments.

pathname must be either a binary executable, or a script starting with a line of the form:

   #!interpreter [optional-arg]

For details of the latter case, see "Interpreter scripts" below.

argv is an array of pointers to strings passed to the new program as its command-line arguments. By convention, the first of these strings (ie, argv[0]) should contain the filename associated with the file being executed. The argv array must be terminated by a NULL pointer. (Thus, in the new program, argv[argc] will be NULL.)

In your case, the pathname should be "/bin/ls" and not "/bin/" . If you want to pass any command line argument with the command, you can provide first argument them with argv vector index 1 , second argument with index 2 and so on and terminate the argument vector with NULL .

A sample program which replace the current executable image with /bin/ls program and runs /bin/ls testfile :

#include <stdio.h>
#include <unistd.h>

int main (void) {
    char *args[] = {"/bin/ls", "testfile", NULL};
    // here you can call fork and then call execve in child process
    execve(args[0], args, NULL);

    return 0;
}

Output:

# ./a.out 
testfile

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM