Jordan,
Following (at the end of this post) is the code for a Unix daemon
(daemon.c). It is setup to run on both System V and BSD. I am not familar
with Linux. In any case, you link in the object built from this code with
your main C program. After you've setup your environment in your main
module, call daemon_start( 1 ). You do not need to start it as a background
process, since it will fork itself and kill the child, anyway. The main
thing the daemon does is disassociate itself from any terminals and ensures
zombie processes are left in the environment.
Apart from starting the daemon, you'll need to setup an infinite loop in
your main module. Here's a snippet from a main module we use to query a
table, scg_system, that our applications in windows write to if they need to
execute a report on our Unix database server: The only thing scg_system has
is a varchar field for the reports command line, a status to tell if the
command line has been run yet, and a time stamp. We use the status of 1 to
tell if scg_sysd has read the row to execute the command line (so it won't
execute it again); 2 to indicate that scg_sysd successfully executed the
command; and 3 if scg_sysd tried, but could not execute the command, in
which case the error is logged by the LogError() function.
A good way to test your daemon, is to just setup main(), call
daemon_start(), and then in your infinite loop open a tty and write to it ,
then close the tty. After the wait() in your main() program, another child
will be forked and it will write to the tty again. Once you're satisfied
it works, just kill the process. Warning: Do not test a daemon on a
production system. It is not difficult to code in an error that might cause
the program to start forking until it fills-up the process table.
/*
* check for an open database before continuing. This first loop is used
because the daemon is started when the system
* inits and the database will not yet be running.
*/
while( 1 ) {
if( !fork( ) ) {
i = nCreateTable( ); /* nCreateTable() returns 0 when it has
successfully checked for/created the table */
fprintf( fp, %d, i ); /* write 1-char stat to tmp for parent
*/
fclose( fp );
exit( i );
} else {
wait( (int*)0 ); /* wait for child to exit */
if( ( fp = fopen( szTmpNam, r ) ) == NULL ) {
LogError( Can't open tmp file(2), 0 );
exit( 1 );
}
fread( szBuf, sizeof( szBuf ), 256, fp ); /* get status */
fclose( fp );/* close and unlink tmpfile */
unlink( szTmpNam );
status = atoi( szBuf );
if( !status ) break;/* the database is started;
scg_system exists */
signal( SIGALRM, alarm_catch );
alarm( nSLEEPTIME );/* nSLEEPTIME is the number of
seconds to sleep */
pause( );
tmpnam( szTmpNam );
if( ( fp = fopen( szTmpNam, w+ ) ) == NULL ) {
LogError( Can't open tmp file(3), 0 );
exit( 1 );
}
}
} /* end while */
fclose( fp );
unlink( szTmpNam );
/* this is the processing loop */
while( 1 ) {
if( !fork() ) {
nRunDBCommands( ); /* look up the command line and system() the
command */
exit( 0 );
} else {
wait( (int*) 0 );
signal( SIGALRM, alarm_catch );
alarm( nSLEEPTIME );
pause( );
}
} /* end while */
/* alarm catcher doesn't need to do anything. It could call alarm(), but we
did it in the while loop */
int alarm_catch()
{
return(0);
}/* end alarm_catch */
/** here's daemon.c /
/*
* daemon.c - start process as a UNIX daemon
*
* syntax: void daemon_start( int ignsigcld )
*
* description: daemon is called by the main process to disconnect
*the process from any terminals and/or group
*leader roles. The nonzero ignsigcld flag is
*to handle SIGCLDs so zombies don't clog.
*
* databases/files accessed:
* name type description
* ===
* scg_systemtable hold command lines to be executed by scg_sysd
*
* function calls:
* name description
* ===
*
* global variables:
* name type description
* ===
*
* edit history:
* Date Programmer Description
* == ===
* Thu Oct 24 02:34:24 EDT 1996 jlp baselined for fm_sysd.ec
*
* Programmer's Note:
*/
static char ident[] =SCG Id: @(#) daemon.c 1.1.0.0. 10/14/97 17:00:50;
/*
* defines
*/
/*
* externals
*/
extern int errno ;
/*
* includes
*/
#include stdio.h
#include signal.h
#include errno.h
#include sys/types.h
#include sys/param.h
#include SCGdefs.h
/*
* globals
*/
/*
* function declarations
*/
/*
*
*** Function definitions ***
*
*/
#ifdef SIGSTP