Redirect STDOUT and STDERR to socket in C?
Read again the man dup2
page (excerpts):
SYNOPSIS
int dup2(int oldfd, int newfd);
DESCRIPTION
dup2() makes newfd be the copy of oldfd, closing newfd
So it should be dup2 (STDOUT_FILENO, newsock);
Your use of dup2()
looks fine, so the problem is probably elsewhere. The simple program I threw together to test with does not have the issues you are experiencing, so I'll just go over the core of it (around the fork()
/execvp()
area) with some error checking omitted for brevity:
int lsock, /* listening socket */
csock; /* active connection's socket */
pid_t cpid; /* child process ID from fork() */
char *cmd = "somecommand";
char *cmd_args[] = { "somecommand",
"firstarg",
"secondarg",
"howevermanyargs",
NULL }; /* note: last item is NULL */
/* ...
call socket(), bind(), listen(), etc.
... */
for (;;) { /* loop, accepting connections */
if ( (csock = accept( lsock, NULL, NULL )) == -1) exit(1);
cpid = fork();
if (cpid < 0) exit(1); /* exit if fork() fails */
if ( cpid ) {
/* In the parent process: */
close( csock ); /* csock is not needed in the parent after the fork */
waitpid( cpid, NULL, 0 ); /* wait for and reap child process */
} else {
/* In the child process: */
dup2( csock, STDOUT_FILENO ); /* duplicate socket on stdout */
dup2( csock, STDERR_FILENO ); /* duplicate socket on stderr too */
close( csock ); /* can close the original after it's duplicated */
execvp( cmd, cmd_args ); /* execvp() the command */
}
}
The above is the core of a very basic server (only one client at a time) that, when it receives a connection, forks a new process to run a command and sends its stderr and stdout to the client over the socket. Hopefully you can solve your problem by examining it -- but don't just copy the code without understanding what it does.
Try testing by connecting with a telnet client first... if it works with telnet but not with your client program, then look for problems in your client program.
Your usage of dup2
is correct. Your write calls are not writing the entire buffer you're giving them, as the data hasn't been received by the remote peer yet, and the kernel buffer allocated for this is likely full. The typical buffer size is 64KB. You should make sure that the receiver is receiving the data, and wrap your writes in a loop. Alternatively use MSG_SENDALL
, and the send
syscall.