linux终端shell解析,Linux shell命令解析器(一),bash终端

环境:

Ubuntu14-4   内核 4.4.0-135

vim编辑器 7.4

gcc  4.8.4

1.1 知识点

Shell 的基本概念

进程控制相关的系统调用的使用(如 fork,exec函数族)

整理框架:

1.命令解释器首先是一个死循环。

2.打印一个命令提示符。

3.取得命令行输入放在数组里面,要求命令带参数。可以getc()、fgets()、scanf()等。

4.如果用fgets()的话,取得的字符串包括最后输入的换行符,故要去掉命令字符串末尾的“/n”,变成“/0”。

5.用字符串切割函数将得到的命令行以空格切割存储在字符串数组中。

6.创建一个子进程,调用exec执行命令,将切割得到的命令以及参数传入。

7.父进程调用waitpid()等待子进程的退出,然后进入下一次循环。

bash终端部分:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define STRLEN 128

//命令行提示符

void PrintfFlag()

{

struct passwd *pw=getpwuid(getuid());//得到当前用户的名称的结构体指针pw

assert(pw!=NULL);

struct utsname un;//得到主机标识

uname(&un);

//assert(uname!=NULL);

char shortname[STRLEN]={0};

memmove(shortname,un.nodename,9);

char path[STRLEN]={0};//得到当前工作路径

getcwd(path,STRLEN-1);

char *p=path;

if(strcmp(path,"/")==0)

{

p="/";

}

//else if(strcmp(p,getenv("HOME"))==0)

else if(strcmp(p,pw->pw_dir)==0)

{

p="~";

}

else

{

p=path+strlen(path);

while(*p--!='/');

p+=2;

}

char flag='$';//得到当前用户状态

if(getuid()==0)

{

flag='#';

}

printf("[%s@%s %s]%c ",pw->pw_name,shortname,p,flag);

}

void CutCmd(char *cmd,char *argv[])

{

int count=0;

char *p=strtok(cmd," "); //以空格分割cmd,将得到的字符串存储在argv字符串数组中

while(p!=NULL)

{

argv[count++]=p;

if(count==STRLEN)

{

break;

}

p=strtok(NULL," ");

}

}

void CdCmd(char *path)

{

static char PrePath[STRLEN]={0}; //静态区存储上一次目录

struct passwd*pw=NULL;

if(strcmp(path,"~")==0)

{

pw=getpwuid(getuid());

assert(pw!=NULL);

path=pw->pw_dir;

}

else if(strcmp(path,"-")==0)

{

if(strlen(PrePath)==0)

{

printf("OLDPWD not set\n");

return ;

}

path=PrePath;

}

char NowPath[STRLEN]={0};

getcwd(NowPath,STRLEN-1); //获得当前工作目录

if(-1==chdir(path)) //工作目录转移

{

printf("bash: cd: %s: No such file or director\n",path);

}

else

{

strcpy(PrePath,NowPath);

}

}

int main()

{

while(1)

{

PrintfFlag();

char cmd[STRLEN] = {0};

fgets(cmd,STRLEN,stdin);// 输入命令

cmd[strlen(cmd) - 1] = 0;

if(strlen(cmd) == 0)

{

continue;

}

if(strcmp(cmd,"exit") == 0)

{

exit(0);

}

char *argv[STRLEN] = {0};

CutCmd(cmd,argv); //比如:argv[0]="ls",argv[1]="-al",argv[2]=getcwd();

if(strcmp(argv[0],"cd") == 0)

{

CdCmd(argv[1]);

continue;

}

pid_t pid=fork();

assert(pid != -1);

if(pid == 0)

{

char path[STRLEN] = {"/home/zhao/Desktop/shell/bin/"};

if(strstr(argv[0],"/") != NULL)//防止带路经命令引起路径错误

{

memset(path,0,STRLEN);

}

strcat(path,argv[0]);

execv(path,argv);

printf("bash: %s: command not found\n",argv[0]);

exit(0); //当exec函数调用失败时,子进程能够安全推出

}

else

{

wait(NULL);

}

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值