2017-03-25 6 views
-1

私はシェルプログラムをcで書こうとしています。 プログラムはfork関数で作成された複数のプロセスを持つ必要があり、1つのコマンドで複数の出力行を出力することができます。 たとえば、linux terminalのように、入力が "ls; ps; pwd;"の場合、出力は次のようになります。は、Cでシェルを書いているときに問題があります

$./shell 
shell> ls ; ps ; pwd ; 
(ls output) 
(ps output) 
(pwd output) 

そして、ファイルを開き、ファイルに含まれているコマンドリストと出力を表示することができるはずです。(バッチモード私は推測?)

のは、これらのコマンドリストは、バッチファイルであるとしましょう。

batch 
1 ls 
2 ps 
3 ls ; pwd ; ps 

、出力が

$./shell batch 
shell> ls 
shell> (ls output) 
shell> ps 
shell> (ps output) 
shell> ls ; pwd ; ps 
shell> (ls output) 
(ps output) 
(pwd output) 

ですここで私はこのコードは正常に動作しますが、いくつかの問題があり

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <string.h> 
#include <fcntl.h> 

void command(char* myargs[][10], char* buffer); 
int tokenizing(char* myargs[][10], char* buffer); 

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

    int fd; 
    char buffer[200]; 
    char* myargs[10][10]; 
    char* token; 

    if(argc >= 2) { 
     if((fd=open(argv[1], O_RDONLY)) == -1) 
      printf("cannot open file\n"); 
     else { 
      read(fd, buffer, 200); 
      printf("%s\n", buffer); 
      token = strtok(buffer, "\n"); 
      while(token != NULL) { 
       printf("%s\n", token); 
       command(myargs, token); 
       token = strtok(NULL, "\n"); 
      } 
      return 0; 
     } 
    } 



    while(1) { 
     printf("prompt> "); 
     if(fgets(buffer, 200, stdin) == NULL|| 
       strcmp(buffer, "quit\n") == 0) 
      break; 
     command(myargs, buffer); 
    } 

    return 0; 
} 

void command(char* myargs[][10], char* buffer) { 

    int rc = fork(); 

    if(rc < 0) { 
     fprintf(stderr, "fork failed\n"); 
    } else if(rc == 0) { 

     int n = tokenizing(myargs, buffer); 

     for(int i = 0 ; i < n; i++) { 

      int rc2 = fork(); 
      if(rc2 < 0) { 
       fprintf(stderr, "for failed\n"); 
      } else if(rc2 == 0) { 
       execvp(myargs[i][0], myargs[i]); 
       printf("%s: command not found\n", myargs[i][0]); 
       exit(0); 
      } else { 
       wait(NULL); 
      } 
     } 
     exit(0); 
    } 
    else { 

     wait(NULL); 


    } 
} 

int tokenizing(char* myargs[][10], char* buffer) { 

    int i = 0; 
    int j = 0; 
    int k = 0; 

    char* token; 
    char* subCommand[10]; 

    token = strtok(buffer, ";\n"); 

    while(token != NULL) { 
     subCommand[k] = token; 
     k++; 
     token = strtok(NULL, ";\n"); 
    } 


    for(int i = 0; i < k; i++) { 
     token = strtok(subCommand[i], " \n"); 
     while(token != NULL) { 
      myargs[i][j] = token; 
      j++; 
      token = strtok(NULL, " \n"); 
     } 
     myargs[i][j] = NULL; 
     j=0; 
    } 
} 

を書いたコードです。このコードをバッチファイルで実行すると、いくつかのエラーが発生します。

enter image description here

プログラムが実行されると、私は、出力が上記の画像ファイルのようにあるべきだと思う - 私の知る限りでは。

enter image description here

しかし、頻繁にプログラムが私も入力していなかったいくつかの奇妙なコマンドラインで出てきます。これらの結果は、代わりに起こります。

また、 'ps'リストが表示されている場合は、2つのシェルプログラムが実行されていることがわかります。

これらの問題を解決するのにお手伝いしてもらえますか?

答えて

0

Cの 'strings'にはNULターミネータが必要です。 printf( "%s ....")やstrtok()のようなstrng関数を、NULで終端されていないchar配列で呼び出すと、定義されていない動作になります。

read()は値を返します。ターミネータを「バッファ」にロードするために使用することができます。スーパーセーフであるためには、ターミネータに十分なスペースがあることを確認するために、[バッファサイズ-1]の文字のみを読み取ろうとしてください。例:

buffer[read(fd, buffer, 199)]='\0'; 
+0

スーパーセーフで、それをインデックスとして使用する前に、それが負であるかどうかを調べる 'read()'戻り値。 – chux

関連する問題