2017-04-22 15 views
2

こんにちは、ありがとうございます。自分のシェルを実装しようとしています。私は自分のコードとタスクの解決についていくつかの質問があります。私は私の前のコードとの質問提示下:独自のシェルを実装する

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <string.h> 
#include <sys/wait.h> 
#include <sys/types.h> 
#include <ctype.h> 
#include <errno.h> 
#include <sys/stat.h> 
#include <fcntl.h> 

void parse(char *line, char **argv, char **argv2) 
{ 
    while (*line != '\0') 
    { 
     while (*line == ' ' || *line == '\t' || *line == '\n') 
     { 
      *line++ = '\0'; 
     } 

     if(*line == '>' && *(line+1) == '>') 
     { 
      while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n') 
      { 
       line++; 
      }   
      while (*line == ' ' || *line == '\t' || *line == '\n') 
      {   
       *line++ = '\0'; 
      } 
      *argv2 = line; 
      break; 
     } 

     if(*line == '&') 
     { 
      break; 
     } 

     *argv++ = line; 

     while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n') 
     { 
      line++; 
     } 
    } 
    *argv = '\0'; 
} 

void execute(char **argv, int option) 
{ 
    pid_t pid; 
    int status; 

    if ((pid = fork()) < 0) 
    { 
     printf("*** ERROR ***\n"); 
     exit(1); 
    } 
    else if (pid == 0) 
    { 
     if (execvp(*argv, argv) < 0) 
     { 
      printf("*** ERROR ***\n"); 
      exit(1); 
     } 
    } 
    else if(option == 1) 
    { 
     while (wait(&status) != pid); 
    } 
} 

void execute2(char *command, char **argv, char **argv2) 
{ 
    pid_t pid; 
    int status; 

    if ((pid = fork()) < 0) 
    { 
     printf("*** ERROR ***\n"); 
     exit(1); 
    } 
    else if (pid == 0) 
    { 
     //close(1); 
     parse(command, argv, argv2); 
     int output = open(*argv2, O_APPEND | O_WRONLY); 
     dup2(output,1); 
     if (strcmp(argv[0], "exit") == 0) 
      exit(0); 
     if (execvp(*argv, argv) < 0) 
     { 
      printf("*** ERROR ***\n"); 
      exit(1); 
     } 
     close(output); 
    } 
    else 
    { 
     while (wait(&status) != pid); 
    } 
} 

int specialChar(char *argv) 
{ 
    int i=0; 
    while(argv[i]!='\0') 
    { 
     if(argv[i]=='>' && argv[i+1]=='>') 
      return 1;   
     else if(argv[i]=='&') 
      return 2;   
     else if(argv[i]=='|') 
      return 3;   
     i++; 
    } 
} 

void main() 
{ 
    char command[20]; 
    char *argv[64]; 
    char *argv2[1]; 
    char **history = (char**)malloc(20*sizeof(char*)); 
    int counterHistory1=-1; 
    int counterHistory2=0; 
    int i; 

    for(counterHistory2 = 0; counterHistory2<20; counterHistory2++) 
    { 
     history[counterHistory2]=(char*)malloc(100*sizeof(char)); 
    } 

    FILE *file; 
    file=fopen("history", "w"); 
    if(!file) 
     printf("ERROR"); 

    while (1) 
    { 
     printf("Shell -> "); 
     gets(command); 

     counterHistory1++; 
     strcpy(history[counterHistory1],command); 
     fopen("history", "w"); 
     if(counterHistory1<20) 
      for(i=0; i<=counterHistory1; i++) 
      { 
       fprintf(file,"%s\n",history[i]); 
      } 
     else 
      for(i=counterHistory1-20; i<counterHistory1; i++) 
      { 
       fprintf(file,"%s\n",history[i]); 
      } 

     fflush(file); 
     printf("\n"); 

     switch(specialChar(command)) 
     { 
      case 1: 
       //close(1); 
       execute2(command,argv,argv2); 
      break; 

      case 2:        //running program in background 
       parse(command, argv, argv2); 
       if (strcmp(argv[0], "exit") == 0) 
        exit(0); 
       execute(argv,0); 
      break; 

      case 3: 

      break; 

      default: 
       parse(command, argv, argv2); 
       if (strcmp(argv[0], "exit") == 0) 
        exit(0); 
       execute(argv,1); 
      break; 
     } 
     fclose(file); 
     } 
} 

1)利用者からのgettin最後の記号は「&は、」私は、バックグラウンドで私のプログラムを実行する必要があります。私は待っていないとこれを行うことができると私は読んだ。私はこれをうまくやったのか、何か変えなければならないのか?

2)「>>」を見つけたら出力をファイルにリダイレクトする必要があります。たとえば、ls >>出力を取得すると、すべてのカタログとファイルをファイル "output"に書き込む必要があります。残念ながら、それは一度しか動作しません。その後、私のプログラムは停止されます。 procesは決して終わっていないと思うし、次のコマンドを書くことはできません。私はそのプロセスを殺そうとしましたが、うまくいかなかったか、何か間違ったことをしました。

3)私のシェルでは、任意の長さのパイプを|符号。私はその問題を解決する方法を知りません...

ありがとうございました。

+0

サブポイント2へのアクセスを取得することにより、端末の制御を必要とする)であります改善しました – ByQ

+0

あなたはインタプリタ自体を書いてほしいということですか? "counterHistory1,2,2"、 "歴史"について教えてください。 –

+0

ちょっとした提案 - 履歴ファイルを開くことに失敗した場合、なぜあなたは挫折しないのですか?あなたはなぜ最大長20のコマンドを使用しますか?それは何もない! –

答えて

0

回答1シェルで

、作成されたプロセスは、シェルの子であり、STDOUT、STDINおよびstderr

signal(SIGTTOU, SIG_IGN); 

    setpgid(getpid(),getpid()); 

    if(background==false) //shell for foreground process 
    { 
     tcsetpgrp(0,getpgid(getpid())); //access to stdin 
     tcsetpgrp(1,getpgid(getpid())); //access to stdout 
     tcsetpgrp(2,getpgid(getpid())); //access to stderr 
    } 
    execvp(command,args); 
関連する問題