2013-09-03 16 views
6

Sto provando a codificare una shell. Ma la mia shell non esegue il comando - ls -l | Di meno. Sto usando execvp. il codice è riportato di seguito.linux execvp; ls non può accedere |, No such file or directory

#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; 
} 
+4

'|' è un token relativo alla shell, per quanto ne so. Farlo fuori da una shell non funziona davvero perché è la shell che legge '|' e fa sì che la magia avvenga. Senza il guscio per far funzionare la piping magica ... non funziona. – Cornstalks

+0

SO c'è un altro modo per eseguire | |? posso in qualche modo la stringa e con la forza bruta farlo funzionare –

+3

@Cornstalks parla veramente. 'execvp' viene scritto per eseguire un comando con un set di parametri (se necessario). Puoi provare 'system' per chiamare una linea di comando della shell in piena regola. – lurker

risposta

9

ls -l | less è in realtà una riga di comando shell che consiste di due processi collegati da un tubo. La chiamata execvp() può generare solo un singolo processo.

Se si desidera eseguire questa operazione dal programma, è necessario richiamare esplicitamente lo shell, utilizzando la chiamata system() o modificando la riga di comando su sh -c 'ls -l | less'. L'array word dovrebbe essere simile a questo:

word[0] = "sh" 
word[1] = "-c" 
word[2] = "ls -l | less" 
word[3] = NULL 

[EDIT] In alternativa, si potrebbe fare ciò che la shell sta facendo internamente: deporre le uova due processi e collegarli con un tubo. Ciò comporterebbe l'utilizzo delle chiamate fork(), pipe(), dup2() e execve(). Tuttavia, invocare la shell è molto meno lavoro, e dal momento che less è comunque un programma interattivo, non è necessario preoccuparsi troppo delle prestazioni: tutto ciò che richiede meno di 100 ms viene percepito come istantaneo.

+0

Grazie mille per l'aiuto –

+0

+1 Proprio per l'abuso di 'sh' come comando execvp. Non ho visto che sta arrivando = P. – WhozCraig

+2

@WhozCraig: GNU libc 'system()' internamente fa esattamente la stessa cosa sotto il cofano. Vedi: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/system.c;hb=HEAD –

Problemi correlati