I am building a shell and am having some trouble with the system call 'execvp'. I saw some other questions on this topic but they were vague, and did not appear to be completely addressed (whoever asked the questions didn't provide much information and didn't get good answers).
Obviously I have my own command line and I'm reading user input from stdin like
mysh some/path $ ps -a
and I am building an args array as a char ** and the array itself works (I think) since when I print out the values within my function it shows
args[0] = 'ps'
args[1] = '-a'
args[2] = '(null)'
So, I call fork and execvp(cmnd, args) within my process, where cmnd is "ps" and args is as above, and perror etc.
I get
'Error: no such file or directory.'
Do I need to put in the $PATH variable? Am I doing something else whacky?
Here's my code for generating the args array:
char ** get_args(char * cmnd) {
int index = 0;
char **args = (char **)emalloc(sizeof(char *));
char * copy = (char *) emalloc(sizeof(char)*(strlen(cmnd)));
strncpy(copy,cmnd,strlen(cmnd));
char * tok = strtok(copy," ");
while(tok != NULL) {
args[index] = (char *) emalloc(sizeof(char)*(strlen(tok)+1));
strncpy(args[index],tok,strlen(tok)+1);
index++;
tok = strtok(NULL," ");
args = (char**) erealloc(args,sizeof(char*)*(index+1));
}
args[index] = NULL;
return args;
}
(emalloc and erealloc are just malloc and realloc with error checking built in)
So then I do this:
void exec_cmnd(char*cmnd, char**args) {
pid_t pid;
if((pid=fork())==0) {
execvp(cmnd, args);
perror("Error");
free(args);
free(cmnd);
exit(1);
}
else {
int ReturnCode;
while(pid!=wait(&ReturnCode)) {
;
}
}
}
And like I said above, when execvp is called inside my process it fails when I supply any arguments whatsoever but works without them (i.e. when argv == {'ps', NULL} )
If you need more information don't hesitate to ask. I need to solve this.
It think you passed whole command line in first argument to execvp
you have to separate first token(command name) from cmnd
to pass as first argument of execvp
You can call it as
execvp(args[0], args);
Note in passing that you have a non-terminated string as a result of:
char * copy = (char *) emalloc(sizeof(char)*(strlen(cmnd)));
strncpy(copy, cmnd, strlen(cmnd));
strncpy()
does not null terminate for you when you use it like that. You also need to allocate one more byte for the null. Consider using strdup()
if it is available to you. If not, consider writing it. This misallocation is a problem even with the error checking versions of emalloc()
and erealloc()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With