mybash(linux)

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

猜你喜欢

转载自blog.csdn.net/qq_42111463/article/details/84171215