셸 의 실현

오늘 큰 작업 을 완성 하고 있 습 니 다. 주요 임 무 는 Liux 의 셸 프로그램 을 작성 하 는 것 입 니 다. 이것 은 우리 가 셸 이 무엇 인지 이해 하 는 데 도움 이 됩 니 다. 그리고 사실은 그 도 * * Liux 운영 체제 마이크로 커 널 의 개념 을 작 성 했 습 니 다. 아래 에 괜 찮 은 자료 가 몇 편 있 습 니 다. 참고 하 시기 바 랍 니 다.
먼저 셸 의 원 리 를 해석 하 는 글 입 니 다. 저 에 게 큰 도움 이 되 지 않 습 니 다. 저 는 아직 완전한 셸 을 만 들 필요 가 없 기 때문에 자료 만 대충 보 았 습 니 다.http://files.linjian.org/articles/bash_study/bash_linjian.html
그 다음 에 다음 두 편의 글 입 니 다. 안의 코드 가 아주 좋 습 니 다. 셸 의 기본 기능 을 실 현 했 고 그의 코드 도 붙 여 보 았 습 니 다. 단점 은 내부 명령 을 실현 하지 못 한 것 입 니 다.
http://www.jiechic.com/archives/24.html
http://www.jiechic.com/archives/25.html
 
   
   
   
   
  1. #include  
  2. #include  
  3. #include  
  4. #include  
  5. #include  
  6. #include  
  7. #include  
  8. #include  
  9. #include  
  10. #define normal      0  /*   */ 
  11. #define out_redirect    1  /*   */ 
  12. #define in_redirect 2  /*   */ 
  13. #define have_pipe   3  /*   */  
  14.   
  15. void print_prompt();                    /*   */ 
  16. void get_input(char *);                 /*   */ 
  17. void explain_input(char *buf, int *argcount, char arglist[100][256]);       /*   */ 
  18. void do_cmd(int argcount, char arglist[100][256]);      /*   */ 
  19. int  find_command(char *);                  /*   */ 
  20.   
  21. int main(int argc, char **argv) 
  22.     int    i; 
  23.     int    argcount = 0; 
  24.     char   arglist[100][256]; 
  25.     //char   **arg = NULL; 
  26.     char   *buf  = NULL; 
  27.     buf = (char *)malloc(256); 
  28.     if( buf == NULL ) { 
  29.         perror("malloc failed"); 
  30.         exit(-1); 
  31.     } 
  32.     while(1) { 
  33.         /*  buf  */ 
  34.         memset(buf, 0, 256); 
  35.         print_prompt(); 
  36.         get_input(buf); 
  37.         /*  exit logout  */ 
  38.         if( strcmp(buf,"exit
    "
    ) == 0 || strcmp(buf,"logout
    "
    ) == 0 ) 
  39.             break
  40.         for (i=0; i 
  41.         { 
  42.             arglist[i][0]='\0'
  43.   
  44.         } 
  45.         argcount = 0; 
  46.         explain_input(buf, &argcount, arglist); 
  47.         do_cmd(argcount, arglist);   
  48.   
  49.     } 
  50.     if(buf != NULL) { 
  51.         free(buf); 
  52.         buf = NULL; 
  53.     } 
  54.     exit(0); 
  55.   
  56. void print_prompt() 
  57.     printf("myshell$$ "); 
  58.   
  59. /* */ 
  60. void get_input(char *buf) 
  61.     int len = 0; 
  62.     int ch; 
  63.     ch = getchar(); 
  64.     while (len '
    '
    ) { 
  65.         buf[len++] = ch; 
  66.         ch = getchar(); 
  67.     } 
  68.     if(len == 256) { 
  69.         printf("command is too long 
    "
    ); 
  70.         exit(-1); /*   */ 
  71.     } 
  72.     buf[len] = '
    '
  73.     len++; 
  74.     buf[len] = '\0';         
  75.   
  76.   
  77. /*  buf , arglist ,
     */
     
  78. /*  "ls -l /tmp", arglist[0]、arglist[1]、arglsit[2] ls、-l /tmp */ 
  79. void explain_input(char *buf, int *argcount, char arglist[100][256]) 
  80.     char    *p  = buf; 
  81.     char    *q  = buf; 
  82.     int number  = 0; 
  83.     while (1) { 
  84.         if ( p[0] == '
    '
     ) 
  85.             break
  86.         if ( p[0] == ' '  ) 
  87.             p++; 
  88.         else { 
  89.             q = p; 
  90.             number = 0; 
  91.             while( (q[0]!=' ') && (q[0]!='
    '
    ) ) { 
  92.                 number++; 
  93.                 q++; 
  94.             } 
  95.             strncpy(arglist[*argcount], p, number+1); 
  96.             arglist[*argcount][number] = '\0'
  97.             *argcount = *argcount + 1; 
  98.             p = q; 
  99.         } 
  100.     } 
  101.   
  102. void do_cmd(int argcount, char arglist[100][256]) 
  103.     int flag = 0; 
  104.     int how = 0;        /*  >、 
  105.     int background = 0; /*  & */ 
  106.     int status; 
  107.     int i; 
  108.     int fd; 
  109.     char*   arg[argcount+1]; 
  110.     char*   argnext[argcount+1]; 
  111.     char*   file; 
  112.     pid_t   pid; 
  113.     /* */ 
  114.     for (i=0; i 
  115.         arg[i] = (char *) arglist[i]; 
  116.     } 
  117.     arg[argcount] = NULL; 
  118.     /* */ 
  119.     for (i=0; i 
  120.         if (strncmp(arg[i], "&",1) == 0) { 
  121.             if (i == argcount-1) { 
  122.                 background = 1; 
  123.                 arg[argcount-1] = NULL; 
  124.                 break
  125.             } 
  126.             else { 
  127.                 printf("wrong command
    "
    ); 
  128.                 return ; 
  129.             } 
  130.         } 
  131.     } 
  132.     for (i=0; arg[i]!=NULL; i++) { 
  133.         if (strcmp(arg[i], ">") == 0 ) { 
  134.             flag++; 
  135.             how = out_redirect; 
  136.             if (arg[i+1] == NULL) 
  137.                 flag++; 
  138.         } 
  139.         if ( strcmp(arg[i],") == 0 ) { 
  140.             flag++; 
  141.             how = in_redirect; 
  142.             if(i == 0) 
  143.                 flag++; 
  144.         } 
  145.         if ( strcmp(arg[i],"|")==0 ) { 
  146.             flag++; 
  147.             how = have_pipe; 
  148.             if(arg[i+1] == NULL) 
  149.                 flag++; 
  150.             if(i == 0 ) 
  151.                 flag++; 
  152.         } 
  153.     } 
  154.     /* flag 1, > , 
  155.         , "ls -l /tmp >" */ 
  156.     if (flag > 1) { 
  157.         printf("wrong command
    "
    ); 
  158.         return
  159.     } 
  160.     if (how == out_redirect) {  /* > */ 
  161.         for (i=0; arg[i] != NULL; i++) { 
  162.             if (strcmp(arg[i],">")==0) { 
  163.                 file   = arg[i+1]; 
  164.                 arg[i] = NULL; 
  165.             } 
  166.         } 
  167.     } 
  168.     if (how == in_redirect) {    /*  
  169.         for (i=0; arg[i] != NULL; i++) { 
  170.             if (strcmp (arg[i],") == 0) { 
  171.                 file   = arg[i+1]; 
  172.                 arg[i] = NULL; 
  173.             } 
  174.         } 
  175.     } 
  176.     if (how == have_pipe) {  /*  | */ 
  177. /*  argnext , shell  */ 
  178.         for (i=0; arg[i] != NULL; i++) { 
  179.             if (strcmp(arg[i],"|")==0) { 
  180.                 arg[i] = NULL; 
  181.                 int j; 
  182.                 for (j=i+1; arg[j] != NULL; j++) { 
  183.                     argnext[j-i-1] = arg[j]; 
  184.                 } 
  185.                 argnext[j-i-1] = arg[j]; 
  186.                 break
  187.             } 
  188.         } 
  189.     } 
  190.     if ( (pid = fork()) 
  191.         printf("fork error
    "
    ); 
  192.         return
  193.     } 
  194.     switch(how) { 
  195.         case 0: 
  196.             /* pid 0 ,  */ 
  197.             /*  >、 
  198.             if (pid == 0) { 
  199.                 if ( !(find_command(arg[0])) ) { 
  200.                     printf("%s : command not found
    "
    , arg[0]); 
  201.                     exit (0); 
  202.                 } 
  203.                 execvp(arg[0], arg); 
  204.                 exit(0); 
  205.             } 
  206.             break
  207.         case 1: 
  208.             /*  > */ 
  209.             if (pid == 0) { 
  210.                 if ( !(find_command(arg[0])) ) { 
  211.                     printf("%s : command not found
    "
    ,arg[0]); 
  212.                     exit(0); 
  213.                 } 
  214.                 fd = open(file,O_RDWR|O_CREAT|O_TRUNC,0644); 
  215.                 dup2(fd,1); 
  216.                 execvp(arg[0],arg); 
  217.                 exit(0); 
  218.             } 
  219.             break
  220.         case 2: 
  221.             /*   
  222.             if (pid == 0) { 
  223.                 if ( !(find_command (arg[0])) ) { 
  224.                     printf("%s : command not found
    "
    ,arg[0]); 
  225.                     exit(0); 
  226.                 } 
  227.                 fd = open(file,O_RDONLY); 
  228.                 dup2(fd,0); 
  229.                 execvp(arg[0],arg); 
  230.                 exit(0); 
  231.             } 
  232.             break
  233.         case 3: 
  234.             /*  | */ 
  235.             if(pid == 0) { 
  236.                 int  pid2; 
  237.                 int  status2; 
  238.                 int  fd2; 
  239.                 if ( (pid2 = fork()) 
  240.                     printf("fork2 error
    "
    ); 
  241.                     return
  242.                 } 
  243.                 else if (pid2==0) { 
  244.                     if ( !(find_command(arg[0])) ) { 
  245.                         printf("%s : command not found
    "
    ,arg[0]); 
  246.                         exit(0); 
  247.                     } 
  248.                     fd2 = open("/tmp/youdonotknowfile"
  249.                             O_WRONLY|O_CREAT|O_TRUNC,0644); 
  250.                     dup2(fd2, 1); 
  251.                     execvp(arg[0], arg); 
  252.                     exit(0); 
  253.                 } 
  254.                 if (waitpid(pid2, &status2, 0) == -1) 
  255.                     printf("wait for child process error
    "
    ); 
  256.                 if ( !(find_command(argnext[0])) ) { 
  257.                     printf("%s : command not found
    "
    ,argnext[0]); 
  258.                     exit(0); 
  259.                 } 
  260.                 fd2 = open("/tmp/youdonotknowfile",O_RDONLY); 
  261.                 dup2(fd2,0); 
  262.                 execvp (argnext[0],argnext); 
  263.                 if ( remove("/tmp/youdonotknowfile") ) 
  264.                     printf("remove error
    "
    ); 
  265.                 exit(0); 
  266.             } 
  267.             break
  268.         default
  269.             break
  270.     } 
  271.     /*  &, ,  */ 
  272.     if ( background == 1 ) { 
  273.         printf("[process id %d]
    "
    ,pid); 
  274.         return ; 
  275.     } 
  276.     /*   */ 
  277.     if (waitpid (pid, &status,0) == -1) 
  278.         printf("wait for child process error
    "
    ); 
  279.   
  280. /*   */ 
  281. int find_command (char *command) 
  282.     DIR*             dp; 
  283.     struct dirent*   dirp; 
  284.     char *path[] = { "./""/bin""/usr/bin", NULL}; 
  285.     /*  , "./fork"  */ 
  286.     if( strncmp(command,"./",2) == 0 ) 
  287.         command = command + 2; 
  288.     /*  、/bin /usr/bin  */ 
  289.     int i = 0; 
  290.     while (path[i] != NULL) { 
  291.         if ( (dp = opendir(path[i]) ) == NULL) 
  292.             printf ("can not open /bin 
    "
    ); 
  293.         while ( (dirp = readdir(dp)) != NULL) { 
  294.             if (strcmp(dirp->d_name,command) == 0) { 
  295.                 closedir(dp); 
  296.                 return 1; 
  297.             } 
  298.         } 
  299.         closedir (dp); 
  300.         i++; 
  301.     } 
  302.     return 0; 
 다음 코드 는 제 가 직접 쓴 것 입 니 다. cd, kill 과 같은 신호 와 일부 내부 명령 을 실 현 했 습 니 다.
 
   
   
   
   
  1. /********************************************************** 
  2. , ,  
  3.  
  4. ls 
  5. ls & 
  6. ls -l 
  7. ls > in 
  8. cat  out 
  9. ls | cat 
  10. cd .. 
  11. cd / 
  12. kill -9 pid 
  13. ***********************************************************/ 
  14. #include  
  15. #include  
  16. #include  
  17. #include  
  18. #include  
  19. #include  
  20. #include  
  21. #include  
  22. #include  
  23. #include  
  24. #include  
  25. #include  
  26. #include  
  27. #include  
  28. #define M 1024 
  29.  
  30. void intHandler()// ctrl-c  
  31.     printf("
    "
    ); 
  32.  
  33. int main() 
  34.     int i,j,n; 
  35.     int flag_back,flag_in,flag_out,flag_pipe,pid,fd_in,fd_out,status,pid2,status2,fd2;// : , , , ,  
  36.     char command[M],path[M],*usr,*com[M],*buf,outfile[M],infile[M],*com2[M]; 
  37.     while(1) 
  38.     { 
  39.         signal(SIGINT,intHandler);// ctrl-c 
  40.         if((usr=getlogin()) == NULL)//  
  41.         { 
  42.             exit(0); 
  43.         } 
  44.         printf("%s:",usr); 
  45.  
  46.         if(getcwd(path,sizeof(path)-1) == NULL)//  
  47.         { 
  48.             exit(0); 
  49.         } 
  50.         printf("%s",path); 
  51.         printf(">"); 
  52.         memset(command,0,sizeof(command));//  
  53.         memset(com,0,sizeof(com)); 
  54.         memset(com2,0,sizeof(com2)); 
  55.         flag_back=0; 
  56.         flag_in=0; 
  57.         flag_out=0; 
  58.         flag_pipe=0; 
  59.         n=0; 
  60.  
  61.         gets(command);//  
  62.  
  63.         buf=strtok(command," ");// ,  
  64.         while( buf!= NULL ) 
  65.         { 
  66.             com[n]=buf; 
  67.             n++; 
  68.             buf=strtok(NULL," "); 
  69.         } 
  70.  
  71.         if (!strcmp(com[0],"cd"))// cd 
  72.         { 
  73.             if (n != 1) 
  74.             { 
  75.                 chdir(com[1]); 
  76.             } 
  77.         } 
  78.         else if (!strcmp(com[0],"kill"))// kill, kill -9 pid  
  79.         { 
  80.             kill(atoi(com[2]),atoi(com[1]+1)); 
  81.         } 
  82.     else if (!strcmp(command,"exit")||!strcmp(command,"logout"))//  
  83.         { 
  84.             break
  85.         } 
  86.         else if (!strcmp(command,""))//  
  87.         { 
  88.             continue
  89.         } 
  90.         else 
  91.         { 
  92.             for ( i = 0; i 
  93.             { 
  94.                 if (!strcmp(com[i],"&"))//  
  95.                 { 
  96.                     flag_back=1; 
  97.                     for ( j = i; j 
  98.                     { 
  99.                         com[j]=com[j+1]; 
  100.                     } 
  101.                     com[n-1]=NULL; 
  102.                     n--; 
  103.                     i--; 
  104.                 } 
  105.                 else if (!strcmp(com[i],">"))//  
  106.                 { 
  107.                     flag_out=1; 
  108.                     strcpy(outfile,com[i+1]); 
  109.                     for ( j = i; j 
  110.                     { 
  111.                         com[j]=com[j+2]; 
  112.                     } 
  113.                     com[n-2]=NULL; 
  114.                     n-=2; 
  115.                     i--; 
  116.                 } 
  117.                 else if (!strcmp(com[i],"))//  
  118.                 { 
  119.                     flag_in=1; 
  120.                     strcpy(infile,com[i+1]); 
  121.                     for ( j = i; j 
  122.                     { 
  123.                         com[j]=com[j+2]; 
  124.                     } 
  125.                     com[n-2]=NULL; 
  126.                     n-=2; 
  127.                     i--; 
  128.                 } 
  129.                 else if (!strcmp(com[i],"|"))//  
  130.                 { 
  131.                     flag_pipe=1; 
  132.                     for ( j = 0; j 
  133.                     { 
  134.                         com2[j]=com[j]; 
  135.                     } 
  136.                     com2[i]=NULL; 
  137.                     for ( j = 0; j 
  138.                     { 
  139.                         com[j]=com[j+i+1]; 
  140.                     } 
  141.                     com[n-i-1]=NULL; 
  142.                     break
  143.                 } 
  144.             } 
  145.             if ( (pid = fork()) //  
  146.             { 
  147.                 printf("fork error
    "
    ); 
  148.                 return
  149.             } 
  150.             if (!pid) 
  151.             { 
  152.                 if (flag_out) 
  153.                 { 
  154.                     fd_out = open(outfile,O_RDWR|O_CREAT|O_TRUNC,0644);//  
  155.                     dup2(fd_out,1); 
  156.                 } 
  157.                 if (flag_in) 
  158.                 { 
  159.                     fd_in = open(infile,O_RDONLY);//  
  160.                     dup2(fd_in,0); 
  161.                 } 
  162.                 if (flag_pipe) 
  163.                 { 
  164.                     if ( (pid2 = fork()) //  
  165.                     { 
  166.                         printf("fork2 error
    "
    ); 
  167.                         return
  168.                     } 
  169.                     else if (!pid2) 
  170.                     { 
  171.                         fd2 = open("/tmp/wb",O_WRONLY|O_CREAT|O_TRUNC,0644);//  
  172.                         dup2(fd2,1); 
  173.                         execvp(com2[0],com2); 
  174.                         exit(0); 
  175.                     } 
  176.                     if (waitpid(pid2, &status2, 0) == -1) 
  177.                     { 
  178.                         //printf("wait for child process error
    ");
     
  179.                     } 
  180.                     fd2 = open("/tmp/wb",O_RDONLY); 
  181.                     dup2(fd2,0); 
  182.                 } 
  183.                 execvp(com[0],com);//  
  184.                 remove("/tmp/wb"); 
  185.                 exit(0); 
  186.             } 
  187.             else 
  188.             { 
  189.                 if (flag_back) 
  190.                 { 
  191.                     printf("[process id %d]
    "
    ,pid);// ,  
  192.                     continue
  193.                 } 
  194.                 else 
  195.                 { 
  196.                     if (waitpid (pid,&status,0) == -1) 
  197.                     { 
  198.                         //printf("wait for child process error
    ");
     
  199.                     } 
  200.                 } 
  201.             } 
  202.         } 
  203.     } 
  204.     return 0; 

좋은 웹페이지 즐겨찾기