static int network_get_link_strv(const char *key, int ifindex, char ***ret) { _cleanup_free_ char *p = NULL, *s = NULL; _cleanup_strv_free_ char **a = NULL; int r; assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) return -ENOMEM; r = parse_env_file(p, NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) { *ret = NULL; return 0; } a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); *ret = a; a = NULL; return r; }
static int network_get_strv(const char *key, char ***ret) { _cleanup_strv_free_ char **a = NULL; _cleanup_free_ char *s = NULL; int r; assert_return(ret, -EINVAL); r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) { *ret = NULL; return 0; } a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); *ret = a; a = NULL; return r; }
static int network_link_get_strv(int ifindex, const char *key, char ***ret) { char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; _cleanup_strv_free_ char **a = NULL; _cleanup_free_ char *s = NULL; int r; assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); xsprintf(path, "/run/systemd/netif/links/%i", ifindex); r = parse_env_file(path, NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) { *ret = NULL; return 0; } a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); *ret = TAKE_PTR(a); return r; }
static int uid_get_array(uid_t uid, const char *variable, char ***array) { _cleanup_free_ char *p = NULL, *s = NULL; char **a; int r; assert(variable); r = file_of_uid(uid, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, variable, &s, NULL); if (r == -ENOENT || (r >= 0 && isempty(s))) { if (array) *array = NULL; return 0; } if (r < 0) return r; a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); if (array) *array = a; else strv_free(a); return r; }
int sd_bus_list_names(sd_bus *bus, char ***l) { _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL; char **x = NULL; int r; if (!bus) return -EINVAL; if (!l) return -EINVAL; r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames", NULL, &reply1, NULL); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListActivatableNames", NULL, &reply2, NULL); if (r < 0) return r; r = bus_message_read_strv_extend(reply1, &x); if (r < 0) { strv_free(x); return r; } r = bus_message_read_strv_extend(reply2, &x); if (r < 0) { strv_free(x); return r; } *l = strv_uniq(x); return 0; }
static int uid_get_array(uid_t uid, const char *variable, char ***array) { _cleanup_free_ char *p = NULL, *s = NULL; char **a; int r; if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0) return -ENOMEM; r = parse_env_file(p, NEWLINE, variable, &s, NULL); if (r < 0) { if (r == -ENOENT) { if (array) *array = NULL; return 0; } return r; } if (!s) { if (array) *array = NULL; return 0; } a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); if (array) *array = a; else strv_free(a); return r; }
static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) { _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **list = NULL; char line[LINE_MAX]; enum { NONE, MODELS, LAYOUTS, VARIANTS, OPTIONS } state = NONE, look_for; int r; if (n > 2) { log_error("Too many arguments."); return -EINVAL; } f = fopen("/usr/share/X11/xkb/rules/base.lst", "re"); if (!f) { log_error("Failed to open keyboard mapping list. %m"); return -errno; } if (streq(args[0], "list-x11-keymap-models")) look_for = MODELS; else if (streq(args[0], "list-x11-keymap-layouts")) look_for = LAYOUTS; else if (streq(args[0], "list-x11-keymap-variants")) look_for = VARIANTS; else if (streq(args[0], "list-x11-keymap-options")) look_for = OPTIONS; else assert_not_reached("Wrong parameter"); FOREACH_LINE(line, f, break) { char *l, *w; l = strstrip(line); if (isempty(l)) continue; if (l[0] == '!') { if (startswith(l, "! model")) state = MODELS; else if (startswith(l, "! layout")) state = LAYOUTS; else if (startswith(l, "! variant")) state = VARIANTS; else if (startswith(l, "! option")) state = OPTIONS; else state = NONE; continue; } if (state != look_for) continue; w = l + strcspn(l, WHITESPACE); if (n > 1) { char *e; if (*w == 0) continue; *w = 0; w++; w += strspn(w, WHITESPACE); e = strchr(w, ':'); if (!e) continue; *e = 0; if (!streq(w, args[1])) continue; } else *w = 0; r = strv_extend(&list, l); if (r < 0) return log_oom(); } if (strv_isempty(list)) { log_error("Couldn't find any entries."); return -ENOENT; } strv_sort(list); strv_uniq(list); pager_open_if_enabled(); strv_print(list); return 0; }
int main(int argc, char *argv[]) { _cleanup_strv_free_ char **disks_done = NULL; _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; int r = EXIT_FAILURE, r2 = EXIT_FAILURE; char **i; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[1]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); if (parse_proc_cmdline(parse_proc_cmdline_item) < 0) goto cleanup; if (!arg_enabled) { r = r2 = EXIT_SUCCESS; goto cleanup; } strv_uniq(arg_disks); if (arg_read_crypttab) { struct stat st; f = fopen("/etc/crypttab", "re"); if (!f) { if (errno == ENOENT) r = EXIT_SUCCESS; else log_error("Failed to open /etc/crypttab: %m"); goto next; } if (fstat(fileno(f), &st) < 0) { log_error("Failed to stat /etc/crypttab: %m"); goto next; } /* If we readd support for specifying passphrases * directly in crypttabe we should upgrade the warning * below, though possibly only if a passphrase is * specified directly. */ if (st.st_mode & 0005) log_debug("/etc/crypttab is world-readable. This is usually not a good idea."); for (;;) { char line[LINE_MAX], *l; _cleanup_free_ char *name = NULL, *device = NULL, *password = NULL, *options = NULL; int k; if (!fgets(line, sizeof(line), f)) break; n++; l = strstrip(line); if (*l == '#' || *l == 0) continue; k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options); if (k < 2 || k > 4) { log_error("Failed to parse /etc/crypttab:%u, ignoring.", n); continue; } /* If options are specified on the kernel commandline, let them override the ones from crypttab. */ STRV_FOREACH(i, arg_options) { _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL; const char *p = *i; k = sscanf(p, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options); if (k == 2 && streq(proc_uuid, device + 5)) { free(options); options = strdup(p); if (!proc_options) { log_oom(); goto cleanup; } } } if (arg_disks) { /* If luks UUIDs are specified on the kernel command line, use them as a filter for /etc/crypttab and only generate units for those. */ STRV_FOREACH(i, arg_disks) { _cleanup_free_ char *proc_device = NULL, *proc_name = NULL; const char *p = *i; if (startswith(p, "luks-")) p += 5; proc_name = strappend("luks-", p); proc_device = strappend("UUID=", p); if (!proc_name || !proc_device) { log_oom(); goto cleanup; } if (streq(proc_device, device) || streq(proc_name, name)) { if (create_disk(name, device, password, options) < 0) goto cleanup; if (strv_extend(&disks_done, p) < 0) { log_oom(); goto cleanup; } } } } else if (create_disk(name, device, password, options) < 0)
int lookup_paths_init( LookupPaths *p, SystemdRunningAs running_as, bool personal, const char *generator, const char *generator_early, const char *generator_late) { const char *e; assert(p); /* First priority is whatever has been passed to us via env * vars */ e = getenv("SYSTEMD_UNIT_PATH"); if (e) { p->unit_path = path_split_and_make_absolute(e); if (!p->unit_path) return -ENOMEM; } else p->unit_path = NULL; if (strv_isempty(p->unit_path)) { /* Nothing is set, so let's figure something out. */ strv_free(p->unit_path); /* For the user units we include share/ in the search * path in order to comply with the XDG basedir * spec. For the system stuff we avoid such * nonsense. OTOH we include /lib in the search path * for the system stuff but avoid it for user * stuff. */ if (running_as == SYSTEMD_USER) { if (personal) p->unit_path = user_dirs(generator, generator_early, generator_late); else p->unit_path = strv_new( /* If you modify this you also want to modify * systemduserunitpath= in systemd.pc.in, and * the arrays in user_dirs() above! */ STRV_IFNOTNULL(generator_early), USER_CONFIG_UNIT_PATH, "/etc/systemd/user", "/run/systemd/user", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/user", "/usr/local/share/systemd/user", USER_DATA_UNIT_PATH, "/usr/lib/systemd/user", "/usr/share/systemd/user", STRV_IFNOTNULL(generator_late), NULL); if (!p->unit_path) return -ENOMEM; } else { p->unit_path = strv_new( /* If you modify this you also want to modify * systemdsystemunitpath= in systemd.pc.in! */ STRV_IFNOTNULL(generator_early), SYSTEM_CONFIG_UNIT_PATH, "/etc/systemd/system", "/run/systemd/system", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/system", SYSTEM_DATA_UNIT_PATH, "/usr/lib/systemd/system", #ifdef HAVE_SPLIT_USR "/lib/systemd/system", #endif STRV_IFNOTNULL(generator_late), NULL); if (!p->unit_path) return -ENOMEM; } } if (!path_strv_canonicalize(p->unit_path)) return -ENOMEM; strv_uniq(p->unit_path); if (!strv_isempty(p->unit_path)) { _cleanup_free_ char *t = strv_join(p->unit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for unit files in (higher priority first):\n\t%s", t); } else { log_debug("Ignoring unit files."); strv_free(p->unit_path); p->unit_path = NULL; } if (running_as == SYSTEMD_SYSTEM) { #ifdef HAVE_SYSV_COMPAT /* /etc/init.d/ compatibility does not matter to users */ e = getenv("SYSTEMD_SYSVINIT_PATH"); if (e) { p->sysvinit_path = path_split_and_make_absolute(e); if (!p->sysvinit_path) return -ENOMEM; } else p->sysvinit_path = NULL; if (strv_isempty(p->sysvinit_path)) { strv_free(p->sysvinit_path); p->sysvinit_path = strv_new( SYSTEM_SYSVINIT_PATH, /* /etc/init.d/ */ NULL); if (!p->sysvinit_path) return -ENOMEM; } e = getenv("SYSTEMD_SYSVRCND_PATH"); if (e) { p->sysvrcnd_path = path_split_and_make_absolute(e); if (!p->sysvrcnd_path) return -ENOMEM; } else p->sysvrcnd_path = NULL; if (strv_isempty(p->sysvrcnd_path)) { strv_free(p->sysvrcnd_path); p->sysvrcnd_path = strv_new( SYSTEM_SYSVRCND_PATH, /* /etc/rcN.d/ */ NULL); if (!p->sysvrcnd_path) return -ENOMEM; } if (!path_strv_canonicalize(p->sysvinit_path)) return -ENOMEM; if (!path_strv_canonicalize(p->sysvrcnd_path)) return -ENOMEM; strv_uniq(p->sysvinit_path); strv_uniq(p->sysvrcnd_path); if (!strv_isempty(p->sysvinit_path)) { _cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV init scripts in:\n\t%s", t); } else { log_debug("Ignoring SysV init scripts."); strv_free(p->sysvinit_path); p->sysvinit_path = NULL; } if (!strv_isempty(p->sysvrcnd_path)) { _cleanup_free_ char *t = strv_join(p->sysvrcnd_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV rcN.d links in:\n\t%s", t); } else { log_debug("Ignoring SysV rcN.d links."); strv_free(p->sysvrcnd_path); p->sysvrcnd_path = NULL; } #else log_debug("SysV init scripts and rcN.d links support disabled"); #endif } return 0; }