linux系统编程综合练习-实现一个小型的shell程序(四)

上节中已经对后台作业进行了简单处理,基本上要实现的功能已经完了,下面回过头来,对代码进行一个调整,把写得不好的地方梳理一下,给代码加入适当的注释,这种习惯其实是比较好了,由于在开发的时候时间都比较紧,都只是想办法去尽快实现,而肯定会有一些代码是写得不太好的,所以有时间的话最好是从头至尾将整个代码进行梳理,也许在梳理的过程中会发现许多不足的地方,好了,下面开始:
linux系统编程综合练习-实现一个小型的shell程序(四)
而这个信号安装函数是在init.c中实现的:
linux系统编程综合练习-实现一个小型的shell程序(四)
接下来进行shell循环:
linux系统编程综合练习-实现一个小型的shell程序(四)
它的实现是在parse.c中:
linux系统编程综合练习-实现一个小型的shell程序(四)
如注释所示,可以挪至init.c中:
linux系统编程综合练习-实现一个小型的shell程序(四)
接下来,获取命令:
linux系统编程综合练习-实现一个小型的shell程序(四)
linux系统编程综合练习-实现一个小型的shell程序(四)
然后解析命令:
linux系统编程综合练习-实现一个小型的shell程序(四)
接下来的这句,是为了测试,在发布时可以注释掉了:
linux系统编程综合练习-实现一个小型的shell程序(四)
最后执行命令:
linux系统编程综合练习-实现一个小型的shell程序(四)
这个方法里面的代码有点乱,下面将其实现抽取到另外一个文件中,使得该函数要看起来清爽一些:
linux系统编程综合练习-实现一个小型的shell程序(四)
linux系统编程综合练习-实现一个小型的shell程序(四)
linux系统编程综合练习-实现一个小型的shell程序(四)
linux系统编程综合练习-实现一个小型的shell程序(四)
其实现execute.c:
#include "execute.h"
#include "def.h"
#include "externs.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <linux/limits.h>
#include <fcntl.h>

void forkexec(int i){
    pid_t pid;
    pid = fork();
    if(pid == -1) {
        /* 创建进程失败了 */
        ERR_EXIT("fork");
    }

    if(pid > 0) {
        /* 父进程 */
        if (backgnd == 1)
            printf("%d
", pid);
        lastpid = pid;
    } else if(pid == 0) {
        /* 子进程 */

        /* 表示将第一条简单命令的infd重定向至/dev/null,其中cmd[i].infd == 0只有可能是第一条简单命令 */
        /* 当第一条命令试图从标准输入获取数据的时候立既返回EOF */
        if(cmd[i].infd == 0 && backgnd == 1){
            //屏蔽后台作业,因为没有实现作业控制
            cmd[i].infd = open("/dev/null", O_RDONLY);
        }

        /* 将第一个简单命令进程作为进程组组长 */
        if(i == 0){
            setpgid(0, 0);
        }
        if(cmd[i].infd != 0){
            //说明该命令的输入是指向管道的读端
            close(0);
            dup(cmd[i].infd);
        }
        if(cmd[i].outfd != 1){
            //说明该命令的输出指向的是管道的写端
            close(1);
            dup(cmd[i].outfd);
        }
        /* 关闭3以上的所有文件描述符 */
        /*int i;
        for(i=3; i<OPEN_MAX; ++i){
            close(i);
        }*/

        /*前台作业能够接收SIGINT,SIGQUIT信号,这两个信号就要恢复成默认操作*/
        if(backgnd == 0){//非后台作业
            signal(SIGINT, SIG_DFL);
            signal(SIGQUIT, SIG_DFL);
        }

        /* 开始替换进程 */
        execvp(cmd[i].args[0], cmd[i].args);
        /* 如果执行到这句,则证明替换失败了 */
        exit(EXIT_FAILURE);
    }
}

int execute_disk_command(void){
    /* ls | grep init | wc -w */
    if(cmd_count == 0) {
        return 0;
    }
    if(infile[0] != '