📄 minishell.c
字号:
#include "minishell.h"char *lookupPath(char **,char **); //查找命令行中所包含的可执行文件在哪条路径下,返回该绝对路径int parseCommand(char *,struct command_t *); //对命令行中的参数进行分割,分别存入argv[]数组中int parsePath(char **); //将环境变量PATH中的路径根据“:”进行分割void printPrompt(); //打印提示符,以便user输入命令行char *pathv[MAX_PATHS]; //包含环境变量PATH中所有路径的数组int main(){ int i; int pid; int status; FILE *fid; char cmdline[LINE_LEN]; //包含命令行的参数 struct command_t command; char path_cp[MAX_PATH_LEN]; if(!parsePath(pathv)) { //解析环境参数PATH中路径,如果失败则输出错误信息提示 printf("Path parse failed"); exit(0); } while(1) //设置死循环可以使user重复输入命令 { printPrompt(); //输出提示符 fgets(cmdline,LINE_LEN,stdin); //将命令行的参数输入到cmdLine中 if(*cmdline == '@') exit(0); //如果是命令是"@"则退出该程序中的死循环 parseCommand(cmdline,&command); //解析命令 command.argv[command.argc] = NULL; //命令行参数的数组最后以NULL结尾 command.name = lookupPath(command.argv, pathv);//查找命令行中可执行文件所在的目录路径 if(command.name == NULL) { //如果未找到,则输处未找到的提示进入下一个命令的执行 continue; } if((pid = fork()) == 0) //创建一个子进程 {//子进程执行下列操作
//execv()的函数实例:execv("/bin/ls",NULL) strcpy(path_cp,command.name); strcat(path_cp,"/"); strcat(path_cp,command.argv[0]); //将path_cp设定为execv()函数指定的路径格式,加上/filename if( execv(path_cp,command.argv)<0) printf("err!\n");
//如果进程执行发生错误则显示错误提示 } else //父进程执行该操作,等待子进程执行完成 wait(&status); } return 0; }int parseCommand(char *cLine,struct command_t *cmd){ //命令解析 int argc; char **clPtr; clPtr = &cLine; argc = 0; cmd->argv[argc] = (char *)malloc(MAX_ARG_LEN); while((cmd->argv[argc] = strsep(clPtr,WHITESPACE)) != NULL) { //strsep()函数根据WHITESPACE的值将clPtr(命令行)分隔开,即根据","、空格和回车分开命令参数 cmd->argv[++argc] = (char *)malloc(MAX_ARG_LEN); } cmd->argc = argc - 1; cmd->name = (char *)malloc(sizeof(cmd->argv[0])); strcpy(cmd->name,cmd->argv[0]); //将文件名存入结构的command.name中 return 1;}void printPrompt(){ //打印提示符,"主机名$" char *promptString; promptString = HOSTNAME; printf("%s$",promptString);}int parsePath(char *dirs[]){ //路径解析 char *pathEnvVar; char *thePath; int i; char *str = ":"; for(i = 0; i<MAX_PATHS; i++) pathv[i] = NULL; //进行数组的初始化 pathEnvVar = (char *) getenv("PATH"); //char *getenv(const char *name);可以得到环境变量 thePath = (char *) malloc(strlen(pathEnvVar) + 1); strcpy(thePath,pathEnvVar); //将环境变量中的目录路径输入到thePath中 i = 0; while((pathv[i++] = strsep(&thePath,str)) != NULL); //将环境变量中的路径根据":"进行分割,存入pathv[]数组中 return 1;}char *lookupPath(char **argv, char *div[]){ //获得命令行中可执行文件所在的目录路径 int i; char *result; char pName[MAX_PATH_LEN]; DIR *pDir = NULL; struct dirent *pDirent = NULL; if(*argv[0] == '/') { //命令本身就是绝对路径,则直接返回 result = argv[0]; return result; } else if(*argv[0] == '.') { //是当前目录下的 result = "/usr/project"; return result; } else { //相对路径 for(i = 0; i < MAX_PATHS; i++) { //对每个目录进行查找,是否存在该可执行文件 if(div[i] == NULL) break; //查找完毕则跳出,否则会出现段错误 pDir = opendir(div[i]); //打开目录 if(pDir) { while(pDirent = readdir(pDir)) { //对目录中的文件进行读,当读完后则返回0值并跳出循环 if(strlen(pDirent->d_name) != strlen(argv[0])) { //比较长度,不同则继续查找下一个文件 continue; } if(!strncmp(pDirent->d_name, argv[0], pDirent->d_reclen)) { //对两个文件名进行比较 result = div[i]; return result; } } } } fprintf(stderr, "%s:command not found\n",argv[0]); //没有找到则返回未找到命令的信息 return NULL; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -