Files
FTL/daemon.c

157 lines
3.4 KiB
C

/* Pi-hole: A black hole for Internet advertisements
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* Daemon routines
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
struct timeval t0[NUMTIMERS];
void go_daemon(void)
{
// Create child process
pid_t process_id = fork();
// Indication of fork() failure
if (process_id < 0)
{
logg("fork failed!\n");
// Return failure in exit status
exit(EXIT_FAILURE);
}
// PARENT PROCESS. Need to kill it.
if (process_id > 0)
{
printf("FTL started!\n");
// return success in exit status
exit(EXIT_SUCCESS);
}
//unmask the file mode
umask(0);
//set new session
// creates a session and sets the process group ID
const pid_t sid = setsid();
if(sid < 0)
{
// Return failure
logg("setsid failed!\n");
exit(EXIT_FAILURE);
}
// Create grandchild process
// Fork a second child and exit immediately to prevent zombies. This
// causes the second child process to be orphaned, making the init
// process responsible for its cleanup. And, since the first child is
// a session leader without a controlling terminal, it's possible for
// it to acquire one by opening a terminal in the future (System V-
// based systems). This second fork guarantees that the child is no
// longer a session leader, preventing the daemon from ever acquiring
// a controlling terminal.
process_id = fork();
// Indication of fork() failure
if (process_id < 0)
{
logg("fork failed!\n");
// Return failure in exit status
exit(EXIT_FAILURE);
}
// PARENT PROCESS. Need to kill it.
if (process_id > 0)
{
// return success in exit status
exit(EXIT_SUCCESS);
}
savepid();
// Closing stdin, stdout and stderr is handled by dnsmasq
}
void timer_start(const int i)
{
if(i >= NUMTIMERS)
{
logg("Code error: Timer %i not defined in timer_start().", i);
exit(EXIT_FAILURE);
}
gettimeofday(&t0[i], 0);
}
double timer_elapsed_msec(const int i)
{
if(i >= NUMTIMERS)
{
logg("Code error: Timer %i not defined in timer_elapsed_msec().", i);
exit(EXIT_FAILURE);
}
struct timeval t1;
gettimeofday(&t1, 0);
return (t1.tv_sec - t0[i].tv_sec) * 1000.0f + (t1.tv_usec - t0[i].tv_usec) / 1000.0f;
}
void sleepms(const int milliseconds)
{
struct timeval tv;
tv.tv_sec = milliseconds / 1000;
tv.tv_usec = (milliseconds % 1000) * 1000;
select(0, NULL, NULL, NULL, &tv);
}
void savepid(void)
{
FILE *f;
const pid_t pid = getpid();
if((f = fopen(FTLfiles.pid, "w+")) == NULL)
{
logg("WARNING: Unable to write PID to file.");
logg(" Continuing anyway...");
}
else
{
fprintf(f, "%i", (int)pid);
fclose(f);
}
logg("PID of FTL process: %i", (int)pid);
}
void removepid(void)
{
FILE *f;
if((f = fopen(FTLfiles.pid, "w+")) == NULL)
{
logg("WARNING: Unable to empty PID file");
return;
}
fclose(f);
}
char *getUserName(void)
{
char * name;
// the getpwuid() function shall search the user database for an entry with a matching uid
// the geteuid() function shall return the effective user ID of the calling process - this is used as the search criteria for the getpwuid() function
const uid_t euid = geteuid();
const struct passwd *pw = getpwuid(euid);
if(pw)
{
name = strdup(pw->pw_name);
}
else
{
if(asprintf(&name, "%u", euid) < 0)
return NULL;
}
return name;
}