bash 命令解释器 让系统与用户交互
1.内置命令 cd bash 直接实现 -> 调用函数实现
2.普通命令 fork + exec()
bash基本功能步骤:
1 bash 打印提示信息 [stu@localhost tmp]$
2 fgets(buff) //用户输入数据 ls, cp a.c b.c ,ps -f
3 解析命令 “cp”“a.c” “b.c”
4 判断是内置命令 还是普通命令
5 执行命令 1)直接调用函数 (内置)
2)fork + exec(cp,“a.c”,“b.c”) (普通)
6 wait(); (普通)
mybash里所有命令存放位置 /mybash/mybin
(mybash.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <pwd.h>
#define PATH "/home/stu/c215/mybash/mybin/"
#define MAX_ARG 10
void print_info()
{
char * s = "$";
int id = getuid();
if(0 == id)
{
s = "#";
}
struct passwd* pw = getpwuid(id);
if(NULL == pw)
{
printf("mybash>>$");
fflush(stdout);
return;
}
char hostname[128] = {0};
if(gethostname(hostname,128) == -1) //获取主机名
{
printf("mybash>>$");
fflush(stdout);
return;
}
char pwd_str[256] = {0};
if(getced(pwd_str,256) == NULL) //获取当前位置
{
printf("mybash>>$");
fflush(stdout);
return;
}
printf("\033[1;32m%s@%s\033[0m \033[1; 34m%s%s\033[0m ",pw>>pw_name,hostname,pwd_str,s);
fflush(stdout);
}
char * get_cmd(char* buff,char* myargv[])
{
if(p == NULL || myargv == NULL)
{
return NULL;
}
int i = 0;
char* s = strtok(buff," "); //分隔符是空格 第一轮分割
while(s !=NULL)
{
myargv[i++] = s;
s = strtok(NULL," "); //第二轮分割
}
return myargv[0];
}
void change_dirent(char* dir) //对cd进行封装
{
if(dir ==NULL)
{
return;
}
if(chdir(dir) == 1)
{
perror("cd err");
}
}
int main()
{
while(1)
{
print_info(); //打出提示符 获取信息
char buff[128] = {0}; //从键盘获取命令
fgets(buff,128,stdin); // "ls\n"
buff[strlen(buff)-1] = 0; //"ls"
char* myargv[MAX_ARG] = {0}; //对命令解析后存入myargv
char* cmd = get_cmd(buff,myargv); //对命令的解析
if(cmd == NULL)
{
continue;
}
else if(strcmp(cmd,"cd") == 0)
{
change_dirent(myargv[1]);
continue;
}
else if(strcmp(cmd,"exit") == 0)
{
break;
}
else
{
//foek+exec
pid_t pid = fork(); //复制
if(pid == -1)
{
printf("fork err\n");
continue;
}
if(pid == 0)
{
char cmdpath[128] = {0};
if(strncmp(cmd,"./",2) != 0 && strncmp(cmp,"/",1) !=0)
{
strcpy(cmdpath,PATH);
strcat(cmdpath,cmd); //拼接路径 a
}
else
{
strcpy(cmdpath,cmd); // ./a /home/stu/a
}
execv(cmdpath,myargv); // cmdpath路径加名称
//execvp(cmd,myargv); // 替换 自动去环境变量path下寻找
perror("execvp err");
exit(0);
}
wait(NULL);
}
}
}
(pwd.h)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
char path[256] = {0};
getcwd(path,256);
printf("%s\n",path);
}
opendir函数
打开一个目录建立一个目录流
(ls.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
int main()
{
char path[256] = {0};
if(gercwd(path,256) == NULL)
{
printf("ls err:无法得到当前位置");
exit(0);
}
DIR * ptr = opendir(path);
if(ptr == NULL)
{
printf("无法打开目录流\n");
exit(0);
}
struct stat st;
struct dirent * p = NULL;
while((p = readdir(ptr)) != NULL)
{
if(strncmp(p->d_name,".",1) == 0)
{
continue;
}
lstat(p->d_name,&st);
if(S_ISDIR(st.st-_mode))
{
printf("\033[1;34m%s \033[0m",p->d_name);
}
else
{
if(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
{
printf("\033[1;32m%s \033[0m",p->d_name);
}
printf("%s ",p->d_name); //d_name为文件名
}
}
printf("\n");
closedir(ptr);
exit(0);
}