zoukankan      html  css  js  c++  java
  • 自己写的shell程序 多层管道、重定向、后台、命令历史

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<fcntl.h>
    #include<string.h>
    #include<stdbool.h>
    #include<signal.h>
    #include <readline/readline.h>
    #include <readline/history.h>
    //#include<errno.h>
    //#include<sys/stat.h>

    #define MAX_LINE_SIZE 100
    #define MAX_ARGC 20 //最多20个参数
    #define MAX_ARGLEN 50  //每个参数最大长度
    #define MAX_FILE_NAME 100
    #define FIFO "/tmp/my_fifo"

    FILE *his;
    char *temp,*temp1,*fileName;
    static char *line_read = (char *)NULL;
    char* nextcmd;
    char *argv[MAX_ARGC];
    unsigned char argc=0;
    bool is_pipe;
    char buf[1000];
    bool is_bg;
    bool fromsigc = false;

    void sig_child(int n){}

    void sig_C(int n)
    {
     printf("\n[COMMAND_LINE_$] ");
     fflush(stdout); 
     fromsigc = true;
     return;
    }

    //提取参数
    void divArgs(char* argv[],char* cmd)
    {
     int argc=0;
     while((argv[argc] = (char*)malloc(sizeof(char)*MAX_ARGLEN)) &&
        EOF!=sscanf(cmd,"%s",argv[argc]) && argc<=MAX_ARGC)
      {
       while(isspace(cmd[0])) cmd++;
       cmd+=strlen(argv[argc++]);
      }
      argv[argc] = NULL;
      
    }
    //输入命令

    char *rl_gets()
    {
     if(line_read)
     {      
      free (line_read);
      line_read = (char *)NULL;
     }
     if(fromsigc)
      line_read = readline(NULL);
     else
      line_read = readline("[COMMAND_LINE_$] ");
     fromsigc = false;

     if(line_read && *line_read)
      add_history(line_read);
     return(line_read);
    }

    void trim_tail(char* str)
    {
     int i=strlen(str)-1;
     for(;isspace(str[i]);str[i--]='\0');
    }

    char* trim(char* str)
    {
     while(isspace(*str))
      str++;
     trim_tail(str);
     return str;
    }

    bool isbg(char* str)
    {
     bool flag = false;
     int i=strlen(str)-1;
     for(;isspace(str[i]) || str[i]=='&';str[i--]='\0')
      if(str[i]=='&')
       flag = true;
     return flag;
    }

    void div_and_deal(char* str,char* delim,void (*fn)(void*))
    {
     char *token=0;
     for(token=strtok(str,delim);token!=NULL;token=strtok(NULL,delim))
     {
      (*fn)(token);
     }
    }

    bool deal_redirect(char* cmd, int *rd, int *in, int *out)
    {
     char *p;
     int i=0;
     //  rd: null:0    <:1     >>2     >3
     while((p=strchr(cmd,'<')) || (p=strchr(cmd,'>'))){
      i = 0;
      *rd = 3;
      if(p[0]=='<')
       *rd = 1;
      *p++ = ' ';
      if((*rd !=1) && (p[0]=='>')){
       *rd = 2;
       *p++ = ' ';
      }
      while(isspace(*p)) p++;
      if(!p)
       return false;
      char fp[MAX_FILE_NAME];
      while(p && *p!='\0' && *p!='>' && *p!='<' && !isspace(*p)){
       fp[i++] = *p;
       *p++ = ' ';
      }
      fp[i]='\0';
      if(*rd == 1)
       *in = open(fp,O_RDONLY);
      else if(*rd == 2)
       *out = open(fp,O_WRONLY | O_CREAT | O_APPEND,0664);
      else
       *out = open(fp,O_WRONLY | O_CREAT | O_TRUNC,0664);
     }
    }

    void execute(char* cmd,int in, int out)
    {
     pid_t pid,pid1,pid2;
     char *cmd1,*cmd2,*p;
     int fd;
     int status;
     int rd = 0;

     if(p=strchr(cmd,'|'))
     {
      cmd1=cmd;
      cmd2=p+1;
      *p='\0';

      deal_redirect(cmd1, &rd, &in, &out);

      divArgs(argv,cmd1);
      unlink(FIFO);
      mkfifo(FIFO, 0666);
         
      if((pid1=fork())==0){
       fd=open(FIFO,O_WRONLY);
       dup2(fd,STDOUT_FILENO);
       dup2(in,STDIN_FILENO);
       dup2(out,STDOUT_FILENO);
       if(execvp(argv[0],argv)<0){
        printf("cmd error!\n");
        close(fd);
       }
      }else{
       if((pid1=fork())==0){
        fd = open(FIFO, O_RDONLY);
        if(rd != 2 && rd != 3)
         in = fd;
        execute(cmd2,in,STDOUT_FILENO);
        close(fd);
        exit(0);
       }else{
        if(!is_bg){
         waitpid(pid1,&status,0);
         waitpid(pid2,&status,0);
        }
       }
      }

     }else{
      deal_redirect(cmd, &rd, &in, &out);
      divArgs(argv,cmd);
      if((pid=fork())==0){
       dup2(in,STDIN_FILENO);
       dup2(out,STDOUT_FILENO);
       if(execvp(argv[0],argv)<0){
        printf("error\n");
        exit(-1);
       }
      }else{
       if(!is_bg)
        waitpid(pid,&status,0);
      }
     }
     if(in != STDIN_FILENO) close(in);
     if(out != STDOUT_FILENO) close(out);
     for(argc;argc>0;free(argv[argc]))argc--;
     
    }

    void execmd(char* cmd)
    {
     //bg
     is_bg = isbg(cmd);
     char* command = strdup(cmd);
     execute(command,STDIN_FILENO,STDOUT_FILENO);
    }

    int main()
    {
     signal(SIGINT,sig_C);
     signal(SIGCHLD,sig_child);
     printf("*************shell*************\n");
     while(true)
     {
      char * line_=trim(rl_gets());
      //退出
      if(!strcmp(line_,"exit"))
      {
       break; 
      }
      //没有输入
      if(line_[0]=='\0')
      {
       continue;
      }
      temp1=temp = strdup(line_);
      //执行
      div_and_deal(temp,";",(void (*)(void*))execmd);
      free(temp1);
     }
     return 0;
    }

    readline 库的使用方法:http://www.cnblogs.com/pswzone/archive/2012/04/14/2446796.html

  • 相关阅读:
    CDZSC_2015寒假新人(4)——搜索 A
    第一次组队赛---2010年全国大学生程序设计邀请赛(福州)L
    ZSC新生赛 沼跃鱼早已看穿了一切
    ZSC新生赛 聪明的员工
    CDZSC_2015寒假新人(1)——基础 I
    Linux 系统时间和硬件时间
    Python 深浅复制
    Python 函数内省
    Python 函数参数
    Python 可调用对象
  • 原文地址:https://www.cnblogs.com/pswzone/p/2447409.html
Copyright © 2011-2022 走看看