static void daemon_select_loop (fd_set serverfds, fd_set sslfds, int maxfd) { fd_set rdfds; int nselect; for (;;) { if (reload) daemon_reload (); if (terminate) daemon_terminate (); rdfds = serverfds; errno = 0; nselect = select (maxfd + 1, &rdfds, NULL, NULL, NULL); if (nselect == -1) { switch (errno) { case EINTR: break; default: syslog(LOG_DEBUG, "select=%d err=%m", nselect); break; } } else { // nselect == 0 doesn't happen for (int fd = 0; fd <= maxfd && nselect > 0; fd++) { if (! FD_ISSET (fd, &rdfds)) continue; nselect--; daemon_accept (fd, serverfds, sslfds, maxfd); } } } }
int run_daemon() { if (getuid() != 0 || getgid() != 0) { PLOGE("daemon requires root. uid/gid not root"); return -1; } prepare(); int fd; struct sockaddr_un sun; fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (fd < 0) { PLOGE("socket"); return -1; } if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { PLOGE("fcntl FD_CLOEXEC"); goto err; } memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_LOCAL; sprintf(sun.sun_path, "%s/server", REQUESTOR_DAEMON_PATH); /* * Delete the socket to protect from situations when * something bad occured previously and the kernel reused pid from that process. * Small probability, isn't it. */ unlink(sun.sun_path); unlink(REQUESTOR_DAEMON_PATH); int previous_umask = umask(027); mkdir(REQUESTOR_DAEMON_PATH, 0777); memset(sun.sun_path, 0, sizeof(sun.sun_path)); memcpy(sun.sun_path, "\0" "SUPERUSER", strlen("SUPERUSER") + 1); if (bind(fd, (struct sockaddr*)&sun, sizeof(sun)) < 0) { PLOGE("daemon bind"); goto err; } chmod(REQUESTOR_DAEMON_PATH, 0755); chmod(sun.sun_path, 0777); umask(previous_umask); if (listen(fd, 10) < 0) { PLOGE("daemon listen"); goto err; } int client; while ((client = accept(fd, NULL, NULL)) > 0) { if (fork_zero_fucks() == 0) { close(fd); return daemon_accept(client); } else { close(client); } } LOGE("daemon exiting"); err: close(fd); return -1; }