将stderr重定向到c中的缓冲区

时间:2016-03-30 09:21:58

标签: c posix stderr

我已经查看了之前提出的问题。我已经提出了这个代码来获取stderr的当前值,将其重定向到buf并重新分配stderr。这是代码。

没有发生stderr到buff的重定向。当我尝试执行代码时,我可以在屏幕上看到这个:

     ls: cannot access system: No such file or directory
     hellow world
     error from buffer

源代码如下所示:

#include<stdio.h>
static int fd;
static fpos_t pos;
char *buf;

void closeerr()
{
    fflush(stderr);
    fgetpos(stderr, &pos);
    fd = dup(fileno(stderr));
    buf =(char *)calloc(sizeof(char *),1024);
    stderr = fmemopen(buf, sizeof(buf), "w");
}

void reverterr()
{
    fflush(stderr);
    dup2(fd, fileno(stderr));
    close(fd);
    clearerr(stderr);
    fsetpos(stderr, &pos);
}

void main()
{
    closeerr();
    printf("hellow world");
    system(" ls -l system"); // this is where I see the error msg
    printf("error from buffer %s",buf);
    reverterr();
}

此代码将stdout(逻辑与重定向stderr的逻辑相同)重定向到临时文件(方法1如下所述,虽然我没有分叉并创建了一个子进程来写入文件)

void switchStdout(const char *newStream)
{
  fflush(stdout);
  fgetpos(stdout, &pos);
  fd = dup(fileno(stdout));
  freopen(newStream, "w", stdout);

}

void revertStdout()
 {
  fflush(stdout);
  dup2(fd, fileno(stdout));
  close(fd);
  clearerr(stdout);
  fsetpos(stdout, &pos);
 }

void main(){
  switchStdout("/tmp/err.txt");
  printf("Hello world");
  revertStdout();
}

1 个答案:

答案 0 :(得分:1)

fmemopen()函数实际上并未打开文件描述符,因此从fileno()获取的FILE上的fmemopen()会返回未定义的值。 fmemopen()是通过直接写入缓冲区而不通过操作系统发送数据来实现的。无法通过fmemopen()保留使用fork()打开的文件。

另一个问题是,您永远不会为缓冲区分配内存,请阅读fmemopen() API以及如何使用它来了解问题。

以下两种方法有效:

  • 打开一个临时文件,然后fork()。在分叉进程中,将其文件描述符加到文件描述符2(STDERR_FILENO)上,然后执行命令。在父级wait()中为子级,然后读取它写入临时文件的内容。请注意,您需要在阅读之前执行lseek(),因为孩子将更改文件指针。
  • 使用pipe()打开一个fifo,然后fork()。在孩子中,将写入结束文件描述符2,关闭读取结束然后执行命令。在父级中,关闭写入结束并在其运行时读取孩子从读取端写入的内容。之后不要忘记wait()给孩子。