static int unit_file_find_dirs( const char *original_root, Set *unit_path_cache, const char *unit_path, const char *name, const char *suffix, char ***dirs) { _cleanup_free_ char *prefix = NULL, *instance = NULL, *built = NULL; bool is_instance, chopped; const char *dash; UnitType type; char *path; size_t n; int r; assert(unit_path); assert(name); assert(suffix); path = strjoina(unit_path, "/", name, suffix); if (!unit_path_cache || set_get(unit_path_cache, path)) { r = unit_file_find_dir(original_root, path, dirs); if (r < 0) return r; } is_instance = unit_name_is_valid(name, UNIT_NAME_INSTANCE); if (is_instance) { /* Also try the template dir */ _cleanup_free_ char *template = NULL;
static int prepare_filename(const char *filename, char **ret) { int r; const char *name; _cleanup_free_ char *abspath = NULL; _cleanup_free_ char *dir = NULL; _cleanup_free_ char *with_instance = NULL; char *c; assert(filename); assert(ret); r = path_make_absolute_cwd(filename, &abspath); if (r < 0) return r; name = basename(abspath); if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { r = unit_name_replace_instance(name, "i", &with_instance); if (r < 0) return r; } dir = dirname_malloc(abspath); if (!dir) return -ENOMEM; if (with_instance) c = path_join(NULL, dir, with_instance); else c = path_join(NULL, dir, name); if (!c) return -ENOMEM; *ret = c; return 0; }
static int specifier_name(char specifier, void *data, void *userdata, char **ret) { const UnitFileInstallInfo *i = userdata; char *ans; assert(i); if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance) return unit_name_replace_instance(i->name, i->default_instance, ret); ans = strdup(i->name); if (!ans) return -ENOMEM; *ret = ans; return 0; }
static void test_u_n_m_one(const char *pattern, const char *expect, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_mangle(pattern, UNIT_NAME_NOGLOB, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expect)); if (t) { _cleanup_free_ char *k = NULL; assert_se(unit_name_is_valid(t, UNIT_NAME_ANY)); assert_se(unit_name_mangle(t, UNIT_NAME_NOGLOB, &k) == 0); assert_se(streq_ptr(t, k)); } }
static void test_unit_name_mangle_one(UnitNameMangle allow_globs, const char *pattern, const char *expect, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_mangle(pattern, allow_globs, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expect)); if (t) { _cleanup_free_ char *k = NULL; assert_se(unit_name_is_valid(t, UNIT_NAME_ANY) || (allow_globs == UNIT_NAME_GLOB && string_is_glob(t))); assert_se(unit_name_mangle(t, allow_globs, &k) == 0); assert_se(streq_ptr(t, k)); } }
/* non-static only for testing purposes */ int cgroup_to_unit(char *cgroup, char **unit){ int r; char *p; assert(cgroup); assert(unit); r = instance_unit_from_cgroup(cgroup); if (r < 0) return r; p = strrchr(cgroup, '/'); assert(p); r = unit_name_is_valid(p + 1, true); if (!r) return -EINVAL; *unit = strdup(p + 1); if (!*unit) return -ENOMEM; return 0; }
static int add_dbus(const char *path, const char *fname, const char *type) { _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL; const ConfigTableItem table[] = { { "D-BUS Service", "Name", config_parse_string, 0, &name }, { "D-BUS Service", "Exec", config_parse_string, 0, &exec }, { "D-BUS Service", "User", config_parse_string, 0, &user }, { "D-BUS Service", "SystemdService", config_parse_string, 0, &service }, { }, }; char *p; int r; assert(path); assert(fname); p = strjoina(path, "/", fname); r = config_parse(NULL, p, NULL, "D-BUS Service\0", config_item_table_lookup, table, true, false, true, NULL); if (r < 0) return r; if (!name) { log_warning("Activation file %s lacks name setting, ignoring.", p); return 0; } if (!service_name_is_valid(name)) { log_warning("Bus service name %s is not valid, ignoring.", name); return 0; } if (streq(name, "org.freedesktop.systemd1")) { log_debug("Skipping %s, identified as systemd.", p); return 0; } if (service) { if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { log_warning("Unit name %s is not valid, ignoring.", service); return 0; } if (!endswith(service, ".service")) { log_warning("Bus names can only activate services, ignoring %s.", p); return 0; } } else { if (streq(exec, "/bin/false") || !exec) { log_warning("Neither service name nor binary path specified, ignoring %s.", p); return 0; } if (exec[0] != '/') { log_warning("Exec= in %s does not start with an absolute path, ignoring.", p); return 0; } } return create_dbus_files(p, name, service, exec, user, type); }
static int add_dbus(const char *path, const char *fname, const char *type) { _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL; ConfigTableItem table[] = { { "D-BUS Service", "Name", config_parse_string, 0, &name }, { "D-BUS Service", "Exec", config_parse_string, 0, &exec }, { "D-BUS Service", "User", config_parse_string, 0, &user }, { "D-BUS Service", "SystemdService", config_parse_string, 0, &service }, }; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; assert(path); assert(fname); p = strjoin(path, "/", fname, NULL); if (!p) return log_oom(); f = fopen(p, "re"); if (!f) { if (errno == -ENOENT) return 0; log_error("Failed to read %s: %m", p); return -errno; } r = config_parse(NULL, p, f, "D-BUS Service\0", config_item_table_lookup, table, true, false, NULL); if (r < 0) return r; if (!name) { log_warning("Activation file %s lacks name setting, ignoring.", p); return 0; } if (!service_name_is_valid(name)) { log_warning("Bus service name %s is not valid, ignoring.", name); return 0; } if (streq(name, "org.freedesktop.systemd1")) { log_debug("Skipping %s, identified as systemd.", p); return 0; } if (service) { if (!unit_name_is_valid(service, TEMPLATE_INVALID)) { log_warning("Unit name %s is not valid, ignoring.", service); return 0; } if (!endswith(service, ".service")) { log_warning("Bus names can only activate services, ignoring %s.", p); return 0; } } else { if (streq(exec, "/bin/false") || !exec) { log_warning("Neither service name nor binary path specified, ignoring %s.", p); return 0; } if (exec[0] != '/') { log_warning("Exec= in %s does not start with an absolute path, ignoring.", p); return 0; } } return create_dbus_files(p, name, service, exec, user, type); }
static void test_unit_name_is_valid(void) { assert_se(unit_name_is_valid("foo.service", UNIT_NAME_ANY)); assert_se(unit_name_is_valid("foo.service", UNIT_NAME_PLAIN)); assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE)); assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_TEMPLATE)); assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("*****@*****.**", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("*****@*****.**", UNIT_NAME_PLAIN)); assert_se(unit_name_is_valid("*****@*****.**", UNIT_NAME_INSTANCE)); assert_se(!unit_name_is_valid("*****@*****.**", UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("*****@*****.**", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("[email protected]", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("[email protected]", UNIT_NAME_PLAIN)); assert_se(!unit_name_is_valid("[email protected]", UNIT_NAME_INSTANCE)); assert_se(unit_name_is_valid("[email protected]", UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("[email protected]", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("foo.waldo", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("@.service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY)); }
static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { int r; char *orig; assert(s); assert(p); orig = p; p = strstrip(p); /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */ if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) { log_warning("Control protocol line not properly terminated."); return -EINVAL; } switch (s->state) { case STDOUT_STREAM_IDENTIFIER: if (!isempty(p)) { s->identifier = strdup(p); if (!s->identifier) return log_oom(); } s->state = STDOUT_STREAM_UNIT_ID; return 0; case STDOUT_STREAM_UNIT_ID: if (s->ucred.uid == 0 && unit_name_is_valid(p, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { s->unit_id = strdup(p); if (!s->unit_id) return log_oom(); } s->state = STDOUT_STREAM_PRIORITY; return 0; case STDOUT_STREAM_PRIORITY: r = safe_atoi(p, &s->priority); if (r < 0 || s->priority < 0 || s->priority > 999) { log_warning("Failed to parse log priority line."); return -EINVAL; } s->state = STDOUT_STREAM_LEVEL_PREFIX; return 0; case STDOUT_STREAM_LEVEL_PREFIX: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse level prefix line."); return -EINVAL; } s->level_prefix = !!r; s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG; return 0; case STDOUT_STREAM_FORWARD_TO_SYSLOG: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse forward to syslog line."); return -EINVAL; } s->forward_to_syslog = !!r; s->state = STDOUT_STREAM_FORWARD_TO_KMSG; return 0; case STDOUT_STREAM_FORWARD_TO_KMSG: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse copy to kmsg line."); return -EINVAL; } s->forward_to_kmsg = !!r; s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE; return 0; case STDOUT_STREAM_FORWARD_TO_CONSOLE: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse copy to console line."); return -EINVAL; } s->forward_to_console = !!r; s->state = STDOUT_STREAM_RUNNING; /* Try to save the stream, so that journald can be restarted and we can recover */ (void) stdout_stream_save(s); return 0; case STDOUT_STREAM_RUNNING: return stdout_stream_log(s, orig, line_break); } assert_not_reached("Unknown stream state"); }