编写一个C程序作为Linux内核的shell命令行解释程序。Shell程序应该使用与Bource shell相同的方式运行程序。 1、增加功能以使用户可以使用“&”操作符作为命令的结束符。一个以“&”结尾的命令应该与shell并发执行。 2、增加功能以使用户可以使用“<”和“>”作为文件名前缀来重定向stdin和stdout描述符。同样,允许用户使用管道操作符“|”来同时执行两个进程,并把第一个进程的stdout重定向为第二个进程的stdin。
时间: 2023-12-25 07:05:26 浏览: 64
好的,以下是一个简单的示例程序,可以实现您所需的功能:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_LINE 80
#define MAX_ARGS 10
int main(void) {
char *args[MAX_ARGS];
char line[MAX_LINE];
int should_run = 1;
while (should_run) {
printf("my_shell> ");
fflush(stdout);
fgets(line, MAX_LINE, stdin);
int i = 0;
int j = 0;
int k = 0;
int fd_in = 0;
int fd_out = 1;
int pipefd[2];
int pipe_exists = 0;
int background = 0;
while (line[i] != '\0') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\n') {
if (k != 0) {
args[j] = (char*)malloc(k+1);
strncpy(args[j], &line[i-k], k);
args[j][k] = '\0';
j++;
k = 0;
}
} else if (line[i] == '&') {
background = 1;
break;
} else if (line[i] == '|') {
pipe_exists = 1;
pipe(pipefd);
fd_out = pipefd[1];
break;
} else if (line[i] == '<') {
args[j] = NULL;
i++;
while (line[i] == ' ' || line[i] == '\t') {
i++;
}
k = 0;
while (line[i] != ' ' && line[i] != '\t' && line[i] != '\n') {
k++;
i++;
}
char *filename = (char*)malloc(k+1);
strncpy(filename, &line[i-k], k);
filename[k] = '\0';
fd_in = open(filename, O_RDONLY);
if (fd_in < 0) {
perror("open input file failed");
exit(1);
}
} else if (line[i] == '>') {
args[j] = NULL;
i++;
while (line[i] == ' ' || line[i] == '\t') {
i++;
}
k = 0;
while (line[i] != ' ' && line[i] != '\t' && line[i] != '\n') {
k++;
i++;
}
char *filename = (char*)malloc(k+1);
strncpy(filename, &line[i-k], k);
filename[k] = '\0';
fd_out = open(filename, O_CREAT|O_WRONLY|O_TRUNC, 0666);
if (fd_out < 0) {
perror("open output file failed");
exit(1);
}
} else {
if (k == 0) {
args[j] = (char*)malloc(1);
}
args[j][k] = line[i];
k++;
}
i++;
}
args[j] = NULL;
if (background) {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
if (pid == 0) {
if (fd_in != 0) {
dup2(fd_in, 0);
close(fd_in);
}
if (fd_out != 1) {
dup2(fd_out, 1);
close(fd_out);
}
execvp(args[0], args);
perror("execvp failed");
exit(1);
}
} else if (pipe_exists) {
pid_t pid1 = fork();
if (pid1 < 0) {
perror("fork failed");
exit(1);
}
if (pid1 == 0) {
close(pipefd[0]);
if (fd_in != 0) {
dup2(fd_in, 0);
close(fd_in);
}
if (fd_out != 1) {
dup2(fd_out, 1);
close(fd_out);
}
execvp(args[0], args);
perror("execvp failed");
exit(1);
}
pid_t pid2 = fork();
if (pid2 < 0) {
perror("fork failed");
exit(1);
}
if (pid2 == 0) {
close(pipefd[1]);
dup2(pipefd[0], 0);
close(pipefd[0]);
execvp(args[j+1], &(args[j+1]));
perror("execvp failed");
exit(1);
}
close(pipefd[0]);
close(pipefd[1]);
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
} else {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
if (pid == 0) {
if (fd_in != 0) {
dup2(fd_in, 0);
close(fd_in);
}
if (fd_out != 1) {
dup2(fd_out, 1);
close(fd_out);
}
execvp(args[0], args);
perror("execvp failed");
exit(1);
}
waitpid(pid, NULL, 0);
}
for (i = 0; i < j; i++) {
free(args[i]);
}
if (fd_in != 0) {
close(fd_in);
}
if (fd_out != 1) {
close(fd_out);
}
}
return 0;
}
```
这个程序可以实现基本的命令解释功能,并支持&、<、>和|操作符。请注意,这只是一个简单的示例程序,可能需要进一步调整和优化,以适应实际需求。
阅读全文