⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minishell.c

📁 模拟实现一个迷你小内核
💻 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 + -