使用 dup2 重定向标准输入和标准输出
Redirecting stdin and stdout using dup2
我正在编写自己的自定义 shell,作为我项目的一部分,当程序从用户输入中读取“<”或“>”字符时,它需要重定向标准输入和标准输出到自定义文件。我在下面为此写了一个函数。我苦苦挣扎的部分是,即使我以几乎相同的方式编写输入和输出重定向的代码,输出重定向似乎按预期工作,而输入重定向却没有。请看下面的代码:
void inOutReDirector(char **toks, char *inputFile, char *outputFile, int *fd0, int *fd1, int *in, int *out) {
fflush(0);
for (int i = 0; toks[i] != NULL; i++) {
if (strcmp(toks[i], "<") == 0) {
toks[i] = NULL;
strcpy(inputFile, toks[i + 1]);
toks[i + 1] = NULL;
*in = 1;
}
if (strcmp(toks[i], ">") == 0) {
toks[i] = NULL;
strcpy(outputFile, toks[i + 1]);
toks[i + 1] = NULL;
*out = 1;
}
}
//input redirection
if (*in == 1) {
if ((*fd0 = open(inputFile, O_RDONLY, 0)) < 0) {
printf("Couldn't open input file: %s", strerror(errno));
exit(1);
}
dup2(*fd0, STDIN_FILENO);
close(*fd0);
}
//output redirection
if (*out == 1) {
if ((*fd1 = creat(outputFile, 0644)) < 0) {
printf("Couldn't open output file: %s", strerror(errno));
exit(1);
}
dup2(*fd1, STDOUT_FILENO);
close(*fd1);
}
}
下面是我如何从我的 main 中调用这个函数:
int main() {
char *toks[STD_INPUT_SIZE] = {0};
int fd0, fd1, in = 0, out = 0;
char inputFile[64], outputFile[64];
pid_t pid;
while (1) {
//print prompt
//get user input
pid = fork();
if (pid < 0) {
printf("%s \n", strerror(errno));
exit(1);
}
int stopNeeded = strcmp(toks[0], "exit") == 0;
if (pid == 0 && !stopNeeded) {
pathFinder(toks, shellInput, currentDir); //finding path for execv input
inOutReDirector(toks, inputFile, outputFile, &fd0, &fd1, &in, &out); // I/O redirection
if (execv(shellInput, toks) != 0) {
char *errMsg = strerror(errno);
printf("%s \n", errMsg);
//clean the old contents of toks
for (int i = 0; i < STD_INPUT_SIZE; ++i) {
free(toks[i]);
toks[i] = NULL;
}
exit(1);
}
}
if (pid > 0) {
pid_t childPid = waitpid(pid, NULL, 0);
(void) childPid;
}
}
return 0;
}
这是从我的终端屏幕输出重定向的示例
$ ls > output.txt
$
这将创建“output.txt”文件并在当前目录中打印此文件中的结果。
这是从我的终端屏幕输入重定向的示例
$ cat < output.txt
$
输入重定向无法正常工作。它打印提示并等待输入,而不是在我的终端中显示 output.txt 的内容。
感谢您提前提供的任何帮助!
问题应该出在函数的这一行inOutReDirector
if (strcmp(toks[i], ">") == 0) {
应该改为
else if (strcmp(toks[i], ">") == 0) {
当toks[i]
等于"<"时,上面的toks[i]
会被设置为NULL,这行调用strcmp会导致SIGSEGV,所以子进程会退出,后续的execv
不会被执行。
我正在编写自己的自定义 shell,作为我项目的一部分,当程序从用户输入中读取“<”或“>”字符时,它需要重定向标准输入和标准输出到自定义文件。我在下面为此写了一个函数。我苦苦挣扎的部分是,即使我以几乎相同的方式编写输入和输出重定向的代码,输出重定向似乎按预期工作,而输入重定向却没有。请看下面的代码:
void inOutReDirector(char **toks, char *inputFile, char *outputFile, int *fd0, int *fd1, int *in, int *out) {
fflush(0);
for (int i = 0; toks[i] != NULL; i++) {
if (strcmp(toks[i], "<") == 0) {
toks[i] = NULL;
strcpy(inputFile, toks[i + 1]);
toks[i + 1] = NULL;
*in = 1;
}
if (strcmp(toks[i], ">") == 0) {
toks[i] = NULL;
strcpy(outputFile, toks[i + 1]);
toks[i + 1] = NULL;
*out = 1;
}
}
//input redirection
if (*in == 1) {
if ((*fd0 = open(inputFile, O_RDONLY, 0)) < 0) {
printf("Couldn't open input file: %s", strerror(errno));
exit(1);
}
dup2(*fd0, STDIN_FILENO);
close(*fd0);
}
//output redirection
if (*out == 1) {
if ((*fd1 = creat(outputFile, 0644)) < 0) {
printf("Couldn't open output file: %s", strerror(errno));
exit(1);
}
dup2(*fd1, STDOUT_FILENO);
close(*fd1);
}
}
下面是我如何从我的 main 中调用这个函数:
int main() {
char *toks[STD_INPUT_SIZE] = {0};
int fd0, fd1, in = 0, out = 0;
char inputFile[64], outputFile[64];
pid_t pid;
while (1) {
//print prompt
//get user input
pid = fork();
if (pid < 0) {
printf("%s \n", strerror(errno));
exit(1);
}
int stopNeeded = strcmp(toks[0], "exit") == 0;
if (pid == 0 && !stopNeeded) {
pathFinder(toks, shellInput, currentDir); //finding path for execv input
inOutReDirector(toks, inputFile, outputFile, &fd0, &fd1, &in, &out); // I/O redirection
if (execv(shellInput, toks) != 0) {
char *errMsg = strerror(errno);
printf("%s \n", errMsg);
//clean the old contents of toks
for (int i = 0; i < STD_INPUT_SIZE; ++i) {
free(toks[i]);
toks[i] = NULL;
}
exit(1);
}
}
if (pid > 0) {
pid_t childPid = waitpid(pid, NULL, 0);
(void) childPid;
}
}
return 0;
}
这是从我的终端屏幕输出重定向的示例
$ ls > output.txt
$
这将创建“output.txt”文件并在当前目录中打印此文件中的结果。
这是从我的终端屏幕输入重定向的示例
$ cat < output.txt
$
输入重定向无法正常工作。它打印提示并等待输入,而不是在我的终端中显示 output.txt 的内容。
感谢您提前提供的任何帮助!
问题应该出在函数的这一行inOutReDirector
if (strcmp(toks[i], ">") == 0) {
应该改为
else if (strcmp(toks[i], ">") == 0) {
当toks[i]
等于"<"时,上面的toks[i]
会被设置为NULL,这行调用strcmp会导致SIGSEGV,所以子进程会退出,后续的execv
不会被执行。