【Linux】写一个基础的bash
头文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<string.h>
#include<pwd.h>
#include<dirent.h>
分割输入的命令串
字符串或参数内容为空则退出
strtok( , )以空格为分隔分割字符串,分割出的第一段赋给p
将分出来的一段装入myargv[]作为参数内容
继续分直到分完为止
将命令名(第一个参数内容)返回
//分割参数
char*get_cmd(char*s,char*myargv[])
{
if(s==NULL || myargv==NULL)return NULL;
char*p = strtok(s," ");
int i=0;
while(p!=NULL)
{
myargv[i++]=p;
p = strtok(NULL," ");
}
return myargv[0];
}
打印提示信息
普通成员的提示信息:
管理员的提示信息:
提示信息需要知道用户名、主机名、路径、提示符样式;
getuid()获取当前用户的id,管理员的uid永远是0,普通成员为其他的。以此区分提示符:$#;
getpwuid(uid)获取用户名;
gethostname( , )获取主机名;
getcwd( , )获取路径;
最后将它们按一定的颜色粗细拼接输出。
//打印提示信息
//查找失败
void find_err(char*s)
{
printf("mybash 1.1 %s ",s);
fflush(stdout);
}
void printf_info()
{
int id = getuid();
//提示符
char*s="$";
if(id==0) s="#";
//用户名
struct passwd* ptr = getpwuid(id);
if(ptr==NULL)//没有得到用户名
{
find_err(s);return;
}
char* username = ptr->pw_name;
//主机名
char hostname[128] = {0};
if(gethostname(hostname,128)==-1)
{
find_err(s);return;
}
//位置
char path[128] = {0};
if(getcwd(path,128)==NULL)
{
find_err(s);return;
}
//拼接输出
printf("\033[1;32m%s@%s\033[0m:\033[1;34m%s\033[0m%s ",username,hostname,path,s);
fflush(stdout);//刷屏
}
主函数
调用输出提示信息
fgets( , ,stdin )从键盘得到用户输入信息
分割参数
如果输入exit则退出
有些命令需要自己实现
fork()+exec()替换进程
int main()
{
while(1)
{
//给一个buff装输入的信息
char buff[128] = {0};
printf_info();
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;//去掉回车
//分离参数进myargv
char* myargv[10]={0};
char* cmd = get_cmd(buff,myargv);
//实现
if(cmd == NULL)continue;//如果为空继续
if(strcmp(cmd,"exit")==0)break;//退出
else if(strcmp(cmd,"cd")==0)//内置命令
{
if(myargv[1]!=NULL)
{
chdir(myargv[1]);
}
}
else//普通命令
{
pid_t pid = fork();
if(pid==-1)exit(0);
if(pid==0)
{
execvp(cmd,myargv);
printf("exec err\n");
exit(0);
}
wait(0);
}
}
exit(0);
}
使用: