Linux execvp; ls cannot access |, There is no such file or directory

I am trying to code a shell. But my shell does not execute the command - ls -l | Less. I am using execvp. The code is 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; } 
+6
source share
1 answer

ls -l | less ls -l | less is actually a shell command line consisting of two processes connected by a pipe. A call to execvp() can spawn only one process.

If you want to do this from your program, you must explicitly call the shell - either by calling system() , or by changing the command line to sh -c 'ls -l | less' 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 can do what the shell does internally: create two processes and link them to the channel. This involves using calls to fork() , pipe() , dup2() and execve() . However, the shell call is much smaller, and since less is an interactive program, in any case you do not need to worry about performance: everything that takes less than 100 ms is perceived as instantaneous.

+9
source

Source: https://habr.com/ru/post/953102/


All Articles