Skip to content

Instantly share code, notes, and snippets.

@faberyx
Last active December 21, 2021 19:59
Show Gist options
  • Save faberyx/b07d146e11efbad1643f3e8ba6f1a475 to your computer and use it in GitHub Desktop.
Save faberyx/b07d146e11efbad1643f3e8ba6f1a475 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <signal.h>
#include <syslog.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define DAEMON_NAME "simpledaemon"
void daemonShutdown();
void signal_handler(int sig);
void daemonize(const char *rundir, const char *pidfile);
bool exitdaemon = false;
int pidFilehandle;
void signal_handler(int sig)
{
switch(sig)
{
case SIGINT:
case SIGTERM:
exitdaemon = true;
break;
}
}
void daemonShutdown()
{
syslog(LOG_INFO, "Daemon exiting");
close(pidFilehandle);
}
void daemonize(const char *rundir, const char *pidfile)
{
int pid, sid, i;
char str[10];
struct sigaction newSigAction;
sigset_t newSigSet;
/* Check if parent process id is set */
if (getppid() == 1)
{
/* PPID exists, therefore we are already a daemon */
return;
}
/* Set signal mask - signals we want to block */
sigemptyset(&newSigSet);
sigaddset(&newSigSet, SIGCHLD); /* ignore child - i.e. we don't need to wait for it */
sigaddset(&newSigSet, SIGTSTP); /* ignore Tty stop signals */
sigaddset(&newSigSet, SIGTTOU); /* ignore Tty background writes */
sigaddset(&newSigSet, SIGTTIN); /* ignore Tty background reads */
sigprocmask(SIG_BLOCK, &newSigSet, NULL); /* Block the above specified signals */
/* Set up a signal handler */
newSigAction.sa_handler = signal_handler;
sigemptyset(&newSigAction.sa_mask);
newSigAction.sa_flags = 0;
/* Signals to handle */
sigaction(SIGHUP, &newSigAction, NULL); /* catch hangup signal */
sigaction(SIGTERM, &newSigAction, NULL); /* catch term signal */
sigaction(SIGINT, &newSigAction, NULL); /* catch interrupt signal */
/* Fork*/
pid = fork();
if (pid < 0)
{
/* Could not fork */
exit(EXIT_FAILURE);
}
if (pid > 0)
{
/* Child created ok, so exit parent process */
//printf("Child process created: %d\n", pid);
exit(EXIT_SUCCESS);
}
/* Child continues */
umask(027); /* Set file permissions 750 */
/* Get a new process group */
sid = setsid();
if (sid < 0)
{
exit(EXIT_FAILURE);
}
/* close all descriptors */
for (i = getdtablesize(); i >= 0; --i)
{
close(i);
}
/* Route I/O connections */
/* Open STDIN */
i = open("/dev/null", O_RDWR);
/* STDOUT */
dup(i);
/* STDERR */
dup(i);
chdir(rundir); /* change running directory */
/* Ensure only one copy */
pidFilehandle = open(pidfile, O_RDWR|O_CREAT, 0600);
if (pidFilehandle == -1 )
{
/* Couldn't open lock file */
syslog(LOG_INFO, "Could not open PID lock file %s, exiting", pidfile);
exit(EXIT_FAILURE);
}
/* Try to lock file */
if (lockf(pidFilehandle,F_TLOCK,0) == -1)
{
/* Couldn't get lock on lock file */
syslog(LOG_INFO, "Could not lock PID lock file %s, exiting", pidfile);
exit(EXIT_FAILURE);
}
/* Get and format PID */
sprintf(str,"%d\n",getpid());
/* write pid to lockfile */
write(pidFilehandle, str, strlen(str));
}
int main()
{
/* Logging */
setlogmask(LOG_UPTO(LOG_INFO));
openlog(DAEMON_NAME, LOG_CONS | LOG_PERROR, LOG_USER);
syslog(LOG_INFO, "Daemon starting up");
/* Deamonize */
const char* daemonpid = "/var/run/srv_test.pid";
const char* daemonpath = "/";
daemonize(daemonpath, daemonpid);
syslog(LOG_INFO, "Daemon running");
while (!exitdaemon)
{
// syslog(LOG_INFO, "daemon says hello");
sleep(10);
}
daemonShutdown();
}
@Lungdjos
Copy link

So how does this source code operates??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment