C语言实现Shell脚本重定向函数check4redirection(char **arg_array, shellstatus *status)和执行函数execute(char **arg_array, shellstatus status)代码
时间: 2023-05-25 15:06:31 浏览: 66
以下是一个简单的实现,仅支持重定向到文件或管道:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
typedef struct {
int redirect_stdout;
char *output_file;
int redirect_stdin;
char *input_file;
int pipe_to_next;
} redirection_info;
typedef struct {
int last_status;
} shellstatus;
void parse_redirection(char **arg_array, redirection_info *redir_info) {
int i;
for (i = 0; arg_array[i]; i++) {
// Output redirection
if (strcmp(arg_array[i], ">") == 0) {
if (arg_array[i+1]) {
redir_info->redirect_stdout = 1;
redir_info->output_file = arg_array[i+1];
arg_array[i] = NULL; // Remove redirection symbol from arg list
arg_array[i+1] = NULL; // Remove output file name from arg list
} else {
printf("Error: missing output file name after >\n");
}
// Input redirection
} else if (strcmp(arg_array[i], "<") == 0) {
if (arg_array[i+1]) {
redir_info->redirect_stdin = 1;
redir_info->input_file = arg_array[i+1];
arg_array[i] = NULL; // Remove redirection symbol from arg list
arg_array[i+1] = NULL; // Remove input file name from arg list
} else {
printf("Error: missing input file name after <\n");
}
// Pipe to next command
} else if (strcmp(arg_array[i], "|") == 0) {
redir_info->pipe_to_next = 1;
arg_array[i] = NULL; // Remove pipe symbol from arg list
}
}
}
void execute(char **arg_array, shellstatus status) {
pid_t pid;
int status_code;
redirection_info redir_info;
redir_info.redirect_stdout = 0;
redir_info.output_file = NULL;
redir_info.redirect_stdin = 0;
redir_info.input_file = NULL;
redir_info.pipe_to_next = 0;
parse_redirection(arg_array, &redir_info);
pid = fork();
if (pid == 0) {
// Child process - execute command
if (redir_info.redirect_stdout) {
int fd = open(redir_info.output_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
printf("Error: cannot open output file %s\n", redir_info.output_file);
exit(1);
}
dup2(fd, STDOUT_FILENO);
close(fd);
}
if (redir_info.redirect_stdin) {
int fd = open(redir_info.input_file, O_RDONLY);
if (fd < 0) {
printf("Error: cannot open input file %s\n", redir_info.input_file);
exit(1);
}
dup2(fd, STDIN_FILENO);
close(fd);
}
if (redir_info.pipe_to_next) {
int pipefd[2];
pipe(pipefd);
pid_t pipe_pid = fork();
if (pipe_pid == 0) {
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
execvp(arg_array[0], arg_array);
printf("Error: cannot execute command %s\n", arg_array[0]);
exit(1);
} else if (pipe_pid > 0) {
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
execvp(arg_array[0], arg_array);
printf("Error: cannot execute command %s\n", arg_array[0]);
exit(1);
} else {
printf("Error: cannot fork process\n");
}
} else {
execvp(arg_array[0], arg_array);
printf("Error: cannot execute command %s\n", arg_array[0]);
exit(1);
}
} else if (pid > 0) {
// Parent process - wait for child to finish
waitpid(pid, &status_code, 0);
status.last_status = WIFEXITED(status_code) ? WEXITSTATUS(status_code) : -1;
} else {
printf("Error: cannot fork process\n");
}
}
int main() {
char command[1024];
char *arg_array[256];
int i;
shellstatus status;
status.last_status = 0;
while (1) {
printf(">");
fgets(command, sizeof(command), stdin);
if (command[strlen(command)-1] == '\n') {
command[strlen(command)-1] = '\0'; // Remove trailing newline
}
if (strlen(command) == 0) {
continue; // Ignore empty command
}
// Split command into args
char *token = strtok(command, " ");
i = 0;
while (token != NULL && i < 256) {
arg_array[i] = token;
token = strtok(NULL, " ");
i++;
}
arg_array[i] = NULL;
execute(arg_array, status);
}
return 0;
}
```