86e89066aedf048757cc2f4e55674e909a0168a0
[dss.git] / daemon.c
1 /*
2 * Copyright (C) 1997-2010 Andre Noll <maan@tuebingen.mpg.de>
3 *
4 * Licensed under the GPL v2. For licencing details see COPYING.
5 */
6
7 /** \file daemon.c Some helpers for programs that detach from the console. */
8
9 #include <string.h>
10 #include <stdlib.h>
11 #include <pwd.h>
12 #include <errno.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <grp.h>
16 #include <assert.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20
21 #include "gcc-compat.h"
22 #include "err.h"
23 #include "log.h"
24 #include "str.h"
25 #include "daemon.h"
26
27 /**
28 * Do the usual stuff to become a daemon.
29 *
30 * Fork, become session leader, dup fd 0, 1, 2 to /dev/null.
31 *
32 * \sa fork(2), setsid(2), dup(2).
33 */
34 void daemon_init(void)
35 {
36 pid_t pid;
37 int null;
38
39 DSS_INFO_LOG(("daemonizing\n"));
40 pid = fork();
41 if (pid < 0)
42 goto err;
43 if (pid)
44 exit(EXIT_SUCCESS); /* parent exits */
45 /* become session leader */
46 if (setsid() < 0)
47 goto err;
48 umask(0);
49 null = open("/dev/null", O_RDWR);
50 if (null < 0)
51 goto err;
52 if (dup2(null, STDIN_FILENO) < 0)
53 goto err;
54 if (dup2(null, STDOUT_FILENO) < 0)
55 goto err;
56 if (dup2(null, STDERR_FILENO) < 0)
57 goto err;
58 close(null);
59 return;
60 err:
61 DSS_EMERG_LOG(("fatal: %s\n", strerror(errno)));
62 exit(EXIT_FAILURE);
63 }
64
65 /**
66 * fopen() the given file in append mode.
67 *
68 * \param logfile_name The name of the file to open.
69 *
70 * \return Either calls exit() or returns a valid file handle.
71 */
72 FILE *open_log(const char *logfile_name)
73 {
74 FILE *logfile;
75
76 assert(logfile_name);
77 logfile = fopen(logfile_name, "a");
78 if (!logfile) {
79 DSS_EMERG_LOG(("can not open %s: %s\n", logfile_name,
80 strerror(errno)));
81 exit(EXIT_FAILURE);
82 }
83 setlinebuf(logfile);
84 return logfile;
85 }
86
87 /**
88 * Close the log file of the daemon.
89 *
90 * \param logfile The log file handle.
91 *
92 * It's OK to call this with logfile == \p NULL.
93 */
94 void close_log(FILE* logfile)
95 {
96 if (!logfile)
97 return;
98 DSS_INFO_LOG(("closing logfile\n"));
99 fclose(logfile);
100 }
101
102 /**
103 * Log the startup message.
104 */
105 void log_welcome(int loglevel)
106 {
107 DSS_INFO_LOG(("***** welcome to dss ******\n"));
108 DSS_DEBUG_LOG(("using loglevel %d\n", loglevel));
109 }