2013-09-03 14 views
6

Próbuję zakodować powłokę. Ale moja powłoka nie wykonuje polecenia - ls -l | mniej. Używam execvp. kod podano poniżej.linux execvp; ls nie może uzyskać dostępu |, Brak takiego pliku lub katalogu

#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

'|' jest tokenem powiązanym z powłoką, o ile wiem. Robiąc to poza powłoką, tak naprawdę nie działa, ponieważ jest powłoką, która czyta '|' i sprawia, że ​​magia się wydarza. Bez powłoki, dzięki której magiczne rury mogą się wydarzyć ... to nie działa. – Cornstalks

+0

SO jest jakiś inny sposób, w jaki mogę uruchomić |? czy mogę w jakiś sposób ciąg i brutalna siła sprawiają, że działa –

+3

@Cornstalks mówi naprawdę. 'execvp' jest napisane, aby wykonać jedno polecenie z zestawem parametrów (jeśli jest to konieczne). Możesz wypróbować 'system', aby wywołać pełnowymiarową linię poleceń powłoki. – lurker

Odpowiedz

9

ls -l | less jest rzeczywiście linia poleceń, które składa się z dwóch procesów połączonych rur. Wywołanie execvp() może wywołać tylko jeden proces.

Jeśli chcesz zrobić to ze swojego programu, musisz wywołać powłokę jawnie - za pomocą wywołania system() lub zmieniając wiersz polecenia na sh -c 'ls -l | less'. Twój word tablica powinna wyglądać następująco:

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

[EDIT] Alternatywnie, można robić to, co robi powłoka wewnętrznie: tarło dwa procesy i połączyć je z rurą. Obejmowałoby to użycie wywołań fork(), pipe(),i execve(). Jednak wywołanie powłoki jest znacznie mniej pracochłonne, a ponieważ less jest tak czy inaczej programem interaktywnym, nie musisz się martwić wydajnością: wszystko, co zajmuje mniej niż 100 ms, jest postrzegane jako natychmiastowe.

+0

wielkie dzięki za pomoc –

+0

+1 Tylko za nadużycie 'sh' jako polecenie execvp. Nie widziałem, że nadchodzi = P. – WhozCraig

+2

@WhozCraig: GNU libc 'system()' wewnętrznie robi dokładnie to samo pod maską. Zobacz: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/system.c;hb=HEAD –

Powiązane problemy