C语言execve管道实现问题:输出被readline误解析致崩溃
管道命令输出被readline误解析问题
实现基于execve的管道处理逻辑时,已将带管道符|的命令拆分后逐个传入处理函数,通过fork、dup2和close完成管道搭建,命令整体可正常执行,但最后一条命令的输出会同时发送到终端和readline函数,导致readline将该输出当作用户输入的命令进行解析。例如执行ls | wc时,输出结果“8”被readline识别为命令,触发“8不是命令”的错误提示,甚至引发段错误。
主循环代码
while (++i < nproc) { rdl->main_str = ft_strdup(rdl->pipe_str[i]); rdl->len = ft_strlen(rdl->pipe_str[i]); parser(rdl); command(rdl); // => run a pipe_exec function token_clear(&rdl->token); free(rdl->main_str); printf("*****************\n"); } while (nproc-- > 0) waitpid(-1, 0, 0);
pipe_exec相关代码
#define READ 0 #define WRITE 1 static void ft_fatality(void) { ft_putstr_fd("error: fatal\n", 2); exit(1); } // static void ft_exec_error(char *str) // { // ft_putstr_fd("error: cannot execute ", 2); // ft_putstr_fd(str, 2); // ft_putstr_fd("\n", 2); // exit(1); // } static void ft_openpipes(int fd[2]) { if (close(fd[READ]) == -1) ft_fatality(); if (dup2(fd[WRITE], STDOUT_FILENO) == -1) ft_fatality(); if (close(fd[WRITE]) == -1) ft_fatality(); } static void ft_closepipes(int fd[2]) { if (dup2(fd[READ], STDIN_FILENO) == -1) ft_fatality(); if (close(fd[READ]) == -1) ft_fatality(); if (close(fd[WRITE]) == -1) ft_fatality(); } int pipe_exec(t_command command) { printf("pipe_exec\n"); printf("pipe_exec command count %d\n", command.count); int i; int j; int fd[2]; int type_size; int size; int result; char *arg; char *path; char **type; pid_t pid; i = -1; j = 1; result = 0; size = token_size(command.tokens); type_size = 0; arg = ft_strdup(""); if (pipe(fd) == -1) ft_fatality(); while (++i < size) { if (command.tokens->type_id == 12) type_size++; get_next_token(&command.tokens); } i = -1; path = command_find_path(command.keyword); type = (char **)malloc(sizeof(char *) * ((type_size + 1) + 2)); type[0] = ft_strdup(path); while (++i < size) { if (command.tokens->type_id == 13 || command.tokens->type_id == 7) { arg = ft_strjoin(arg, command.tokens->context); printf("arg %s\n", arg); } if (command.tokens->type_id == 12 || size - 1 == command.tokens->id) { type[j++] = ft_strdup(arg); arg = ft_strdup(""); } get_next_token(&command.tokens); } type[j] = NULL; j = -1; while (type[++j]) { printf("type : %s\n", type[j]); } pid = fork(); // signal(SIGINT, proc_signal_handler); if (pid < 0) return (-1); if (pid == 0) { ft_openpipes(fd); result = execve(path, type, g_env.env); } else ft_closepipes(fd); if (result == -1) return (1); waitpid(pid, 0, 0); command.fd[0] = fd[0]; command.fd[1] = fd[1]; free(arg); ft_free_dbl_str(type); free(path); return (0); }
运行日志
bash % ./minishell ->ls | wc -l ------------------- ls token->type->context keyword token->type->id 0 token->t_flag 0 | token->type->context pipe token->type->id 6 token->t_flag 6 wc token->type->context keyword token->type->id 0 token->t_flag 0 l token->type->context arg token->type->id 13 token->t_flag -1 ------------------- ------------------- ls token->type->context keyword token->type->id 0 token->t_flag 0 ------------------- pipe_exec pipe_exec command count 1 type : /bin/ls ***************** ------------------- wc token->type->context keyword token->type->id 0 token->t_flag 0 - token->type->context option token->type->id 7 token->t_flag 5 l token->type->context arg token->type->id 13 token->t_flag -1 ------------------- pipe_exec pipe_exec command count 2 arg - arg -l type : /usr/bin/wc type : -l ***************** -> 8 ------------------- 8 token->type->context string token->type->id 12 token->t_flag -1 token->type->context string token->type->id 12 token->t_flag -1 ------------------- **bash: 8: command not found ->zsh: segmentation fault ./minishell**
内容的提问来源于stack exchange,提问作者Enes Özmert
相关产品推荐
相关产品推荐

