mybash,在linux上用代码实现bash命令,C语言

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/utsname.h>

#define CMDNUM  10


void PrintfTag()
{
	//1、获取用户信息 -- 用户名
	//2、获取主机信息 -- 主机名
	//3、获取当前工作目录名
	//4、判断符号是$  or  #
	//5、将以上信息全部打印
	struct passwd *pw = getpwuid(getuid());     //获取当前目录 
	struct utsname un;     //获取localhost 
	uname(&un);

	char pwd[128] = {0};
	getcwd(pwd, 127);
	char *p = pwd + strlen(pwd);     //p的指针从后往前读目录 
	if(strcmp(pwd, pw->pw_dir) == 0)     //cd ~ 操作相当于 cd 
	{
		p = "~";     //特殊目录名,家目录-〉~ 
	}
	else
	{
		while(*p != '/') p--;     //从后往前读目录遇到的第一个'/' 时停止 
		if(strlen(pwd) != 1) p++;     
	}

	char flag = '$';     //flag默认为'$' 
	if(pw->pw_uid == 0) flag = '#';      //如果pw_uid=0(意思是他是root用户)flag='#' 

	printf("[%s@%s %s]%c ", pw->pw_name, un.nodename, p, flag);//[stu@localhost Desktop]$
}

int GetCmd(char  *cmd)
{
	fgets(cmd, 127, stdin);
	cmd[strlen(cmd) - 1] = 0;     //去掉空格 

	if(strlen(cmd) == 0) return 0;     //未输入 

	return 1;
}

void OperatorCd(char *path)
{
	static char OLDPWD[128] = {0};     //记录之前的命令 
	char nowpwd[128] = {0};
	getcwd(nowpwd, 127);   

	if(path == NULL || strncmp(path, "~", 1) == 0)     //path=cd or cd ~ 
	{
		struct passwd *pw = getpwuid(getuid());
		chdir(pw->pw_dir);
	}
	else if(strncmp(path, "-", 1) == 0)
	{
		if(strlen(OLDPWD) == 0)     //如果之前没有命令 
		{
			printf("mybash:: OLDPWD not set\n");
			return;
		}
		else     //之前输入过命令
		{
			chdir(OLDPWD);
		}
	}
	else
	{
		if(-1 == (chdir(path)))
		{
			perror("mybash : ");
			return;
		}
	}

	memset(OLDPWD, 0, 128);
	strcpy(OLDPWD, nowpwd);
}

int AnalyCmd(char *CMD[]) //  cmd = "         cd path"
{
	if(strncmp(CMD[0], "cd", 2) == 0)     //如果输入的命令前面是cd,则跳到函数OperatorCd里处理 
	{
		OperatorCd(CMD[1]);
		return 0;
	}
	else if(strncmp(CMD[0], "exit", 4) == 0)     //如果输入命令exit,则退出 
	{
		exit(0);
	}

	return 1;
}

void CutCmd(char *cmd, char *CMD[])     //对命令进行剪辑 
{
	int count = 0;
	char *p = strtok(cmd, " ");
	while(p != NULL)     //遇到空格就剪辑,然后放在数组CMD[]里 
	{
		CMD[count++] = p;
		if(count == CMDNUM)
		{
			break;
		}
		p = strtok(NULL, " ");
	}
}

void OperatorCmd(char *CMD[])
{
	pid_t pid = fork();
	assert(-1 != pid);     //断言fork()未成功

	if(0 == pid)
	{
		// CMD[0] = command
		char path[128] = "/home/stu/dir2019/ufe1212/shell/mybin/";
		if(strstr(CMD[0], "/") == NULL)
		{
			strcat(path, CMD[0]);  //  "/home/stu/dir2019/ufe1212/shell/mybin/pwd"
		}
		else
		{
			memset(path, 0, 128);
			strcpy(path, CMD[0]);
		}

		execv(path, CMD);
		perror(CMD[0]);
		exit(0);
	}
	else
	{
		wait(NULL);
	}
}

int main()
{
	while(1)
	{
		PrintfTag();     //输出[stu@localhost Desktop]$ 

		char cmd[128] = {0};

		if(!GetCmd(cmd))  continue;     //获取命令 
		
		char *CMD[CMDNUM] = {0};
		CutCmd(cmd, CMD);     //剪辑命令 

		if(!AnalyCmd(CMD)) continue;     //判断命令

		OperatorCmd(CMD);     //操作 
	}

	exit(0);
}

猜你喜欢

转载自blog.csdn.net/obitosbb/article/details/94043663