I'm trying to make a program that will prompt the user for a command, then use exec to execute that command.
For instance if they gave me "ls -la" I would have to execute that command. I've tried the following code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int ret, num_args;
printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): ");
scanf("%d", &num_args);
char *cmd[num_args];
printf("Enter command name: ");
scanf("%s", &cmd[0]);
int i;
for (i = 0; i < num_args; i++)
{
printf("Enter parameter: ");
scanf("%s", &cmd[i]);
}
execvp(cmd[0], cmd);
}
However, when I tried the following run it gave me a "segmentation fault"
$ ./a.out
Enter number of arguments (Example: "ls -la" has 1 argument): 2
Enter command name: ls
Enter parameter: -la
Enter parameter: .
Segmentation fault
$
Any ideas?
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);
}