bash程序的仿写

bash工作流程
死循环{
1.打印提示信息 [stu@localhost linuxlearn]$
2.等待用户输入命令 $
用户直接敲回车
1.对用户输入的字符串做拆分
2.对命令分类:内置命令(cd + exit) +外置命令(ps ls pwd…)
3.调用fork复制要给子进程,子进程执行用户输入的命令对应的程序
1.程序的名称 2.给程序传递的参数
前台:父进程等待子进程结束
}

//仿写bash程序
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<unistd.h>

#include<sys/types.h>
#include<pwd.h>
#include<sys/utsname.h>

#define CMDLEN 128 //定义输入命令长度
#define NUM 20 //参数的个数

//[用户名@主机名 当前工作目录]标识符
void PrintInfo()
{
	//获取当前用户名
	struct passwd *pw=getpwuid(getuid());
	assert(pw!=NULL);
	
	//获取当前主机信息
	struct utsname host;
	uname(&host);
	
	//获取当前路径
	char path[CMDLEN]={0};
	getcwd(path,CMDLEN-1);//绝对路径
	char *dirname =NULL;
	if(strcmp(path,pw->pw_dir)==0)//为家目录
	{
		dirname="~";
		//dirname=pw->pw_dir;
	}
	else
	{
		dirname = path +strlen(path);
		while(*dirname != '/')
		{
			dirname--;
		}
		if(strlen(path) != 1)
		{
			dirname++;
		}
	}
	
	//获取标识符
	char flag='$';
	if(getuid()==0)//0是root用户的ID
	{
		flag='#';
	}
	printf("[%s@%s %s]%c ",pw->pw_name,host.nodename,dirname,flag);
}

//将命令与参数切割,分别存储到指针数组中
void CutCommand(char *cmd,char *cmdArr[])
{
	char *p=strtok(cmd," ");//以空格进行且分
	int index=0;
	while(p!=NULL && index < NUM)
	{
		cmdArr[index++]=p;
		p=strtok(NULL," ");
	}
}

void MyCdCommand(char *path)
{
	static char oldpwd[CMDLEN]={0};
	//path为空
	if(path == NULL || strncmp(path,"~",1)==0)
	{
		//切换到家目录
		struct passwd *pw=getpwuid(getuid());
		assert(pw!=NULL);
		path=pw->pw_dir;
	}
	else if(strncmp(path,"-",1)==0)
	{
		//切换到上一次所在位置
		if(strlen(oldpwd) == 0)
		{
			printf("cd error, OLDPWD NOT SET\n");
			return;
		}
		path=oldpwd;
	}
	
	char nowpwd[CMDLEN] = {0};
	getcwd(nowpwd, CMDLEN - 1);
	
	if(-1 == chdir(path))//chdir切换路径,切换成功,返回为0,切换失败,返回为-1
	{
		perror("cd ");
		return;
	}
	
	memset(oldpwd,0,CMDLEN);
	strcpy(oldpwd,nowpwd);
}

void DealExec(char *cmdArr[])
{
	pid_t pid = fork();
	assert(pid != -1);
	if(pid==0)
	{
		//用户给定的一个命令  ls pwd su  ps
		//用户想执行一个程序  ./main  ./mybash
		char file[CMDLEN]={0};
		if(strstr(cmdArr[0],"/")!=NULL)
		{
			strcpy(file,cmdArr[0]);
		}
		else
		{
			strcpy(file,"/bin/");
			strcat(file,cmdArr[0]);
		}
		
		execv(file,cmdArr);//如果命令不存在,则execv会失败
		perror("execv ");
		exit(0); //如果替换失败,子进程要能正常结束
	}
	else
	{
		//前后台处理
		wait(NULL);
	}
}

int main()
{
	while(1)
	{
		//1.打印提示符信息
		PrintInfo();
		
		//2.获取用户输入的命令
		char cmd[CMDLEN]={0};
		fgets(cmd,127,stdin);//最后的回车符也在cmd数组中
		cmd[strlen(cmd) - 1]=0;//将最后一个回车符置为0
		if(strlen(cmd)==0)
		{
			continue;
		}
		
		//命令与各参数的分割 ls -a -l -i
		char *cmdArr[NUM]={0};
		CutCommand(cmd,cmdArr);
		
		//3.划分命令  空  内置  外置
		if(strlen(cmdArr[0])==2 && strncmp(cmdArr[0],"cd",2)==0)
		{
			MyCdCommand(cmdArr[1]);
			//continue;
		}
		else if(strlen(cmdArr[0])==4 && strncmp(cmdArr[0],"exit",4)==0)
		{
			exit(0);//结束进程
		}
		else//外置命令
		{
			DealExec(cmdArr);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值