Search code examples
ciosystem-callsexecvp

C system calls fails


I'm trying to write a code which manipulates standard input and output and redirect them to files, and then use execvp (also tried other exec's) to run a program that simply uses printf and scanf , but the execvp fails..

Relevant code:

    int pid2 = fork();
    if (pid2 == 0) {
        int fdInput = open("myinputfile", O_RDONLY);
        close(0);
        dup(fdInput);
        int fdOutput = open("results.txt", O_WRONLY | O_CREAT | O_TRUNC);
        close(1);
        dup(fdOutput);
        char* tmp[]={"...somepath/prog"};
        execvp("...somepath/prog", tmp);
    }

My prog:

int main(){
    int x;
    scanf("%d",&x);
    printf("Hello World! %d",x);
    return 0;
}

myinputfile contains only -> 4

I tried two main things:

  • copying the code from prog and hardcoding it into my code instead of the call to execvp, which works fine and I can see "Hello world! 4" in results.txt
  • running "mypath" in the terminal manually which also seems to work(with the standard I/O).

I can't understand why it's not working, I tried everything I could think of..


Solution

  • Your array of arguments passed to execvp() is not NULL-terminated.

    Per the POSIX exec() documentation:

    ...

    The argument argv is an array of character pointers to null-terminated strings. The application shall ensure that the last member of this array is a null pointer. These strings shall constitute the argument list available to the new process image. The value in argv[0] should point to a filename string that is associated with the process being started by one of the exec functions.

    ...

    Your code should be

    int pid2 = fork();
    if (pid2 == 0) {
        int fdInput = open("myinputfile", O_RDONLY);
        close(0);
        dup(fdInput);
        int fdOutput = open("results.txt", O_WRONLY | O_CREAT | O_TRUNC);
        close(1);
        dup(fdOutput);
    
        // note the NULL terminator
        char* tmp[]={"...somepath/prog", NULL };
        execvp("...somepath/prog", tmp);
    }