| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 609 人关注过本帖
标题:麻烦大佬们帮我看看为什么我的这段shell程序如果直接回车会报错啊
只看楼主 加入收藏
oped02
Rank: 2
等 级:论坛游民
帖 子:38
专家分:20
注 册:2022-10-16
结帖率:100%
收藏
 问题点数:0 回复次数:2 
麻烦大佬们帮我看看为什么我的这段shell程序如果直接回车会报错啊
程序代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <readline/readline.h>
#include <readline/history.h>

pid_t pid;
int bg = 0;//是否后台运行
char commands[256][256];//分割后的命令
int inNum, outNum;//是否有重定向输出输入

int pipe_command(int, int);

//父进程处理信号函数
void signalCat() {
    if (pid != 0) {
        kill(pid, SIGINT);
        int status;
        waitpid(pid, &status, 0);
    }
}

//分割命令并返回条数
int split(char *command) {
    int num = 0;
    int i, j;
    int len = strlen(command);
    for (i = 0, j = 0; i < len; i++) {
        if (command[i] != ' ') {
            commands[num][j++] = command[i];
        } else {
            if (j != 0) {
                commands[num][j] = '\0';
                num++;
                j = 0;
            }
        }
    }
    if (j != 0) {
        commands[num][j] = '\0';
        num++;
    }
    return num;
}


//执行函数
int redo_command(int l, int r) {
    char *inFile = NULL, *outFile = NULL;
int in_h = r, out_h = r, flag = 0;
//寻找重定向
    for (int i = l; i < r; i++) { 
        if (strcmp(commands[i], "<") == 0) {
            inNum++;
            if (i + 1 < r) {
                inFile = commands[i + 1];
            } else {
                perror("in have no parameter\n");
                return -1; //重定向符号后缺少文件名
            }
            in_h = i;
        }
        if (strcmp(commands[i], ">") == 0 || strcmp(commands[i], ">>") == 0) {
            outNum++;
            if (i + 1 < r) {
                outFile = commands[i + 1];
            } else {
                perror("out have no parameter\n");
                return -1; //重定向符号后缺少文件名
            }
            out_h = i;
            if (strcmp(commands[i], ">>")==0) flag = 1;
        }
}
//如果多个重定向,错误
    if (inNum > 1 || outNum > 1) {
        perror("have too much in and out\n");
        return -1;
}
//分段递归执行
    int max_h = in_h;  
    if (in_h < out_h) max_h = out_h;
    int result = 0;

    pid = fork();

    int min_h = in_h;
    if (in_h > out_h) min_h = out_h;

    if (inNum == 1)
        freopen(inFile, "r", stdin);
    if (outNum == 1) {
        if (flag == 0)
            freopen(outFile, "w", stdout);
        else
            freopen(outFile, "a", stdout);
    }

    if (pid < 0) {
        perror("creat process fail\n");
        result = -1;
    } else if (pid == 0) {
        char *comm[256];
        int tag = 0;
        for (int i = l; i < min_h; i++)
            comm[tag++] = commands[i];
        comm[tag] = NULL;
        execvp(comm[0], comm);
        perror("input error!\n");
        exit(EXIT_FAILURE);
    } else {
        if (abs(in_h - out_h) > 2) {
            pipe_command(min_h + 2, max_h);
        }
        if (max_h + 1 < r) pipe_command(max_h + 2, r);
        int status;
        if (bg == 0) {
            waitpid(pid, &status, 0);
        } else {
            printf("BACKGROUND RUNNING\n");
        }
    }
    return result;
}




//是否有管道,有管道就相当于父子进程间的通信
int pipe_command(int l, int r) {
    if (l >= r) return 0;
    int pipe_h = -1; //判断是否有管道命令
    for (int i = l; i < r; i++) {
        if (strcmp(commands[i], "|") == 0) {
            pipe_h = i;
            break;
        }
    }
    if (pipe_h == -1) { //无管道命令
        return redo_command(l, r);
    } else if (pipe_h + 1 == r) { //管道命令'|'后没有指令,也就是没有参数
        printf("| have no parameter\n");
        return -1;
    }

//开始执行命令
    int pipe_id[2];
    if (pipe(pipe_id) < 0) {
        perror("create pipe error\n");
        return -1;
    }



    int result = 0;
    pid = fork();
    if (pid == -1) {
        result = -1;
    } else if (pid == 0) {//子进程执行单个命令
        close(pipe_id[0]);
        dup2(pipe_id[1], STDOUT_FILENO); //将标准输出重定向到pipe_id[1]
        result = redo_command(l, pipe_h);
        exit(result);
    } else { // 父进程递归执行后续命令
        int status;
        waitpid(pid, &status, 0);
        if (pipe_h + 1 < r) {
            close(pipe_id[1]);
            dup2(pipe_id[0], STDIN_FILENO);
            result = pipe_command(pipe_h + 1, r);
        }
    }
    return result;
}



int main() {
    signal(SIGINT, signalCat);
    read_history(NULL);
    while (1) {
        inNum = 0;
        outNum = 0;
        char *argv;
        argv = readline("Myshell$ ");
        add_history(argv);
        int len = strlen(argv);
        if (strcmp(argv, "exit") == 0) {
            printf("thanks for your use!\n");
            exit(EXIT_SUCCESS);
        }

        if (argv[len - 1] == '&') {//是否后台
            bg = 1;
            argv[len - 1] = '\0';
        } else bg = 0;
        int commandNum = split(argv);
//        for (int i = 0; i < commandNum; i++) {
//            printf("%s\n", commands[i]);
//        }
    // 获取标准输入、输出的文件标识符
        int inPipe = dup(STDIN_FILENO);
        int outPipe = dup(STDOUT_FILENO);
        pipe_command(0, commandNum);

    //还原标准输入、输出重定向
        dup2(inPipe, STDIN_FILENO);
        dup2(outPipe, STDOUT_FILENO);
        free(argv);
    }
    return 0;
}
搜索更多相关主题的帖子: include pid result return int 
2022-11-03 09:40
oped02
Rank: 2
等 级:论坛游民
帖 子:38
专家分:20
注 册:2022-10-16
收藏
得分:0 
图片附件: 游客没有浏览图片的权限,请 登录注册

这里是其错误截图
2022-11-03 09:41
oped02
Rank: 2
等 级:论坛游民
帖 子:38
专家分:20
注 册:2022-10-16
收藏
得分:0 
图片附件: 游客没有浏览图片的权限,请 登录注册

如果我不使用-g -fsanitize=address编译的话,直接回车也不会有问题
2022-11-03 09:43
快速回复:麻烦大佬们帮我看看为什么我的这段shell程序如果直接回车会报错啊
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.055041 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved