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. Theexecvp()
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 tosh -c 'ls -l | less'
. Yourword
array should look like this:[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()
andexecve()
calls. However, invoking the shell is much less work, and sinceless
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.