尝试使用 dup2() 和 open() 以及 execv() 将文件重定向到标准输入时出现问题
Having issues trying to redirect file to stdin using dup2() and open() and execv()
编辑:问题是 echo 显然没有从 stdin 读取。谢谢@Jonathan Leffler
我有一个编程练习,我的代码如下:
int processProgram(char **tokens, int requireWait) {
char *cmd = tokens[0];
if (access(cmd, R_OK) == -1) {
printf("%s not found\n", cmd);
return -1;
}
int index = 1;
char *iterator = tokens[index];
int inputTokenIndex = 0;
// Look for a < to figure out where the redirection is
while (iterator != NULL) {
if (strcmp(iterator, "<") == 0) { // <---- THIS IS WHERE I ATTEMPT TO FIND THE INDEX OF "<"
if (access(tokens[index + 1], R_OK) == -1) {
printf("%s does not exist\n", tokens[index + 1]);
return -1;
}
// set null at <
tokens[index] = NULL;
inputTokenIndex = index + 1;
break;
}
index++;
iterator = tokens[index];
}
// basically create a struct to store pids and stuff....
processList *process = addNewProcess();
int childPid = fork();
if (childPid == 0) {
// is the child
if (inputTokenIndex > 0) {
// if previously strcmp "<" is true
// set redirection for input....
int fd = open(tokens[inputTokenIndex], O_RDONLY); // <----- THIS IS WHERE I DO THE REDIRECTING FOR STDIN!
dup2(fd, STDIN_FILENO);
close(fd);
}
// start from where inputTokenIndex could have left off
// since > is always at least after < in our test cases
index = inputTokenIndex + 1;
iterator = tokens[index];
while (iterator != NULL) { // <--- LOOKING FOR ">" and "2>", CURRENTLY THIS WORKS FINE
// look for output redirection FROM previous while loop onwards
int out = 0;
if (strcmp(iterator, ">") == 0) {
// stdout
out = STDOUT_FILENO;
} else if (strcmp(iterator, "2>") == 0) {
// stderr
out = STDERR_FILENO;
}
if (out != 0) {
int fd = open(tokens[index + 1], O_WRONLY | O_TRUNC | O_CREAT, 0777);
dup2(fd, out);
tokens[index] = NULL;
close(fd);
}
index++;
iterator = tokens[index];
}
int value = execv(cmd, tokens); // <----- EXEC IS HERE!!
if (value == -1) {
exit(errno);
}
exit(0);
} else {
int status;
if (requireWait == 1) {
// wait for process to finish
process->pid = childPid;
wait(&status);
process->running = 0;
process->status = status;
if (status != 0) {
printf("%s failed", cmd);
}
} else {
process->pid = childPid;
printf("Child[%d] in background\n", childPid);
// no return should be expected
status = 0;
}
return status;
}
}
想法是使用 < 和 >
模拟 linux 重定向
tokens 是提供给 shell.
的字符串数组
向“a.txt”打招呼的示例调用:/bin/echo hello > ./a.txt
问题
它不适用于重定向,即“/bin/echo < ./a.txt”会像没有传入参数一样回显,这是一个空行。 “/bin/sleep < ./a.txt”表示当文件不为空时没有参数传入。
文件 a.txt 是使用此程序创建的。完整的例子是
/bin/echo 你好 > ./a.txt
/bin/echo < ./a.txt
其中第一个命令成功创建并写入a.txt,但第二个命令只产生一个空行
你能帮上什么忙
假设标记是正确的,并且文件名存在,为什么 execv() 调用不接受来自我重定向的文件名的输入????
感谢您阅读本文!!
正如我在 中指出的那样,echo
命令不读取标准输入,因此您无法判断 echo
的输入重定向是否成功(或使用 sleep
)。
使用读取标准输入的命令 — cat
是最简单的示例,但 tr
和 sed
可能是明智的选择。
编辑:问题是 echo 显然没有从 stdin 读取。谢谢@Jonathan Leffler
我有一个编程练习,我的代码如下:
int processProgram(char **tokens, int requireWait) {
char *cmd = tokens[0];
if (access(cmd, R_OK) == -1) {
printf("%s not found\n", cmd);
return -1;
}
int index = 1;
char *iterator = tokens[index];
int inputTokenIndex = 0;
// Look for a < to figure out where the redirection is
while (iterator != NULL) {
if (strcmp(iterator, "<") == 0) { // <---- THIS IS WHERE I ATTEMPT TO FIND THE INDEX OF "<"
if (access(tokens[index + 1], R_OK) == -1) {
printf("%s does not exist\n", tokens[index + 1]);
return -1;
}
// set null at <
tokens[index] = NULL;
inputTokenIndex = index + 1;
break;
}
index++;
iterator = tokens[index];
}
// basically create a struct to store pids and stuff....
processList *process = addNewProcess();
int childPid = fork();
if (childPid == 0) {
// is the child
if (inputTokenIndex > 0) {
// if previously strcmp "<" is true
// set redirection for input....
int fd = open(tokens[inputTokenIndex], O_RDONLY); // <----- THIS IS WHERE I DO THE REDIRECTING FOR STDIN!
dup2(fd, STDIN_FILENO);
close(fd);
}
// start from where inputTokenIndex could have left off
// since > is always at least after < in our test cases
index = inputTokenIndex + 1;
iterator = tokens[index];
while (iterator != NULL) { // <--- LOOKING FOR ">" and "2>", CURRENTLY THIS WORKS FINE
// look for output redirection FROM previous while loop onwards
int out = 0;
if (strcmp(iterator, ">") == 0) {
// stdout
out = STDOUT_FILENO;
} else if (strcmp(iterator, "2>") == 0) {
// stderr
out = STDERR_FILENO;
}
if (out != 0) {
int fd = open(tokens[index + 1], O_WRONLY | O_TRUNC | O_CREAT, 0777);
dup2(fd, out);
tokens[index] = NULL;
close(fd);
}
index++;
iterator = tokens[index];
}
int value = execv(cmd, tokens); // <----- EXEC IS HERE!!
if (value == -1) {
exit(errno);
}
exit(0);
} else {
int status;
if (requireWait == 1) {
// wait for process to finish
process->pid = childPid;
wait(&status);
process->running = 0;
process->status = status;
if (status != 0) {
printf("%s failed", cmd);
}
} else {
process->pid = childPid;
printf("Child[%d] in background\n", childPid);
// no return should be expected
status = 0;
}
return status;
}
}
想法是使用 < 和 >
模拟 linux 重定向tokens 是提供给 shell.
的字符串数组向“a.txt”打招呼的示例调用:/bin/echo hello > ./a.txt
问题
它不适用于重定向,即“/bin/echo < ./a.txt”会像没有传入参数一样回显,这是一个空行。 “/bin/sleep < ./a.txt”表示当文件不为空时没有参数传入。
文件 a.txt 是使用此程序创建的。完整的例子是
/bin/echo 你好 > ./a.txt
/bin/echo < ./a.txt
其中第一个命令成功创建并写入a.txt,但第二个命令只产生一个空行
你能帮上什么忙
假设标记是正确的,并且文件名存在,为什么 execv() 调用不接受来自我重定向的文件名的输入????
感谢您阅读本文!!
正如我在 echo
命令不读取标准输入,因此您无法判断 echo
的输入重定向是否成功(或使用 sleep
)。
使用读取标准输入的命令 — cat
是最简单的示例,但 tr
和 sed
可能是明智的选择。