Trying to use execvp() in C with user input in unix Trying to use execvp() in C with user input in unix unix unix

Trying to use execvp() in C with user input in unix


If your implementation supports it you should use the safer getline() instead on scanf() or fgets(). getline() will safely handle long lines and NULL characters. It will allocate enough memory to fit the entire line. getline() can allocate memory so you will have to free it yourself later on.

Here is the glibc getline() documentation.

Here is a quick modification to use getline (It still needs work, error checking and I haven't fully checked it for correctness yet):

#include <stdio.h>#include <unistd.h>#include <string.h>int main(){    printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): \n");    char *num = NULL;    size_t sz = 0;    getline(&num, &sz, stdin);    int num_args;    sscanf(num, "%d", &num_args);    char *cmd[num_args+2];    memset(cmd, 0, sizeof(char*) * (num_args+2));    printf("Enter command name: \n");    int len = getline(&cmd[0], &sz, stdin);     cmd[0][len-1] = '\0';    int i;    for (i = 1; i < num_args+1; i++)    {        printf("Enter parameter: \n");        sz = 0;        len = getline(&cmd[i], &sz, stdin);        cmd[i][len-1] = '\0';    }    return execvp(cmd[0], cmd);}


You need to allocate memory for your strings. The following line only allocates num_args worth of pointers to char:

char *cmd[num_args];

First of all, you'll be getting num_args + 1 strings (don't forget that the command itself is cmd[0]). The easiest way is to statically allocate the memory as an array of character buffers:

const unsigned int MAX_LEN = 512; // Arbitrary numberchar cmd[num_args + 1][MAX_LEN];

However, now you can't use scanf to read in a line because the user could input a string that's longer than your character buffer. Instead, you'll have to use fgets, which can limit the number of characters the user can input:

fgets(cmd[i], MAX_LEN, stdin);

Keep in mind that fgets also reads newline characters, so make sure to strip any stray ones that show up (but don't assume that they're there).


Also, you need one more entry in the argv you pass to execvp, which has to be (char *)NULL to let it know that it's reached the end of the list.