static int setup_signals(sd_event *event) { sigset_t signals; int result; CC_LOG_DEBUG("invoked setup_signals()\n"); assert(event); sigemptyset(&signals); sigaddset(&signals, SIGTERM); sigaddset(&signals, SIGINT); result = sigprocmask(SIG_BLOCK, &signals, NULL); if (result != 0) { CC_LOG_ERROR("unable to block signals: %s\n", strerror(result)); return -result; } result = sd_event_add_signal(event, NULL, SIGTERM, &signal_handler, event); if (result < 0) { CC_LOG_ERROR("unable to setup SIGTERM handler: %s\n", strerror(-result)); return result; } result = sd_event_add_signal(event, NULL, SIGINT, &signal_handler, event); if (result < 0) { CC_LOG_ERROR("unable to setup SIGINT handler: %s\n", strerror(-result)); return result; } return 0; }
static int manager_new(Manager **ret) { _cleanup_(manager_unrefp) Manager *m = NULL; int r; assert(ret); m = new0(Manager, 1); if (!m) return -ENOMEM; m->machines = hashmap_new(&string_hash_ops); m->machine_units = hashmap_new(&string_hash_ops); m->machine_leaders = hashmap_new(NULL); if (!m->machines || !m->machine_units || !m->machine_leaders) return -ENOMEM; r = sd_event_default(&m->event); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); if (r < 0) return r; (void) sd_event_set_watchdog(m->event, true); *ret = TAKE_PTR(m); return 0; }
static void test_rtqueue(void) { sd_event_source *u = NULL, *v = NULL, *s = NULL; sd_event *e = NULL; assert_se(sd_event_default(&e) >= 0); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0); assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0); assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0); assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0); assert_se(sd_event_source_set_priority(v, -10) >= 0); assert(sigqueue(getpid(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
static int run(int argc, char *argv[]) { _cleanup_(context_clear) Context context = {}; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_setup_service(); umask(0022); mac_selinux_init(); if (argc != 1) { log_error("This program takes no arguments."); return -EINVAL; } assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); (void) sd_event_set_watchdog(event, true); r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to install SIGINT handler: %m"); r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to install SIGTERM handler: %m"); r = connect_bus(&context, event, &bus); if (r < 0) return r; r = context_read_data(&context); if (r < 0) return log_error_errno(r, "Failed to read hostname and machine information: %m"); r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); return 0; }
static int setup_signals(Manager *m) { sigset_t mask; int r; assert(m); assert_se(sigemptyset(&mask) == 0); sigset_add_many(&mask, SIGINT, SIGTERM, -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m); if (r < 0) return r; r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m); if (r < 0) return r; return 0; }
static int defer_handler(sd_event_source *s, void *userdata) { sd_event_source *p = NULL; assert_se(s); log_info("got defer on %c", PTR_TO_INT(userdata)); assert_se(userdata == INT_TO_PTR('d')); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0); assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0); assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); raise(SIGUSR1); sd_event_source_unref(s); return 1; }
int pty_forward_new( sd_event *event, int master, PTYForwardFlags flags, PTYForward **ret) { _cleanup_(pty_forward_freep) PTYForward *f = NULL; struct winsize ws; int r; f = new0(PTYForward, 1); if (!f) return -ENOMEM; f->flags = flags; if (event) f->event = sd_event_ref(event); else { r = sd_event_default(&f->event); if (r < 0) return r; } if (!(flags & PTY_FORWARD_READ_ONLY)) { r = fd_nonblock(STDIN_FILENO, true); if (r < 0) return r; r = fd_nonblock(STDOUT_FILENO, true); if (r < 0) return r; } r = fd_nonblock(master, true); if (r < 0) return r; f->master = master; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) (void) ioctl(master, TIOCSWINSZ, &ws); if (!(flags & PTY_FORWARD_READ_ONLY)) { if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) { struct termios raw_stdin_attr; f->saved_stdin = true; raw_stdin_attr = f->saved_stdin_attr; cfmakeraw(&raw_stdin_attr); raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag; tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr); } if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) { struct termios raw_stdout_attr; f->saved_stdout = true; raw_stdout_attr = f->saved_stdout_attr; cfmakeraw(&raw_stdout_attr); raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag; raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag; tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr); } r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f); if (r < 0 && r != -EPERM) return r; } r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f); if (r == -EPERM) /* stdout without epoll support. Likely redirected to regular file. */ f->stdout_writable = true; else if (r < 0) return r; r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f); if (r < 0) return r; r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f); if (r < 0) return r; *ret = f; f = NULL; return 0; }
int main(int argc, char * argv[]) { int r; _cleanup_(sd_event_unrefp) sd_event *event; ClockState state = { .timerfd_fd = -1, .inotify_fd = -1, .run_systemd_wd = -1, .run_systemd_timesync_wd = -1, }; assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = sd_event_default(&event); if (r < 0) { log_error_errno(r, "Failed to allocate event loop: %m"); goto finish; } r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to create sigterm event source: %m"); goto finish; } r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to create sigint event source: %m"); goto finish; } r = sd_event_set_watchdog(event, true); if (r < 0) { log_error_errno(r, "Failed to create watchdog event source: %m"); goto finish; } r = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (r < 0) { log_error_errno(errno, "Failed to create inotify descriptor: %m"); goto finish; } state.inotify_fd = r; r = sd_event_add_io(event, &state.inotify_event_source, state.inotify_fd, EPOLLIN, inotify_handler, &state); if (r < 0) { log_error_errno(r, "Failed to create notify event source: %m"); goto finish; } r = inotify_add_watch(state.inotify_fd, "/run/systemd/", IN_CREATE); if (r < 0) { log_error_errno(errno, "Failed to watch /run/systemd/: %m"); goto finish; } state.run_systemd_wd = r; (void) update_notify_run_systemd_timesync(&state); r = clock_state_update(&state, event); if (r > 0) { r = sd_event_loop(event); if (r < 0) log_error_errno(r, "Failed in event loop: %m"); } if (state.has_watchfile) log_debug("Exit enabled by: /run/systemd/timesync/synchonized"); if (state.adjtime_state == TIME_ERROR) log_info("Exit without adjtimex synchronized."); finish: clock_state_release(&state); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }
int manager_new(Manager **out) { _cleanup_(manager_freep) Manager *m = NULL; int r; assert(out); m = new0(Manager, 1); if (!m) return -ENOMEM; r = sd_event_default(&m->event); if (r < 0) return r; r = sd_event_set_watchdog(m->event, true); if (r < 0) return r; r = sigprocmask_many(SIG_BLOCK, SIGTERM, SIGQUIT, SIGINT, SIGWINCH, SIGCHLD, -1); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGQUIT, NULL, NULL); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); if (r < 0) return r; r = sd_bus_open_system(&m->sysbus); if (r < 0) return r; r = sd_bus_attach_event(m->sysbus, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) return r; r = unifont_new(&m->uf); if (r < 0) return r; r = sysview_context_new(&m->sysview, SYSVIEW_CONTEXT_SCAN_LOGIND | SYSVIEW_CONTEXT_SCAN_EVDEV | SYSVIEW_CONTEXT_SCAN_DRM, m->event, m->sysbus, NULL); if (r < 0) return r; r = grdev_context_new(&m->grdev, m->event, m->sysbus); if (r < 0) return r; r = idev_context_new(&m->idev, m->event, m->sysbus); if (r < 0) return r; *out = m; m = NULL; return 0; }
int cli_init(sd_bus *bus, const struct cli_cmd *cmds) { static const int sigs[] = { SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD, 0 }; unsigned int i; sigset_t mask; int r; if (cli_event) return cli_EINVAL(); r = sd_event_default(&cli_event); if (r < 0) { cli_vERR(r); goto error; } cli_cmds = cmds; cli_bus = bus; r = sd_bus_attach_event(cli_bus, cli_event, 0); if (r < 0) { cli_vERR(r); goto error; } for (i = 0; sigs[i]; ++i) { sigemptyset(&mask); sigaddset(&mask, sigs[i]); sigprocmask(SIG_BLOCK, &mask, NULL); r = sd_event_add_signal(cli_event, &cli_sigs[i], sigs[i], cli_signal_fn, NULL); if (r < 0) { cli_vERR(r); goto error; } } r = sd_event_add_io(cli_event, &cli_stdin, fileno(stdin), EPOLLHUP | EPOLLERR | EPOLLIN, cli_stdin_fn, NULL); if (r < 0) { cli_vERR(r); goto error; } cli_rl = true; rl_erase_empty_line = 1; rl_callback_handler_install(NULL, cli_handler_fn); rl_set_prompt(CLI_PROMPT); printf("\r"); rl_on_new_line(); rl_redisplay(); return 0; error: cli_destroy(); return r; }
int main(int argc, char *argv[]) { sd_event *e = NULL; sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; static const char ch = 'x'; int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 }; assert_se(pipe(a) >= 0); assert_se(pipe(b) >= 0); assert_se(pipe(d) >= 0); assert_se(pipe(k) >= 0); assert_se(sd_event_default(&e) >= 0); assert_se(sd_event_set_watchdog(e, true) >= 0); /* Test whether we cleanly can destroy an io event source from its own handler */ got_unref = false; assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0); assert_se(write(k[1], &ch, 1) == 1); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_unref); got_a = false, got_b = false, got_c = false, got_d = 0; /* Add a oneshot handler, trigger it, re-enable it, and trigger * it again. */ assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0); assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0); assert_se(write(d[1], &ch, 1) >= 0); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_d == 1); assert_se(write(d[1], &ch, 1) >= 0); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_d == 2); assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0); assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0); assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0); assert_se(sd_event_source_set_priority(x, 99) >= 0); assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0); assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0); assert_se(sd_event_source_set_priority(z, 50) >= 0); assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0); /* Test for floating event sources */ assert_se(sigprocmask_many(SIG_BLOCK, SIGRTMIN+1, -1) == 0); assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0); assert_se(write(a[1], &ch, 1) >= 0); assert_se(write(b[1], &ch, 1) >= 0); assert_se(!got_a && !got_b && !got_c); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(!got_a && got_b && !got_c); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(!got_a && got_b && got_c); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_a && got_b && got_c); sd_event_source_unref(x); sd_event_source_unref(y); do_quit = true; assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0); assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); assert_se(sd_event_loop(e) >= 0); sd_event_source_unref(z); sd_event_source_unref(q); sd_event_source_unref(w); sd_event_unref(e); safe_close_pair(a); safe_close_pair(b); safe_close_pair(d); safe_close_pair(k); return 0; }
static int evcat_new(Evcat **out) { _cleanup_(evcat_freep) Evcat *e = NULL; int r; assert(out); e = new0(Evcat, 1); if (!e) return log_oom(); r = sd_pid_get_session(getpid(), &e->session); if (r < 0) return log_error_errno(r, "Cannot retrieve logind session: %m"); r = sd_session_get_seat(e->session, &e->seat); if (r < 0) return log_error_errno(r, "Cannot retrieve seat of logind session: %m"); e->managed = is_managed(e->session); r = sd_event_default(&e->event); if (r < 0) return r; r = sd_bus_open_system(&e->bus); if (r < 0) return r; r = sd_bus_attach_event(e->bus, e->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) return r; r = sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1); if (r < 0) return r; r = sd_event_add_signal(e->event, NULL, SIGTERM, NULL, NULL); if (r < 0) return r; r = sd_event_add_signal(e->event, NULL, SIGINT, NULL, NULL); if (r < 0) return r; r = sysview_context_new(&e->sysview, SYSVIEW_CONTEXT_SCAN_LOGIND | SYSVIEW_CONTEXT_SCAN_EVDEV, e->event, e->bus, NULL); if (r < 0) return r; r = idev_context_new(&e->idev, e->event, e->bus); if (r < 0) return r; *out = e; e = NULL; return 0; }
static int import_tar(int argc, char *argv[], void *userdata) { _cleanup_(tar_import_unrefp) TarImport *import = NULL; _cleanup_event_unref_ sd_event *event = NULL; const char *path = NULL, *local = NULL; _cleanup_free_ char *ll = NULL; _cleanup_close_ int open_fd = -1; int r, fd; if (argc >= 2) path = argv[1]; if (isempty(path) || streq(path, "-")) path = NULL; if (argc >= 3) local = argv[2]; else if (path) local = basename(path); if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = tar_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } } else local = "imported"; if (path) { open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (open_fd < 0) return log_error_errno(errno, "Failed to open tar image to import: %m"); fd = open_fd; log_info("Importing '%s', saving as '%s'.", path, local); } else { _cleanup_free_ char *pretty = NULL; fd = STDIN_FILENO; (void) readlink_malloc("/proc/self/fd/0", &pretty); log_info("Importing '%s', saving as '%s'.", strna(pretty), local); } r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = tar_import_new(&import, event, arg_image_root, on_tar_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate importer: %m"); r = tar_import_start(import, fd, local, arg_force, arg_read_only); if (r < 0) return log_error_errno(r, "Failed to import image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; }
static int manager_new(struct manager **out) { struct manager *m; static const int sigs[] = { SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD, 0 }; unsigned int i; sigset_t mask; int r; m = calloc(1, sizeof(*m)); if (!m) return log_ENOMEM(); shl_htable_init_uint(&m->links); r = sd_event_default(&m->event); if (r < 0) { log_vERR(r); goto error; } r = sd_event_set_watchdog(m->event, true); if (r < 0) { log_vERR(r); goto error; } r = sd_bus_default_system(&m->bus); if (r < 0) { log_error("cannot connect to system bus: %d", r); goto error; } r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) { log_vERR(r); goto error; } for (i = 0; sigs[i]; ++i) { sigemptyset(&mask); sigaddset(&mask, sigs[i]); sigprocmask(SIG_BLOCK, &mask, NULL); r = sd_event_add_signal(m->event, &m->sigs[i], sigs[i], manager_signal_fn, m); if (r < 0) { log_vERR(r); goto error; } /* low-priority to allow others to handle it first */ sd_event_source_set_priority(m->sigs[i], 100); } m->udev = udev_new(); if (!m->udev) { r = log_ENOMEM(); goto error; } m->udev_mon = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_mon) { r = log_ENOMEM(); goto error; } r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_mon, "net", "wlan"); if (r < 0) { log_vERR(r); goto error; } r = udev_monitor_enable_receiving(m->udev_mon); if (r < 0) { log_vERR(r); goto error; } r = sd_event_add_io(m->event, &m->udev_mon_source, udev_monitor_get_fd(m->udev_mon), EPOLLHUP | EPOLLERR | EPOLLIN, manager_udev_fn, m); if (r < 0) { log_vERR(r); goto error; } r = manager_dbus_connect(m); if (r < 0) goto error; if (out) *out = m; return 0; error: manager_free(m); return r; }
static int pull_dck(int argc, char *argv[], void *userdata) { _cleanup_(dck_import_unrefp) DckImport *import = NULL; _cleanup_event_unref_ sd_event *event = NULL; const char *name, *tag, *local; int r; tag = strchr(argv[1], ':'); if (tag) { name = strndupa(argv[1], tag - argv[1]); tag++; } else { name = argv[1]; tag = "latest"; } if (argc >= 3) local = argv[2]; else { local = strchr(name, '/'); if (local) local++; else local = name; } if (streq(local, "-") || isempty(local)) local = NULL; if (!dck_name_is_valid(name)) { log_error("Remote name '%s' is not valid.", name); return -EINVAL; } if (!dck_tag_is_valid(tag)) { log_error("Tag name '%s' is not valid.", tag); return -EINVAL; } if (local) { const char *p; if (!machine_name_is_valid(tag)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } p = strappenda("/var/lib/container/", local); if (laccess(p, F_OK) >= 0) { if (!arg_force) { log_info("Image '%s' already exists.", local); return 0; } } else if (errno != ENOENT) return log_error_errno(errno, "Can't check if image '%s' already exists: %m", local); log_info("Pulling '%s' with tag '%s', saving as '%s'.", name, tag, local); } else log_info("Pulling '%s' with tag '%s'.", name, tag); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0); sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); r = dck_import_new(&import, event, on_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate importer: %m"); r = dck_import_pull(import, name, tag, local, arg_force); if (r < 0) return log_error_errno(r, "Failed to pull image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return 0; }
static int start_transient_service( sd_bus *bus, char **argv, int *retval) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; _cleanup_free_ char *service = NULL, *pty_path = NULL; _cleanup_close_ int master = -1; int r; assert(bus); assert(argv); assert(retval); if (arg_pty) { if (arg_transport == BUS_TRANSPORT_LOCAL) { master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY); if (master < 0) return log_error_errno(errno, "Failed to acquire pseudo tty: %m"); r = ptsname_malloc(master, &pty_path); if (r < 0) return log_error_errno(r, "Failed to determine tty name: %m"); if (unlockpt(master) < 0) return log_error_errno(errno, "Failed to unlock tty: %m"); } else if (arg_transport == BUS_TRANSPORT_MACHINE) { _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL; const char *s; r = sd_bus_default_system(&system_bus); if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); r = sd_bus_call_method(system_bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "OpenMachinePTY", &error, &pty_reply, "s", arg_host); if (r < 0) { log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(pty_reply, "hs", &master, &s); if (r < 0) return bus_log_parse_error(r); master = fcntl(master, F_DUPFD_CLOEXEC, 3); if (master < 0) return log_error_errno(errno, "Failed to duplicate master fd: %m"); pty_path = strdup(s); if (!pty_path) return log_oom(); } else assert_not_reached("Can't allocate tty via ssh"); } if (!arg_no_block) { r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_error_errno(r, "Could not watch jobs: %m"); } if (arg_unit) { r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); } else { r = make_unit_name(bus, UNIT_SERVICE, &service); if (r < 0) return r; } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); if (r < 0) return bus_log_create_error(r); /* Name and mode */ r = sd_bus_message_append(m, "ss", service, "fail"); if (r < 0) return bus_log_create_error(r); /* Properties */ r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_service_set_properties(m, argv, pty_path); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); /* Auxiliary units */ r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return bus_log_create_error(r); polkit_agent_open_if_enabled(); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r)); if (w) { const char *object; r = sd_bus_message_read(reply, "o", &object); if (r < 0) return bus_log_parse_error(r); r = bus_wait_for_jobs_one(w, object, arg_quiet); if (r < 0) return r; } if (!arg_quiet) log_info("Running as unit: %s", service); if (arg_wait || master >= 0) { _cleanup_(run_context_free) RunContext c = {}; c.bus = sd_bus_ref(bus); r = sd_event_default(&c.event); if (r < 0) return log_error_errno(r, "Failed to get event loop: %m"); if (master >= 0) { assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL); (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL); if (!arg_quiet) log_info("Press ^] three times within 1s to disconnect TTY."); r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward); if (r < 0) return log_error_errno(r, "Failed to create PTY forwarder: %m"); pty_forward_set_handler(c.forward, pty_forward_handler, &c); } if (arg_wait) { _cleanup_free_ char *path = NULL; const char *mt; path = unit_dbus_path_from_name(service); if (!path) return log_oom(); mt = strjoina("type='signal'," "sender='org.freedesktop.systemd1'," "path='", path, "'," "interface='org.freedesktop.DBus.Properties'," "member='PropertiesChanged'"); r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c); if (r < 0) return log_error_errno(r, "Failed to add properties changed signal."); r = sd_bus_attach_event(bus, c.event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop."); } r = sd_event_loop(c.event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); if (c.forward) { char last_char = 0; r = pty_forward_get_last_char(c.forward, &last_char); if (r >= 0 && !arg_quiet && last_char != '\n') fputc('\n', stdout); } if (!arg_quiet) { if (!isempty(c.result)) log_info("Finished with result: %s", strna(c.result)); if (c.exit_code == CLD_EXITED) log_info("Main processes terminated with: code=%s/status=%i", sigchld_code_to_string(c.exit_code), c.exit_status); else if (c.exit_code > 0) log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status)); if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY && c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY && c.inactive_enter_usec > c.inactive_exit_usec) { char ts[FORMAT_TIMESPAN_MAX]; log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC)); } if (c.cpu_usage_nsec > 0 && c.cpu_usage_nsec != NSEC_INFINITY) { char ts[FORMAT_TIMESPAN_MAX]; log_info("CPU time consumed: %s", format_timespan(ts, sizeof(ts), (c.cpu_usage_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC, USEC_PER_MSEC)); } } /* Try to propagate the service's return value */ if (c.result && STR_IN_SET(c.result, "success", "exit-code") && c.exit_code == CLD_EXITED) *retval = c.exit_status; else *retval = EXIT_FAILURE; } return 0; }
static int modeset_new(Modeset **out) { _cleanup_(modeset_freep) Modeset *m = NULL; int r; assert(out); m = new0(Modeset, 1); if (!m) return log_oom(); r = sd_pid_get_session(getpid(), &m->session); if (r < 0) return log_error_errno(r, "Cannot retrieve logind session: %m"); r = sd_session_get_seat(m->session, &m->seat); if (r < 0) return log_error_errno(r, "Cannot retrieve seat of logind session: %m"); m->my_tty = is_my_tty(m->session); m->managed = m->my_tty && geteuid() > 0; m->r = rand() % 0xff; m->g = rand() % 0xff; m->b = rand() % 0xff; m->r_up = m->g_up = m->b_up = true; r = sd_event_default(&m->event); if (r < 0) return r; r = sd_bus_open_system(&m->bus); if (r < 0) return r; r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) return r; r = sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); if (r < 0) return r; r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); if (r < 0) return r; r = sd_event_add_exit(m->event, &m->exit_src, modeset_exit_fn, m); if (r < 0) return r; /* schedule before sd-bus close */ r = sd_event_source_set_priority(m->exit_src, -10); if (r < 0) return r; r = sysview_context_new(&m->sysview, SYSVIEW_CONTEXT_SCAN_LOGIND | SYSVIEW_CONTEXT_SCAN_DRM, m->event, m->bus, NULL); if (r < 0) return r; r = grdev_context_new(&m->grdev, m->event, m->bus); if (r < 0) return r; *out = m; m = NULL; return 0; }
static int pull_tar(int argc, char *argv[], void *userdata) { _cleanup_(tar_pull_unrefp) TarPull *pull = NULL; _cleanup_event_unref_ sd_event *event = NULL; const char *url, *local; _cleanup_free_ char *l = NULL, *ll = NULL; int r; url = argv[1]; if (!http_url_is_valid(url)) { log_error("URL '%s' is not valid.", url); return -EINVAL; } if (argc >= 3) local = argv[2]; else { r = import_url_last_component(url, &l); if (r < 0) return log_error_errno(r, "Failed get final component of URL: %m"); local = l; } if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = tar_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } log_info("Pulling '%s', saving as '%s'.", url, local); } else log_info("Pulling '%s'.", url); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = tar_pull_new(&pull, event, arg_image_root, on_tar_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate puller: %m"); r = tar_pull_start(pull, url, local, arg_force, arg_verify, arg_settings); if (r < 0) return log_error_errno(r, "Failed to pull image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; }
static int pull_dkr(int argc, char *argv[], void *userdata) { _cleanup_(dkr_pull_unrefp) DkrPull *pull = NULL; _cleanup_event_unref_ sd_event *event = NULL; const char *name, *reference, *local, *digest; int r; if (!arg_dkr_index_url) { log_error("Please specify an index URL with --dkr-index-url="); return -EINVAL; } if (arg_verify != IMPORT_VERIFY_NO) { log_error("Pulls from dkr do not support image verification, please pass --verify=no."); return -EINVAL; } digest = strchr(argv[1], '@'); if (digest) { reference = digest + 1; name = strndupa(argv[1], digest - argv[1]); } else { reference = strchr(argv[1], ':'); if (reference) { name = strndupa(argv[1], reference - argv[1]); reference++; } else { name = argv[1]; reference = "latest"; } } if (!dkr_name_is_valid(name)) { log_error("Remote name '%s' is not valid.", name); return -EINVAL; } if (!dkr_ref_is_valid(reference)) { log_error("Tag name '%s' is not valid.", reference); return -EINVAL; } if (argc >= 3) local = argv[2]; else { local = strchr(name, '/'); if (local) local++; else local = name; } if (isempty(local) || streq(local, "-")) local = NULL; if (local) { if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } log_info("Pulling '%s' with reference '%s', saving as '%s'.", name, reference, local); } else log_info("Pulling '%s' with reference '%s'.", name, reference); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = dkr_pull_new(&pull, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate puller: %m"); r = dkr_pull_start(pull, name, reference, local, arg_force, DKR_PULL_V2); if (r < 0) return log_error_errno(r, "Failed to pull image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; }
int main(int argc, char *argv[]) { if (argc < 5) { ERROR("usage: %s baseroot envroot program cmdl..", program_invocation_short_name); } const char *root = poe_init_playground(argv[1], argv[2]); const char *prog = copy_program(root, argv[3]); char **cmdl = construct_cmdl(argc - 4, argv + 4, prog); int stdout_fd[2], stderr_fd[2]; NONNEGATIVE(pipe2(stdout_fd, O_DIRECT)); NONNEGATIVE(pipe2(stderr_fd, O_DIRECT)); // TODO: CLONE_NEWUSER pid_t pid = (pid_t)syscall(SYS_clone, SIGCHLD | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET, 0); NONNEGATIVE(pid); if (pid == 0) { dup2(stdout_fd[1], STDOUT_FILENO); close(stdout_fd[0]); close(stdout_fd[1]); dup2(stderr_fd[1], STDERR_FILENO); close(stderr_fd[0]); close(stderr_fd[1]); child(root, cmdl); } else { sd_event *event = NULL; uint64_t now; int stdout_fileno = STDOUT_FILENO; int stderr_fileno = STDERR_FILENO; int fflags; fflags = fcntl(stdout_fd[0], F_GETFL, 0); NONNEGATIVE(fflags); NONNEGATIVE(fcntl(stdout_fd[0], F_SETFL, fflags | O_NONBLOCK)); fflags = fcntl(stderr_fd[0], F_GETFL, 0); NONNEGATIVE(fflags); NONNEGATIVE(fcntl(stderr_fd[0], F_SETFL, fflags | O_NONBLOCK)); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); sigprocmask(SIG_BLOCK, &mask, NULL); NONNEGATIVE(sd_event_default(&event)); NONNEGATIVE(sd_event_add_signal(event, NULL, SIGCHLD, sigchld_handler, &pid)); NONNEGATIVE(sd_event_add_signal(event, NULL, SIGINT, sigint_handler, &pid)); NONNEGATIVE(sd_event_add_signal(event, NULL, SIGTERM, sigint_handler, &pid)); NONNEGATIVE(sd_event_now(event, CLOCK_MONOTONIC, &now)); NONNEGATIVE(sd_event_add_time(event, NULL, CLOCK_MONOTONIC, now + POE_TIME_LIMIT, 0, timer_handler, &pid)); NONNEGATIVE(sd_event_add_io(event, NULL, stdout_fd[0], EPOLLIN, stdout_handler, &stdout_fileno)); NONNEGATIVE(sd_event_add_io(event, NULL, stderr_fd[0], EPOLLIN, stdout_handler, &stderr_fileno)); NONNEGATIVE(ptrace(PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACESECCOMP | PTRACE_O_TRACEVFORK)); poe_init_systemd(pid); NONNEGATIVE(sd_event_loop(event)); } ERROR("unreachable"); }