
/* daemon.q: how to implement a daemon program in Q (UNIX only) */

import system;

/* Becoming a daemon is easy: Just fork, have the parent exit, and call setsid
   in the child to start a new session. The new process becomes a child of the
   init process and has no controlling terminal. Thus it keeps running even if
   you log out, until it gets killed or the system shuts down. */

daemon		= setsid || main if fork = 0;
		= exit 0 otherwise;

/* The main code of the daemon then closes file descriptors inherited by the
   parent and starts executing. In this example we just open a logfile and
   start logging messages in regular intervals. We also handle the condition
   that we are terminated by a signal. */

main		= do close [0,1,2] || log F "daemon started" ||
		  do (trap 1) [SIGINT, SIGTERM, SIGHUP, SIGQUIT] ||
		  catch (sig F) (loop F) where F:File = fopen "log" "w";
		= perror "daemon" || exit 1 otherwise;

sig F (syserr SIG)
		= log F (sprintf "daemon stopped by signal %d" (-SIG)) ||
		  exit 0;

loop F		= sleep 5 || log F "daemon still alive" || loop F;

log F MSG	= fprintf F "%s at %s" (MSG, ctime time) || fflush F;
