Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

linux execvp ; ls cannot access |, No such file or directory

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;
}
like image 423
odbhut.shei.chhele Avatar asked Sep 03 '13 23:09

odbhut.shei.chhele


1 Answers

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.

like image 139
Krzysztof Kosiński Avatar answered Nov 08 '22 18:11

Krzysztof Kosiński