进程实践——myshell

来源:互联网 发布:10月份经济数据2017 编辑:程序博客网 时间:2024/05/10 13:54

要求:

解释执行命令,支持输入输出重定向,支持管道,后台运行程序。

/*************************************************************************> File Name: shell.c> Author:wyf > Mail:Catherine199787@outlook.com > Created Time: 2016年07月30日 星期六 10时54分55秒************************************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<sys/wait.h>#include<unistd.h>#include<fcntl.h>#include<stdlib.h>#include<dirent.h>#include<string.h>#include<malloc.h>#define normal 0#define out 1#define in 2#define pipe 3//自定义错误函数void err(char* err_string, int line){    perror(err_string);    fprintf(stderr, "line:%d", line);    return;}//判断命名的正确性int right(char *arg){    DIR *dir;    struct dirent* ptr;    char *path[] = {"./","/bin","/usr/bin/",NULL};   //环境变量PATH的路径    int i;    if(strncmp(arg, "./", 2) == 0){  //将路径改为当前目录        arg = arg + 2;                  //指针移到/下一个字节    }    for(i = 0; path[i] != NULL; i++){           //查找命令        dir = opendir(path[i]);        if(dir == NULL){            err("open_bin error", __LINE__);        }        while((ptr = readdir(dir)) != NULL){            if(strcmp(ptr->d_name, arg) == 0){                closedir(dir);                return 1;            }        }        closedir(dir);    }    return 0;}//管道的执行函数void argpipe(char *argn[], char *arg[]){    int pid;    int status;    int fd;    pid = fork();    if(pid < 0){        err("pipe_fork", __LINE__);    }    else if(pid == 0){        if(!right(arg[0])){            err("pipe arg", __LINE__);        }        fd = open("/tmp/youdonotknowfile", O_WRONLY | O_CREAT | O_TRUNC,0644);        dup2(fd, 1);        execvp(arg[0], arg);        exit(0);    }    if(waitpid(pid, &status, 0) == -1){        err("pipe_wait", __LINE__);    }    if(!right(argn[0])){        err("pipe_arg", __LINE__);    }    fd = open("/tmp/youdonotknowfile", O_RDONLY);    dup2(fd, 0);    execvp(argn[0], argn);    if(remove("/tmp/youdonotknowfile")){        err("remove", __LINE__);    }}//输入函数void arginput(char *buf){    int len = 0;    gets(buf);    len = strlen(buf);    if(len >= 255){        err("arginput", __LINE__);    }}//解析输入的命令void argexplain(char * buf, char arglist[][255], int *argcount){       int number = 0;    int i = 0;    while(1){        if(buf[i] == '\0'){            break;        }        else if(buf[i] != ' '){            arglist[*argcount][number] = buf[i];            number++;        }         else{            arglist[*argcount][number] = '\0';            number = 0;            *argcount = *argcount + 1;           //*argcount 为下标         }        i++;    }}//执行输入void argdo(int argcount, char arglist[][255]){    char *arg[argcount+1];    int wrong = 0;    int how = 0;    int background = 0;    int fd;    int i;    int status;    char path[100];   //各种无法清空path的缓存,有八阿哥。    char *argn[argcount+1];    pid_t pid;    for(i = 0; i <= argcount ; i++){       //准备execvp的第二个参数        arg[i] = arglist[i];    }    arg[i] = NULL;    for(i = 0; i <= argcount; i++){        if(strcmp(arg[i], "&") == 0){            if(i == (argcount - 1)){                background = 1;                arg[argcount-1] = NULL;                break;            }            else{                err("too many '&'", __LINE__);                return;            }        }          }    for(i = 0; arg[i] != NULL; i++){        if(strcmp(arg[i], ">") == 0){            wrong++;            how = out;            if(arg[i+1] == NULL){                wrong++;            }        }        else if(strcmp(arg[i], "<") == 0){            wrong++;            how = in;            if(arg[i+1] == NULL){                wrong++;            }        }        else if(strcmp(arg[i], "|") == 0){            wrong++;            how = pipe;            if(arg[i+1] == NULL){                wrong++;            }            else if(i == 0){                wrong++;            }        }    }    if(wrong > 1){                    err("too many arg", __LINE__);    }    pid = fork();    if(pid < 0){        err("fork error", __LINE__);    }    switch(how){        case 0:{            if(pid == 0){                if( !right(arg[0]) ){                //    perror("wrong arg");                    exit(0);                }                execvp(arg[0], arg);                exit(0);            }        }        break;        case 1:{            for(i = 0; arg[i] != NULL; i++){                if(strcmp(arg[i], ">") == 0){                    strcpy(path, arg[i+1]);                    arg[i] = NULL;                }            }            if(pid == 0){                if( !right(arg[0]) ){                    err("wrong arg", __LINE__);                }                printf("%s\n",path);                fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);                if(fd < 0){                    err("open faild", __LINE__);                }                dup2(fd, 1);  //通过dup2实现标准输出                execvp(arg[0], arg);            }        }        break;        case  2:{            for(i = 0; arg[i] != NULL; i++){                if(strcmp(arg[i], "<") == 0){                    strcpy(path, arg[i+1]);                    arg[i] = NULL;                }            }            if(pid == 0){                if( !right(arg[0]) ){                    err("wrong arg", __LINE__);                }                fd = open(path, O_RDONLY);                if(fd < 0){                    err("open faild", __LINE__);                }                dup2(fd, 0);                execvp(arg[0], arg);                exit(0);            }        }    break;case 3:{    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++){  //管道命令数组                argn[j-i-1] = arg[j];                }            argn[j-1-i] = NULL;            break;        }    }    if(pid == 0){        argpipe(argn, arg);    }}break;        default:            break;    }//switch    if(background == 1){     //后台运行父进程不管子进程直接返回        return ;    }    if(waitpid(pid, &status, 0) == -1){  //他爸等他娃结束        err("wait for chil error", __LINE__);    }    }/******************主函数***********************/int main(int argc,char *argv[]){    char *buf;    int argcount = 0, i;    char arglist[100][255];    char **arg = NULL;    buf = (char *)malloc(255);    if(buf == NULL){        err("malloc", __LINE__);    }    while(1){        memset(buf, 0 ,256);        printf("my_shell$$");        arginput(buf);        if(strcmp(buf, "exit") == 0 || strcmp(buf, "logout") == 0)        {            break;        }        for(i = 0; i < 100; i++){            arglist[i][0] = '\0';        }        argcount = 0;        argexplain(buf, arglist, &argcount);        argdo(argcount, arglist);    }    if(buf != NULL){        free(buf);        buf = NULL;    }    return 0;}

总结:

参考了课本,对于重定向,管道的概念不是很清晰,程序的布局把握的不好,二级指针的运用不是很熟练。

问题:

很多。

0 0
原创粉丝点击