小项目-linux下简单shell

目的:
分享大家学习入门linux-c、熟悉shell命令执行,解析的过程

实现过程:
在linux的bashshell中执行我的应用程序,进入自己制作的shell界面(while循环),定制自己的shell提示符,通过fgets获得输入,并将所传入的参数写入一个指针数组中(整理参数),判断是不是空操作或exit(退出),如果不是再判断是不是重定向输入输出,或管道。最后通过fork创建子进程,调用execvp执行命令。最终程序能实现所有单linux命令,重定向输入输出,及管道(最多两层管道)。

内容(分为三个文件):
main.c
function.c
head.c

文档下载


main.c

#include "head.h"
#include "function.c"
int main(){
    int ret,i,j,k=0;
    pid_t pid;
    char buf[ MAXLINE ];
    while(1){
    again:
        print();
        bzero(buf,MAXLINE);
        fgets(buf,MAXLINE,stdin);//从stdin中输入MAXLINE到buf里面最后一个字符是\n(enter换行符)
        if(buf[strlen(buf)-1]=='\n'){//将最后一个字符\n改为\0
            buf[strlen(buf)-1]='\0';
        }

//      printf("%s\n",buf);
        canshuzhengli(canshu,buf);//将所传入的参数用一个指针数组(*canshu[])来指向buf中的每个参数
        if(*(canshu+0)==NULL){//没有输入,直接按下了enter
            goto again;
        }
        if(strcmp(*(canshu+0),"exit")==0){//判断是不是输入了exit命令,是我们就直接退出
            exit(1);
        }

/*****************重定向输入,输出***************************************************/
        if(*(canshu+1)!=NULL){
            if((*(*(canshu+1)+0)==60)||(*(*(canshu+1)+0)==62)){//60==<    62==> 
                chongdingxiang(canshu);
                goto again;

            }   
        }
/******************管道命令*********************************************************/
        for(i=0;*(canshu+i) != NULL;i++){
            if(*(*(canshu+i)+0)=='|'){
                guandao(canshu,i);
                k=1000;
                break;
            }
            printf("%d++++++++++\n",__LINE__);
        }
        if(k==1000){
            printf("%d++++++++++\n",__LINE__);
            goto again;
        }


/**************输出指针数组*canshu[]中的每一个参数***********************************/
        for(i=0;*(canshu+i) != NULL;i++){
            printf("%s\n",*(canshu+i));
        }
/*************创建子进程,用来执行和序********************************************/
        if((pid=fork())<0){
            perror("fork is failure!\n");
            exit(1);
        }else if(pid == 0){
            if(execvp(*(canshu+0),canshu)<0){
                perror(NULL);
                exit(111);
            }
        }
        if((pid=waitpid(pid,NULL,0))<0){
            perror("fork is failure!\n");
            exit(1);
        }
    }
    return 0;
}

function.c

/*********************************************************************
********参数整理,将所有的参数都放在一个指针数组。ls -la /root******** 
********在指针数组的存放:"ls\0"  "-la\0" "/root\0" "NULL"    ********
**********************************************************************/
int canshuzhengli(char **ptr,char *buf){

        while(*buf != '\0'){
            *ptr=buf;
            while(*buf != 32){//124==>管道字符;32==>空格
                if(*buf=='\0'){
                    *++ptr=NULL;
                    return 0;
                }
                buf++;
            }
            *buf='\0';
            buf++;
            ptr++;
            while(*buf == 32){
                buf++;
            }
        }
        *ptr = NULL;
        return 0;
}
/**************打印提示符********************************************/
void print(){
    int ret;
    char *user;
    char *dir;
    char name[HOST_LEN];
    bzero(name,sizeof(name));
    if((ret = gethostname(name,sizeof(name)))<0){//获取主机名
        perror("gethostname is failure!\n");
        exit(1);
    }
    user=getlogin();                 //获取登陆者名字
    dir=(char *)get_current_dir_name();      //获取当前路径
    printf("%s@%s##%s##%%",user,name,dir);       //最终打印 
}

/*****************输入输出重定向***********************************/
void chongdingxiang(char **canshu){
        pid_t pidd,pid;
        int fd;
        if(*(*(canshu+1)+0) == 62){//输出重定向:目前只支持这种形式:ls > bb
            pidd=fork();
            if(pidd<0){
                perror("chongdingxiang fork is failure!");
                exit(1);
            }else if(pidd==0){
                if((fd=open(*(canshu+2),O_RDWR|O_CREAT|O_TRUNC,770))<0){
                    perror(">open is failure!");
                    exit(111);  
                }
                if(dup2(fd,STDOUT_FILENO)<0){
                    perror(">dup2 is failure!");
                    exit(111);
                }
                if(execlp(*(canshu+0),*(canshu+0),NULL)<0){
                    perror(NULL);
                    exit(111);
                }
            }
            if(pidd>0){
                if(waitpid(pidd,NULL,0)<0){
                    perror("chongdingxiang waitpid is failure!");
                    exit(1);
                }
            }
        }else{//wc < 1.c 输入重定向
            pid=fork();
            if(pid<0){
                perror("chongdingxiang fork is failure!");
                exit(1);
            }else if(pid==0){

                if((fd=open(*(canshu+2),O_RDWR))<0){
                    perror("open is failure!");
                    exit(111);
                }
                if(dup2(fd,STDIN_FILENO)<0){
                    perror(");
                    exit(111);
                }
//              printf("line:%d,canshu1:%s\n",__LINE__,*(canshu+0));
                if(execlp(*(canshu+0),*(canshu+0),NULL)<0){
                    perror("+++++++");
                    exit(111);
                }       
//              printf("line:%d,canshu1:%s\n",__LINE__,*(canshu+0));
            }
            if(pid>0){
                if(waitpid(pid,NULL,0)<0){
                    perror("chongdingxiang < waitpid is failure!");
                    exit(1);
                }
            }

        }   
}

/***************************管道处理*************************************************/
int  guandao(char **canshu,int i){
    printf("++++++++++%d\n",__LINE__);
    *(canshu+i)=NULL;
    pid_t pid;
    int ret,n;
    int fd[2];
    ret = pipe(fd);
    if(ret<0){
        perror("pipe is failure!");
        return 1;
    }
    pid = fork();
    if(pid < 0){
        perror("fork is failure!");
        return 1;
    }
    if(pid == 0){
    printf("++++++++++%d\n",__LINE__);
        close(fd[0]);
        if(dup2(fd[1],STDOUT_FILENO)<0){
            perror("| is dup2");
            return 1;
        }
        if(execvp(*(canshu+0),canshu)<0){
            perror("| is exe failure!");
            return 1;
        }
    }
    if(pid>0){
    printf("++++++++++%d\n",__LINE__);
        if(waitpid(pid,NULL,0)<0){
            perror("| father waitpid is failure!");
            return 1;
        }
        close(fd[1]);
        if(dup2(fd[0],STDIN_FILENO)<0){
            perror("| father dup2 is failure!");
            return 1;
        }
        if(execvp(*(canshu+i+1),(canshu+i+1))<0){
            perror("| father exe is failure!");
            return 1;
        }
    }
    printf("++++++++++%d\n",__LINE__);
    return 0;


}

head.h

#include
#include
#include               
#include
#include
#include
#include
#define MAXLINE 100
#define HOST_LEN 40
#define CANSHU_LEN 10
void print();
int guandao(char **canshu,int i);
int canshuzhengli(char **ptr,char *buf);
static char *canshu[ CANSHU_LEN ];

你可能感兴趣的:([,linux应用c编程,])