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

📄 execute.c

📁 linux下的简单的shell解释器
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <string.h>#include <ctype.h>#include <unistd.h>#include <fcntl.h>#include <math.h>#include <errno.h>#include <signal.h>#include <stddef.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/ioctl.h>#include <sys/termios.h>#include "global.h"int goon = 0, ingnore = 0;       //用于设置signal信号量char *envPath[10], cmdBuff[40];  //外部命令的存放路径及读取外部命令的缓冲空间History history;                 //历史命令Job *head = NULL;                //作业头指针pid_t fgPid;                     //当前前台作业的进程号/*******************************************************                  工具以及辅助方法********************************************************/
/*判断命令是否存在*/int exists(char *cmdFile){    int i = 0;    if((cmdFile[0] == '/' || cmdFile[0] == '.') && access(cmdFile, F_OK) == 0){ //命令在当前目录        strcpy(cmdBuff, cmdFile);        return 1;    }else{  //查找ysh.conf文件中指定的目录,确定命令是否存在        while(envPath[i] != NULL){ //查找路径已在初始化时设置在envPath[i]中            strcpy(cmdBuff, envPath[i]);            strcat(cmdBuff, cmdFile);                        if(access(cmdBuff, F_OK) == 0){ //命令文件被找到                return 1;            }                        i++;        }    }        return 0; }/*将字符串转换为整型的Pid*/int str2Pid(char *str, int start, int end){    int i, j;    char chs[20];        for(i = start, j= 0; i < end; i++, j++){        if(str[i] < '0' || str[i] > '9'){            return -1;        }else{            chs[j] = str[i];        }    }    chs[j] = '\0';        return atoi(chs);}
/*调整部分外部命令的格式*/void justArgs(char *str){    int i, j, len;    len = strlen(str);        for(i = 0, j = -1; i < len; i++){        if(str[i] == '/'){            j = i;        }    }
    if(j != -1){ //找到符号'/'
        for(i = 0, j++; j < len; i++, j++){
            str[i] = str[j];
        }
        str[i] = '\0';
    }}
/*设置goon*/void setGoon(){    goon = 1;}
/*释放环境变量空间*/void release(){    int i;    for(i = 0; strlen(envPath[i]) > 0; i++){        free(envPath[i]);    }}
/*******************************************************
                  信号以及jobs相关
********************************************************/
/*添加新的作业*/Job* addJob(pid_t pid){    Job *now = NULL, *last = NULL, *job = (Job*)malloc(sizeof(Job));    
	//初始化新的job    job->pid = pid;    strcpy(job->cmd, inputBuff);    strcpy(job->state, RUNNING);    job->next = NULL;        if(head == NULL){ //若是第一个job,则设置为头指针        head = job;    }else{ //否则,根据pid将新的job插入到链表的合适位置
		now = head;
		while(now != NULL && now->pid < pid){
			last = now;
			now = now->next;
		}        last->next = job;        job->next = now;    }        return job;}
/*移除一个作业*/void rmJob(int sig, siginfo_t *sip, void* noused){    pid_t pid;    Job *now = NULL, *last = NULL;        if(ingnore == 1){        ingnore = 0;        return;    }        pid = sip->si_pid;
    now = head;
	while(now != NULL && now->pid < pid){
		last = now;
		now = now->next;
	}        if(now == NULL){ //作业不存在,则不进行处理直接返回        return;    }    
	//开始移除该作业    if(now == head){        head = now->next;    }else{        last->next = now->next;    }        free(now);}
/*组合键命令ctrl+z*/void ctrl_Z(){    Job *now = NULL;        if(fgPid == 0){ //前台没有作业则直接返回        return;    }        //SIGCHLD信号产生自ctrl+z    ingnore = 1;    
	now = head;
	while(now != NULL && now->pid != fgPid)
		now = now->next;        if(now == NULL){ //未找到前台作业,则根据fgPid添加前台作业        now = addJob(fgPid);    }    
	//修改前台作业的状态及相应的命令格式,并打印提示信息    strcpy(now->state, STOPPED);     now->cmd[strlen(now->cmd)] = '&';    now->cmd[strlen(now->cmd) + 1] = '\0';    printf("[%d]\t%s\t\t%s\n", now->pid, now->state, now->cmd);    
	//发送SIGSTOP信号给正在前台运作的工作,将其停止    kill(fgPid, SIGSTOP);    fgPid = 0;}
/*fg命令*/void fg_exec(int pid){        Job *now = NULL; 
	int i;        //SIGCHLD信号产生自此函数    ingnore = 1;    
	//根据pid查找作业
    now = head;
	while(now != NULL && now->pid != pid)
		now = now->next;        if(now == NULL){ //未找到作业        printf("pid为7%d 的作业不存在!\n", pid);        return;    }
    //记录前台作业的pid,修改对应作业状态    fgPid = now->pid;    strcpy(now->state, RUNNING);        signal(SIGTSTP, ctrl_Z); //设置signal信号,为下一次按下组合键Ctrl+Z做准备    i = strlen(now->cmd) - 1;
    while(i >= 0 && now->cmd[i] != '&')
		i--;    now->cmd[i] = '\0';        printf("%s\n", now->cmd);    kill(now->pid, SIGCONT); //向对象作业发送SIGCONT信号,使其运行    waitpid(fgPid, NULL, 0); //父进程等待前台进程的运行}
/*bg命令*/void bg_exec(int pid){    Job *now = NULL;        //SIGCHLD信号产生自此函数    ingnore = 1;    
	//根据pid查找作业
	now = head;
    while(now != NULL && now->pid != pid)
		now = now->next;        if(now == NULL){ //未找到作业        printf("pid为7%d 的作业不存在!\n", pid);        return;    }        strcpy(now->state, RUNNING); //修改对象作业的状态    printf("[%d]\t%s\t\t%s\n", now->pid, now->state, now->cmd);        kill(now->pid, SIGCONT); //向对象作业发送SIGCONT信号,使其运行}
/*******************************************************
                    命令历史记录
********************************************************/void addHistory(char *cmd){    if(history.end == -1){ //第一次使用history命令        history.end = 0;        strcpy(history.cmds[history.end], cmd);        return;	}        history.end = (history.end + 1)%HISTORY_LEN; //end前移一位    strcpy(history.cmds[history.end], cmd); //将命令拷贝到end指向的数组中        if(history.end == history.start){ //end和start指向同一位置        history.start = (history.start + 1)%HISTORY_LEN; //start前移一位    }}/*******************************************************
                     初始化环境
********************************************************/
/*通过路径文件获取环境路径*/void getEnvPath(int len, char *buf){    int i, j, last = 0, pathIndex = 0, temp;    char path[40];        for(i = 0, j = 0; i < len; i++){        if(buf[i] == ':'){ //将以冒号(:)分隔的查找路径分别设置到envPath[]中            if(path[j-1] != '/'){                path[j++] = '/';            }            path[j] = '\0';            j = 0;                        temp = strlen(path);            envPath[pathIndex] = (char*)malloc(sizeof(char) * (temp + 1));            strcpy(envPath[pathIndex], path);                        pathIndex++;        }else{            path[j++] = buf[i];        }    }        envPath[pathIndex] = NULL;}/*初始化操作*/void init(){    int fd, n, len;    char c, buf[80];

	//打开查找路径文件ysh.conf    if((fd = open("ysh.conf", O_RDONLY, 660)) == -1){        perror("init environment failed\n");        exit(1);    }    
	//初始化history链表

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -