/* * ZFS Event Daemon (ZED). */ int main(int argc, char *argv[]) { struct zed_conf *zcp; uint64_t saved_eid; int64_t saved_etime[2]; zed_log_init(argv[0]); zed_log_stderr_open(LOG_NOTICE); zcp = zed_conf_create(); zed_conf_parse_opts(zcp, argc, argv); if (zcp->do_verbose) zed_log_stderr_open(LOG_INFO); if (geteuid() != 0) zed_log_die("Must be run as root"); (void) umask(0); _setup_sig_handlers(); zed_conf_parse_file(zcp); zed_file_close_from(STDERR_FILENO + 1); if (chdir("/") < 0) zed_log_die("Failed to change to root directory"); if (zed_conf_scan_dir(zcp) < 0) exit(EXIT_FAILURE); if (zcp->do_memlock) _lock_memory(); if (!zcp->do_foreground) { _become_daemon(); zed_log_syslog_open(LOG_DAEMON); zed_log_stderr_close(); } zed_log_msg(LOG_NOTICE, "ZFS Event Daemon %s-%s", ZFS_META_VERSION, ZFS_META_RELEASE); (void) zed_conf_write_pid(zcp); if (zed_conf_open_state(zcp) < 0) exit(EXIT_FAILURE); if (zed_conf_read_state(zcp, &saved_eid, saved_etime) < 0) exit(EXIT_FAILURE); zed_event_init(zcp); zed_event_seek(zcp, saved_eid, saved_etime); while (!_got_exit) { if (_got_hup) { _got_hup = 0; (void) zed_conf_scan_dir(zcp); } zed_event_service(zcp); } zed_log_msg(LOG_NOTICE, "Exiting"); zed_event_fini(zcp); zed_conf_destroy(zcp); zed_log_fini(); exit(EXIT_SUCCESS); }
/* * ZFS Event Daemon (ZED). */ int main(int argc, char *argv[]) { struct zed_conf *zcp; uint64_t saved_eid; int64_t saved_etime[2]; zed_log_init(argv[0]); zed_log_stderr_open(LOG_NOTICE); zcp = zed_conf_create(); zed_conf_parse_opts(zcp, argc, argv); if (zcp->do_verbose) zed_log_stderr_open(LOG_INFO); if (geteuid() != 0) zed_log_die("Must be run as root"); (void) umask(0); _setup_sig_handlers(); zed_conf_parse_file(zcp); zed_file_close_from(STDERR_FILENO + 1); if (chdir("/") < 0) zed_log_die("Failed to change to root directory"); if (zed_conf_scan_dir(zcp) < 0) exit(EXIT_FAILURE); if (zcp->do_memlock) _lock_memory(); if (!zcp->do_foreground) { _become_daemon(); zed_log_syslog_open(LOG_DAEMON); zed_log_stderr_close(); } zed_log_msg(LOG_NOTICE, "ZFS Event Daemon %s-%s", ZFS_META_VERSION, ZFS_META_RELEASE); (void) zed_conf_write_pid(zcp); if (zed_conf_open_state(zcp) < 0) exit(EXIT_FAILURE); if (zed_conf_read_state(zcp, &saved_eid, saved_etime) < 0) exit(EXIT_FAILURE); retry: if (zed_event_init(zcp)) { /* * If we failed to open /dev/zfs, but force was requested, we * sleep waiting for it to come alive. This lets zed sit around * waiting for the kernel module to load. */ if (zcp->do_force) { sleep(30); if (!_got_exit) goto retry; } zed_log_die("Failed to initialize libzfs"); } zed_event_seek(zcp, saved_eid, saved_etime); while (!_got_exit) { if (_got_hup) { _got_hup = 0; (void) zed_conf_scan_dir(zcp); } if (zed_event_service(zcp)) break; } zed_log_msg(LOG_NOTICE, "Exiting"); zed_event_fini(zcp); if (zcp->do_force && !_got_exit) { goto retry; } zed_conf_destroy(zcp); zed_log_fini(); exit(EXIT_SUCCESS); }
/* * Fork a child process to handle event [eid]. The program [prog] * in directory [dir] is executed with the envionment [env]. * * The file descriptor [zfd] is the zevent_fd used to track the * current cursor location within the zevent nvlist. */ static void _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog, char *env[], int zfd) { char path[PATH_MAX]; int n; pid_t pid; int fd; pid_t wpid; int status; assert(dir != NULL); assert(prog != NULL); assert(env != NULL); assert(zfd >= 0); n = snprintf(path, sizeof (path), "%s/%s", dir, prog); if ((n < 0) || (n >= sizeof (path))) { zed_log_msg(LOG_WARNING, "Failed to fork \"%s\" for eid=%llu: %s", prog, eid, strerror(ENAMETOOLONG)); return; } pid = fork(); if (pid < 0) { zed_log_msg(LOG_WARNING, "Failed to fork \"%s\" for eid=%llu: %s", prog, eid, strerror(errno)); return; } else if (pid == 0) { (void) umask(022); if ((fd = open("/dev/null", O_RDWR)) != -1) { (void) dup2(fd, STDIN_FILENO); (void) dup2(fd, STDOUT_FILENO); (void) dup2(fd, STDERR_FILENO); } (void) dup2(zfd, ZEVENT_FILENO); zed_file_close_from(ZEVENT_FILENO + 1); execle(path, prog, NULL, env); _exit(127); } else { zed_log_msg(LOG_INFO, "Invoking \"%s\" eid=%llu pid=%d", prog, eid, pid); /* FIXME: Timeout rogue child processes with sigalarm? */ restart: wpid = waitpid(pid, &status, 0); if (wpid == (pid_t) -1) { if (errno == EINTR) goto restart; zed_log_msg(LOG_WARNING, "Failed to wait for \"%s\" eid=%llu pid=%d", prog, eid, pid); } else if (WIFEXITED(status)) { zed_log_msg(LOG_INFO, "Finished \"%s\" eid=%llu pid=%d exit=%d", prog, eid, pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { zed_log_msg(LOG_INFO, "Finished \"%s\" eid=%llu pid=%d sig=%d/%s", prog, eid, pid, WTERMSIG(status), strsignal(WTERMSIG(status))); } else { zed_log_msg(LOG_INFO, "Finished \"%s\" eid=%llu pid=%d status=0x%X", prog, eid, (unsigned int) status); } } }