目录
1.bash项目:
命令解释器
mybash
2.命令的分类:
1.内置命令
cd exit
2.普通命令:
通过
which
可以找到
ls pwd cp ps
3.项目框架
while(1)
{
printf("stu@stu-virtual-machine:~/dir223/day16$" );
char buff[128];
fgets(buff); //cp a.c b.c
分割命令:myargv[0],......
char *cmd=myargv[0];//获取命令
if(内置命令) {cd ,exit}
else fork+exec;//普通命令:ls,ps,cp
}
strtok
内部定义了一个指针
,
专门用来记录刚才分割到哪里
;
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#define ARG_MAX 10
char* get_cmd(char* buff, char* myargv[])
{
if (buff == NULL || myargv == NULL)
{
return NULL;
}
int i = 0;
char* s = strtok(buff, " ");
while (s != NULL)
{
myargv[i++] = s;
s = strtok(NULL, " ");
}
return myargv[0];
}
void run_cmd(char* path, char* myargv[])
{
if (path == NULL || myargv == NULL)
{
return;
}
pid_t pid = fork();
if (pid == -1)
{
return;
}
if (pid == 0)
{
//替换
execvp(path, myargv);
perror("execvp error\n");
exit(0);//子进程必须要退出
}
else
{
wait(NULL);
}
}
int main()
{
while (1)
{
printf("stu@localhost ~$");
fflush(stdout);
char buff[128] = { 0 };
fgets(buff, 128, stdin);
buff[strlen(buff) - 1] = 0;
char* myargv[ARG_MAX] = { 0 };
char* cmd = get_cmd(buff, myargv);
if (cmd == NULL)
{
continue;
}
else if (strcmp(cmd, "cd") == 0)
{
}
else if (strcmp(cmd, "exit") == 0)
{
break;
}
else//普通命令
{
//fork+exec;
run_cmd(cmd, myargv);
}
}
exit(0);
}
4.完整代码
mybash.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <pwd.h>
#define ARG_MAX 10
#define PATH_BIN "/home/stu/mybash/mybin/" //注意,这个路径不能 抄,必须是自己的mybin的路径;
char *get_cmd(char *buff,char *myargv[])
{
if(buff==NULL||myargv==NULL)
{
return NULL;
}
int i=0;
char *s=strtok(buff," ");
while(s!=NULL)
{
myargv[i++]=s;
s=strtok(NULL," ");
}
return myargv[0];
}
void run_cmd(char *path,char *myargv[])
{
if(path==NULL||myargv==NULL)
{
return ;
}
pid_t pid=fork();
if(pid==-1)
{
return;
}
if(pid==0)
{
//execvp(path,myargv);
char pathname[128]={0};
if(strncmp(path,"/",1)==0|| strncmp(path,"./",2)==0)
{
strcpy(pathname,path);
}
else
{
strcpy(pathname,PATH_BIN);
strcat(pathname,path);
}
execv(pathname,myargv);
perror("execvp error\n");
exit(0);
}
else
{
wait(NULL);
}
}
void printf_info()
{
char *user_str="$";
int user_id=getuid();
if(user_id==0)
{
user_str="#";
}
struct passwd *ptr= getpwuid(user_id);
if(ptr==NULL)
{
printf("mybash1.0>> ");
fflush(stdout);
return ;
}
char hostname[128]={0};
if(gethostname(hostname,128)==-1)
{
printf("mybash1.0>> ");
fflush(stdout);
return ;
}
char dir[256]={0};
if(getcwd(dir,256)==NULL)
{
printf("mybash1.0>> ");
fflush(stdout);
return ;
}
printf("\033[1;32m%s@%s\033[0m \033[1;34m%s\033[0m%s ",ptr->pw_name,hostname,dir,user_str);
fflush(stdout);
}
int main()
{
while(1)
{
printf_info();
// printf("stu@localhost ~$");
// fflush(stdout);
char buff[128]={0};
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;
char *myargv[ARG_MAX]={0};
char *cmd=get_cmd(buff,myargv);
if(cmd==NULL)
{
continue;
}
else if(strcmp(cmd,"cd")==0)
{
if(myargv[1]!=NULL)//必须保证有第二个参数
{ if(chdir(myargv[1])==-1)
{
perror("cd err");
}
}
}
else if(strcmp(cmd,"exit")==0)
{
// exit(0);//Ok
break;
}
else
{
//fork+exec;
run_cmd(cmd,myargv);
}
}
exit(0);
}
// 下面的三个文件放到 mybin 底下 ;//clear.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("\033[2]\033[O;OH");
}
~
//pwd.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
char path[256]={0};
if(getcwd(path,256)==NULL)
{
perror("getcwd error");
exit(1);
}
printf("%s\n",path);
exit(0);
}
~
//ls.c
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
int main()
{
char path[256]={0};
if(getcwd(path,256)==NULL)
{
perror("getcwd error");
exit(1);
}
DIR *pdir= opendir(path);
if(pdir==NULL)
{
perror("opendir error");
exit(1);
}
struct dirent *s=NULL;
while((s=readdir(pdir))!=NULL)
{
if(strncmp(s->d_name,".",1)==0)
{
continue;
}
// printf("%s ",s->d_name);
struct stat filestat;
stat(s->d_name,&filestat);
if(S_ISDIR(filestat.st_mode))
{
printf("\033[1;34m%s\033[0m ",s->d_name);//蓝色
}
else
{
if(filestat.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
{
printf("\033[1;32m%s\033[0m ",s->d_name);
}
else
{
printf("%s ",s->d_name);
}
}
}
printf("\n");
closedir(pdir);
exit(0);
}
运行结果:
已写bash
未写bash
退出
总体
5.总结
在这里要注意的就是有关用户信息与主机信息的提取
,
也就是相关函数的使用
;
其实代码写到这里可以算是相关功能已经完全完成了
,
只不过我们想所有的命令都不
是用的系统自带的命令
,
那么我们就可以自己写命令
:
其实我们会发现
,
我们前面自己写过
kill
命令
,
自己写过
cp
命令
.
那么我们自己建立一个
mybin
文件
,
依次实现
clear,pwd,ls
命令等等
...