I wrote this program in order to use the execvp
command and this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
char **cmd;
int i;
if (argc == 1){
fprintf(stdout, "No command inserted!\n");
exit(EXIT_SUCCESS);
}
cmd = (char **) malloc( (argc + 1) * sizeof(char *));
cmd[0] = (char *) malloc( strlen(argv[1] + 1 ) * sizeof(char) );
strcpy(cmd[i], argv[i+1]);
if (argc > 2){
for (i = 1 ; i < argc - 1 ; i++ ){
cmd[i] = (char *) malloc( strlen(argv[i+1] + 1 ) * sizeof(char) );
strcpy(cmd[i], argv[i+1]);
}
cmd[argc] = NULL;
execvp(cmd[0], cmd);
fprintf(stderr, "Failed Execution or not existing command!!\n");
exit(EXIT_FAILURE);
}
cmd[1] = NULL;
execvp(cmd[0], cmd);
fprintf(stderr, "Failed Execution or not existing command!!\n");
exit(EXIT_FAILURE);
return 0;
}
I run this program on the terminal using these commands
./a.out ls
./a.out who
./a.out ls -l
./a.out mkdir newdir
The first two worked fine as well as the other commands without arguments. With the last two I get a No such File or Directory
error in the terminal, but actually the mkdir
command creates the directory newdir...
Can someone help me
you're setting cmd[argc] = NULL;
but that's too much by 1 (argc
is the count of args with your command included). So cmd[argc - 1]
isn't initialized (note that the loop above stops at argc - 2
You need to set cmd[argc - 1]
to NULL
instead or else another trash argument is passed to execvp
, which explains for instance that mkdir
works for the first argument, but fails when processing the garbage arg. All commands receive a garbage argument because of this shift.
You need an array of pointers of size argc
, not argc + 1
since the a.out
command isn't considered.
Also, as noted in comments, you're using i
not initialized at first, which work (since your mkdir
command works) but out of luck (undefined behaviour)
A much simpler way to do it would be to copy the array of argv
pointers (ignoring the first one which is your comment) without duplicating the memory for the string contents (since you're not modifying them).
cmd = malloc( argc * sizeof(char *)); // argc because we need 1 slot for NULL termination
for (i=0;i<argc-1;i++)
{
cmd[i] = argv[i+1];
}
cmd[i] = NULL; // i is argc-1 now