2012-11-10 10 views
8

Zrobiłem prosty shell dla Linuksa. Odczytuje linię po linii z getline(), dopóki ctrl + d (eof/-1) nie zostanie wprowadzone do standardowego wejścia.Jak zrobić skrypt w Linuxie używając mojego interptetru i pracy? (#!)

Podczas wprowadzania do linii stdin kodem linii tak:

ls -al & 
ls -a -l 

Moja skorupa działa całkiem dobrze.

Próbowałem uruchomić skrypt przez powłokę, ale to nie działa. Kiedy wykonuję skrypt, moja powłoka jest wykonywana automatycznie (pierwsza linia), ale powłoka nie interpretuje innych linii.

#!/home/arbuz/Patryk/projekt/a.out 
ls -al & 
ls -a -l 

Co może spowodować? Muszę powiedzieć, że jestem bardzo początkującym w linuxes i nauczyciel nic nie mówił o tych rzeczach. Tylko praca domowa. Zrobiłem kilka badań, ale to wszystko, co znalazłem.

Oto kod mojej powłoki. Dodałem ścieżkę do powłoki etc/shells, ale to nadal nie działa

#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdbool.h> 

int main() 
{ 

    ssize_t bufer_size = 0; 
    char* line = NULL; 
    int line_size; 

    while ((line_size = getline(&line, &bufer_size, stdin)) != -1) // while end of file 
    { 
     char** words_array; 
     words_array = (char**)malloc(200 * sizeof(char*)); 

     int words_count = 0; 
     int i; 
     int j = 0; 
     int words_length = 0; 
     char word[100]; 
     for (i = 0; i < line_size; i++) 
     { 
      if (line[i] == ' ' || line[i] == '\n') 
      { 
       words_array[words_count] = (char*)malloc(words_length * sizeof(char)); 
       int b; 
       for (b = 0; b < words_length; b++) 
       { 
        words_array[words_count][b] = word[b]; 
       } 
       j = 0; 
       words_count++; 
       words_length = 0; 
      } 
      else 
      { 
       word[j] = line[i]; 
       j++; 
       words_length++; 
      } 
     } 

     bool run_in_background = false; 

     if (words_array[words_count - 1][0] == '&') 
     { 
      run_in_background = true; 
      words_array[words_count - 1] = NULL; 
     } 

     int a = fork(); 

     if (a == 0) // child process 
     { 
      execvp(words_array[0], words_array); 
     } 
     else  // parent process 
     { 
      if (run_in_background == true) 
      { 
       printf("\n ---- running in background. \n"); 
      } 
      else 
      { 
       printf("\n ---- running normal \n"); 
       wait(NULL); 
      } 
     } 
    } 

    return 0; 
} 
+1

Może być cokolwiek. Czy otrzymujesz w ogóle jakieś wyjście? –

+0

Po prostu uruchamiam moją powłokę (więc mogę samodzielnie pisać linie skryptu na stdin) – Patryk

+1

Czy możesz zrobić krótki przykład, który możesz nam pokazać? Zobacz http://sscce.org/. –

Odpowiedz

12

Twoja powłoka musi akceptować argumenty wiersza poleceń. W tym przypadku program będzie nazwany tak:

/home/arbuz/Patryk/projekt/a.out your_script

Więc trzeba main() tego podpisu:

int main(int argc, char* argv[]) 

a następnie analizowania argumentów. argc zawiera liczbę argumentów. Nazwa pliku skryptu jest przekazywana w postaci argv[1]. Musisz go otworzyć (używając fopen()) i przeczytać polecenia z niego zamiast stdin. Powinieneś prawdopodobnie upewnić się, że twoja powłoka ignoruje pierwszą linię pliku, jeśli zaczyna się od #.

Jeśli skrypt zostanie wywołany bez bezwzględnej ścieżki (ścieżka, która nie rozpoczyna się od /), nazwa pliku jest względna w stosunku do bieżącego katalogu. Możesz to uzyskać ze środowiska lub programowo za pomocą getcwd().

+6

Musi także powiedzieć swojemu parserowi, aby zignorował shebang (i przez każdy wiersz zaczynający się od '# ') –

+0

, a jeśli skrypt znajduje się w innym folderze niż skorupa ?, umieści całą ścieżkę do powłoki w miejsce twojego_scriptu?Czy powinienem stworzyć warunek, który sprawdzi, czy coś jest w argumentach (tak będzie zapisywać z pliku), czy nie ma niczego (tak, to czyta ze standardowego wejścia)? – Patryk

+0

@Patryk Obecna powłoka to wymyśli. Na przykład twoja powłoka może zostać wywołana w ten sposób: '/home/arbuz/Patryk/projekt/a.out/tmp/your_script' Ścieżka jest zawarta w argumencie. W tym przypadku 'argv [1]' wskaże '/ tmp/your_script'. –

6

Problemem jest to, że powłoka wczytuje ze standardowego wejścia, podczas gdy ona bang #! wywołuje skrypt przekazany jako argument wiersza poleceń . Tak więc twoja powłoka nazywa się

/home/arbuz/Patryk/projekt/a.out <script> 
... ignoruje argument wiersza poleceń i czeka na polecenia na standardowym wejściu. Musisz przeczytać skrypt z argv[1].

+0

Czy istnieje sposób, aby to naprawić? – Patryk

+1

@Patryk: tak, 'fopen (argv [1]," r ")' i odczytaj linie z tego. –

Powiązane problemy