4

How can I redirect fprintf output to a socket?

I am editing source code which has a lot of fprintf calls. It logs to a file. But I would like to redirect this log to a socket.

How can this be done?

Mat
  • 202,337
  • 40
  • 393
  • 406
Behrouz.M
  • 3,445
  • 6
  • 37
  • 64

3 Answers3

6

On Unix-like systems, open the socket (getting a file descriptor).

Map socket to stderr

If you've not yet used stderr, you can simply use dup2() to make the socket into the output channel. You may be able to do that even if you have sent some data to the original stderr. The suggestion in the comment about using fflush() may be relevant, though stderr is usually unbuffered rather than fully buffered (so there is not usually anything to flush).

The freopen() function can be used to change the output of a stream such as stderr (in particular). Hmmm, could you use freopen() to map stderr to /dev/fd/N where N is the file descriptor of the socket? Yes, you probably could.

Map socket to other stream

Re-reading your question - I don't see stderr in it. So the fdopen() function creates a stream from a file descriptor. So if you can specify the stream for the logging to write to, you're home. If you can't specify it but can see it, then the freopen() trick above should work here too.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
4

There is no such thing as a "C socket" but you are probably referring to one of two things (WinSock or libsocket). Either way, the basic method I'd use would be to use a #define and a simple function, similar to this:

#define fprintf(a,b,...) fprintfsock(a,b,__VA_ARGS__)

void fprintfsock( SOCKET s, const char* f, ... )
{
    va_list a;
    va_start( a, f );
    int l = vsnprintf( 0, 0, f, a );
    char* buf = (char*) malloc( l + 1 );
    va_start( a, f );
    vsnprintf( buf, l, f, a );
    send( s, buf, l, 0 );
    free( buf );
}

That will work in either, except with libsocket you should typedef or use int for SOCKET. Make sure you #undef fprintf after you're done logging to the socket!

Kaslai
  • 2,445
  • 17
  • 17
  • POSIX.1-2001 says otherwise. Technically "C sockets" (meaning POSIX sockets) are just file descriptors though. The other answers address this a lot better. – arjunyg Apr 09 '18 at 21:18
  • @arjunyg there is more to the world than just POSIX, though. Sockets may be file descriptors on *nix but the specific platform was not provided in the question. However, given the accepted answer, it appears they were indeed asking about sockets on a *nix system. Also in retrospect, this answer is kind of gross ;) – Kaslai Apr 12 '18 at 20:23
2

I realize this isn't your question, but you might consider using a tool like netcat instead of messing with the code (which doesn't seem like a trivial change).

You can do something like this (updated to use a log fifo):

mkfifo /path/to/log

nc <ip> <port> < /path/to/log

http://netcat.sourceforge.net/

Eve Freeman
  • 32,467
  • 4
  • 86
  • 101