mybash:通常shell中执行命令的流程都是bash进程创建一个子进程,然后子进程进程替换,替换成可执行的命令文件。
本质:不断进行fork()+ exec()
bash输出信息的格式:[用户名@主机名所在文件]$(root用户:[用户名@主机名所在文件]#)。当所在文件就是当前用户的家目录时显示“~”。
程序代码如下:(此程序(1.mybash.c)只可以用系统的个命令,也就是输入的命令调用的是系统的bin,要想执行自己文件夹的命令则需要自己写一个mybin(文件夹)像系统的bin目录一样,调用自己的文件夹代码如2.binmybash.c)
//1.mybash.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define MAX 10
#define PATH "/home/stu/dir2018/mybin"
void printf_info()
{
printf("[stu@localhost ~]$");//每次敲回车输出当前所在用户信息,此处固定它的用户信息为当前用户的家目录
fflush(stdin);
}
int main()
{
while(1)
{
char buff[128]={0};//存放要分割的字符串,以数组形式存储
printf_info();
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;
char *s=strtok(buff," ");//字符串分割函数,把空格分开每次都把空格换成“\0”,返回第一次分割出的字符串
if(s==NULL)//如果用户没有输入信息则在敲回车时继续输出用户信息
{
continue;
}
char* myargv[MAX] ={0};
myargv[0]=s;
int i=1;
while((s=strtok(NULL,""))!=NULL)
{
myargv[i++]=s;
}
if(strcmp(myargv[0],"exit")==0)//看输入的字符串是否与exit退出匹配,如果匹配则直接结束函数
{
break;
}
//如果是其他命令,则都用fork()+ exec()复制子进程替换自身
pid_t pid = fork();
assert(pid!=-1);
if(pid==0)
{
execvp(myargv[0],myargv);
exit(0);
}
wait(NULL);
}
}
//2.binmybash.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define MAX 10
#define PATH "/home/stu/dir2018/mybin/"//路径名称,此路径为我的mybin存放的位置
void printf_info()
{
printf("[stu@localhost ~]$");//每次敲回车输出当前所在用户信息,此处固定它的用户信息为当前用户的家目录
fflush(stdin);
}
int main()
{
while(1)
{
char buff[128]={0};
printf_info();
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;
char *s=strtok(buff," ");
if(s==NULL)
{
continue;
}
char *myargv[MAX]={0};
myargv[0]=s;
int i=1;
while((s=strtok(NULL,""))!=NULL)
{
myargv[i++]=s;
}
if(strcmp(myargv[0],"exit")==0)
{
break;
}
else if(strcmp(myargv[0],"cd")==0)
{
if(myargv[1]==NULL)
{
continue;
}
chdir(myargv[1]);
continue;
}
pid_t pid=fork();
assert(pid!=-1);
//修改的地方
if(pid==0)
{
char path[256]={0};
if(strncmp(myargv[0],"./",2)!=0&&strncmp(myargv[0],"/",1)!=0)
{
strcpy(path,PATH);//先把路径放入path中
}
strcat(path,myargv[0]);//进行命令拼接,路径+名称
execv(path,myargv);
perror("execv error");
}
wait(NULL);
}
}