Browse Source

Add faux_daemon() function

Serj Kalichev 1 year ago
parent
commit
dc5dc505a1
4 changed files with 83 additions and 1 deletions
  1. 2 1
      faux/base/Makefile.am
  2. 76 0
      faux/base/sys.c
  3. 3 0
      faux/faux.h
  4. 2 0
      faux/faux.map

+ 2 - 1
faux/base/Makefile.am

@@ -1,7 +1,8 @@
 libfaux_la_SOURCES += \
 libfaux_la_SOURCES += \
 	faux/base/mem.c \
 	faux/base/mem.c \
 	faux/base/io.c \
 	faux/base/io.c \
-	faux/base/fs.c
+	faux/base/fs.c \
+	faux/base/sys.c
 
 
 if TESTC
 if TESTC
 libfaux_la_SOURCES += faux/base/testc_base.c
 libfaux_la_SOURCES += faux/base/testc_base.c

+ 76 - 0
faux/base/sys.c

@@ -0,0 +1,76 @@
+/** @file sys.c
+ * @brief System-related faux functions.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "faux/faux.h"
+
+
+/** Implementation of daemon() function.
+ *
+ * The original daemon() function is not POSIX. Additionally parent doesn't
+ * create PID file as UNIX services do. So after parent exiting there is no
+ * PID file yet. This function fix that problems.
+ *
+ * @param [in] nochdir On zero changes working dir to "/". Compatible with daemon().
+ * @param [in] noclose On zero redirects standard streams to "/dev/null". Compatible with daemon().
+ * @param [in] pidfile Name of PID file to create.
+ * @param [in] mode PID file mode.
+ * @return BOOL_TRUE on success, BOOL_FALSE else.
+ * @sa daemon()
+ */
+bool_t faux_daemon(int nochdir, int noclose, const char *pidfile, mode_t mode)
+{
+	pid_t pid = -1;
+
+	pid = fork();
+	if (-1 == pid)
+		return BOOL_FALSE;
+
+	// Parent
+	if (pid > 0) {
+		// Parent writes PID file
+		if (pidfile && (pidfile[0] != '\0')) {
+			int fd = -1;
+			if ((fd = open(pidfile,
+				O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
+				mode)) >= 0) {
+				char str[20] = {};
+				snprintf(str, sizeof(str), "%u\n", pid);
+				str[sizeof(str) - 1] = '\0';
+				write(fd, str, strlen(str));
+				close(fd);
+			}
+		}
+		_exit(0); // Exit parent
+	}
+
+	// Child
+	if (setsid() == -1)
+		return BOOL_FALSE;
+	if (0 == nochdir) {
+		if (chdir("/"))
+			return BOOL_FALSE;
+	}
+	if (0 == noclose) {
+		int fd = -1;
+		fd = open("/dev/null", O_RDWR, 0);
+		if (fd < 0)
+			return BOOL_FALSE;
+		dup2(fd, STDIN_FILENO);
+		dup2(fd, STDOUT_FILENO);
+		dup2(fd, STDERR_FILENO);
+		if (fd > STDERR_FILENO)
+			close(fd);
+	}
+
+	return BOOL_TRUE;
+}

+ 3 - 0
faux/faux.h

@@ -9,6 +9,9 @@
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/uio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 
 
 /**
 /**
  * A standard boolean type. The possible values are
  * A standard boolean type. The possible values are

+ 2 - 0
faux/faux.map

@@ -107,6 +107,8 @@ FAUX_2.0 {
 		faux_mkdir_p;
 		faux_mkdir_p;
 		faux_expand_tilde;
 		faux_expand_tilde;
 
 
+		faux_daemon;
+
 		faux_file_fdopen;
 		faux_file_fdopen;
 		faux_file_open;
 		faux_file_open;
 		faux_file_close;
 		faux_file_close;