I'm trying to redirect a tracee's stdout to a file.
For this I've:
attached to tracee
mmap'd some memory
copied the filename to tracee's memory
asked tracee to open the file
To reach these results I had to dig myself into this repository.
So far my results look good, I'm ptracing into a top command, and lsof can detect my effort (see last line):
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
top 421762 root cwd DIR 179,2 4096 17528 /root
top 421762 root rtd DIR 179,2 4096 2 /
top 421762 root txt REG 179,2 124856 12493 /usr/bin/top
top 421762 root 0u CHR 136,1 0t0 4 /dev/pts/1
top 421762 root 1u CHR 136,1 0t0 4 /dev/pts/1
top 421762 root 2w CHR 1,3 0t0 5 /dev/null
top 421762 root 3u CHR 136,1 0t0 4 /dev/pts/1
top 421762 root 4r REG 0,17 0 4026533347 /proc/stat
top 421762 root 5r REG 0,17 0 4026533348 /proc/uptime
top 421762 root 6r REG 0,17 0 4026533346 /proc/meminfo
top 421762 root 7r REG 0,17 0 4026533345 /proc/loadavg
top 421762 root 8u FIFO 0,28 0t0 827 /tmp/mystdout
And this is my command's output (just for completeness):
[+] Allocated scratch page: 7fbd357000
[+] Opened the new fd in the child: 8 (/tmp/mystdout)
[+] Saved fd 1 to -1 in the child
[+] Duplicated fd 8 to 1
[+] Freed scratch page: 7fbd357000
What I'm trying to do now is the final step, which is to dup2 the stdout of the tracee to the opened file_fd (8).
Feasibility
I wrote a very small program to test how dup2 works on the target platform (aarch64):
int i = 0;
while(1) {
printf("helloworld %d\n", i++);
sleep(1);
if (i==5) {
printf("Opening tmp file\n");
int file_fd = open("/tmp/mystdout", O_RDWR | O_CREAT, 0666, 0, 0);
printf("File opened=%d\n", file_fd);
int err = dup2(file_fd, 1);
printf("dup2 result=%d\n", err);
close(file_fd);
}
}
This test program verified that I can close the file_fd after the dup2 call and still the program will continue logging to this file by default.
Even my "dup2 result=1" is printed into the file (and not onto stdout).
Considering dup2's return value of 1 matches with its expected behavior by its documentation:
On success, these system calls return the new file descriptor.
Trying to dup2 with ptrace
After verified dup2 is working if called directly, I'm calling dup2 now with ptrace in the tracee with arguments of file_fd (8) and orig_fd (1):
int err = do_syscall(child, dup2, file_fd, orig_fd, 0, 0, 0, 0);
debug("Duplicated fd %d to %d, return=%d", file_fd, orig_fd, err);
With this, the program's output changes to this:
[+] Allocated scratch page: 7fbd357000
[+] Opened the new fd in the child: 8 (/tmp/mystdout)
[+] Saved fd 1 to -1 in the child
[+] Duplicated fd 8 to 1, return=8 !!!
[+] Freed scratch page: 7fbd357000
As you can see, dup2 is executed successfully (positive return value), BUT it returned with 8 instead of 1.
Again, I'm calling ptraced dup2 with this method:
int err = do_syscall(child, dup2, 8, 1, 0, 0, 0, 0);
I don't know how could I detail this method here as it's a bit too large, but for reference here is how I called openat which actually opened the desired file in tracee's process:
int file_fd = do_syscall(child, openat, AT_FDCWD, scratch_page, O_RDWR | O_CREAT, 0666, 0, 0);
(Note: scratch_page is a memory mapped in tracee's space, and "/tmp/mystdout" is copied into it before using this instruction above)
So the question is:
How can I debug the injected dup2? For example with strace?
I wish to understand why it behaves different than when called directly from the small test application.
It turned out that on aarch64 for some reason, dup2 is not able to injected.
No matter what I've tried, it always returned with weird results.
However after I changed dup2 to dup3 everything magically started working.
I'm still wondering on why dup2 syscall can't work, but for now after days of digging and learning I'm happy with this result.
Related
I'm running Pi OS Bullseye on a Pi4 and I'm trying to do the following:
Run a systemd service
Have that service display images (child process C1 exec fbi)
On demand, display next images (child process C2 exec fbi) and tidy up
To this end, the parent process (P) and child attempt this:
P: fork a child (C2)
C2: exec fbi
P: kill and waitpid the previous fbi instance of C1
I get a left-over process and a zombie is killed then new one created every time I run the sequence - it looks like fbi itself forks another child (C3).
My ps output looks like this:
PID PPID PGRP USER NI S COMMAND
5706 1 5706 root -5 S fbi
5705 5499 5499 root -5 Z fbi
5704 1 5704 root -5 S fbi
5702 1 5702 root -5 S fbi
5700 1 5700 root -5 S fbi
5698 1 5698 root -5 S fbi
5696 1 5696 root -5 S fbi
5694 1 5694 root -5 S fbi
If I manually kill an old instance of fbi (e.g. 5694 in the above trace) they all die, which makes me think this is a peculiarity with fbi.
Also, my app reported 5705 as the forked process - what is 5706?
And how is PID 1 launching fbi (PID 5706) instead of my app (PID 5499)?
I could ignore the zombie as there is only a single instance. If there are multiple new image requests (and another display) the number of running fbi instances will mount up.
I've also tried using Process Groups (setgid, killpg) with the same outcome.
Can someone please explain what I'm doing wrong? This is beginning to hurt.
My code (display_front_img is called - yes, there will be more displays) -
void show_image(char *fb_dev_file, char *img_path, pid_t forked_pid, pid_t last_pid)
{
if(forked_pid == 0) // child executes fbi
{
execlp("/usr/bin/fbi", "fbi", "-d", fb_dev_file, "-T", "1", "--noverbose", img_path, NULL);
}
// parent cleans up
else if(last_pid != 0) // if previous fbi called
{
fprintf(stderr, "kill %d returned %d\n", last_pid, kill(last_pid, SIGTERM));
fprintf(stderr, "wait %d returned %d\n", last_pid, waitpid(last_pid, NULL, 0));
}
}
void display_front_img(char * img_path)
{
pid_t last_pid = front_fbi_pid; // get previous assigned PID
front_fbi_pid = fork(); // get newly assigned PID or 0
show_image("/dev/fb0", img_path, front_fbi_pid, last_pid);
}
I'm trying to debug why ngspice prints annoying newlines to stderr while running a simulation. I'm trying to locate it in one of the 2400 source files tracing back to 1993 but it's not as easy as it sounds! It does however mean that I have a binary with all debug information embedded.
My first idea was that strace could help me locate what I believe is the offending call and trace it back to the source code. For example, I'm pretty sure that this is the offending syscall:
brk(0x55d1a84e9000) = 0x55d1a84e9000
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, {tv_sec=0, tv_nsec=61462905}) = 0
>> write(2, "\n", 1) = 1
getrusage(RUSAGE_SELF, {ru_utime={tv_sec=0, tv_usec=26269}, ru_stime={tv_sec=0, tv_usec=35243}, ...}) = 0
openat(AT_FDCWD, "/proc/self/statm", O_RDONLY) = 3
I had hoped that if I traced an executable that had debug information, strace would show me the place in the source code, but that did not happen automatically and the manual is a little overwhelming.
I found a section in the manual called Tracing but couldn't find anything specific.
Is it possible with strace, and if so: How? If not, do you have any other suggestions?
Obvious in hindsight, but one very useful flag is -k. From the man-page:
-k Print the execution stack trace of the traced processes after each system call.
This needs a binary with debug information, and it will get extremely noisy, but combined with a simple filter (-e write in this case) you will eventually get something that looks like this:
write(2, "\n", 1
) = 1
> /lib/x86_64-linux-gnu/libc-2.28.so(__write+0x14) [0xea504]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_write+0x2d) [0x7b3bd]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_setbuf+0xef) [0x7a75f]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_do_write+0x19) [0x7c509]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_overflow+0x103) [0x7c8f3]
> /home/pipe/src/ngspice/debug/src/ngspice(OUTendPlot+0x1ae) [0xd7643]
> /home/pipe/src/ngspice/debug/src/ngspice(DCop+0x167) [0x4cd788]
> /home/pipe/src/ngspice/debug/src/ngspice(CKTdoJob+0x428) [0x4c70dd]
> /home/pipe/src/ngspice/debug/src/ngspice(if_run+0x3b9) [0xe5d3e]
> /home/pipe/src/ngspice/debug/src/ngspice(dosim+0x428) [0xe02ee]
From this I could eventually find the right place after tracking some function inline optimizations.
Using gdb, you can set conditional syscall catchpoints based on the args to the system call (analogous to the way you'd set conditional breakpoints on entry to a function based on the args to the function call). Then, when the catchpoint is triggered, you can see where the caller is (file name, line number, and source code).
Here's an example for x86_64.
$ cat gtest.c
#include <unistd.h>
int main()
{
write(1, "text\n", 5);
write(2, "text2\n", 6);
write(2, "\n", 1);
return 0;
}
$ cc gtest.c -g -o gtest
$ gdb -q gtest
Reading symbols from gtest...done.
(gdb) list
1 #include <unistd.h>
2 int main()
3 {
4 write(1, "text\n", 5);
5 write(2, "text2\n", 6);
6 write(2, "\n", 1);
7 return 0;
8 }
(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [1])
(gdb) condition 1 $rdi == 2 && *(char *)$rsi == '\n' && $rdx == 1
(gdb) r
Starting program: /home/mp/gtest
text
text2
Catchpoint 1 (call to syscall write), 0x00007fffff13b970 in __write_nocancel ()
at ../sysdeps/unix/syscall-template.S:84
84 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 0x00007fffff13b970 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1 0x00000000080006f6 in main () at gtest.c:6
(gdb) up
#1 0x00000000080006f6 in main () at gtest.c:6
6 write(2, "\n", 1);
(gdb)
My first idea was that strace could help me locate what I believe is the offending call and trace it back to the source code.
You guessed right, but must have overlooked this in the strace manual page:
-i Print the instruction pointer at the time of the system call.
Background
I have some very complex application. It is composition of couple libraries.
Now QA team found the some problem (something reports an error).
Fromm logs I can see that application is leaking a file descriptors (+1000 after 7 hours of automated tests).
QA team has delivered rapport "opened files and ports" from "Activity monitor" and I know exactly to which server connection is not closed.
From full application logs I can see that leak is quite systematic (there is no sudden burst), but I was unable to reproduce issue to see even a small leak of file descriptors.
Problem
Even thou I'm sure for which server connection is never closed, I'm unable to find code responsible.
I'm unable reproduce issue.
In logs I can see that all resources my library maintains are properly freed, still server address suggest this is my responsibility or NSURLSession (which is invalidated).
Since there are other libraries and application code it self there is small chance that leak is caused by third party code.
Question
How to locate code responsible for leaking file descriptor?
Best candidate is use dtruss which looks very promising.
From documentation I can see it can print stack backtraces -s when system API is used.
Problem is that I do not know how to use this in such way that I will not get flooded with information.
I need only information who created opened file descriptor and if it was closed destroyed.
Since I can't reproduce issue I need a script which could be run by QA team so the could deliver me an output.
If there are other ways to find the source of file descriptor leak please let me know.
There is bunch of predefined scripts which are using dtruss, but I don't see anything what is matching my needs.
Final notes
What is strange the only code I'm aware is using problematic connection, do not use file descriptors directly, but uses custom NSURLSession (configured as: one connection per host, minimum TLS 1.0, disable cookies, custom certificate validation). From logs I can see NSURLSession is invalidated properly. I doubt NSURLSession is source of leak, but currently this is the only candidate.
OK, I found out how to do it - on Solaris 11, anyway. I get this output (and yes, I needed root on Solaris 11):
bash-4.1# dtrace -s fdleaks.d -c ./fdLeaker
open( './fdLeaker' ) returned 3
open( './fdLeaker' ) returned 4
open( './fdLeaker' ) returned 5
falloc fp: ffffa1003ae56590, fd: 3, saved fd: 3
falloc fp: ffffa10139d28f58, fd: 4, saved fd: 4
falloc fp: ffffa10030a86df0, fd: 5, saved fd: 5
opened file: ./fdLeaker
leaked fd: 3
libc.so.1`__systemcall+0x6
libc.so.1`__open+0x29
libc.so.1`open+0x84
fdLeaker`main+0x2b
fdLeaker`_start+0x72
opened file: ./fdLeaker
leaked fd: 4
libc.so.1`__systemcall+0x6
libc.so.1`__open+0x29
libc.so.1`open+0x84
fdLeaker`main+0x64
fdLeaker`_start+0x72
The fdleaks.d dTrace script that finds leaked file descriptors:
#!/usr/sbin/dtrace
/* this will probably need tuning
note there can be significant performance
impacts if you make these large */
#pragma D option nspec=4
#pragma D option specsize=128k
#pragma D option quiet
syscall::open*:entry
/ pid == $target /
{
/* arg1 might not have a physical mapping yet so
we can't call copyinstr() until open() returns
and we don't have a file descriptor yet -
we won't get that until open() returns anyway */
self->path = arg1;
}
/* arg0 is the file descriptor being returned */
syscall::open*:return
/ pid == $target && arg0 >= 0 && self->path /
{
/* get a speculation ID tied to this
file descriptor and start speculative
tracing */
openspec[ arg0 ] = speculation();
speculate( openspec[ arg0 ] );
/* this output won't appear unless the associated
speculation id is commited */
printf( "\nopened file: %s\n", copyinstr( self->path ) );
printf( "leaked fd: %d\n\n", arg0 );
ustack();
/* free the saved path */
self->path = 0;
}
syscall::close:entry
/ pid == $target && arg0 >= 0 /
{
/* closing the fd, so discard the speculation
and free the id by setting it to zero */
discard( openspec[ arg0 ] );
openspec[ arg0 ] = 0;
}
/* Solaris uses falloc() to open a file and associate
the fd with an internal file_t structure
When the kernel closes file descriptors that the
process left open, it uses the closeall() function
which walks the internal structures then calls
closef() using the file_t *, so there's no way
to get the original process file descritor in
closeall() or closef() dTrace probes.
falloc() is called on open() to associate the
file_t * with a file descriptor, so this
saves the pointers passed to falloc()
that are used to return the file_t * and
file descriptor once they're filled in
when falloc() returns */
fbt::falloc:entry
/ pid == $target /
{
self->fpp = args[ 2 ];
self->fdp = args[ 3 ];
}
/* Clause-local variables to make casting clearer */
this int fd;
this uint64_t fp;
/* array to associate a file descriptor with its file_t *
structure in the kernel */
int fdArray[ uint64_t fp ];
fbt::falloc:return
/ pid == $target && self->fpp && self->fdp /
{
/* get the fd and file_t * values being
returned to the caller */
this->fd = ( * ( int * ) self->fdp );
this->fp = ( * ( uint64_t * ) self->fpp );
/* associate the fd with its file_t * */
fdArray[ this->fp ] = ( int ) this->fd;
/* verification output */
printf( "falloc fp: %x, fd: %d, saved fd: %d\n", this->fp, this->fd, fdArray[ this->fp ] );
}
/* if this gets called and the dereferenced
openspec array element is a still-valid
speculation id, the fd associated with
the file_t * passed to closef() was never
closed by the process itself */
fbt::closef:entry
/ pid == $target /
{
/* commit the speculative tracing since
this file descriptor was leaked */
commit( openspec[ fdArray[ arg0 ] ] );
}
First, I wrote this little C program to leak fds:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main( int argc, char **argv )
{
int ii;
for ( ii = 0; ii < argc; ii++ )
{
int fd = open( argv[ ii ], O_RDONLY );
fprintf( stderr, "open( '%s' ) returned %d\n", argv[ ii ], fd );
fd = open( argv[ ii ], O_RDONLY );
fprintf( stderr, "open( '%s' ) returned %d\n", argv[ ii ], fd );
fd = open( argv[ ii ], O_RDONLY );
fprintf( stderr, "open( '%s' ) returned %d\n", argv[ ii ], fd );
close( fd );
}
return( 0 );
}
Then I ran it under this dTrace script to figure out what the kernel does to close orphaned file descriptors, dtrace -s exit.d -c ./fdLeaker:
#!/usr/sbin/dtrace -s
#pragma D option quiet
syscall::rexit:entry
{
self->exit = 1;
}
syscall::rexit:return
/ self->exit /
{
self->exit = 0;
}
fbt:::entry
/ self->exit /
{
printf( "---> %s\n", probefunc );
}
fbt:::return
/ self->exit /
{
printf( "<--- %s\n", probefunc );
}
That produced a lot of output, and I noticed closeall() and closef() functions, examined the source code, and wrote the dTrace script.
Note also that the process exit dTrace probe on Solaris 11 is the rexit one - that probably changes on OSX.
The biggest problem on Solaris is getting the file descriptor for the file in the kernel code that closes orphaned file descriptors. Solaris doesn't close by file descriptor, it closes by struct file_t pointers in the kernel open files structures for the process. So I had to examine the Solaris source to figure out where the fd is associated with the file_t * - and that's in the falloc() function. The dTrace script associates a file_t * with its fd in an associative array.
None of that is likely to work on OSX.
If you're lucky, the OSX kernel will close orphaned file descriptors by the file descriptor itself, or at least provide something that tells you the fd is being closed, perhaps an auditing function.
Consider the kernel module testhrarr.c given in debugging - Watch a variable (memory address) change in Linux kernel, and print stack trace when it changes? - Stack Overflow, which tracks write accesses to a memory location.
Now, I'm trying to track read/write accesses, which I've done by changing this line in the testhrarr_init function:
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
First subquestion here is this: on my platform (Linux kernel 2.6.38); HW_BREAKPOINT_W on its own works, and HW_BREAKPOINT_W | HW_BREAKPOINT_R for read/write works too - however trying only read access with HW_BREAKPOINT_R doesn't work; as I get "Breakpoint registration failed" in /var/log/syslog, and insmod fails with "insmod: error inserting './testhrarr.ko': -1 Invalid parameters". Does anyone have any idea why?
Anyways, the problem here is that once I'm watching for read/write access with HW_BREAKPOINT_W | HW_BREAKPOINT_R, I cannot tell in my handler whether the stack trace I'm getting is due to a read or a write access. I have gone through:
struct perf_event_attr in include/linux/perf_event.h
struct hw_perf_event include/linux/perf_event.h
include/linux/hw_breakpoint.h for the HW_BREAKPOINT_* enum definitions
... and I couldn't find anywhere an explicit technique to retrieve from the hw breakpoint handler, whether it was a read or write access that triggered. I only found something in kernel/trace/trace_ksym.c, but trace_ksym has been deprecated (not even found in my 2.6.38), and besides it simply reads attr.bp_type, which is what we ourselves set in the kernel module.
So, after some brute-forcing, I realized that the hw_perf_event->interrupts may contain this information; so I modified the handler callback as:
static void sample_hbp_handler(struct perf_event *bp,
struct perf_sample_data *data,
struct pt_regs *regs)
{
struct perf_event_attr attr = bp->attr;
struct hw_perf_event hw = bp->hw;
char hwirep[8];
//it looks like printing %llu, data->type here causes segfault/oops when `cat` runs?
// apparently, hw.interrupts changes depending on read/write access (1 or 2)
// when only HW_BREAKPOINT_W, getting hw.interrupts == 1 always;
// only HW_BREAKPOINT_R - fails for me
// when both, hw.interrupts is either 1 or 2
// defined in include/linux/hw_breakpoint.h:
// HW_BREAKPOINT_R = 1, HW_BREAKPOINT_W = 2,
if (hw.interrupts == HW_BREAKPOINT_R) {
strcpy(hwirep, "_R");
} else if (hw.interrupts == HW_BREAKPOINT_W) {
strcpy(hwirep, "_W");
} else {
strcpy(hwirep, "__");
}
printk(KERN_INFO "+--- %s value is accessed (.bp_type %d, .type %d, state %d htype %d hwi %llu / %s ) ---+\n", ksym_name, attr.bp_type, attr.type, hw.state, hw.info.type, hw.interrupts, hwirep);
dump_stack();
printk(KERN_INFO "|___ Dump stack from sample_hbp_handler ___|\n");
}
... and this seems to work somewhat; as I get the following in syslog:
$ grep "testhrarr_arr_first value" /var/log/syslog
kernel: [ 200.887620] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
kernel: [ 200.892163] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
kernel: [ 200.892634] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 2 / _W ) ---+
kernel: [ 200.912192] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
kernel: [ 200.912713] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 2 / _W ) ---+
kernel: [ 200.932138] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
... however, if attr.bp_type is just HW_BREAKPOINT_W, then just three hw.interrupts == 1 are reported (which would be then wrongly reported as _R with the above code).
So then, if I just invert the meanings of _R and _W, I may get something that matches what I guess should occur - but this is quite obviously a shot in the dark, since I have no idea what hw_perf_event->interrupts should actually stand for.
So - does anyone know the proper way of determining the "direction" (read or write) of access to a hardware-watched memory location?
Edit: the answer for my first subquestion: for my architecture, x86, there is this piece of code:
http://lxr.free-electrons.com/source/arch/x86/kernel/hw_breakpoint.c?v=2.6.38#L252
static int arch_build_bp_info(struct perf_event *bp)
{
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
info->address = bp->attr.bp_addr;
/* Type */
switch (bp->attr.bp_type) {
case HW_BREAKPOINT_W:
info->type = X86_BREAKPOINT_WRITE;
break;
case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
info->type = X86_BREAKPOINT_RW;
break;
case HW_BREAKPOINT_X:
info->type = X86_BREAKPOINT_EXECUTE;
// ...
default:
return -EINVAL;
}
...
}
... which clearly states that X86 has either _WRITE or _RW breakpoints; so if we try to set up just for HW_BREAKPOINT_R, the process would fail returning -EINVAL.
So, I guess, I'd need the answer here primarily for X86, although if there is a generic portable mechanism for determining read/write access, I'd rather know about that...
I'm using a library in my C++ application and trying to capture all the output in a file. I tried to redirect the stderr to stdout and then stdout to a file like so:
./a.out 2>&1 > out.txt
This captures pretty much everything in my application but there are still some output on the console related to the library I'm using. My question is:
Are there anything besides stdout/stderr? (other than stdin)
If there are, how can I identify these in my case?
And then how can I redirect these to the same file?
Note: In case someone is familiar, library is called SystemC (which is an event driven simulation library/language on top of C++ for mainly system/hardware design).
You must set output file before any stream-to-stream redirection, else bash can't detect file name to output. In your case you can see stderr output.
See bash redirections reference manual.
Solution:
./a.out >out.txt 2>&1
Or just:
./a.out &>out.txt
Hmm, well I think what might be happening is that your program is printing to the controlling terminal. One possibility could be to have your program run as a daemon with no controlling terminal. I have a C function that I call to turn my code into a daemon, I got this from a book called The Linux Programming Interface which I highly recommend.
#define BD_NO_CHDIR 01 /* Don't chdir("/") */
#define BD_NO_CLOSE_FILES 02 /* Don't close all open files */
#define BD_NO_REOPEN_STD_FDS 04 /* Don't reopen stdin, stdout, and
stderr to /dev/null */
#define BD_NO_UMASK0 010 /* Don't do a umask(0) */
#define BD_MAX_CLOSE 8192 /* Maximum file descriptors to close if
sysconf(_SC_OPEN_MAX) is indeterminate */
int becomeDaemon(int flags){
int maxfd, fd, new_stdout;
switch (fork()) { /* Become background process */
case -1: return -1;
case 0: break; /* Child falls through... */
default: _exit(EXIT_SUCCESS); /* while parent terminates */
}
if (setsid() == -1) /* Become leader of new session */
return -1;
switch (fork()) { /* Ensure we are not session leader */
case -1: return -1;
case 0: break;
default: _exit(EXIT_SUCCESS);
}
if (!(flags & BD_NO_UMASK0))
umask(0); /* Clear file mode creation mask */
if (!(flags & BD_NO_CHDIR))
chdir("/"); /* Change to root directory */
if (!(flags & BD_NO_CLOSE_FILES)) { /* Close all open files */
maxfd = sysconf(_SC_OPEN_MAX);
if (maxfd == -1) /* Limit is indeterminate... */
maxfd = BD_MAX_CLOSE; /* so take a guess */
for (fd = 0; fd < maxfd; fd++)
close(fd);
}
if (!(flags & BD_NO_REOPEN_STD_FDS)) {
/*
STDIN = 0
STDOUT = 1
STDERR = 2
*/
close(0); /* Reopen standard fd's to /dev/null */
fd = open("/dev/null", O_RDWR);
if (fd != 0) /* 'fd' should be 0 */
return -1;
if (dup2(0, 1) != 1)
return -1;
if (dup2(0, 2) != 2)
return -1;
}
return 0;
}
Now I suppose that you can change the line open("/dev/null", O_RDWR) to open("/home/you/output.txt", O_RDWR) and redirect the output there. Ofcourse then you wouldn't be able to directly input from the terminal to your program, but from the sounds of the error message you're getting I think you're using a socket anyway so could possible write a client to do that for you if it was necessary.
Hope that helps.