编写一个简单的shell

来源:互联网 发布:淘宝贷款买家改卖家 编辑:程序博客网 时间:2024/04/29 01:14

Shell实现代码

#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>#include<stdlib.h>#include<ctype.h>#include<pwd.h>#include<string.h>void GetLoginName(){    struct passwd* pass;    pass = getpwuid(getuid());    printf("[%s@",pass->pw_name);   }void GetHostName(){    char name[128];    gethostname(name,sizeof(name)-1);    printf("%s",name);  }void GetDir(){    char pwd[128];    getcwd(pwd,sizeof(pwd)-1);    int len = strlen(pwd);    char *p = pwd+len-1;    while(*p !='/' && len--)        {            p--;            }        p++;        printf(" %s]#",p);}int main(){    while(1)    {        GetLoginName();        GetHostName();        GetDir();        fflush(stdout);        char buf[1024];        size_t s=read(0,buf,sizeof(buf)-1);        if(s>0)        {            buf[s-1] = 0;            //printf("%s\n",buf);        }        char *_argv[32];        char *start = buf;        _argv[0] = start;        int i = 1;        while(*start)        {            if(*start == ' ')            {                *start = '\0';                start++;                _argv[i++] = start;            }            else            {                start++;            }        }        _argv[i] = NULL;        pid_t id = fork();        if(id ==0)        {            execvp(_argv[0],_argv);            perror("Perror!");                exit(1);        }           else         {            int status = 0;            pid_t ret = waitpid(id,NULL,0);            if(ret > 0)            {                printf("wait success,ret:%d,exitcode:%d,sig:%d\n",\                    ret,(status>>8)&0xff,status&0xff);            }        }    }    return 0;

读取命令分析图:
这里写图片描述
水平有限,首先拿到read()函数所读取到的命令。

ssize_t read(int fd, void *buf, size_t count);

这里是read()函数的原型,上面的代码我们用到了size_t s=read(0,buf,sizeof(buf)-1);
可以看到第一个参数为文件标识符,0对应的是输入流,所以我们可以拿到在命令行输入的字符串。

实现shell的机理是利用进程程序替换。这里写图片描述
这里简单说一下这几个函数的区别,
p(path):则第一个参数为路径。
l(list):即把每个命令都当做参数传递。
v(vector):通过指向各参数的指针数组来传递命令。
e(environment):可以传递新的环境变量
这里需要注意的是,l和v不可能同时出现,对于l来说最后一个参数必须为NULL,对于v来说,数组中最后一个指针必须是NULL。