Redirecting perror

  • Thread starter Guillaume Dargaud
  • Start date
G

Guillaume Dargaud

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 ?
 
J

jacob navia

Guillaume said:
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
 
B

Ben Bacarisse

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.
 
A

alex

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.



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

Ralf Damaschke

alex said:
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
 
M

Mark Bluemel

alex said:
....

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)


....
 
B

Ben Bacarisse

Mark Bluemel said:
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.
 
A

Army1987

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...
 
M

Mark Bluemel

Army1987 said:
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) ( 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 :)
 
A

Army1987

Army1987 said:
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) ( 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.
 
G

Guillaume Dargaud

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.
 
B

Ben Bacarisse

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.
 
K

Keith Thompson

Guillaume Dargaud said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top