Redirecting perror

Discussion in 'C Programming' started by Guillaume Dargaud, Aug 7, 2007.

  1. Hello all,
    I have some error checking using the function 'perror', which writes
    messages on stderr. I'd like to send all error messages to a file instead.
    Is there some way to do this, short of replacing all the perror calls with a
    custom function ?
    --
    Guillaume Dargaud
    http://www.gdargaud.net/
    Guillaume Dargaud, Aug 7, 2007
    #1
    1. Advertising

  2. Guillaume Dargaud

    jacob navia Guest

    Guillaume Dargaud wrote:
    > Hello all,
    > I have some error checking using the function 'perror', which writes
    > messages on stderr. I'd like to send all error messages to a file instead.
    > Is there some way to do this, short of replacing all the perror calls with a
    > custom function ?

    reopen stderr to point to a file
    jacob navia, Aug 7, 2007
    #2
    1. Advertising

  3. "Guillaume Dargaud" <>
    writes:

    > Hello all,
    > I have some error checking using the function 'perror', which writes
    > messages on stderr. I'd like to send all error messages to a file instead.
    > Is there some way to do this, short of replacing all the perror calls with a
    > custom function ?


    strerror is standard:

    #include <string.h>
    char *strerror(int errnum);

    The strerror function maps the number in errnum to a message
    string. Typically, the values for errnum come from errno, but
    strerror shall map any value of type int to a message.

    Returns: The strerror function returns a pointer to the string,
    the contents of which are locale- specific. The array pointed to
    shall not be modified by the program, but may be overwritten by a
    subsequent call to the strerror function.

    --
    Ben.
    Ben Bacarisse, Aug 7, 2007
    #3
  4. Guillaume Dargaud

    alex Guest

    On Aug 7, 7:32 pm, Ben Bacarisse <> wrote:
    > "Guillaume Dargaud" <>
    > writes:
    >
    > > Hello all,
    > > I have some error checking using the function 'perror', which writes
    > > messages on stderr. I'd like to send all error messages to a file instead.
    > > Is there some way to do this, short of replacing all the perror calls with a
    > > custom function ?

    >
    > strerror is standard:
    >
    > #include <string.h>
    > char *strerror(int errnum);
    >
    > The strerror function maps the number in errnum to a message
    > string. Typically, the values for errnum come from errno, but
    > strerror shall map any value of type int to a message.
    >
    > Returns: The strerror function returns a pointer to the string,
    > the contents of which are locale- specific. The array pointed to
    > shall not be modified by the program, but may be overwritten by a
    > subsequent call to the strerror function.
    >
    > --
    > Ben.




    just close(stderr)
    and try to open a file immediately .......
    alex, Aug 7, 2007
    #4
  5. alex wrote:

    > just close(stderr)
    > and try to open a file immediately .......


    We all know that close() is not a standard C function, so
    we cannot tell whether this advice is correct for the
    OP's environment.

    <OT>
    Just out of curiosity: which extension are *you* using,
    where close() accepts an argument of type FILE*?
    </OT>

    Ralf
    Ralf Damaschke, Aug 7, 2007
    #5
  6. Guillaume Dargaud

    Mark Bluemel Guest

    alex wrote:
    >>"Guillaume Dargaud" <>
    >>writes:
    >>
    >>
    >>>Hello all,
    >>>I have some error checking using the function 'perror', which writes
    >>>messages on stderr. I'd like to send all error messages to a file instead.
    >>>Is there some way to do this, short of replacing all the perror calls with a
    >>>custom function ?

    ....
    >
    > just close(stderr)
    > and try to open a file immediately .......


    By no means guaranteed.

    Ben's solution is the right one but doesn't mean Guillaume's requirement
    not to replace all the perror calls.

    Jacob got it right, IMHO - use freopen. Indeed the spec describes this
    as the primary use for freopen. Naturally, all output written to stderr
    will now go to this file.

    The alternative, if only perror() is to be affected, is some fun with a
    function and a macro, something like this (untested) :-

    #include <errno.h>
    #include <stdio.h>
    static FILE *errorstream; /* opened somewhere */
    void my_perror(char *string) {
    char *buffer;
    char *errtxt = strerror(errno);
    int buflen = strlen(errtxt) + strlen(string) + 4;
    buffer = malloc(buflen);
    if (buffer == NULL) {
    /* Your choice! */
    }
    sprintf(buffer,"%s: %s\n",string,errtxt);
    fputs(buffer,errorstream);
    free(buffer);
    }

    #define perror(x) my_perror(x)


    ....
    Mark Bluemel, Aug 7, 2007
    #6
  7. Mark Bluemel <> writes:

    > alex wrote:
    >>>"Guillaume Dargaud" <>
    >>>writes:
    >>>
    >>>
    >>>>Hello all,
    >>>>I have some error checking using the function 'perror', which writes
    >>>>messages on stderr. I'd like to send all error messages to a file instead.
    >>>>Is there some way to do this, short of replacing all the perror calls with a
    >>>>custom function ?

    > ...
    >>
    >> just close(stderr)
    >> and try to open a file immediately .......

    >
    > By no means guaranteed.
    >
    > Ben's solution is the right one but doesn't mean Guillaume's
    > requirement not to replace all the perror calls.


    Perfectly true. I just (deliberately) ignored that part! It is rare
    that one should pass up an opportunity to make ones code more
    flexible, so while the reopen path is fast, it sends everything to the
    file (which may, one day, be the wrong thing to do) and it passes up a
    chance to make the error reporting more flexible (e.g. one might need
    it to more configurable one day).

    Of course, if the perror calls are not available (because the OP does
    not have the source), then Jacob's solution is pretty much the ony way
    to go.

    > Jacob got it right, IMHO - use freopen. Indeed the spec describes this
    > as the primary use for freopen. Naturally, all output written to
    > stderr will now go to this file.


    If sending all stderr out to a file is OK, that is indeed the way to go.

    --
    Ben.
    Ben Bacarisse, Aug 7, 2007
    #7
  8. Guillaume Dargaud

    Army1987 Guest

    On Tue, 07 Aug 2007 17:06:27 +0100, Mark Bluemel wrote:

    > alex wrote:
    >>>"Guillaume Dargaud" <>
    >>>writes:
    >>>
    >>>
    >>>>Hello all,
    >>>>I have some error checking using the function 'perror', which writes
    >>>>messages on stderr. I'd like to send all error messages to a file instead.
    >>>>Is there some way to do this, short of replacing all the perror calls with a
    >>>>custom function ?

    > ...
    >>
    >> just close(stderr)
    >> and try to open a file immediately .......

    >
    > By no means guaranteed.
    >
    > Ben's solution is the right one but doesn't mean Guillaume's requirement
    > not to replace all the perror calls.
    >
    > Jacob got it right, IMHO - use freopen. Indeed the spec describes this
    > as the primary use for freopen. Naturally, all output written to stderr
    > will now go to this file.
    >
    > The alternative, if only perror() is to be affected, is some fun with a
    > function and a macro, something like this (untested) :-
    >
    > #include <errno.h>
    > #include <stdio.h>
    > static FILE *errorstream; /* opened somewhere */
    > void my_perror(char *string) {
    > char *buffer;
    > char *errtxt = strerror(errno);
    > int buflen = strlen(errtxt) + strlen(string) + 4;
    > buffer = malloc(buflen);
    > if (buffer == NULL) {
    > /* Your choice! */
    > }
    > sprintf(buffer,"%s: %s\n",string,errtxt);

    Why not doing a fprintf on errorstream, so eliminating the need
    for a malloc()ated buffer?
    > fputs(buffer,errorstream);
    > free(buffer);
    > }
    >
    > #define perror(x) my_perror(x)

    #define perror(x) ( fprintf(errorstream, "%s: %s\n", (x), \
    strerror(errno)), fflush(errorstream) )
    This doesn't handle the case in which x == NULL || *x == '\0', in
    which the "real" perror() simply writes strerror(errno) and a
    newline. But neither does your function...

    --
    Army1987 (Replace "NOSPAM" with "email")
    "Never attribute to malice that which can be adequately explained
    by stupidity." -- R. J. Hanlon (?)
    Army1987, Aug 7, 2007
    #8
  9. Guillaume Dargaud

    Mark Bluemel Guest

    Army1987 wrote:
    > On Tue, 07 Aug 2007 17:06:27 +0100, Mark Bluemel wrote:


    >>
    >>The alternative, if only perror() is to be affected, is some fun with a
    >>function and a macro, something like this (untested) :-

    [Snip]

    >
    > Why not doing a fprintf on errorstream, so eliminating the need
    > for a malloc()ated buffer?


    Because I was posting at the end of a longish day and not thinking
    particularly well....

    [Snip]

    >>#define perror(x) my_perror(x)

    >
    > #define perror(x) ( fprintf(errorstream, "%s: %s\n", (x), \
    > strerror(errno)), fflush(errorstream) )


    I'm borderline allergic to macros (so would you be if you'd worked on
    some of the code I have in my time), so anything beyond very simple
    substitutions tends not to occur to me :)
    Mark Bluemel, Aug 8, 2007
    #9
  10. Guillaume Dargaud

    Army1987 Guest

    On Wed, 08 Aug 2007 08:33:05 +0100, Mark Bluemel wrote:

    > Army1987 wrote:
    >> On Tue, 07 Aug 2007 17:06:27 +0100, Mark Bluemel wrote:

    >
    >>>
    >>>The alternative, if only perror() is to be affected, is some fun with a
    >>>function and a macro, something like this (untested) :-

    > [Snip]
    >
    >>
    >> Why not doing a fprintf on errorstream, so eliminating the need
    >> for a malloc()ated buffer?

    >
    > Because I was posting at the end of a longish day and not thinking
    > particularly well....
    >
    > [Snip]
    >
    >>>#define perror(x) my_perror(x)

    >>
    >> #define perror(x) ( fprintf(errorstream, "%s: %s\n", (x), \
    >> strerror(errno)), fflush(errorstream) )

    >
    > I'm borderline allergic to macros (so would you be if you'd worked on
    > some of the code I have in my time), so anything beyond very simple
    > substitutions tends not to occur to me :)

    The point was showing what to do, I could have written
    void my_perror(const char *x)
    {
    fprintf(errorstream, "%s: %s\n", x, strerror(errno));
    fflush(errorsteram);
    }
    But since it had to be used as in #define perror(x) my_perror(x)
    I found no reason in not writing it as a macro in the first place.
    --
    Army1987 (Replace "NOSPAM" with "email")
    "Never attribute to malice that which can be adequately explained
    by stupidity." -- R. J. Hanlon (?)
    Army1987, Aug 8, 2007
    #10
  11. > just close(stderr)
    > and try to open a file immediately .......


    I didn't know you could do that... Seems like a good solution for me. Thanks
    for all who contributed, I'd thought of the macro solution but it's not so
    elegant as I also have custom error messages such as fprintf(stderr, ...)
    which I want redirected along perror.
    --
    Guillaume Dargaud
    http://www.gdargaud.net/Antarctica/
    Guillaume Dargaud, Aug 8, 2007
    #11
  12. "Guillaume Dargaud" <>
    writes:

    >> just close(stderr)
    >> and try to open a file immediately .......

    >
    > I didn't know you could do that...


    You can't! If re-directing all error output to the file is what you
    want, ignore my (previous) answer and follow Jacob Navia's.

    > Seems like a good solution for me.


    close is not a standard C function, and relying on what happens
    "immediately" after a close is highly suspect. freopen is the way to go.

    --
    Ben.
    Ben Bacarisse, Aug 8, 2007
    #12
  13. "Guillaume Dargaud" <> writes:
    >> just close(stderr)
    >> and try to open a file immediately .......

    >
    > I didn't know you could do that...

    [...]

    And you were right. Even assuming it's 'fclose(stderr)' rather than
    'close(stderr)', there's no guarantee that a newly opened file will
    have any relationship to the one you just closed. Any attempt to
    write to stderr after you've closed it (unless you've opened it again)
    will invoke undefined behavior. The worst case is that it will do
    exactly what you want it to do, failing only at the most inconvenient
    possible moment (either during an important demo, or after you've
    ported the code to another implementation and forgotten what you did).

    See freopen() if you want all writes to stderr to go somewhere else
    (<OT>or redirect stderr when you invoke the program</OT>), or use a
    macro or some other replacement for perror() if you want only perror
    calls to be affected.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 8, 2007
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    761
  2. L. Westmeier

    When to use "perror" and "fprintf"

    L. Westmeier, May 4, 2004, in forum: C Programming
    Replies:
    6
    Views:
    721
    OSHIMA
    May 13, 2004
  3. Martin
    Replies:
    7
    Views:
    673
    Chris Torek
    Dec 9, 2004
  4. Clunixchit

    perror question

    Clunixchit, Jun 19, 2005, in forum: C Programming
    Replies:
    1
    Views:
    320
    SM Ryan
    Jun 19, 2005
  5. puzzlecracker

    cout and perror

    puzzlecracker, Oct 22, 2005, in forum: C++
    Replies:
    3
    Views:
    330
    Branimir Maksimovic
    Oct 23, 2005
Loading...

Share This Page