+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
#include "exit-status.h"
#include "fd-util.h"
#include "fileio.h"
+#include "generator.h"
#include "hashmap.h"
#include "hexdecoct.h"
#include "install.h"
#include "path-util.h"
#include "set.h"
#include "special.h"
+#include "specifier.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub);
static void free_sysvstub_hashmapp(Hashmap **h) {
- SysvStub *stub;
-
- while ((stub = hashmap_steal_first(*h)))
- free_sysvstub(stub);
-
- hashmap_free(*h);
-}
-
-static int add_symlink(const char *service, const char *where) {
- const char *from, *to;
- int r;
-
- assert(service);
- assert(where);
-
- from = strjoina(arg_dest, "/", service);
- to = strjoina(arg_dest, "/", where, ".wants/", service);
-
- mkdir_parents_label(to, 0755);
-
- r = symlink(from, to);
- if (r < 0) {
- if (errno == EEXIST)
- return 0;
-
- return -errno;
- }
-
- return 1;
+ hashmap_free_with_destructor(*h, free_sysvstub);
}
static int add_alias(const char *service, const char *alias) {
}
static int generate_unit_file(SysvStub *s) {
+ _cleanup_free_ char *path_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *unit;
char **p;
if (!s->loaded)
return 0;
+ path_escaped = specifier_escape(s->path);
+ if (!path_escaped)
+ return log_oom();
+
unit = strjoina(arg_dest, "/", s->name);
/* We might already have a symlink with the same name from a Provides:,
"[Unit]\n"
"Documentation=man:systemd-sysv-generator(8)\n"
"SourcePath=%s\n",
- s->path);
+ path_escaped);
- if (s->description)
- fprintf(f, "Description=%s\n", s->description);
+ if (s->description) {
+ _cleanup_free_ char *t;
+
+ t = specifier_escape(s->description);
+ if (!t)
+ return log_oom();
+
+ fprintf(f, "Description=%s\n", t);
+ }
STRV_FOREACH(p, s->before)
fprintf(f, "Before=%s\n", *p);
"RemainAfterExit=%s\n",
yes_no(!s->pid_file));
- if (s->pid_file)
- fprintf(f, "PIDFile=%s\n", s->pid_file);
+ if (s->pid_file) {
+ _cleanup_free_ char *t;
+
+ t = specifier_escape(s->pid_file);
+ if (!t)
+ return log_oom();
+
+ fprintf(f, "PIDFile=%s\n", t);
+ }
/* Consider two special LSB exit codes a clean exit */
if (s->has_lsb)
fprintf(f,
"ExecStart=%s start\n"
"ExecStop=%s stop\n",
- s->path, s->path);
+ path_escaped, path_escaped);
if (s->reload)
- fprintf(f, "ExecReload=%s reload\n", s->path);
+ fprintf(f, "ExecReload=%s reload\n", path_escaped);
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to write unit %s: %m", unit);
- STRV_FOREACH(p, s->wanted_by) {
- r = add_symlink(s->name, *p);
- if (r < 0)
- log_warning_errno(r, "Failed to create 'Wants' symlink to %s, ignoring: %m", *p);
- }
+ STRV_FOREACH(p, s->wanted_by)
+ (void) generator_add_symlink(arg_dest, *p, "wants", s->name);
return 1;
}
if (res)
*res = 0;
- if (unit_name_mangle(c, UNIT_NAME_NOGLOB, &res) < 0)
+ if (unit_name_mangle(c, 0, &res) < 0)
return NULL;
return res;
r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET);
if (r < 0)
return log_oom();
+ r = strv_extend(&s->wants, SPECIAL_NETWORK_TARGET);
+ if (r < 0)
+ return log_oom();
}
break;
continue;
}
- if ((state == LSB_DESCRIPTION || state == LSB) && streq(t, "### END INIT INFO")) {
+ if (IN_SET(state, LSB_DESCRIPTION, LSB) && streq(t, "### END INIT INFO")) {
state = NORMAL;
continue;
}
chkconfig_description = d;
}
- } else if (state == LSB || state == LSB_DESCRIPTION) {
+ } else if (IN_SET(state, LSB, LSB_DESCRIPTION)) {
if (startswith_no_case(t, "Provides:")) {
state = LSB;
if (!path_strv_resolve_uniq(l, NULL))
return log_oom();
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
}
return log_oom();
service->sysv_start_priority = -1;
- service->name = name;
- service->path = fpath;
- name = fpath = NULL;
+ service->name = TAKE_PTR(name);
+ service->path = TAKE_PTR(fpath);
r = hashmap_put(all_services, service->name, service);
if (r < 0)
if (argc > 1)
arg_dest = argv[3];
- log_set_target(LOG_TARGET_SAFE);
+ log_set_prohibit_ipc(true);
+ log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();