I am trying to code a shell. But my shell doesn't execute the command - ls -l | less. I am using execvp. the code is given below.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(){
int pid, status, num, len;
char str[1000], cwd[100];
char* word[100];
getcwd(cwd, sizeof(cwd));
while(1){
chdir(cwd);
printf("%s > ", cwd);
gets(str);
pid=vfork();
if(pid == 0){
num = 0;
word[num] = strtok (str, " ");
while (word[num] != NULL) {
word[num] = strdup (word[num]);
len = strlen (word[num]);
if (strlen (word[num]) > 0)
if (word[num][len-1] == '\n')
word[num][len-1] = '\0';
word[++num] = strtok (NULL, " ");
}
if(strcmp(word[0], "cd") == 0){
chdir(word[1]);
getcwd(cwd, sizeof(cwd));
}
else{
execvp(word[0],word);
}
exit(0);
}
else{
wait(&status);
}
}
return 0;
}
ls -l | less
is actually a shell command line that consists of two processes connected by a pipe. The execvp()
call can only spawn a single process.
If you want to do this from your program, you must invoke the shell explicitly - either by using the system()
call, or by changing the command line to sh -c 'ls -l | less'
. Your word
array should look like this:
word[0] = "sh"
word[1] = "-c"
word[2] = "ls -l | less"
word[3] = NULL
[EDIT] Alternatively, you could do what the shell is doing internally: spawn two processes and connect them with a pipe. This would involve using the fork()
, pipe()
, dup2()
and execve()
calls. However, invoking the shell is much less work, and since less
is an interactive program anyway, you don't need to worry about performance that much: anything that takes less than 100 ms is perceived as instantaneous.
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