功能
- 打印提示符信息:[当前用户名@主机名 当前工作目录名] 标识符($ #)
- 获取用户的命令:命令名称 选项 参数
- 对命令做分类:
1)内置命令:exit cd
2)外置命令:单独的程序,由bash创建的子进程运行/bin下的可执行文件 - 创建子进程:子进程替换用户输入的命令对应的可执行文件
源码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <pwd.h>
#include <signal.h>
#define NUM 20
#define LENGTH 128
char OLDPWD[LENGTH] = { 0 };
void PrintfTag()
{
char flag = '$';
if(getuid() == 0)
{
flag = '#';
}
struct passwd *pw = getpwuid(getuid());
assert(pw != NULL);
struct utsname hostname;
uname(&hostname);
char path[LENGTH] = { 0 };
getcwd(path, LENGTH - 1);
char *dirName = NULL;
if(strcmp(path, pw->pw_dir) == 0)
{
dirName = "~";
}
else if(strlen(path) == 1)
{
dirName = "/";
}
else
{
dirName = path + strlen(path);
while(*dirName != '/')
{
dirName--;
}
dirName++;
}
printf("[%s@%s %s]%c", pw->pw_name, hostname.nodename, dirName, flag);
}
void CutCommandString(char *cmd, char *Argv[])
{
int index = 0;
char *p = strtok(cmd, " ");
while(p != NULL)
{
Argv[index++] = p;
p = strtok(NULL, " ");
}
}
void AchieveCd(char *path)
{
char nowPath[LENGTH] = { 0 };
getcwd(nowPath, LENGTH - 1);
if(path == NULL || strncmp(path, "~", 1) == 0)
{
struct passwd *pw = getpwuid(getuid());
path = strcat(pw->pw_dir, path + 1);
}
if(strncmp(path, "-", 1) == 0)
{
if(strlen(OLDPWD) == 0)
{
printf("mybush: OLDPWD no set\n");
return;
}
path = OLDPWD;
}
if(-1 == chdir(path))
{
perror(path);
return;
}
memset(OLDPWD, 0, LENGTH);
strcpy(OLDPWD, nowPath);
}
int DealBuiltInCmd(char *Argv[])
{
if(strncmp(Argv[0], "exit", 4) == 0)
{
exit(0);
}
if(strncmp(Argv[0], "cd", 2) == 0)
{
AchieveCd(Argv[1]);
return 1;
}
return 0;
}
void SignBack(int sign)
{
wait(NULL);
}
void CreatChild(char *Argv[])
{
signal(SIGCHLD, SignBack);
pid_t pid = fork();
assert(pid != -1);
if(pid == 0)
{
char path[LENGTH] = "/bin/";
if(strstr(Argv[0], "/") != NULL)
{
memset(path, 0, LENGTH);
strcpy(path, Argv[0]);
}
else
{
strcat(path, Argv[0]);
}
execv(path, Argv);
perror(path);
exit(0);
}
else
{
int i = NUM - 1;
for(; i >= 0; i--)
{
if(Argv[i] != NULL)
{
break;
}
}
if(strcmp(Argv[i], "&") != 0)
{
wait(NULL);
}
}
}
int main()
{
while(1)
{
PrintfTag();
char cmd[LENGTH] = { 0 };
fgets(cmd, LENGTH - 1, stdin);
cmd[strlen(cmd) - 1] = 0;
char *Argv[NUM] = { 0 };
CutCommandString(cmd, Argv);
if(DealBuiltInCmd(Argv))
{
continue;
}
CreatChild(Argv);
}
}