problems about redirect popened FILE stream to stdout - Unix

This is a discussion on problems about redirect popened FILE stream to stdout - Unix ; Hello All: I want to redirect popened FILE stream to stdout using dup or dup2, but i cann't figure out where goes wrong, the out put just disappeared, my code : /* i want the program work like this , ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: problems about redirect popened FILE stream to stdout

  1. problems about redirect popened FILE stream to stdout

    Hello All:

    I want to redirect popened FILE stream to stdout using dup or dup2,
    but i cann't figure out where goes wrong, the out put just
    disappeared,
    my code :

    /* i want the program work like this ,

    $ ./a.out pwd
    /home/user-name/test/

    but the output just disappeared, can any tell me why ?

    thank you!
    */

    #include
    #include
    #include
    #include
    #include

    int main (int argc, char **argv) {
    char *buf =malloc(10);
    FILE *fp;
    assert (buf);
    if (argc != 2)
    exit (-1);
    fp = popen(argv[1], "r");
    int cnt = 0;
    int fd = fileno(fp);
    int stdout_fd = fileno(stdout);
    int t = 0;

    printf("before dup2 , stdout_fd:%d , popen_fd:%d\n", stdout_fd, fd);
    if (fd != stdout_fd)
    if ((t =dup2(fd, stdout_fd))!= stdout_fd)
    perror("dup2 to stdout error");
    perror("some error ?");


    /* while (!feof(fp)) { */
    /* memset(buf, 0, 10); */
    /* fgets(buf, 10, fp); */
    /* printf("%s",buf); */
    /* cnt++; */
    /* } */

    fprintf(fp, "cnt:%d\n", cnt);
    }


  2. Re: problems about redirect popened FILE stream to stdout

    On 18 Oct, 06:03, Anson Zhang wrote:
    >
    > int main (int argc, char **argv) {
    > * * * * char *buf =malloc(10);
    > * * * * FILE *fp;
    > * * * * assert (buf);


    So, in testing, if you don't have memory the program
    run will abort with an error, but when you go to production
    you'll just get random errors. This is the WRONG way to
    use assert. Check the return value properly, or acknowledge
    that you are not doing error checking at all. (Which one
    can argue is acceptable for example code, but totally
    unacceptable for production code.)

    > * * * * if (argc != 2)
    > * * * * * * * * exit (-1);
    > * * * * fp = popen(argv[1], "r");


    popen can fail just as easily as malloc.

    > * * * * int cnt = 0;
    > * * * * int fd = fileno(fp);
    > * * * * int stdout_fd = fileno(stdout);


    Probably easier to do stdout_fd = STDOUT_FILENO, or
    better yet just use STDOUT_FILENO throughout the
    program.


    > * * * * int t = 0;
    >
    > * * * * printf("before dup2 , stdout_fd:%d , popen_fd:%d\n", stdout_fd, fd);
    > * * * * if (fd != stdout_fd)
    > * * * * * * * * if ((t =dup2(fd, stdout_fd))!= stdout_fd)
    > * * * * * * * * * * * * perror("dup2 to stdout error");


    You've just set your stdout to the file descriptor of the
    pipe from which you are trying to read. Why would you
    do that? You don't want to change stdout at all.

    > * * * * perror("some error ?");
    >
    > * * * * /* while (!feof(fp)) { */
    > * * * * /* * * *memset(buf, 0, 10); */
    > * * * * /* * * *fgets(buf, 10, fp); */
    > * * * * /* * * *printf("%s",buf); */
    > * * * * /* * * *cnt++; */
    > * * * * /* } */


    This is not the correct way to write the loop. In this
    case, I believe it works, but only because of the
    otherwise redundant memset. For example,
    if the command you popen is "cat /dev/null", then
    you will enter the loop once, at which time fgets
    will read zero characters and you will call
    printf with buf[ 0 ] == '\0'. Why do you
    want to do that? It would be cleaner to write this:

    while( fgets( buf, 10, fp ) != NULL )
    fputs( buf, stdout );



  3. Re: problems about redirect popened FILE stream to stdout

    thank for you help,
    the code was very bad.

    and i just write these code in hurry, for testing new function,

    i fix this problem ,

    the new code is


    #include
    #include
    #include
    #include
    #include
    #include

    int main (int argc, char **argv) {
    char buf[10];
    FILE *fp;
    if (argc != 2)
    exit (-1);
    fp = popen(argv[1], "w");
    int fd = fileno(fp);
    close(STDOUT_FILENO);
    if (dup(fd) != STDOUT_FILENO)
    perror("stdout error");
    close(fd);
    }

    In the wrong code , i pass popen "r", so can't redirect it to stdout,
    since it's a dup of stdin.

    thanks a lot !


    On Oct 18, 3:54*pm, William Pursell wrote:
    > On 18 Oct, 06:03, Anson Zhang wrote:
    >
    >
    >
    > > int main (int argc, char **argv) {
    > > * * * * char *buf =malloc(10);
    > > * * * * FILE *fp;
    > > * * * * assert (buf);

    >
    > So, in testing, if you don't have memory the program
    > run will abort with an error, but when you go to production
    > you'll just get random errors. *This is the WRONG way to
    > use assert. *Check the return value properly, or acknowledge
    > that you are not doing error checking at all. *(Which one
    > can argue is acceptable for example code, but totally
    > unacceptable for production code.)
    >
    > > * * * * if (argc != 2)
    > > * * * * * * * * exit (-1);
    > > * * * * fp = popen(argv[1], "r");

    >
    > popen can fail just as easily as malloc.
    >
    > > * * * * int cnt = 0;
    > > * * * * int fd = fileno(fp);
    > > * * * * int stdout_fd = fileno(stdout);

    >
    > Probably easier to do stdout_fd = STDOUT_FILENO, or
    > better yet just use STDOUT_FILENO throughout the
    > program.
    >
    > > * * * * int t = 0;

    >
    > > * * * * printf("before dup2 , stdout_fd:%d , popen_fd:%d\n", stdout_fd, fd);
    > > * * * * if (fd != stdout_fd)
    > > * * * * * * * * if ((t =dup2(fd, stdout_fd))!= stdout_fd)
    > > * * * * * * * * * * * * perror("dup2 to stdout error");

    >
    > You've just set your stdout to the file descriptor of the
    > pipe from which you are trying to read. *Why would you
    > do that? *You don't want to change stdout at all.
    >
    > > * * * * perror("some error ?");

    >
    > > * * * * /* while (!feof(fp)) { */
    > > * * * * /* * * *memset(buf, 0, 10); */
    > > * * * * /* * * *fgets(buf, 10, fp); */
    > > * * * * /* * * *printf("%s",buf); */
    > > * * * * /* * * *cnt++; */
    > > * * * * /* } */

    >
    > This is not the correct way to write the loop. * In this
    > case, I believe it works, but only because of the
    > otherwise redundant memset. *For example,
    > if the command you popen is "cat /dev/null", then
    > you will enter the loop once, at which time fgets
    > will read zero characters and you will call
    > printf with buf[ 0 ] == '\0'. *Why do you
    > want to do that? *It would be cleaner to write this:
    >
    > while( fgets( buf, 10, fp ) != NULL )
    > * fputs( buf, stdout );



  4. Re: problems about redirect popened FILE stream to stdout

    On 18 Oct, 17:48, Anson Zhang wrote:


    > int main (int argc, char **argv) {
    > * * * * char buf[10];
    > * * * * FILE *fp;
    > * * * * *if (argc != 2)
    > * * * * * * * * exit (-1);
    > * * * * fp = popen(argv[1], "w");
    > * * * * int fd = fileno(fp);
    > * * * * close(STDOUT_FILENO);
    > * * * * if (dup(fd) != STDOUT_FILENO)
    > * * * * * * * * perror("stdout error");
    > * * * * close(fd);
    >
    > }
    >
    > In the wrong code , i pass popen "r", so can't redirect it to stdout,
    > since it's a dup of stdin.
    >


    Not quite. Here's something from the man popen page:

    Writing to such a stream writes to the standard input of the command;
    the
    command's standard output is the same as that of the process that
    called
    popen()

    You don't need to dup at all. All your dup does is set your stdout
    to the input of the cmd, and then you immediately close it. By
    passing
    "w" as the mode to popen, the child process inherits the stdout
    of the parent. Setting mode to "r" makes the child's output
    go to your FILE *.

+ Reply to Thread