【发布时间】:2018-04-24 21:32:20
【问题描述】:
我正在尝试实现 shell 重定向,使用它我将 stdout 重定向到 fd1
int redirectOut(int fd1)
{
fflush(stdout);
int fd2 = dup(STDOUT_FILENO);
dup2(fd1, STDOUT_FILENO);
close(fd1);
return fd2;
}
然后我 fork 并调用一个可执行文件,它可以工作,除非可执行文件使用 putchar。
在 putchar 手册页上写着它使用标准输出。
putchar(c);等价于 putc(c,stdout)。
为什么 putchar 既不在标准输出中也不在我将流重定向到的文件中写入任何位置?
我尝试将 putchar 更改为 putc 但没有帮助,这可能与 stdout 的事实有关,如果*FILE 和 STDOUT_FILENO 一个 int
我怎样才能使我的代码工作,为什么它可以与使用 (code for printf) 的 printf 一起工作
done = vfprintf (stdout, format, arg);
编辑更多代码
int executeBlocs(execBloc *bloc,int fileIn,int fileOut){
if(bloc->first != NULL){
if (strcmp(bloc->ope, ">") == 0){
int out = open(bloc->command[0], O_WRONLY | O_CREAT | O_TRUNC , 0644);
int returnCode = executeBlocs(bloc->first, STDIN_FILENO, out);
redirectOut(fileOut);
redirectIn(fileIn);
return returnCode;
}
}
else{
redirectIn(fileIn);
redirectOut(fileOut);
return call(bloc->nbWords, bloc->command);
}
}
execBloc 是一个结构,它包含执行(或文件名)操作符(>>、|、> ...)的命令和对包含命令其余部分的另一个块的引用。
如果用户输入 cat /tmp/testCat > /tmp/testCatRedirection
然后将创建包含运算符 > 和命令 /tmp/testCatRedirection 的第一个结构,第一个结构是对包含命令 cat /tmp/testCat
int call(int argc, char const *argv[]) {
if (argc > 0){
if (executeProgram(argv) == 1) return 1;
if (executeStandardLibrary(argc, argv) == 1) return 1;
if (executeDynamicLibrary(argc, argv) == 1) return 1;
}
return -1;
}
int executeProgram(char const *argv[]){
//Creation de la chaine de caractère /home/kerdam/cbin/nonExecutable
char *path = strdup(binFolder);
strcat(path, argv[0]);
//Test si le fichier existe et est executable
if (access(path, F_OK|X_OK) != -1){
//Le fichier existe et on peut l'éxecuter
int pid = fork();
// Error
if (pid == -1){
return -1;
}
//Fils
else if (pid == 0) {
// Executer la commande
execv(path, argv);
return 1;
}
// Parent process
else {
// Wait for child process to finish
int childStatus;
waitpid(pid, &childStatus, 0);
return 1;
}
}
else return -1;
}
最后是我要执行的程序的代码
#include<stdio.h>
#include<string.h>
#define MAX_FILE_NAME_CHARS 255
int main(int argc, char *argv[])
{
FILE *fp;
char file_name[MAX_FILE_NAME_CHARS], ch;
int i;
/*
* after creating a.out, rename it as mycat for our own cat command
* and it usage is same as standard cat command
*/
if(argc<=1){
printf("Utiliser cat avec aumoin un argument (un fichier) <nomfichier> \n");
return 0;
}
/*
* This is for multiple file in argument
*/
for(i=1; i<=argc;i++){
strncpy(file_name, argv[i], MAX_FILE_NAME_CHARS);
fp=fopen(file_name, "r");
if(fp == NULL) {
printf("%s: No such file or directory\n", file_name);
return 0;
}
/*
* read file and feed contents to STDIO
*/
while((ch=fgetc(fp)) != EOF || ch == '}'){
putchar(ch);
}
fclose(fp);
}
return 0;
}
备注
我不应该更改我正在尝试执行的可执行文件的代码,因为我的 shell 的用户应该能够执行他们的程序,而不受他们可以使用的功能的限制。
【问题讨论】:
-
您在哪个平台上进行实验?
putc(c, stdout)切换文件后是否按预期工作?fputc(c, stdout)呢?从表面上看,您只是在更改文件描述符 0 引用的内容;标准 I/O 代码应继续工作,写入文件描述符 0。您确定fd1已打开以供写入吗? (我知道这听起来很傻,但有必要检查一下,因为我们没有可以使用的 MCVE (minimal reproducible example)。) -
您检查了
fileno(stdout)的值吗?但是由于乔纳森的要求,我们需要一个minimal reproducible example,我回答这个问题太快了。 -
您确定要输出带有
putchar()调用的换行符吗?是否只是在更改文件描述符以引用文件时将其恢复(更改)为完全缓冲的输出,因此在刷新之前看不到输出?如果是行缓冲,换行可能就足够了;如果它是完全缓冲的,您可能需要使用fflush()。但是,您说printf()等人的工作,这表明这不是问题。 -
首先这里有一个固定的测试程序,rextester.com/QSD96627,其次,你还是没有提供minimal reproducible example。第三,
int out = open(bloc->command[0], O_WRONLY | O_CREAT | O_TRUNC , 0644);是可疑的,你不想要int out = open(bloc->command[1], O_WRONLY | O_CREAT | O_TRUNC , 0644);吗? -
请记住,
fflush(stdout)将任何挂起的输出写入 o/s,而不是将其保存在标准 I/O 缓冲区中。即使末尾没有换行符,它也会这样做。这使您有最大机会看到潜伏在stdout缓冲区中的输出。因此,fflush(stdout)绝不应该造成任何损害(除非您将减速时间计算为足够长的时间以确保缓冲区是空的)并且可以帮助您了解发生了什么。