Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reopening Stdout in C

2,042 views
Skip to first unread message

tom.c...@gmail.com

unread,
Apr 5, 2006, 4:39:21 AM4/5/06
to
Hello,

I've been working on a program that daemonizes a process specificed as
a command parameter, (specifically, for a cross-platform Java IRC bot)
and am having some trouble reassigning stdout and stdin to it.

>From what I gather, the general steps of daemonizing a process seem to
be that one needs to fork (twice?) it then redirect the 0, 1, and 2
descriptors away from the console session so that control is put back
in the hands of the user. I've had no problem forking or closing the
descriptors, but reopening them is proving troublesome.

Unfortunately the process I want to demonize is written in Java, is
small, jailed, and was written by a Windows guy, so there are no stock
provisions for giving it service-type functionality--so I'm seeing if I
can write it myself.

My own knowledge of C is somewhere in between Novice and Intermediate,
and across all my programming skills, I/O has been a weak spot for me.
Knowing this, I wrote a quick program to simplify things that would
attempt to close stdout then reopen it and try to printf some text to
the user afterwards:

#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void main() {
int desc;

printf("This is done before the STDOUT is closed.");

close(1);

desc = fopen(stdout, "wa");
/* desc = open(stdout); */

fprintf(desc, "This is done after STDOUT is reopened.");
}

The program is crashing with a segmentation fault and gcc is reporting
the following warning:
forktest.c:16: warning: passing arg 1 of `fprintf' makes pointer from
integer without a cast

I suspect the segmentation is the result of me not managing the
pointers correctly, because open() and fopen() (which I have both
tried) return NULL if there's an I/O error. Good documentation on using
open() or fopen() to reopen stdout seems to be sketchy, and since the
commands are fairly generic I'm having a hard time sorting through all
the perl/php/C++/everything else results. I've read the man pages on
open() and fopen() and neither of them are much help for my uses, and I
can't find any other online resources or my own library that mention
this kind of thing.

I'd just like to know what I'm doing wrong... while it may be easier
just to close stdout, etc, and >> the child process' output into a log
file, this method has piqued my curiosity so I'd like to learn it as
well.

Thanks in advance,

Tom

Jeff

unread,
Apr 6, 2006, 8:34:32 AM4/6/06
to
Tom,
You must open a file via open(2) or fopen(3) with a file name, ie a
char* value. The type of stdout is FILE *. It's value is null, since it
is not initialized. Your open or fopen
needs to be open("/dev/console", O_RDONLY) or fopen("/dev/console",
"w").
This is shown on the man page as the parameter open(char *fname, int
mode),
or fopen(char *fname, char *mode).
The reason for the SEGV fault is you are passing a NULL pointer to
open(2) or
fopen(3), so when it is dereferenced to get a filename it accesses
memory location 0.

Jeff Fellin

tom.c...@gmail.com

unread,
Apr 6, 2006, 11:34:01 PM4/6/06
to
Ok, thank you very much. That was most helpful. I was able to get both
the test program and the program I've been working on finished.

I do have one other question: is there really any point in reopening
STDIN, STDOUT, and STDERR? If a child process is run after a setsid(),
is there any real point to reopen these channels when they have no
controlling terminal? After giving it some thought, it would seem that
>>ing the output into a file would be the most reliable way to log the child process' output.

-tom

0 new messages