enum nss_status _nss_resolve_gethostbyname3_r( const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; size_t l, idx, ms, alen; const char *canonical; int c, r, i = 0; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(result); assert(buffer); assert(errnop); assert(h_errnop); if (af == AF_UNSPEC) af = AF_INET; if (af != AF_INET && af != AF_INET6) { r = -EAFNOSUPPORT; goto fail; } r = sd_bus_open_system(&bus); if (r < 0) goto fallback; r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname"); if (r < 0) goto fail; r = sd_bus_message_set_auto_start(req, false); if (r < 0) goto fail; r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0); if (r < 0) goto fail; r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (bus_error_shall_fallback(&error)) goto fallback; goto fail; } c = count_addresses(reply, af, &canonical); if (c < 0) { r = c; goto fail; } if (c == 0) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (isempty(canonical)) canonical = name; alen = FAMILY_ADDRESS_SIZE(af); l = strlen(canonical); ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*); if (buflen < ms) { *errnop = ENOMEM; *h_errnop = TRY_AGAIN; return NSS_STATUS_TRYAGAIN; } /* First, append name */ r_name = buffer; memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); /* Second, create empty aliases array */ r_aliases = buffer + idx; ((char**) r_aliases)[0] = NULL; idx += sizeof(char*); /* Third, append addresses */ r_addr = buffer + idx; r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) goto fail; while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { int ifindex, family; const void *a; size_t sz; r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) goto fail; if (ifindex < 0) { r = -EINVAL; goto fail; } r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) goto fail; r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; if (family != af) continue; if (sz != alen) { r = -EINVAL; goto fail; } memcpy(r_addr + i*ALIGN(alen), a, alen); i++; } if (r < 0) goto fail; assert(i == c); idx += c * ALIGN(alen); /* Fourth, append address pointer array */ r_addr_list = buffer + idx; for (i = 0; i < c; i++) ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); ((char**) r_addr_list)[i] = NULL; idx += (c+1) * sizeof(char*); assert(idx == ms); result->h_name = r_name; result->h_aliases = (char**) r_aliases; result->h_addrtype = af; result->h_length = alen; result->h_addr_list = (char**) r_addr_list; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; if (ttlp) *ttlp = 0; if (canonp) *canonp = r_name; return NSS_STATUS_SUCCESS; fallback: { _nss_gethostbyname3_r_t fallback; fallback = (_nss_gethostbyname3_r_t) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r"); if (fallback) return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); } fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; }
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, SIGTERM, SIGINT, -1) == 0); sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); 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; }
if (t == *q) { *q = NULL; } else { (*q)->link = t->link; } assert(t->inqueue == q); t->link = NULL; t->inqueue = NULL; return t; } static void delete(T t, T* q) { T p; assert(t->link && t->inqueue == q); assert(!isempty(*q)); for (p = *q; p->link != t; p = p->link) ; if (p == t) { *q = NULL; } else { p->link = t->link; if (*q == t) { *q = p; } } t->link = NULL;
enum nss_status _nss_resolve_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *canonical = NULL; size_t l, ms, idx; char *r_name; int c, r, i = 0; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(pat); assert(buffer); assert(errnop); assert(h_errnop); r = sd_bus_open_system(&bus); if (r < 0) goto fallback; r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname"); if (r < 0) goto fail; r = sd_bus_message_set_auto_start(req, false); if (r < 0) goto fail; r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0); if (r < 0) goto fail; r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (bus_error_shall_fallback(&error)) goto fallback; goto fail; } c = count_addresses(reply, AF_UNSPEC, &canonical); if (c < 0) { r = c; goto fail; } if (c == 0) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (isempty(canonical)) canonical = name; l = strlen(canonical); ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c; if (buflen < ms) { *errnop = ENOMEM; *h_errnop = TRY_AGAIN; return NSS_STATUS_TRYAGAIN; } /* First, append name */ r_name = buffer; memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); /* Second, append addresses */ r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) goto fail; while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { int family, ifindex; const void *a; size_t sz; assert_cc(sizeof(int32_t) == sizeof(int)); r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) goto fail; if (ifindex < 0) { r = -EINVAL; goto fail; } r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) goto fail; r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; if (!IN_SET(family, AF_INET, AF_INET6)) continue; if (sz != FAMILY_ADDRESS_SIZE(family)) { r = -EINVAL; goto fail; } r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); r_tuple->name = r_name; r_tuple->family = family; r_tuple->scopeid = ifindex; memcpy(r_tuple->addr, a, sz); idx += ALIGN(sizeof(struct gaih_addrtuple)); i++; } if (r < 0) goto fail; assert(i == c); assert(idx == ms); if (*pat) **pat = *r_tuple_first; else *pat = r_tuple_first; if (ttlp) *ttlp = 0; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; fallback: { _nss_gethostbyname4_r_t fallback; fallback = (_nss_gethostbyname4_r_t) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r"); if (fallback) return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp); } fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; }
static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *name; int interactive; int r; assert(m); assert(c); r = sd_bus_message_read(m, "sb", &name, &interactive); if (r < 0) return r; name = empty_to_null(name); if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME])) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-static-hostname", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ if (isempty(name)) c->data[PROP_STATIC_HOSTNAME] = mfree(c->data[PROP_STATIC_HOSTNAME]); else { char *h; if (!hostname_is_valid(name, false)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name); h = strdup(name); if (!h) return -ENOMEM; free(c->data[PROP_STATIC_HOSTNAME]); c->data[PROP_STATIC_HOSTNAME] = h; } r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); } r = context_write_data_static_hostname(c); if (r < 0) { log_error_errno(r, "Failed to write static host name: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m"); } log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME])); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL); return sd_bus_reply_method_return(m, NULL); }
static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) { int interactive; const char *name; int r; assert(c); assert(m); r = sd_bus_message_read(m, "sb", &name, &interactive); if (r < 0) return r; name = empty_to_null(name); if (streq_ptr(name, c->data[prop])) return sd_bus_reply_method_return(m, NULL); /* Since the pretty hostname should always be changed at the * same time as the static one, use the same policy action for * both... */ r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ if (isempty(name)) c->data[prop] = mfree(c->data[prop]); else { char *h; /* The icon name might ultimately be used as file * name, so better be safe than sorry */ if (prop == PROP_ICON_NAME && !filename_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name); if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name); if (prop == PROP_CHASSIS && !valid_chassis(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name); if (prop == PROP_DEPLOYMENT && !valid_deployment(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name); if (prop == PROP_LOCATION && string_has_cc(name, NULL)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name); h = strdup(name); if (!h) return -ENOMEM; free(c->data[prop]); c->data[prop] = h; } r = context_write_data_machine_info(c); if (r < 0) { log_error_errno(r, "Failed to write machine info: %m"); return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %m"); } log_info("Changed %s to '%s'", prop == PROP_PRETTY_HOSTNAME ? "pretty host name" : prop == PROP_DEPLOYMENT ? "deployment" : prop == PROP_LOCATION ? "location" : prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop])); (void) sd_bus_emit_properties_changed( sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" : prop == PROP_DEPLOYMENT ? "Deployment" : prop == PROP_LOCATION ? "Location" : prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL); return sd_bus_reply_method_return(m, NULL); }
static void display(Hashmap *a) { Iterator i; Group *g; Group **array; signed path_columns; unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */ char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; assert(a); /* Set cursor to top left corner and clear screen */ if (on_tty()) fputs("\033[H" "\033[2J", stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); HASHMAP_FOREACH(g, a, i) if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) array[n++] = g; qsort_safe(array, n, sizeof(Group*), group_compare); /* Find the longest names in one run */ for (j = 0; j < n; j++) { unsigned cputlen, pathtlen; format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); cputlen = strlen(buffer); maxtcpu = MAX(maxtcpu, cputlen); pathtlen = strlen(array[j]->path); maxtpath = MAX(maxtpath, pathtlen); } if (arg_cpu_type == CPU_PERCENT) snprintf(buffer, sizeof(buffer), "%6s", "%CPU"); else snprintf(buffer, sizeof(buffer), "%*s", maxtcpu, "CPU Time"); rows = lines(); if (rows <= 10) rows = 10; if (on_tty()) { path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; printf("%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s\n\n", arg_order == ORDER_PATH ? ON : "", path_columns, "Control Group", arg_order == ORDER_PATH ? OFF : "", arg_order == ORDER_TASKS ? ON : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", arg_order == ORDER_TASKS ? OFF : "", arg_order == ORDER_CPU ? ON : "", buffer, arg_order == ORDER_CPU ? OFF : "", arg_order == ORDER_MEMORY ? ON : "", "Memory", arg_order == ORDER_MEMORY ? OFF : "", arg_order == ORDER_IO ? ON : "", "Input/s", arg_order == ORDER_IO ? OFF : "", arg_order == ORDER_IO ? ON : "", "Output/s", arg_order == ORDER_IO ? OFF : ""); } else path_columns = maxtpath; for (j = 0; j < n; j++) { _cleanup_free_ char *ellipsized = NULL; const char *path; if (on_tty() && j + 5 > rows) break; g = array[j]; path = isempty(g->path) ? "/" : g->path; ellipsized = ellipsize(path, path_columns, 33); printf("%-*s", path_columns, ellipsized ?: path); if (g->n_tasks_valid) printf(" %7" PRIu64, g->n_tasks); else fputs(" -", stdout); if (arg_cpu_type == CPU_PERCENT) { if (g->cpu_valid) printf(" %6.1f", g->cpu_fraction*100); else fputs(" -", stdout); } else printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_output_bps)); putchar('\n'); } }
static int vconsole_convert_to_x11(Context *c, sd_bus *bus) { bool modified = false; assert(bus); if (isempty(c->vc_keymap)) { modified = !isempty(c->x11_layout) || !isempty(c->x11_model) || !isempty(c->x11_variant) || !isempty(c->x11_options); context_free_x11(c); } else { _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); if (!f) return -errno; for (;;) { _cleanup_strv_free_ char **a = NULL; int r; r = read_next_mapping(f, &n, &a); if (r < 0) return r; if (r == 0) break; if (!streq(c->vc_keymap, a[0])) continue; if (!streq_ptr(c->x11_layout, strnulldash(a[1])) || !streq_ptr(c->x11_model, strnulldash(a[2])) || !streq_ptr(c->x11_variant, strnulldash(a[3])) || !streq_ptr(c->x11_options, strnulldash(a[4]))) { if (free_and_strdup(&c->x11_layout, strnulldash(a[1])) < 0 || free_and_strdup(&c->x11_model, strnulldash(a[2])) < 0 || free_and_strdup(&c->x11_variant, strnulldash(a[3])) < 0 || free_and_strdup(&c->x11_options, strnulldash(a[4])) < 0) return -ENOMEM; modified = true; } break; } } if (modified) { int r; r = x11_write_data(c); if (r < 0) { log_error("Failed to set X11 keyboard layout: %s", strerror(-r)); return r; } log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", strempty(c->x11_layout), strempty(c->x11_model), strempty(c->x11_variant), strempty(c->x11_options)); sd_bus_emit_properties_changed(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", "X11Layout", "X11Model", "X11Variant", "X11Options", NULL); } else log_debug("X11 keyboard layout was not modified."); return 0; }
int register_machine( sd_bus *bus, const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, sd_bus_message *properties_message, bool keep_unit, const char *service) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); if (keep_unit) { r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "RegisterMachineWithNetwork", &error, NULL, "sayssusai", machine_name, SD_BUS_MESSAGE_APPEND_ID128(uuid), service, "container", (uint32_t) pid, strempty(directory), local_ifindex > 0 ? 1 : 0, local_ifindex); } else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CreateMachineWithNetwork"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "sayssusai", machine_name, SD_BUS_MESSAGE_APPEND_ID128(uuid), service, "container", (uint32_t) pid, strempty(directory), local_ifindex > 0 ? 1 : 0, local_ifindex); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); if (!isempty(slice)) { r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); if (r < 0) return bus_log_create_error(r); } r = append_controller_property(bus, m); if (r < 0) return r; r = append_machine_properties( m, mounts, n_mounts, kill_signal); if (r < 0) return r; if (properties_message) { r = sd_bus_message_copy(m, properties_message, true); if (r < 0) return bus_log_create_error(r); } r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); } if (r < 0) return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r)); return 0; }
int allocate_scope( sd_bus *bus, const char *machine_name, pid_t pid, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, sd_bus_message *properties_message) { _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 *scope = NULL; const char *description, *object; int r; assert(bus); r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_error_errno(r, "Could not watch job: %m"); r = unit_name_mangle_with_suffix(machine_name, 0, ".scope", &scope); if (r < 0) return log_error_errno(r, "Failed to mangle scope name: %m"); 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_append(m, "ss", scope, "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); description = strjoina("Container ", machine_name); r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)(sv)", "PIDs", "au", 1, pid, "Description", "s", description, "Delegate", "b", 1, "CollectMode", "s", "inactive-or-failed", "AddRef", "b", 1, "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice); if (r < 0) return bus_log_create_error(r); r = append_controller_property(bus, m); if (r < 0) return r; if (properties_message) { r = sd_bus_message_copy(m, properties_message, true); if (r < 0) return bus_log_create_error(r); } r = append_machine_properties( m, mounts, n_mounts, kill_signal); if (r < 0) return r; r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); /* No auxiliary units */ r = sd_bus_message_append( m, "a(sa(sv))", 0); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r)); 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, false); if (r < 0) return r; return 0; }
void session_loop(void(*loophandler)()) { fd_set readfd, writefd; struct timeval timeout; int val; /* main loop, select()s for all sockets in use */ for(;;) { const int writequeue_has_space = (ses.writequeue_len <= 2*TRANS_MAX_PAYLOAD_LEN); timeout.tv_sec = select_timeout(); timeout.tv_usec = 0; FD_ZERO(&writefd); FD_ZERO(&readfd); dropbear_assert(ses.payload == NULL); /* We get woken up when signal handlers write to this pipe. SIGCHLD in svr-chansession is the only one currently. */ FD_SET(ses.signal_pipe[0], &readfd); ses.channel_signal_pending = 0; /* set up for channels which can be read/written */ setchannelfds(&readfd, &writefd, writequeue_has_space); /* Pending connections to test */ set_connect_fds(&writefd); /* We delay reading from the input socket during initial setup until after we have written out our initial KEXINIT packet (empty writequeue). This means our initial packet can be in-flight while we're doing a blocking read for the remote ident. We also avoid reading from the socket if the writequeue is full, that avoids replies backing up */ if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue)) && writequeue_has_space) { FD_SET(ses.sock_in, &readfd); } /* Ordering is important, this test must occur after any other function might have queued packets (such as connection handlers) */ if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { FD_SET(ses.sock_out, &writefd); } val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout); if (exitflag) { dropbear_exit("Terminated by signal"); } if (val < 0 && errno != EINTR) { dropbear_exit("Error in select"); } if (val <= 0) { /* If we were interrupted or the select timed out, we still * want to iterate over channels etc for reading, to handle * server processes exiting etc. * We don't want to read/write FDs. */ FD_ZERO(&writefd); FD_ZERO(&readfd); } /* We'll just empty out the pipe if required. We don't do any thing with the data, since the pipe's purpose is purely to wake up the select() above. */ if (FD_ISSET(ses.signal_pipe[0], &readfd)) { char x; TRACE(("signal pipe set")) while (read(ses.signal_pipe[0], &x, 1) > 0) {} ses.channel_signal_pending = 1; } /* check for auth timeout, rekeying required etc */ checktimeouts(); /* process session socket's incoming data */ if (ses.sock_in != -1) { if (FD_ISSET(ses.sock_in, &readfd)) { if (!ses.remoteident) { /* blocking read of the version string */ read_session_identification(); } else { read_packet(); } } /* Process the decrypted packet. After this, the read buffer * will be ready for a new packet */ if (ses.payload != NULL) { process_packet(); } } /* if required, flush out any queued reply packets that were being held up during a KEX */ maybe_flush_reply_queue(); handle_connect_fds(&writefd); /* process pipes etc for the channels, ses.dataallowed == 0 * during rekeying ) */ channelio(&readfd, &writefd); /* process session socket's outgoing data */ if (ses.sock_out != -1) { if (!isempty(&ses.writequeue)) { write_packet(); } } if (loophandler) { loophandler(); } } /* for(;;) */
static int add_swap( const char *what, struct mntent *me, bool noauto, bool nofail) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(what); assert(me); if (access("/proc/swaps", F_OK) < 0) { log_info("Swap not supported, ignoring fstab swap entry for %s.", what); return 0; } if (detect_container() > 0) { log_info("Running in a container, ignoring fstab swap entry for %s.", what); return 0; } r = unit_name_from_path(what, ".swap", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { if (errno == EEXIST) log_error("Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit); else log_error_errno(errno, "Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=/etc/fstab\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" "[Swap]\n" "What=%s\n", what); if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults")) fprintf(f, "Options=%s\n", me->mnt_opts); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); /* use what as where, to have a nicer error message */ r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL); if (r < 0) return r; if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET, nofail ? ".wants/" : ".requires/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } return 0; }
static const char* nonempty(const char *s) { return isempty(s) ? NULL : s; }
int calendar_spec_from_string(const char *p, CalendarSpec **spec) { const char *utc; CalendarSpec *c; int r; assert(p); assert(spec); c = new0(CalendarSpec, 1); if (!c) return -ENOMEM; c->dst = -1; utc = endswith_no_case(p, " UTC"); if (utc) { c->utc = true; p = strndupa(p, utc - p); } else { const char *e = NULL; int j; tzset(); /* Check if the local timezone was specified? */ for (j = 0; j <= 1; j++) { if (isempty(tzname[j])) continue; e = endswith_no_case(p, tzname[j]); if(!e) continue; if (e == p) continue; if (e[-1] != ' ') continue; break; } /* Found one of the two timezones specified? */ if (IN_SET(j, 0, 1)) { p = strndupa(p, e - p - 1); c->dst = j; } } if (isempty(p)) { r = -EINVAL; goto fail; } if (strcaseeq(p, "minutely")) { r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "hourly")) { r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "daily")) { r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "monthly")) { r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "annually") || strcaseeq(p, "yearly") || strcaseeq(p, "anually") /* backwards compatibility */ ) { r = const_chain(1, &c->month); if (r < 0) goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "weekly")) { c->weekdays_bits = 1; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "quarterly")) { r = const_chain(1, &c->month); if (r < 0) goto fail; r = const_chain(4, &c->month); if (r < 0) goto fail; r = const_chain(7, &c->month); if (r < 0) goto fail; r = const_chain(10, &c->month); if (r < 0) goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "biannually") || strcaseeq(p, "bi-annually") || strcaseeq(p, "semiannually") || strcaseeq(p, "semi-annually")) { r = const_chain(1, &c->month); if (r < 0) goto fail; r = const_chain(7, &c->month); if (r < 0) goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else { r = parse_weekdays(&p, c); if (r < 0) goto fail; r = parse_date(&p, c); if (r < 0) goto fail; r = parse_calendar_time(&p, c); if (r < 0) goto fail; if (*p != 0) { r = -EINVAL; goto fail; } } r = calendar_spec_normalize(c); if (r < 0) goto fail; if (!calendar_spec_valid(c)) { r = -EINVAL; goto fail; } *spec = c; return 0; fail: calendar_spec_free(c); return r; }
static bool hostname_is_useful(const char *hn) { return !isempty(hn) && !is_localhost(hn); }
static char *format_timestamp_internal( char *buf, size_t l, usec_t t, bool utc, bool us) { /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our * generated timestamps may be parsed with parse_timestamp(), and always read the same. */ static const char * const weekdays[] = { [0] = "Sun", [1] = "Mon", [2] = "Tue", [3] = "Wed", [4] = "Thu", [5] = "Fri", [6] = "Sat", }; struct tm tm; time_t sec; size_t n; assert(buf); if (l < 3 + /* week day */ 1 + 10 + /* space and date */ 1 + 8 + /* space and time */ (us ? 1 + 6 : 0) + /* "." and microsecond part */ 1 + 1 + /* space and shortest possible zone */ 1) return NULL; /* Not enough space even for the shortest form. */ if (t <= 0 || t == USEC_INFINITY) return NULL; /* Timestamp is unset */ sec = (time_t) (t / USEC_PER_SEC); /* Round down */ if ((usec_t) sec != (t / USEC_PER_SEC)) return NULL; /* overflow? */ if (!localtime_or_gmtime_r(&sec, &tm, utc)) return NULL; /* Start with the week day */ assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays)); memcpy(buf, weekdays[tm.tm_wday], 4); /* Add the main components */ if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0) return NULL; /* Doesn't fit */ /* Append the microseconds part, if that's requested */ if (us) { n = strlen(buf); if (n + 8 > l) return NULL; /* Microseconds part doesn't fit. */ sprintf(buf + n, ".%06llu", (unsigned long long) (t % USEC_PER_SEC)); } /* Append the timezone */ n = strlen(buf); if (utc) { /* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the * obsolete "GMT" instead. */ if (n + 5 > l) return NULL; /* "UTC" doesn't fit. */ strcpy(buf + n, " UTC"); } else if (!isempty(tm.tm_zone)) { size_t tn; /* An explicit timezone is specified, let's use it, if it fits */ tn = strlen(tm.tm_zone); if (n + 1 + tn + 1 > l) { /* The full time zone does not fit in. Yuck. */ if (n + 1 + _POSIX_TZNAME_MAX + 1 > l) return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */ /* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX * minimum time zone length. In this case suppress the timezone entirely, in order not to dump * an overly long, hard to read string on the user. This should be safe, because the user will * assume the local timezone anyway if none is shown. And so does parse_timestamp(). */ } else { buf[n++] = ' '; strcpy(buf + n, tm.tm_zone); } } return buf; }
static const char* strnulldash(const char *s) { return isempty(s) || streq(s, "-") ? NULL : s; }