셸 의 실현

오늘 큰 작업 을 완성 하고 있 습 니 다. 주요 임 무 는 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. { 
  23.     int    i; 
  24.     int    argcount = 0; 
  25.     char   arglist[100][256]; 
  26.     //char   **arg = NULL; 
  27.     char   *buf  = NULL; 
  28.     buf = (char *)malloc(256); 
  29.     if( buf == NULL ) { 
  30.         perror("malloc failed"); 
  31.         exit(-1); 
  32.     } 
  33.     while(1) { 
  34.         /*  buf  */ 
  35.         memset(buf, 0, 256); 
  36.         print_prompt(); 
  37.         get_input(buf); 
  38.         /*  exit logout  */ 
  39.         if( strcmp(buf,"exit
    "
    ) == 0 || strcmp(buf,"logout
    "
    ) == 0 ) 
  40.             break; 
  41.         for (i=0; i 
  42.         { 
  43.             arglist[i][0]='\0'; 
  44.   
  45.         } 
  46.         argcount = 0; 
  47.         explain_input(buf, &argcount, arglist); 
  48.         do_cmd(argcount, arglist);   
  49.   
  50.     } 
  51.     if(buf != NULL) { 
  52.         free(buf); 
  53.         buf = NULL; 
  54.     } 
  55.     exit(0); 
  56. } 
  57.   
  58. void print_prompt() 
  59. { 
  60.     printf("myshell$$ "); 
  61. } 
  62.   
  63. /* */ 
  64. void get_input(char *buf) 
  65. { 
  66.     int len = 0; 
  67.     int ch; 
  68.     ch = getchar(); 
  69.     while (len '
    '
    ) { 
  70.         buf[len++] = ch; 
  71.         ch = getchar(); 
  72.     } 
  73.     if(len == 256) { 
  74.         printf("command is too long 
    "
    ); 
  75.         exit(-1); /*   */ 
  76.     } 
  77.     buf[len] = '
    '
    ; 
  78.     len++; 
  79.     buf[len] = '\0';         
  80.   
  81. } 
  82.   
  83. /*  buf , arglist ,
     */
     
  84. /*  "ls -l /tmp", arglist[0]、arglist[1]、arglsit[2] ls、-l /tmp */ 
  85. void explain_input(char *buf, int *argcount, char arglist[100][256]) 
  86. { 
  87.     char    *p  = buf; 
  88.     char    *q  = buf; 
  89.     int number  = 0; 
  90.     while (1) { 
  91.         if ( p[0] == '
    '
     ) 
  92.             break; 
  93.         if ( p[0] == ' '  ) 
  94.             p++; 
  95.         else { 
  96.             q = p; 
  97.             number = 0; 
  98.             while( (q[0]!=' ') && (q[0]!='
    '
    ) ) { 
  99.                 number++; 
  100.                 q++; 
  101.             } 
  102.             strncpy(arglist[*argcount], p, number+1); 
  103.             arglist[*argcount][number] = '\0'; 
  104.             *argcount = *argcount + 1; 
  105.             p = q; 
  106.         } 
  107.     } 
  108. } 
  109.   
  110. void do_cmd(int argcount, char arglist[100][256]) 
  111. { 
  112.     int flag = 0; 
  113.     int how = 0;        /*  >、 
  114.     int background = 0; /*  & */ 
  115.     int status; 
  116.     int i; 
  117.     int fd; 
  118.     char*   arg[argcount+1]; 
  119.     char*   argnext[argcount+1]; 
  120.     char*   file; 
  121.     pid_t   pid; 
  122.     /* */ 
  123.     for (i=0; i 
  124.         arg[i] = (char *) arglist[i]; 
  125.     } 
  126.     arg[argcount] = NULL; 
  127.     /* */ 
  128.     for (i=0; i 
  129.         if (strncmp(arg[i], "&",1) == 0) { 
  130.             if (i == argcount-1) { 
  131.                 background = 1; 
  132.                 arg[argcount-1] = NULL; 
  133.                 break; 
  134.             } 
  135.             else { 
  136.                 printf("wrong command
    "
    ); 
  137.                 return ; 
  138.             } 
  139.         } 
  140.     } 
  141.     for (i=0; arg[i]!=NULL; i++) { 
  142.         if (strcmp(arg[i], ">") == 0 ) { 
  143.             flag++; 
  144.             how = out_redirect; 
  145.             if (arg[i+1] == NULL) 
  146.                 flag++; 
  147.         } 
  148.         if ( strcmp(arg[i],") == 0 ) { 
  149.             flag++; 
  150.             how = in_redirect; 
  151.             if(i == 0) 
  152.                 flag++; 
  153.         } 
  154.         if ( strcmp(arg[i],"|")==0 ) { 
  155.             flag++; 
  156.             how = have_pipe; 
  157.             if(arg[i+1] == NULL) 
  158.                 flag++; 
  159.             if(i == 0 ) 
  160.                 flag++; 
  161.         } 
  162.     } 
  163.     /* flag 1, > , 
  164.         , "ls -l /tmp >" */ 
  165.     if (flag > 1) { 
  166.         printf("wrong command
    "
    ); 
  167.         return; 
  168.     } 
  169.     if (how == out_redirect) {  /* > */ 
  170.         for (i=0; arg[i] != NULL; i++) { 
  171.             if (strcmp(arg[i],">")==0) { 
  172.                 file   = arg[i+1]; 
  173.                 arg[i] = NULL; 
  174.             } 
  175.         } 
  176.     } 
  177.     if (how == in_redirect) {    /*  
  178.         for (i=0; arg[i] != NULL; i++) { 
  179.             if (strcmp (arg[i],") == 0) { 
  180.                 file   = arg[i+1]; 
  181.                 arg[i] = NULL; 
  182.             } 
  183.         } 
  184.     } 
  185.     if (how == have_pipe) {  /*  | */ 
  186. /*  argnext , shell  */ 
  187.         for (i=0; arg[i] != NULL; i++) { 
  188.             if (strcmp(arg[i],"|")==0) { 
  189.                 arg[i] = NULL; 
  190.                 int j; 
  191.                 for (j=i+1; arg[j] != NULL; j++) { 
  192.                     argnext[j-i-1] = arg[j]; 
  193.                 } 
  194.                 argnext[j-i-1] = arg[j]; 
  195.                 break; 
  196.             } 
  197.         } 
  198.     } 
  199.     if ( (pid = fork()) 
  200.         printf("fork error
    "
    ); 
  201.         return; 
  202.     } 
  203.     switch(how) { 
  204.         case 0: 
  205.             /* pid 0 ,  */ 
  206.             /*  >、 
  207.             if (pid == 0) { 
  208.                 if ( !(find_command(arg[0])) ) { 
  209.                     printf("%s : command not found
    "
    , arg[0]); 
  210.                     exit (0); 
  211.                 } 
  212.                 execvp(arg[0], arg); 
  213.                 exit(0); 
  214.             } 
  215.             break; 
  216.         case 1: 
  217.             /*  > */ 
  218.             if (pid == 0) { 
  219.                 if ( !(find_command(arg[0])) ) { 
  220.                     printf("%s : command not found
    "
    ,arg[0]); 
  221.                     exit(0); 
  222.                 } 
  223.                 fd = open(file,O_RDWR|O_CREAT|O_TRUNC,0644); 
  224.                 dup2(fd,1); 
  225.                 execvp(arg[0],arg); 
  226.                 exit(0); 
  227.             } 
  228.             break; 
  229.         case 2: 
  230.             /*   
  231.             if (pid == 0) { 
  232.                 if ( !(find_command (arg[0])) ) { 
  233.                     printf("%s : command not found
    "
    ,arg[0]); 
  234.                     exit(0); 
  235.                 } 
  236.                 fd = open(file,O_RDONLY); 
  237.                 dup2(fd,0); 
  238.                 execvp(arg[0],arg); 
  239.                 exit(0); 
  240.             } 
  241.             break; 
  242.         case 3: 
  243.             /*  | */ 
  244.             if(pid == 0) { 
  245.                 int  pid2; 
  246.                 int  status2; 
  247.                 int  fd2; 
  248.                 if ( (pid2 = fork()) 
  249.                     printf("fork2 error
    "
    ); 
  250.                     return; 
  251.                 } 
  252.                 else if (pid2==0) { 
  253.                     if ( !(find_command(arg[0])) ) { 
  254.                         printf("%s : command not found
    "
    ,arg[0]); 
  255.                         exit(0); 
  256.                     } 
  257.                     fd2 = open("/tmp/youdonotknowfile", 
  258.                             O_WRONLY|O_CREAT|O_TRUNC,0644); 
  259.                     dup2(fd2, 1); 
  260.                     execvp(arg[0], arg); 
  261.                     exit(0); 
  262.                 } 
  263.                 if (waitpid(pid2, &status2, 0) == -1) 
  264.                     printf("wait for child process error
    "
    ); 
  265.                 if ( !(find_command(argnext[0])) ) { 
  266.                     printf("%s : command not found
    "
    ,argnext[0]); 
  267.                     exit(0); 
  268.                 } 
  269.                 fd2 = open("/tmp/youdonotknowfile",O_RDONLY); 
  270.                 dup2(fd2,0); 
  271.                 execvp (argnext[0],argnext); 
  272.                 if ( remove("/tmp/youdonotknowfile") ) 
  273.                     printf("remove error
    "
    ); 
  274.                 exit(0); 
  275.             } 
  276.             break; 
  277.         default: 
  278.             break; 
  279.     } 
  280.     /*  &, ,  */ 
  281.     if ( background == 1 ) { 
  282.         printf("[process id %d]
    "
    ,pid); 
  283.         return ; 
  284.     } 
  285.     /*   */ 
  286.     if (waitpid (pid, &status,0) == -1) 
  287.         printf("wait for child process error
    "
    ); 
  288. } 
  289.   
  290. /*   */ 
  291. int find_command (char *command) 
  292. { 
  293.     DIR*             dp; 
  294.     struct dirent*   dirp; 
  295.     char *path[] = { "./", "/bin", "/usr/bin", NULL}; 
  296.     /*  , "./fork"  */ 
  297.     if( strncmp(command,"./",2) == 0 ) 
  298.         command = command + 2; 
  299.     /*  、/bin /usr/bin  */ 
  300.     int i = 0; 
  301.     while (path[i] != NULL) { 
  302.         if ( (dp = opendir(path[i]) ) == NULL) 
  303.             printf ("can not open /bin 
    "
    ); 
  304.         while ( (dirp = readdir(dp)) != NULL) { 
  305.             if (strcmp(dirp->d_name,command) == 0) { 
  306.                 closedir(dp); 
  307.                 return 1; 
  308.             } 
  309.         } 
  310.         closedir (dp); 
  311.         i++; 
  312.     } 
  313.     return 0; 
  314. } 
 다음 코드 는 제 가 직접 쓴 것 입 니 다. 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. { 
  32.     printf("
    "
    ); 
  33. } 
  34.  
  35. int main() 
  36. { 
  37.     int i,j,n; 
  38.     int flag_back,flag_in,flag_out,flag_pipe,pid,fd_in,fd_out,status,pid2,status2,fd2;// : , , , ,  
  39.     char command[M],path[M],*usr,*com[M],*buf,outfile[M],infile[M],*com2[M]; 
  40.     while(1) 
  41.     { 
  42.         signal(SIGINT,intHandler);// ctrl-c 
  43.         if((usr=getlogin()) == NULL)//  
  44.         { 
  45.             exit(0); 
  46.         } 
  47.         printf("%s:",usr); 
  48.  
  49.         if(getcwd(path,sizeof(path)-1) == NULL)//  
  50.         { 
  51.             exit(0); 
  52.         } 
  53.         printf("%s",path); 
  54.         printf(">"); 
  55.         memset(command,0,sizeof(command));//  
  56.         memset(com,0,sizeof(com)); 
  57.         memset(com2,0,sizeof(com2)); 
  58.         flag_back=0; 
  59.         flag_in=0; 
  60.         flag_out=0; 
  61.         flag_pipe=0; 
  62.         n=0; 
  63.  
  64.         gets(command);//  
  65.  
  66.         buf=strtok(command," ");// ,  
  67.         while( buf!= NULL ) 
  68.         { 
  69.             com[n]=buf; 
  70.             n++; 
  71.             buf=strtok(NULL," "); 
  72.         } 
  73.  
  74.         if (!strcmp(com[0],"cd"))// cd 
  75.         { 
  76.             if (n != 1) 
  77.             { 
  78.                 chdir(com[1]); 
  79.             } 
  80.         } 
  81.         else if (!strcmp(com[0],"kill"))// kill, kill -9 pid  
  82.         { 
  83.             kill(atoi(com[2]),atoi(com[1]+1)); 
  84.         } 
  85.     else if (!strcmp(command,"exit")||!strcmp(command,"logout"))//  
  86.         { 
  87.             break; 
  88.         } 
  89.         else if (!strcmp(command,""))//  
  90.         { 
  91.             continue; 
  92.         } 
  93.         else 
  94.         { 
  95.             for ( i = 0; i 
  96.             { 
  97.                 if (!strcmp(com[i],"&"))//  
  98.                 { 
  99.                     flag_back=1; 
  100.                     for ( j = i; j 
  101.                     { 
  102.                         com[j]=com[j+1]; 
  103.                     } 
  104.                     com[n-1]=NULL; 
  105.                     n--; 
  106.                     i--; 
  107.                 } 
  108.                 else if (!strcmp(com[i],">"))//  
  109.                 { 
  110.                     flag_out=1; 
  111.                     strcpy(outfile,com[i+1]); 
  112.                     for ( j = i; j 
  113.                     { 
  114.                         com[j]=com[j+2]; 
  115.                     } 
  116.                     com[n-2]=NULL; 
  117.                     n-=2; 
  118.                     i--; 
  119.                 } 
  120.                 else if (!strcmp(com[i],"))//  
  121.                 { 
  122.                     flag_in=1; 
  123.                     strcpy(infile,com[i+1]); 
  124.                     for ( j = i; j 
  125.                     { 
  126.                         com[j]=com[j+2]; 
  127.                     } 
  128.                     com[n-2]=NULL; 
  129.                     n-=2; 
  130.                     i--; 
  131.                 } 
  132.                 else if (!strcmp(com[i],"|"))//  
  133.                 { 
  134.                     flag_pipe=1; 
  135.                     for ( j = 0; j 
  136.                     { 
  137.                         com2[j]=com[j]; 
  138.                     } 
  139.                     com2[i]=NULL; 
  140.                     for ( j = 0; j 
  141.                     { 
  142.                         com[j]=com[j+i+1]; 
  143.                     } 
  144.                     com[n-i-1]=NULL; 
  145.                     break; 
  146.                 } 
  147.             } 
  148.             if ( (pid = fork()) //  
  149.             { 
  150.                 printf("fork error
    "
    ); 
  151.                 return; 
  152.             } 
  153.             if (!pid) 
  154.             { 
  155.                 if (flag_out) 
  156.                 { 
  157.                     fd_out = open(outfile,O_RDWR|O_CREAT|O_TRUNC,0644);//  
  158.                     dup2(fd_out,1); 
  159.                 } 
  160.                 if (flag_in) 
  161.                 { 
  162.                     fd_in = open(infile,O_RDONLY);//  
  163.                     dup2(fd_in,0); 
  164.                 } 
  165.                 if (flag_pipe) 
  166.                 { 
  167.                     if ( (pid2 = fork()) //  
  168.                     { 
  169.                         printf("fork2 error
    "
    ); 
  170.                         return; 
  171.                     } 
  172.                     else if (!pid2) 
  173.                     { 
  174.                         fd2 = open("/tmp/wb",O_WRONLY|O_CREAT|O_TRUNC,0644);//  
  175.                         dup2(fd2,1); 
  176.                         execvp(com2[0],com2); 
  177.                         exit(0); 
  178.                     } 
  179.                     if (waitpid(pid2, &status2, 0) == -1) 
  180.                     { 
  181.                         //printf("wait for child process error
    ");
     
  182.                     } 
  183.                     fd2 = open("/tmp/wb",O_RDONLY); 
  184.                     dup2(fd2,0); 
  185.                 } 
  186.                 execvp(com[0],com);//  
  187.                 remove("/tmp/wb"); 
  188.                 exit(0); 
  189.             } 
  190.             else 
  191.             { 
  192.                 if (flag_back) 
  193.                 { 
  194.                     printf("[process id %d]
    "
    ,pid);// ,  
  195.                     continue; 
  196.                 } 
  197.                 else 
  198.                 { 
  199.                     if (waitpid (pid,&status,0) == -1) 
  200.                     { 
  201.                         //printf("wait for child process error
    ");
     
  202.                     } 
  203.                 } 
  204.             } 
  205.         } 
  206.     } 
  207.     return 0; 
  208. } 

좋은 웹페이지 즐겨찾기