写一个自己的bash3.0版本(收官)
1、问题描述
我们已经完成了写一个自己的bash1.0版本、写一个自己bash2.0版本在2.0版本中我们改善了1.0版本,让程序打印命令提示符的时候可以自动获取用户名,主机名,当前位置和自动判断当前是管理员用户#还是普通用户$和自己实现了内置命令cd,但是仍有一些缺陷,当启动mybash可执行程序,输入ps,ls,pwd等命令时,mybash是fork一个子进程,然后替换该子进程来实现调用命令,可这些ps,ls,pwd等命令是系统已经提供好的,execvp函数会自动从环境变量$PATH所指出的路径中查找可执行程序。那么我们可以自己写ls,pwd等命令,然后mybash去调用自己的命令吗?当然可以!!!在博客Linux自己实现pwd和ls命令中已经完成pwd命令和ls命令的实现。那么今天的3.0版本中,就改进自己的bash用自己的命令。
2、重写替换进程代码段
2.1因为用自己写的命令,所以替换进程函数改用execv,自己指定路径,首先找出自己写的命令所在路径
在代码中定义一个宏变量
#define PATH "/home/wys/mycode/day18/mybin/"
2.2想一想执行可执行文件常用哪几种方式,1. ./main 在当前路径 2. /home/wys/mycode/main 给出绝对路径 3./home/wys/mycode/ 给出路径然后在该路径下找到可执行文件,考虑这三种情况,用execv的时候我们也要分三种情况
2.3重新编写替换进程片段代码
pid_t pid = fork();
if(pid == -1 )
{
printf("fork error\n");
}
if(pid == 0 )
{
char path[128] = { 0 };
if(strncmp(cmd,"./",2) == 0 || strncmp(cmd,"/",1) == 0 )
{
strcpy(path,cmd);
}
else
{
strcpy(path,PATH);
strcat(path,cmd);
}
execv(path,myargv);
printf("exec error\n");
exit(0);
2.4编译运行
调用自己/home/wys/mycode/day18/mybin目录下的命令成功,因为mybin目录下只有ls和pwd可执行文件,执行ps不等替换进程成功。
在这里可以重新实验一下,咱们把/usr/bin/目录下的ps拷贝到mybin目录下,看看能不能通过mybin目录来调用ps成功。
重新执行mybash
子进程被mybin目录下的ps替换成功
3、完整代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<pwd.h>
#include<errno.h>
#define PATH "/home/wys/mycode/day18/mybin/"
char* get_cmd (char buff[],char* myargv[])
{
if( buff == 0 || myargv == 0)
{
return NULL;
}
char*s = strtok(buff," ");
int i = 0;
while( s != NULL )
{
myargv[i++] = s;
s = strtok(NULL," ");
}
return myargv[0];
}
void print_info()
{
int id = getuid();//获取用户id
char* s = "$";
if( id == 0 )
{
s = "#";
}
struct passwd* ptr = getpwuid(id);//通过uid获取用户详细信息
if( ptr == NULL )
{
printf("$");
fflush(stdout);
return;
}
char hostname[64] = { 0 };
if (gethostname(hostname,64) == -1 )
{
printf("$");
fflush(stdout);
return;
}
//获取当前位置
char pwd_buff[128] = {0};
if(getcwd(pwd_buff,128) == NULL)
{
printf("$");
fflush(stdout);
return;
}
//打印命令提示行信息
printf("\033[1;32;40m %s@%s:\033[0m \033[1;34;40m%s%s\033[0m",ptr->pw_name,hostname,pwd_buff,s);
fflush(stdout);
}
int main()
{
while(1)
{
char buff[128] = { 0 };
print_info();
fgets(buff,128,stdin);
buff[strlen(buff) - 1] = 0;
char* myargv[10] = { 0 };
char* cmd = get_cmd(buff,myargv);
if(cmd == NULL)
{
continue;
}
else if (strcmp(cmd,"exit") == 0 )
{
exit(0);
}
else if (strcmp(cmd,"cd") == 0)
{
if( myargv[1] == NULL )
{
continue;
}
if ( chdir(myargv[1]) == -1)
{
perror("cd err");
}
continue;
}
else
{
pid_t pid = fork();
if(pid == -1 )
{
printf("fork error\n");
}
if(pid == 0 )
{
char path[128] = { 0 };
if(strncmp(cmd,"./",2) == 0 || strncmp(cmd,"/",1) == 0 )
{
strcpy(path,cmd);
}
else
{
strcpy(path,PATH);
strcat(path,cmd);
}
execv(path,myargv);
printf("exec error\n");
exit(0);
}
wait(NULL);
}
}
exit(0);
}
4、结束语
在这里那一个简单的mybash就完成了,当然大家可以继续改进它,比如自己去写ps命令然后去实现。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95568.html