Redirect STDOUT and STDERR to socket in C?
Asked Answered
O

4

9

I am trying to redirect STDOUT AND STDERR to a socket.

I did:

if(fork() == 0)
{
   dup2(newsock, STDOUT_FILENO);
   dup2(newsock, STDERR_FILENO);
   execvp();
}

Somehow, it only showed the first little part of the output.

for example, it showed on "mkdir" when I try to execute ls or mkdir.

What's the problem?

I tried the flollowing it works, but I can only redirect one of STDOUT or STDERR

close(1);
dup(newsock);

Thanks a lot.

Offer answered 11/11, 2011 at 22:36 Comment(1)
@Dmitri could you please help me on this one? thanks!Offer
E
14

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.

Exhortative answered 12/11, 2011 at 4:16 Comment(0)
H
4

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.

Holbein answered 12/11, 2011 at 0:18 Comment(2)
thanks. it turns out ls works well and can list the whole directory. so STDOUT works fine. but when it should return mkdir: sampledirectory already exist, it only returns mkdirOffer
Hi, i just saw this post and im having this issue. When i redirect the stdout to the new socket and use exec, sometimes it will keep date in the buffer and it will print them a loop after. What exacly should i do? Where to make this loop of WRITEs??Stoecker
M
1

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);

Macrobiotic answered 11/11, 2011 at 23:46 Comment(5)
no, that's exactly backward. the op wants newsock to become STDOUT_FILENO.Ballista
But he wrote: "I am trying to redirect STDOUT AND STDERR to a socket." I am not a native English speaker (being French), but doesn't the "to" preposition indicate the destination?Macrobiotic
@BasileStarynkevitch The socket is the destination, but it's the destination of the data -- meaning that whatever is written to stdout or stderr should be sent to the socket. To do that, he needs to make stdout and stderr duplicates of the socket.Exhortative
@BasileStarynkevitch That's an annoying mistake in dup2's man page. The arguments' order is inversed.Presumable
dup2 (STDOUT_FILENO, newsock); would close the socket according to the excerpt you quoted. OP wants to keep the socket open and redirect output to it. To do that, he needs to close the old stdout and make it a copy of the socket, with dup2 (newsock, STDOUT_FILENO);Instrumentation
H
0

I think the problem is that stderr and stdout are one of the same on some systems

Holsworth answered 1/12, 2020 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.