增加功能以使用户可以使用“&”操作符作为命令的结束符。一个以“&”结尾的命令应该与shell并发执行。 增加功能以使用户可以使用“<”和“>”作为文件名前缀来重定向stdin和stdout描述符。同样,允许用户使用管道操作符“|”来同时执行两个进程,并把第一个进程的stdout重定向为第二个进程的stdin。c语言代码
时间: 2023-09-11 17:05:50 浏览: 143
通过管道进行cmd进程输入输出重定向,源代码
4星 · 用户满意度95%
以下是一个简单的C语言代码示例,实现了上述提到的功能。该示例代码使用了execvp()函数来执行命令,使用dup2()函数来重定向stdin和stdout描述符,使用pipe()函数来创建管道,使用fork()函数来创建子进程并实现进程间通信。
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_CMD_LEN 1024
#define MAX_ARG_NUM 64
void execute_command(char **args, int in_fd, int out_fd);
int main(int argc, char *argv[]) {
char command[MAX_CMD_LEN];
char *args[MAX_ARG_NUM];
int in_fd, out_fd, pipe_fd[2];
int i, j, k;
while (1) {
printf(">");
fgets(command, MAX_CMD_LEN, stdin);
command[strlen(command) - 1] = '\0'; // 去掉换行符
// 检查是否以&结尾
int bg_exec = 0;
if (command[strlen(command) - 1] == '&') {
bg_exec = 1;
command[strlen(command) - 1] = '\0';
}
// 检查是否包含管道符
int pipe_exec = 0;
int pipe_pos = -1;
for (i = 0; i < strlen(command); i++) {
if (command[i] == '|') {
pipe_exec = 1;
pipe_pos = i;
break;
}
}
// 检查是否包含重定向符
int in_redirect = 0, out_redirect = 0;
char in_file[MAX_CMD_LEN], out_file[MAX_CMD_LEN];
for (i = 0; i < strlen(command); i++) {
if (command[i] == '<') {
in_redirect = 1;
k = 0;
for (j = i + 1; j < strlen(command); j++) {
if (command[j] == ' ') continue;
if (command[j] == '>' || command[j] == '|') break;
in_file[k++] = command[j];
}
in_file[k] = '\0';
} else if (command[i] == '>') {
out_redirect = 1;
k = 0;
for (j = i + 1; j < strlen(command); j++) {
if (command[j] == ' ') continue;
if (command[j] == '<' || command[j] == '|') break;
out_file[k++] = command[j];
}
out_file[k] = '\0';
}
}
// 解析命令参数
k = 0;
args[k++] = strtok(command, " ");
while ((args[k++] = strtok(NULL, " ")) != NULL);
// 创建子进程并执行命令
pid_t pid;
if (pipe_exec) {
pipe(pipe_fd);
pid = fork();
if (pid == 0) {
close(pipe_fd[0]);
dup2(pipe_fd[1], STDOUT_FILENO);
execute_command(args, in_fd, pipe_fd[1]);
exit(0);
} else {
close(pipe_fd[1]);
dup2(pipe_fd[0], STDIN_FILENO);
waitpid(pid, NULL, 0);
k = 0;
args[k++] = strtok(&command[pipe_pos + 1], " ");
while ((args[k++] = strtok(NULL, " ")) != NULL);
execute_command(args, pipe_fd[0], out_fd);
}
} else {
if (in_redirect) {
in_fd = open(in_file, O_RDONLY);
if (in_fd < 0) {
printf("Failed to open input file!\n");
continue;
}
}
if (out_redirect) {
out_fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (out_fd < 0) {
printf("Failed to open output file!\n");
continue;
}
}
pid = fork();
if (pid == 0) {
execute_command(args, in_fd, out_fd);
exit(0);
} else {
if (bg_exec) {
continue; // 后台执行
} else {
waitpid(pid, NULL, 0); // 前台等待
}
}
}
}
return 0;
}
void execute_command(char **args, int in_fd, int out_fd) {
if (in_fd != STDIN_FILENO) {
dup2(in_fd, STDIN_FILENO);
close(in_fd);
}
if (out_fd != STDOUT_FILENO) {
dup2(out_fd, STDOUT_FILENO);
close(out_fd);
}
execvp(args[0], args);
printf("Failed to execute command!\n");
}
```
请注意,这只是一个简单的示例代码,实现了所需的功能,但可能存在一些问题和限制。实际上,实现一个完整的shell还需要考虑很多其他方面的问题,比如输入输出重定向的错误处理、管道中进程的顺序、后台任务的处理等等。
阅读全文