#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <pwd.h>
#define LEN 10
char* Cmd[LEN] = {0};//定义全局变量 用来存储分割后用户命令
int count = 0;
char OLDPWD[1024] = {0};//定义全局变量 环境变量,用于存储更新的环境变量 cd-
//命令提示符的输出:用户名+主机名+当前目录名+区别用户类型的符号
void out_flag()
{
char flag = '$';//用户类型区别符号,普通用户
struct passwd *pw = getpwuid(getuid());//通过用户的UID查找用户的passwd的数据(getuid() 获取用户的UID)
if(getuid() == 0)//当使用root 身份执行,
{
flag = '#';
}
struct utsname host;
uname(&host);
char *hostname = strtok(host.nodename, ".");//切割目录的节点信息,获取目录名
char path[128] = {0};
getcwd(path, 127);//获取当前目录的绝对路径
char *p = strtok(path, "/");//用‘/’切割字符串
char *nowdir = NULL;//
while(p!= NULL)
{
nowdir = p;
p = strtok(NULL, "/");
}
if(nowdir == NULL)
{
nowdir = "/";
}
if(strcmp(nowdir, pw->pw_name) == 0)
{
nowdir = "~";
}
printf("[%s@%s %s]mybash%c ", pw->pw_name, hostname,
nowdir, flag);
fflush(stdout);
},
//切割用户命令,并存放在Cmd[]
void cut_cmd(char *cmd)
{
char *p = strtok(cmd, " ");
while(p != NULL)
{
Cmd[count++] = p;
p = strtok(NULL, " ");
}
}
//特殊符号的处理 cd exit
int special_cmd()
{
if(strncmp("cd", Cmd[0], 2) == 0)//输入 cd
{
if(Cmd[1] == NULL || strncmp(Cmd[1], "~", 1) == 0)//cd cd ~回到当前目录的家目录
{
struct passwd *pw = getpwuid(getuid());
Cmd[1] = pw->pw_dir;
}
else if(strncmp(Cmd[1], "-", 1) == 0)//cd - 回到上一个目录并显示当前目录
{
//切换到家目录到上一次所在目录
if(strlen(OLDPWD) == 0)//刚登录shell是环境变量OLDPWD中是没有记录的 OLDPWD=0
{
printf("mybash: cd :: OLDPWD not set\n");
return 1;
}
Cmd[1] = OLDPWD;//将上次目录存放在Cmd[1]
printf("%s\n", Cmd[1]);//输出当前目录(上次目录)
}
char str[1024] = {0};//str存放当前路径
getcwd(str, 1023);//在切换当前目录之前保存路径
chdir(Cmd[1]); // 切换路径到Cmd[1]
strcpy(OLDPWD, str);//更新环境变量
return 1;
}
if(strncmp("exit", Cmd[0], 4) == 0)//输入exit
{
exit(0);
}
return 0;
}
void clear_cmd()//清空Cmd[]函数
{
int i = 0;
for(;i < count; ++i)
{
Cmd[i] = 0;
}
count = 0;
}
void main()
{
while(1)
{
out_flag();
char cmd[128] = {0};
fgets(cmd, 128, stdin); //获取命令
cmd[strlen(cmd) - 1] = 0; //去掉最后一个回车符
if(strlen(cmd) == 0) // 判别用户的无效输入
{
continue;
}
cut_cmd(cmd); // 切割cmd
int res = special_cmd(); // 判别是否是需要集成到bash中的特殊命令
if(res == 1)
{
clear_cmd(); //清空全局的指针数组,并将count归0
continue;
}
pid_t pid = fork();
assert(pid != -1);
if(pid == 0)
{
// 用命令的可执行文件(./mybin)替换当前进程
char path[1024] = "/home/stu/mydir/LG1702shell/mybin/";
if(strstr(Cmd[0], "/") != NULL)//用户直接输入指定路径
{
memset(path, 0, 1024);//清空path
}
strcat(path, Cmd[0]);//将用户指定目录链接到cd 后
execv(path, Cmd);//用path下名为Cmd的应用程序替换子进程,执行成功,execv无返回值
printf("mybash: %s : command not found\n", Cmd[0]);
exit(0);
}
else
{
wait(NULL);//等待子进程结束
}
clear_cmd();
}
}
码片
Linux-my_bash(cd)
最新推荐文章于 2022-11-24 20:38:41 发布