【发布时间】:2014-11-24 04:00:47
【问题描述】:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
void tokenizer(char* input, char** output) { //My tokenizer
char* input_dup = strdup(input);
output[0] = strtok(input_dup, " ");
int i = 1;
while ((output[i] = strtok(NULL, " ")) != NULL) {
i++;
}
}
void run_command(char** args, int* fd) { //no pipe
pid_t pid = fork();
if (pid < 0) {
printf("Forking failed...\n");
}
else if (pid == 0) {
close(fd[0]);
if (fd[1] != 1)
dup2(fd[1], 1);
execvp(args[0], args);
printf("Command failed...\n");
exit(1);
}
else {
close(fd[1]);
wait(pid);
char buff[1];
while (read(fd[0], buff, 1) > 0) {
if (buff[0] == EOF || buff[0] == '\0') {
printf("Caught something, returning out...");
return;
}
else {
printf("%c", buff[0]);
}
}
}
}
//pipeline function
void run_pipe(char** args, int* fd) {
pid_t pid = fork();
if (pid < 0) {
printf("Forking failed...\n");
}
else if (pid == 0) {
if (fd[1] != 1) {
dup2(fd[1], 1);
}
execvp(args[0], args);
printf("Command failed...\n");
exit(1);
}
else {
close(fd[1]);
if (fd[0] != 0) {
dup2(fd[0], 0);
}
wait(pid);
}
}
int main(int argc, char** argv) {
printf ("Starting myshell (mysh) \n..\n..\n");
while (1) {
char cwd[1024];
printf ("mysh :: %s -> ", getcwd(cwd, sizeof(cwd)));
char ch[1024];
memset(ch, 0, 1023); //for cleanup
char c = 0;
int i = 0;
while (c != '\n') {
c = getchar();
if (c == EOF) {
printf ("EOF Received, exiting...\n");
return 0;
}
if (c != '\n')
ch[i] = c;
i++;
}
if (ch[0] != '\0') {
char* tokens[128];
tokenizer(ch, tokens);
//first check for keywords
if (strcmp(tokens[0], "cd") == 0) {
if (chdir(tokens[1]) < 0) {
printf("ERROR: Directory %s does not exist\n", tokens[1]);
}
}
else if (strcmp(tokens[0], "exit") == 0) {
printf("Leaving shell...\n");
return 0;
}
else {
char* commands[50];
memset(commands, 0, sizeof(commands));
int j = 0;
int k = 0;
int fd[2];
//try something different...
while (tokens[j] != NULL) {
if (strcmp(tokens[j], "|") == 0) {
commands[k] = NULL;
pipe(fd);
run_pipe(commands, fd);
j++;
k = 0;
}
//more cases here
else { //nothing special
commands[k] = tokens[j];
j++;
k++;
}
}
commands[k] = NULL;
pipe(fd);
run_command(commands, fd);
}
}
}
}
上面的代码是为了模拟一个shell。它处理单个命令并正确处理流水线(即 ps | sort | wc 返回正确的输出),但是当流水线完成时,它返回一个 EOF,该 EOF 被 getchar() 循环中的条件捕获。如果我尝试忽略此 EOF,则会出现段错误。我是否在某处打开了管道并且标准输入被淹没了?任何帮助表示赞赏。
【问题讨论】:
-
用
gcc -Wall -Wextra -Werror -Wmissing-prototypes编译会发现wait()没有被声明;添加#include <sys/wait.h>,你会发现编译错误。这可能是也可能不是你所有麻烦的根源,但它会解释段错误——你在需要指针的地方传递一个整数。 FWIW:始终使用与建议的一样严格甚至更严格的选项进行编译(我通常使用一些额外的选项:-Wold-style-declaration -Wold-style-definition -Wstrict-prototypes,这需要对您的代码进行其他小的更改。) -
修复了对
wait()的调用,我得到了可理解的、不崩溃的结果。 -
@JonathanLeffler 你能发布一个固定等待的小sn-p吗?我已经修复了导入,但现在不知道如何修复等待/waitpids
-
@JonathanLeffler 我实现了等待更改,但这并没有真正解决任何问题,在调用类似 ps |排序
标签: c shell operating-system