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);
}
}
}