简体   繁体   中英

Using execve (linux)

Im confused of the use of the systemcall execve. The second parameter should be a pointer to the arguments but it doesnt work, it does however execute correctly when I send the whole command(/bin/bash) + arg as a second parameter.

./test /bin/bash "echo 'this is a test' | wc -c"

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int main(int argc, char *argv[]) {
    execve(argv[1], &argv[1], NULL); ////works, but I dont understand how since the 2nd param is wrong.
    return 0;
}

int main(int argc, char *argv[]) {
    execve(argv[1], &argv[2], NULL);  ////doenst work, it should since Im sending the correct aguments.
    printf("hi");
    return 0;
}

argv[0] contains the name of the file being executed. Therefore, execve also needs the file being executed as first element (index 0).

From the execve(2) man page :

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 other words, the arguments list that you pass in the second parameter includes the name of the executable itself (even though that is already specified in the first parameter). This is how executables are able to detect how they're being invoked (eg through a symlink) and show the correct name in their "help" output.

In execve man we can see that its prototype is:

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

According to execve man ( https://man7.org/linux/man-pages/man2/execve.2.html )

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 respect to these rules you're code should be:

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

int main ()
{

    char *filepath = "/bin/echo";
    char *argv[] = { filepath, "Hello World", NULL };

    execve (filepath, argv, NULL);
  
  return 0;
}

execve call executes a program from the caller. Just as any program in C, it requires argv[0] to be set to the name of the executable being executed. This is generally done automatically when executing from command line, but since you're using execve you have to do it yourself.
If argv_1[1] = <executable path for program_2> , when you call program_2 from program_1 with execve(argv_1[1], &argv_1[1], NULL) , program_2 recieves an argv array such that argv_2[0] = argv_1[1], argv_2[1] = argv_1[2] , and so on.
Notice how your second main does not follow this rule.

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