📄 execute.c
字号:
history.end = -1; history.start = 0; len = 0;
//将路径文件内容依次读入到buf[]中 while(read(fd, &c, 1) != 0){ buf[len++] = c; } buf[len] = '\0';
//将环境路径存入envPath[] getEnvPath(len, buf); //注册信号 struct sigaction action; action.sa_sigaction = rmJob; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); signal(SIGTSTP, ctrl_Z);}
/*******************************************************
命令解析
********************************************************/SimpleCmd* handleSimpleCmdStr(int begin, int end){ int i, j, k; int fileFinished; //记录命令是否解析完毕 char c, buff[10][40], inputFile[30], outputFile[30], *temp = NULL; SimpleCmd *cmd = (SimpleCmd*)malloc(sizeof(SimpleCmd));
//默认为非后台命令,输入输出重定向为null cmd->isBack = 0; cmd->input = cmd->output = NULL; //初始化相应变量 for(i = begin; i<10; i++){ buff[i][0] = '\0'; } inputFile[0] = '\0'; outputFile[0] = '\0'; i = begin;
//跳过空格等无用信息 while(i < end && (inputBuff[i] == ' ' || inputBuff[i] == '\t')){ i++; } k = 0; j = 0; fileFinished = 0; temp = buff[k]; //以下通过temp指针的移动实现对buff[i]的顺次赋值过程 while(i < end){
/*根据命令字符的不同情况进行不同的处理*/ switch(inputBuff[i]){ case ' ': case '\t': //命令名及参数的结束标志 temp[j] = '\0'; j = 0; if(!fileFinished){ k++; temp = buff[k]; } break;
case '<': //输入重定向标志
if(j != 0){
temp[j] = '\0';
j = 0;
if(!fileFinished){
k++;
temp = buff[k];
}
}
temp = inputFile;
fileFinished = 1;
i++;
break; case '>': //输出重定向标志 if(j != 0){ temp[j] = '\0'; j = 0; if(!fileFinished){ k++; temp = buff[k]; } } temp = outputFile; fileFinished = 1; i++; break; case '&': //后台运行标志 if(j != 0){ temp[j] = '\0'; j = 0; if(!fileFinished){ k++; temp = buff[k]; } } cmd->isBack = 1; fileFinished = 1; i++; break; default: //默认则读入到temp指定的空间 temp[j++] = inputBuff[i++]; continue; }
//跳过空格等无用信息 while(i < end && (inputBuff[i] == ' ' || inputBuff[i] == '\t')){ i++; } } if(inputBuff[end-1] != ' ' && inputBuff[end-1] != '\t' && inputBuff[end-1] != '&'){ temp[j] = '\0'; if(!fileFinished){ k++; } }
//依次为命令名及其各个参数赋值 cmd->args = (char**)malloc(sizeof(char*) * (k + 1)); cmd->args[k] = NULL; for(i = 0; i<k; i++){ j = strlen(buff[i]); cmd->args[i] = (char*)malloc(sizeof(char) * (j + 1)); strcpy(cmd->args[i], buff[i]); }
//如果有输入重定向文件,则为命令的输入重定向变量赋值 if(strlen(inputFile) != 0){ j = strlen(inputFile); cmd->input = (char*)malloc(sizeof(char) * (j + 1)); strcpy(cmd->input, inputFile); }
//如果有输出重定向文件,则为命令的输出重定向变量赋值 if(strlen(outputFile) != 0){ j = strlen(outputFile); cmd->output = (char*)malloc(sizeof(char) * (j + 1)); strcpy(cmd->output, outputFile); } return cmd;}
/*******************************************************
命令执行
********************************************************/
/*执行外部命令*/void execOuterCmd(SimpleCmd *cmd){ pid_t pid; int pipeIn, pipeOut; if(exists(cmd->args[0])){ //命令存在
if((pid = fork()) < 0){ perror("fork failed"); return; } if(pid == 0){ //子进程 if(cmd->input != NULL){ //存在输入重定向 if((pipeIn = open(cmd->input, O_RDONLY, S_IRUSR|S_IWUSR)) == -1){ printf("不能打开文件 %s!\n", cmd->input); return; } if(dup2(pipeIn, 0) == -1){ printf("重定向标准输入错误!\n"); return; } } if(cmd->output != NULL){ //存在输出重定向
if((pipeOut = open(cmd->output, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1){
printf("不能打开文件 %s!\n", cmd->output);
return ;
}
if(dup2(pipeOut, 1) == -1){
printf("重定向标准输出错误!\n");
return;
}
} if(cmd->isBack){ //若是后台运行命令,等待父进程增加作业 signal(SIGUSR1, setGoon); //收到信号,setGoon函数将goon置1,以跳出下面的循环 while(goon == 0) ; //等待父进程SIGUSR1信号,表示作业已加到链表中 goon = 0; //置0,为下一命令做准备 printf("[%d]\t%s\t\t%s\n", getpid(), RUNNING, inputBuff); kill(getppid(), SIGUSR1); } justArgs(cmd->args[0]); if(execv(cmdBuff, cmd->args) < 0){ //执行命令 printf("execv failed!\n"); return; } }
else{ //父进程 if(cmd ->isBack){ //后台命令 fgPid = 0; //pid置0,为下一命令做准备 addJob(pid); //增加新的作业 kill(pid, SIGUSR1); //子进程发信号,表示作业已加入 //等待子进程输出 signal(SIGUSR1, setGoon); while(goon == 0) ; goon = 0; }else{ //非后台命令 fgPid = pid; waitpid(pid, NULL, 0); } } }else{ //命令不存在 printf("找不到命令 15%s\n", inputBuff); }}
/*执行命令*/void execSimpleCmd(SimpleCmd *cmd){ int i, pid; char *temp; Job *now = NULL; if(strcmp(cmd->args[0], "exit") == 0) { //exit命令 exit(0); } else if (strcmp(cmd->args[0], "history") == 0) { //history命令 if(history.end == -1){ printf("尚未执行任何命令\n"); return; } i = history.start; do { printf("%s\n", history.cmds[i]); i = (i + 1)%HISTORY_LEN; } while(i != (history.end + 1)%HISTORY_LEN); } else if (strcmp(cmd->args[0], "jobs") == 0) { //jobs命令 if(head == NULL){ printf("尚无任何作业\n"); } else { printf("index\tpid\tstate\t\tcommand\n"); for(i = 1, now = head; now != NULL; now = now->next, i++){ printf("%d\t%d\t%s\t\t%s\n", i, now->pid, now->state, now->cmd); } } } else if (strcmp(cmd->args[0], "cd") == 0) { //cd命令 temp = cmd->args[1]; if(temp != NULL){ if(chdir(temp) < 0){ printf("cd; %s 错误的文件名或文件夹名!\n", temp); } } } else if (strcmp(cmd->args[0], "fg") == 0) { //fg命令 temp = cmd->args[1]; if(temp != NULL && temp[0] == '%'){ pid = str2Pid(temp, 1, strlen(temp)); if(pid != -1){ fg_exec(pid); } }else{ printf("fg; 参数不合法,正确格式为:fg %<int>\n"); } } else if (strcmp(cmd->args[0], "bg") == 0) { //bg命令 temp = cmd->args[1]; if(temp != NULL && temp[0] == '%'){ pid = str2Pid(temp, 1, strlen(temp)); if(pid != -1){ bg_exec(pid); } }
else{ printf("bg; 参数不合法,正确格式为:bg %<int>\n"); } } else{ //外部命令 execOuterCmd(cmd); } //释放结构体空间 for(i = 0; cmd->args[i] != NULL; i++){ free(cmd->args[i]); free(cmd->input); free(cmd->output); }}
/*******************************************************
命令执行接口
********************************************************/void execute(){ SimpleCmd *cmd = handleSimpleCmdStr(0, strlen(inputBuff)); execSimpleCmd(cmd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -