我正在用C设计自己的shell,但是有一个非常奇怪的问题,到目前为止,我只在使用sort
进行管道处理时才遇到这种情况。
每当我使用sort
(例如ls | sort -r
)运行管道时,输出都是正确的,但仅在退出外壳程序时显示。我尝试用不同的方式进行分叉/管道传输,重定向管道的stderror输出(以防万一它被放到那里,等等)而无法解决。
奇怪的是,其他管道命令,例如grep
甚至lolcat
似乎都可以正常工作。如果有人可以在这里指导我,我将不胜感激。我的命令执行功能包括在下面。
int exec_command(char *command) {
pid_t pid;
// Split the arguments
char *args[LENGTH];
int i = 0;
// Gets the first token, tokenizing on ' '
char *token = strtok(command, " ");
while (token != NULL && i < LENGTH - 1) { // Ensures we don't go out of bounds
args[i] = token; // Append it to the args list
token = strtok(NULL, " "); // Fetch next token
i++; // Increment our index
}
args[i] = NULL; // Set the element after last to NULL
// Handles cd
// Removed for simplicity
int pipe_index;
if ((pipe_index = find_pipe(args)) != -1) { // Has a pipe
// Split the args array into two arrays - left half and right half - based on the pipe
args[pipe_index] = NULL; // args (left_args) ends at the pipe
char *right_args[LENGTH];
for (i = pipe_index + 1; i < LENGTH - 1 && args[i] != NULL; i++)
right_args[i - pipe_index - 1] = args[i]; // right_args contains everything after the pipe
right_args[i - pipe_index - 1] = NULL; // end right_args
int pipefd[3];
if (pipe(pipefd) == -1) { // Create pipe
perror("pipe");
return -1;
}
if ((pid = fork()) < 0) { // Create child
perror("fork");
return -1;
}
if (pid == 0) { // In child
if ((pid = fork()) < 0) { // Create grandchild
perror("fork");
return -1;
}
if (pid == 0) { // Grandchild reads from pipe and handles the right-half command
close(pipefd[1]); // Close unused write end
dup2(pipefd[0], 0); // Replaces standard input with pipe input
if(execvp(right_args[0], right_args) == -1)
printf("Command failed. Check spelling and arguments\n");
kill(getpid(), SIGTERM); // Ensure the grandchild is killed
return 0;
} else { // Child writes to pipe and handles the left command
close(pipefd[0]); // Close unused read end
dup2(pipefd[1], 1); // Replaces standard output with pipe output
dup2(pipefd[2], 2); // Replaces standard error with pipe error
if(execvp(args[0], args) == -1)
printf("Command failed. Check spelling and arguments\n");
kill(getpid(), SIGTERM); // Ensure the child is killed
return 0;
}
} else // In parent
wait(0);
return 0;
} // End pipe
// Executes normal commands, those without a pipe
// Removed for simplicity
return 0;
}