linux内核实验二实现过程

来源:互联网 发布:淘宝2015年销售总额 编辑:程序博客网 时间:2024/06/08 05:43
linux内核实验two实现过程#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/wait.h>#include <fcntl.h>#include <sys/stat.h>#include <dirent.h>#define normal         0 /*一般的命令*/#define out_redirect   1 /*输出重定向*/#define in_redirect    2 /*输入重定向*/#define have_pipe      3 /*命令中有管道*/int commandcounts=0;/*命令条数*/void print_prompt();                           /*打印提示符*/void get_input(char *);                        /*得到输入的命令*/void explain_input(char *,int *,char a[100][256]);   /*对输入命令进行解析*/void do_cmd(int ,char a[100][256]);                  /*执行命令*/int find_command(char *);                      /*查找命令中的可执行程序*/int main(int argc,char **argv){    int i;    int argcount = 0;    char arglist[100][256];    char **arg = NULL;    char *buf = NULL;    buf = (char *)malloc(256);    if (buf == NULL){        perror("malloc failed");        exit(-1);    }    char* commands[10];    while(1){        /*将buf所指向的空间清零*/        memset(buf,0,256);        print_prompt();        get_input(buf);        /*若输入的命令为exit或logout则退出本程序*/        if (strcmp(buf,"exit\n") == 0 || strcmp(buf,"logout\n") == 0)          break;        //找出有几条命令,多条命令以分号分割        int index=0;        commandcounts=1;        for(index=0;index<strlen(buf);index++){            if(buf[index]==';')                commandcounts++;                    }        if(commandcounts>10){            printf("%s\n","commandcounts over.max num is 10");            continue;        }        index=0;        char *p=strtok(buf,";");        do{            commands[index]=p;            index++;        }        while(p=strtok(NULL,";"));        for(index=0;index<commandcounts;index++){            for (i=0;i<100;i++){                  arglist[i][0] = '\0';            }            argcount = 0;            explain_input(commands[index],&argcount,arglist);            do_cmd(argcount,arglist);        }            }    if (buf != NULL){        free(buf);        buf = NULL;    }    exit(0);}void print_prompt(){    printf("myshell$$");}/*获取用户输入*/void get_input(char *buf){    int len = 0;    int ch;    ch = getchar();    while (len <256 && ch != '\n'){        buf[len++] = ch;        ch = getchar();    }    if (len ==256){        printf("commond is too long \n");        exit(-1); /*输入的命令过长则退出程序*/    }    buf[len] = '\n';    len++;    buf[len] = '\0';}/*解析buf中的命令,将结果存入arglist中,命令以回车符号\n结束*//*如输入命令为“ls -l /tmp”,则arglist[0],arglist[1],arglist[2]分别为ls,-l和/tmp*/void explain_input(char *buf,int *argcount,char arglist[100][256]){    char *p = buf;    char *q = buf;    int number = 0;    while(1){        if (p[0] == '\n')          break;        if (p[0] == ' ')          p++;        else {          q = p;          number = 0;          while ((q[0] != ' ') && (q[0] != '\n')){              number++;              q++;          }          strncpy(arglist[*argcount],p,number+1);          arglist[*argcount][number] = '\0';          *argcount = *argcount + 1;          p = q;        }    }}void do_cmd (int argcount,char arglist[100][256]){    int flag = 0;    int how = 0;           /*用于指示命令中是否含有>,<,|*/    int background = 0;    /*标识命令中是否有后台运行标识符*/    int status;    int i;    int fd;    char *arg[argcount+1];    char *argnext[argcount+1];    char *file;    pid_t pid;    /*将命令取出*/    for (i=0;i<argcount;i++){        arg[i] = (char *)arglist[i];    }    arg[argcount] = NULL;    /*查看命令行是否有后台运行符*/    for (i=0;i<argcount;i++){        if (strncmp(arg[i],"&",1) == 0){          if (i == argcount - 1){            background = 1;            arg[argcount-1] = NULL;            break;          }          else {            printf("wrong command\n");            return;          }        }    }    for (i=0;arg[i] != NULL;i++){        if (strcmp(arg[i],">") == 0){            flag++;            how = out_redirect;            if (arg[i+1] == NULL)                flag++;        }        if (strcmp(arg[i],"<") == 0){            flag++;            how = in_redirect;            if (i == 0)                flag++;        }        if (strcmp(arg[i],"|") == 0){          flag++;          how = have_pipe;          if (arg[i+1] == NULL)              flag++;          if (i == 0)              flag++;        }    }    /*flag大于1,说明命令中含有多个>,<,|符号,本程序是不支持这样的命令的,        或者命令格式不对,如“ls -l /tmp >”*/    if (flag > 1){        printf("wrong command\n");        return;    }    if (how == out_redirect){/*命令只含有一个输出重定向符号>*/        for (i=0;arg[i] != NULL;i++){          if (strcmp(arg[i],">") == 0){            file = arg[i+1];            arg[i] = NULL;          }        }    }    if (how == in_redirect){/*命令只含有一个输入重定向符号<*/        for (i=0;arg[i] != NULL;i++){          if (strcmp(arg[i],"<") == 0){            file = arg[i+1];            arg[i] = NULL;          }        }    }    if (how == have_pipe){/*命令只含有一个管道符号|*/        /*把管道符号后面的部分存入argnext中,管道后面的部分是一个可执行的Shell命令*/        for (i=0;arg[i] != NULL;i++){          if (strcmp(arg[i],"|") == 0){            arg[i] = NULL;            int j;            for (j=i+1;arg[j] != NULL;j++){                argnext[j-i-1] =arg[j];            }            argnext[j-i-1] = arg[j];            break;          }        }    }    if ((pid = fork()) < 0) {        printf("fork error\n");        return;    }    switch(how) {        case 0:          /*pid为0说明是子进程,在子进程中执行输入的命令*/          /*输入的命令中不含>,<和|*/          if (pid == 0){            if (!(find_command(arg[0]))){            printf("%s:command not found\n",arg[0]);            exit(0);            }            execvp(arg[0],arg);            exit(0);          }          break;        case 1:          if (pid == 0){            if (!(find_command(arg[0]))){                printf("%s: commandnot found\n",arg[0]);                exit(0);            }            fd = open(file,O_RDWR|O_CREAT|O_TRUNC,0644);            dup2(fd,1);            execvp(arg[0],arg);            exit(0);          }          break;        case 2:          /*输入的命令中含有重定向符<*/          if (pid == 0){            if (!(find_command(arg[0]))){                printf("%s:command not found\n",arg[0]);                exit(0);            }            fd = open(file,O_RDONLY);            dup2(fd,0);            execvp(arg[0],arg);            exit(0);          }          break;        case 3:          /*输入的命令中含有管道*/          if (pid == 0){            int pid2;            int status2;            int fd2;            if ((pid2 = fork()) < 0){                printf("fork2 error\n");                return;            }            else if (pid2 == 0){                if (!(find_command(arg[0]))){                    printf("%s:command not found\n",arg[0]);                    exit(0);                }                fd2 = open("/tmp/youdonotknowfile",O_WRONLY|O_CREAT|O_TRUNC,0644);                dup2(fd2,1);                execvp(arg[0],arg);                exit(0);//子进程在此退出            }            //父进程在此执行            if (waitpid(pid2,&status2,0) == -1)                printf("wait for child process error\n");            if (!(find_command(argnext[0]))){                printf("%s:command not found\n",argnext[0]);                exit(0);            }            fd2 = open("/tmp/youdonotknowfile",O_RDONLY);            dup2(fd2,0);            execvp(argnext[0],argnext);            if (remove("/tmp/youdonotknowfile"))            printf("remove error\n");            exit(0);          }          break;        default:          break;    }    /*若命令中有&,表示后台执行,父进程直接返回,不等待子进程结束*/    if (background == 1){        printf("[process id %d]\n",pid);        return;    }    /*父进程等待子进程结束*/    if (waitpid(pid,&status,0) == -1)        printf("wait for child process error\n");}/* * 产看这个命令是否存在 */int find_command(char *command){    DIR *dp;    struct dirent *dirp;    char *path[] = {"./","/bin","/usr/bin",NULL};    /*使当前目录下的程序可以运行,如命令"./fork"可以被正确解释和执行*/    if (strncmp(command,"./",2) == 0)        command = command + 2;    /*分别在当前目录、/bin和/usr/bin目录查找要执行的程序*/    int i = 0;    while (path[i] != NULL){        if ((dp = opendir(path[i])) == NULL)          printf("can not open /bin \n");        while((dirp = readdir(dp))!= NULL){//读目录中的所有的文件          if (strcmp(dirp->d_name,command) == 0){//有这个文件            closedir(dp);            return 1;          }        }        closedir(dp);        i++;    }    return 0;}