2012-04-15 4 views
-2

私はシェルプログラムを作成しており、値をexecv()に渡すときには、プログラムの名前(ls)です。引数のcharポインタの配列の配列へのポインタが必要です。char * = "ls 0"の配列を指し示すChar *は、 "ls 0"に相当する文字列と等しくありません。

ユーザーの入力を調べて、lsと入力した場合、char *を印刷するとprintf()が "ls"を出力します。だから私は正しく行を解析し、正しい情報を格納しています。これをexecv()に渡すと、不正なパス名が表示されますが、手動でポインタをprogs[0] = "ls"に変更すると動作します。 2つの文字列、つまりstrcmp(mypointer, "ls")を比較すると、mypointerは"ls"を出力しますが、それは"ls"と等価ではありません。

誰でも知っていますか?ここで

は私のシェルプロセスコードです:

#include <string.h> 
#include <stdio.h> 
#include "myshell.h" 

int parse(char * buff){ 

//Initialize all variables and pointers 
int cmd = 0; 
int argument = 0; 
int mod = 0; 
int j = 0; 
int hitargs = 0; 
int gotcommand = 0; 
int multiarg = 0; 

char ** argptr = arguments[cmd]; 
char * ptr1 = progs[cmd]; 
char * argptr2 = argptr[argument]; 
char * ptr2 = mode[mod]; 

while(buff[j] != '\0'){ 

    switch(buff[j]){ 

     case ';': 
      cmd++; 
      argument = 0; 
      multiarg = 1; 
      *argptr2++ = '\0'; 

      argptr = arguments[cmd]; 
      argptr2 = argptr[argument]; 
      ptr1 = progs[cmd]; 

      *ptr2 = buff[j]; 
      mod += 2; 
      ptr2 = mode[mod]; 

     case ' ': 
      if(gotcommand == 0){ 
      break; 
      } 
      else{ 
       if(hitargs == 0){ 
       hitargs = 1; 
       *ptr1++ = '\0'; 
       argument++; 
       argptr2 = argptr[argument]; 
       } 
       else{ 
       argument++; 
       argptr2 = argptr[argument]; 
       } 
       break; 
      } 
     default: 
      if(gotcommand == 0){ 
       *ptr1++ = (char) buff[j]; 
       *argptr2++ = buff[j]; 
       gotcommand = 1; 
      } 
      else if(gotcommand == 1 && hitargs == 0){ 
       *ptr1++ = (char) buff[j]; 
       *argptr2++ = buff[j]; 
      } 
      else if(gotcommand == 1 && hitargs == 1){ 
       *argptr2++ = buff[j]; 
      } 
    } 

j++; 
} 

*argptr2++ = '\0'; 
*ptr1++ = '\0'; 

int cmdflag = 0; 
int spaceflag = 0; 
int argflag = 0; 
int cmdct = 1; //account for null 
int argumentct = 1; //account for null termination 

return 1; 
} 

ランダムのprintf文については申し訳ありません:

#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

char **progs; 
char ***arguments; 
char **mode; 
char pathname[] = "/bin/"; 

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

//printf("\n %s \n", progs); 
//fflush(stdout); 

char buff[100]; 
FILE *p; 

p = fdopen(0, "r"); //opens FD 0 (Stdin) as a stream 

char * pathname; 

while(1){ 

    //printf("I'm at the top"); 

    if(isatty(1) == 1){ //check to see if stdout is going to the terminal 
    printstart();  //if so, print 
    } 

    fgets(buff, 100, p); // Gets the input from the stdin and puts it in buff 

    int processid = fork(); //fork into child to complete task 

    if(processid == 0){ 

     //initialize all variables 

     int numcmd = countcmd(buff); 
     int pipes = countpipes(buff); 
     int i; 
     int j; 

     //allocate memory for tokenization 

     progs = malloc(numcmd * sizeof(char *)); 
     arguments = malloc((numcmd) * sizeof(char *)); 
     mode = malloc((numcmd*2) * sizeof(char *)); 

     for(i = 0; i < numcmd; i++){ 
      progs[i] = malloc(10* sizeof(char *)); 
      mode[i] = malloc(10 * sizeof(char *)); 
      mode[2*numcmd-1-i] = malloc(10 * sizeof(char*)); 
      arguments[i] = malloc(15 * sizeof(char *)); 
       for(j = 0; j < 15; j++){ 
       arguments[i][j] = malloc(15 * sizeof(char*)); 
       } 
      } 

     ///////////////////////////////////////////////////////////////////// 

     parse(buff); //parses input and places it in the static progs 

     for(i = 0; i < 1; i++){ 

     printf("\n This is progs %s", arguments[0][0]); 

     char temp[25]; 
     //strcpy(temp, "/bin/"); 
     strcpy(temp, progs[0]); 
     //strcat(temp, ' \0'); 

     //*progs = "ls"; 
     char * ptr = progs[0]; 
     for(;*ptr != '\0';){ 
      printf("This is what pointer poitns to %c \n", *ptr++); 
      } 
     printf("This is the program: <<%s>>", progs[0]); 
     fflush(stdout); 
     char * argument[2]; 
     argument[0] = "ls"; 
     argument[1] = '\0'; 
     char * hell = "l\0"; 

     printf("This is the value of comparison %d\n", strcmp(progs[0], hell)); 

     char **temparg = arguments[0]; 
     //char temp[20] = progs[0]; 

     errno = 0; 
     execvp("ls", *argument); 

     char * error = strerror(errno); 
     printf("This is the error %s", error); 
     return; 
     } 

    }  
     else{ 
     int status; 
     waitpid(processid, &status, WIFEXITED(status)); 

     } 
} 

return 0; 
} 

ここに私のパース()コードがあります。

 while (buff[j] != '\0' && buff[j] != '\n') 

これはあなたが追加しない保証します:あなたは、解析コードに以下を追加する必要がある他のバグが、「1!」問題へのi番目の点があるかもしれないので、全体のコードに見えない

+12

コードを表示します。 –

+0

問題をコンピュータに記述することができず、プログラムが表示されることを期待していないのと同じように、この問題と説明を表示することはできません。両方のソリューションは同じです、コードを使用! –

+8

私が推測しなければならないのは、あなたの文字列が '' ls "ではなく' 'ls \ n" 'であると言うでしょう。幸いにも、私は推測する必要はないので、私はしません。 –

答えて

2
  • メインプログラムには、解析コードのようにmyshell.hが含まれている必要があります。
  • 欠けている機能(例えば、countcmd()countpipes() —など)があるとわかりますが、その名前から少しは推測できるものの、明確には分かりません。
  • メインプログラムに<unistd.h>を含める必要があります。
  • 宣言されていない関数(例えば、fork())についての警告が表示されているはずです。警告を注意して修正する必要があります。
    • これらの警告が表示されない場合は、コンパイルに警告オプションを追加する必要があります。
    • gccを使用する場合は、-Wallを使用するとよいでしょう。有効な警告が

は、あなたが見ることを得る:

shex.c:95: warning: passing argument 2 of ‘execvp’ from incompatible pointer type 
shex.c:99: warning: ‘return’ with no value, in function returning non-void 
  • 後者は最高return EXIT_FAILURE;またはexit(EXIT_FAILURE);を介して処理されます。
  • 前者はexecvp("ls", *argument);によってトリガーされます。
  • 多くの引数を含むものには複数の単語(arguments?)を使用する方が良いかもしれません。
  • ...ああ、わかりましたが、グローバル変数argumentsがあります。
  • char ***arguments;と宣言します。 よろしく!私は時々トリプルポインタを使用しましたが、非常にときどきしか使用しませんでした。これは、ほとんどの時間、特にこのエクササイズのためのポインターのレベルが多すぎます。
  • ローカル変数char *argument[2];もあります。
  • したがって、正しい呼び出しはexecvp("ls", argument);です。

私はすぐに、少なくとも情報を印刷するために待機中のコードに拡大する:あなたの解析コードで

else 
    { 
     int status; 
     int corpse = waitpid(processid, &status, WIFEXITED(status)); 
     printf("Command exited: PID = %d; status = 0x%.4X\n", corpse, status); 
    } 

を、case ';':case ' ':に通じ落ちます。これが意図的なものであれば、文書化してください(/* DROP THROUGH */などのコメント付き)。もしそうでなければ、欠けているブレークを挿入します。あなたのdefault:ケースには、おそらくそれの後に休憩が必要です。それは非常に重要ではありませんが、従来の方法であり、新しいケースを処理する必要がある場合には、ドロップスルーからあなたを守ります。

parse()の最後に宣言された5つの変数の文字列は余分です。それらは決して使用されないローカル変数です(コンパイラから指示されるように)。 main()あなたが行うの上部に

FILE *p; 
p = fdopen(0, "r"); //opens FD 0 (Stdin) as a stream 

は、これは必要ありません。 stdinはすでにストリームとして開いています。

p(別名stdin)からfgets()と読みます。全体として、これは良いです(gets()より)が、fgets()には改行が含まれており、返品の状態を確認する必要があります(何も読んでいない可能性があります)。 sizeof()も使用する必要があります。

if (fgets(buff, sizeof(buff), stdin) == 0) 
    ...error - read failed... 

メモリ割り当ては非常に複雑です。 char buff[100];のような固定サイズの入力に対しては、非動的割り当てを使用する余裕があります。空白で区切られているので、合計約50個の引数を取ることはできません。

など

0

それは新しい行に遭遇した場合*ptr1++ = (char) buff[j];

fgetsのコマンドポインタに「改行」は読むのを止めますが、文字列の一部として、それが含まれるであろう。

関連する問題