Search code examples
cechoexecl

Why does this program prints an empty line?


This program is called program.c. When I run ./program echo test, I would expect the program to print test, even if the command is run in a subshell. Why is the output an empty line? Does it have to do with filepath? When I try ./program /bin/echo test I still get an empty line output.

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

int function(char **argv) {
    execl("/bin/bash", "sh", "-c", *argv, argv, (char*)NULL);
}

int main(int argc, char **argv) {
    int return2;
    
    function(argv + 1);
}

Solution

  • There are two problems with your program.

    The first problem is that the argument argv to execl() does not do what you think it does. The pointer argv is a pointer to a char * (i.e. a char **), and it is only permitted to pass a char * as an argument to execl(). That is, variable argument lists in C do not work how you are expecting them to.

    In order to accomplish what you want, consider not using execl() and use execv() instead, passing an array of char *s which you have constructed yourself. You could do this in the following way, for example:

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    
    int function(char **argv) {
        // Consider passing `argc` as well to eliminate
        // the need for this loop.
        int len = 0;
        while(argv[len]) {
            len++;
        }
        
        char *new_argv[len + 3];
        new_argv[0] = "sh";
        new_argv[1] = "-c";
        for(int i = 0; i <= len; i++) {
            new_argv[i + 2] = argv[i];
        }
        
        execv("/bin/bash", new_argv);
    }
    
    int main(int argc, char **argv) {
         function(argv+1);
    }
    

    However, you still have a problem: ./program echo test will still print a blank line because if you execute sh -c echo test in a terminal you just get a blank line! In order to fix this, you need to do ./program 'echo test' (corresponding to sh -c 'echo test' at the terminal), which should then work.