2012-11-10 3 views
8

私はLinux用のシンプルなシェルを作った。 ctrl + d(eof/-1)が標準入力に入力されるまで、getline()で1行ずつ読み込みます。Linuxでスクリプトを作成する方法は私のinterpteterと仕事を使用する? (#!)

そのような行のコードで標準入力ラインに入る中:私のシェルはかなりうまく機能

ls -al & 
ls -a -l 

私のシェルを通してスクリプトを実行しようとしましたが、動作しません。スクリプトを実行すると、シェルは自動的に実行されます(1行目)が、シェルは他の行を解釈しません。

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

何が原因の可能性がありますか?私は、Linuxで非常に初心者であり、教師はすべてのことについて何も言わなかったと言わなければなりません。ちょうど宿題。私はいくつかの研究をしましたが、それは私が見つけたすべてです。

ここに私のシェルのコードがあります。私は、/ etcシェルにシェルのパスを追加しましたが、まだ

#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

何でもかまいません。出力はまったく得られますか? –

+0

私のシェルが実行されているので(私は自分自身でstdinにスクリプト行を書くことができます) – Patryk

+1

私たちに見せることができる簡単な例ができますか? http://sscce.org/を参照してください。 –

答えて

12

シェルは、コマンドライン引数を受け入れる必要があります。この場合は、あなたのプログラムは次のように呼び出されます。

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

ですから、この署名のmain()必要があります

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

をして、引数を解析します。 argcには引数の量が含まれています。スクリプトのファイル名はargv[1]に渡されます。それを開いて(fopen()を使用して)、stdinの代わりにコマンドを読む必要があります。シェルが#で始まる場合、ファイルの最初の行を無視するようにしてください。

スクリプトが絶対パス(/で始まらないパス)なしで呼び出された場合、ファイル名は現在のディレクトリからの相対パスになります。あなたはそれを環境から取得するか、getcwd()でプログラムで取得できます。

+6

彼はまた、パーサーにshebang(そして、 '#'で始まる任意の行)を無視するようにしなければなりません –

+0

そして、スクリプトがシェルとは違うフォルダにあればどうでしょうか?あなたの_スクリプトの場所?引数に何かがあるかどうかを調べる(ファイルから書き込む)か、何もない(つまりstdinから読み込む)条件を作りますか? – Patryk

+0

@Patryk現在のシェルがそれを把握しています。たとえば、シェルは次のように呼び出すことができます: '/home/arbuz/Patryk/projekt/a.out/tmp/your_script'パスは引数に含まれています。この場合、 'argv [1]'は '/ tmp/your_script'をポイントします。 –

6

問題が動作していないそのあなたのシェルは、標準入力から読み込むことであり、一方、コマンドライン引数として渡されたにスクリプトを引き起こし#!彼女バング。したがってシェルは、

/home/arbuz/Patryk/projekt/a.out <script> 

...と呼ばれ、標準入力のコマンドを待っています。あなたはargv[1]からスクリプトを読む必要があります。

+0

これを修正する方法はありますか? – Patryk

+1

@Patryk:はい、 'fopen(argv [1]、" r ")'とそれから行を読み込みます。 –

関連する問題