11 #include <sys/types.h>
18 #include "appconfig.h"
20 #include "web_client.h"
21 #include "plugins_d.h"
27 void sig_handler(int signo)
39 infoerr("Death signaled exit (signal %d).", signo);
40 signal(signo, SIG_DFL);
50 infoerr("Signaled exit (signal %d).", signo);
51 signal(SIGPIPE, SIG_IGN);
52 signal(SIGTERM, SIG_IGN);
53 signal(SIGQUIT, SIG_IGN);
54 signal(SIGHUP, SIG_IGN);
55 signal(SIGINT, SIG_IGN);
56 signal(SIGCHLD, SIG_IGN);
57 netdata_cleanup_and_exit(1);
61 infoerr("Signaled PIPE (signal %d).", signo);
62 // this is received when web clients send a reset
64 // infoerr("Ignoring signal %d.", signo);
68 info("Signal %d received. Falling back to default action for it.", signo);
69 signal(signo, SIG_DFL);
74 char rundir[FILENAME_MAX + 1] = RUN_DIR;
75 char pidfile[FILENAME_MAX + 1] = "";
76 void prepare_rundir() {
78 mkdir("/run/user", 0775);
79 snprintf(rundir, FILENAME_MAX, "/run/user/%d", getuid());
81 snprintf(rundir, FILENAME_MAX, "/run/user/%d/netdata", getuid());
84 snprintf(pidfile, FILENAME_MAX, "%s/netdata.pid", rundir);
86 if(mkdir(rundir, 0775) != 0) {
87 if(errno != EEXIST) error("Cannot create directory '%s'.", rundir);
91 int become_user(const char *username)
93 struct passwd *pw = getpwnam(username);
95 error("User %s is not present.", username);
99 if(chown(rundir, pw->pw_uid, pw->pw_gid) != 0) {
100 error("Cannot chown directory '%s' to user %s.", rundir, username);
104 if(setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
105 error("Cannot switch to user's %s group (gid: %d).", username, pw->pw_gid);
109 if(setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
110 error("Cannot switch to user %s (uid: %d).", username, pw->pw_uid);
114 if(setgid(pw->pw_gid) != 0) {
115 error("Cannot switch to user's %s group (gid: %d).", username, pw->pw_gid);
118 if(setegid(pw->pw_gid) != 0) {
119 error("Cannot effectively switch to user's %s group (gid: %d).", username, pw->pw_gid);
122 if(setuid(pw->pw_uid) != 0) {
123 error("Cannot switch to user %s (uid: %d).", username, pw->pw_uid);
126 if(seteuid(pw->pw_uid) != 0) {
127 error("Cannot effectively switch to user %s (uid: %d).", username, pw->pw_uid);
134 int become_daemon(int dont_fork, int close_all_files, const char *user, const char *input, const char *output, const char *error, const char *access, int *access_fd, FILE **access_fp)
138 // open the files before forking
139 int input_fd = -1, output_fd = -1, error_fd = -1, dev_null;
141 if(input && *input) {
142 if((input_fd = open(input, O_RDONLY, 0666)) == -1) {
143 error("Cannot open input file '%s'.", input);
148 if(output && *output) {
149 if((output_fd = open(output, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
150 error("Cannot open output log file '%s'", output);
151 if(input_fd != -1) close(input_fd);
156 if(error && *error) {
157 if((error_fd = open(error, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
158 error("Cannot open error log file '%s'.", error);
159 if(input_fd != -1) close(input_fd);
160 if(output_fd != -1) close(output_fd);
165 if(access && *access && access_fd) {
166 if((*access_fd = open(access, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
167 error("Cannot open access log file '%s'", access);
168 if(input_fd != -1) close(input_fd);
169 if(output_fd != -1) close(output_fd);
170 if(error_fd != -1) close(error_fd);
175 *access_fp = fdopen(*access_fd, "w");
177 error("Cannot migrate file's '%s' fd %d.", access, *access_fd);
178 if(input_fd != -1) close(input_fd);
179 if(output_fd != -1) close(output_fd);
180 if(error_fd != -1) close(error_fd);
188 if((dev_null = open("/dev/null", O_RDWR, 0666)) == -1) {
189 perror("Cannot open /dev/null");
190 if(input_fd != -1) close(input_fd);
191 if(output_fd != -1) close(output_fd);
192 if(error_fd != -1) close(error_fd);
193 if(access && access_fd && *access_fd != -1) {
210 perror("cannot fork");
214 exit(0); // the parent
217 // become session leader
219 perror("Cannot become session leader.");
224 signal(SIGCHLD, SIG_IGN);
225 signal(SIGHUP, SIG_IGN);
226 signal(SIGWINCH, SIG_IGN);
232 perror("cannot fork");
236 exit(0); // the parent
240 // Set new file permissions
244 if(close_all_files) {
246 for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
248 ((access_fd && i != *access_fd) || !access_fd)
258 close(STDOUT_FILENO);
259 close(STDERR_FILENO);
262 // put the opened files
263 // to our standard file descriptors
265 if(input_fd != STDIN_FILENO) {
266 dup2(input_fd, STDIN_FILENO);
271 else dup2(dev_null, STDIN_FILENO);
273 if(output_fd != -1) {
274 if(output_fd != STDOUT_FILENO) {
275 dup2(output_fd, STDOUT_FILENO);
280 else dup2(dev_null, STDOUT_FILENO);
283 if(error_fd != STDERR_FILENO) {
284 dup2(error_fd, STDERR_FILENO);
289 else dup2(dev_null, STDERR_FILENO);
292 if(dev_null != STDIN_FILENO && dev_null != STDOUT_FILENO && dev_null != STDERR_FILENO)
295 // generate our pid file
298 int fd = open(pidfile, O_RDWR | O_CREAT, 0666);
301 sprintf(b, "%d\n", getpid());
302 ssize_t i = write(fd, b, strlen(b));
303 if(i <= 0) perror("Cannot write pid to file.");
309 if(become_user(user) != 0) {
310 error("Cannot become user '%s'. Continuing as we are.", user);
312 else info("Successfully became user '%s'.", user);