+ rc = add_metadata(jdesc, conf);
+ if (rc)
+ ERROR("can't set the metadata. %m");
+ else {
+ rc = template ? 0 : unit_generator_on(NULL);
+ if (!rc) {
+ instance = NULL;
+ rc = apply_mustach(template, jdesc, &instance, &size);
+ if (!rc)
+ rc = process_all_units(instance, conf, process, closure);
+ free(instance);
+ }
+ }
+ return rc;
+}
+
+/**************** SPECIALIZED PART *****************************/
+
+static int check_unit_desc(const struct unitdesc *desc, int tells)
+{
+ if (desc->scope != unitscope_unknown && desc->type != unittype_unknown && desc->name != NULL)
+ return 0;
+
+ if (tells) {
+ if (desc->scope == unitscope_unknown)
+ ERROR("unit of unknown scope");
+ if (desc->type == unittype_unknown)
+ ERROR("unit of unknown type");
+ if (desc->name == NULL)
+ ERROR("unit of unknown name");
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+static int get_unit_path(char *path, size_t pathlen, const struct unitdesc *desc)
+{
+ int rc = systemd_get_unit_path(
+ path, pathlen, desc->scope == unitscope_user,
+ desc->name, desc->type == unittype_socket ? "socket" : "service");
+
+ if (rc < 0)
+ ERROR("can't get the unit path for %s", desc->name);
+
+ return rc;
+}
+
+static int get_wants_path(char *path, size_t pathlen, const struct unitdesc *desc)
+{
+ int rc = systemd_get_wants_path(
+ path, pathlen, desc->scope == unitscope_user, desc->wanted_by,
+ desc->name, desc->type == unittype_socket ? "socket" : "service");
+
+ if (rc < 0)
+ ERROR("can't get the wants path for %s and %s", desc->name, desc->wanted_by);
+
+ return rc;
+}
+
+static int get_wants_target(char *path, size_t pathlen, const struct unitdesc *desc)
+{
+ int rc = systemd_get_wants_target(
+ path, pathlen,
+ desc->name, desc->type == unittype_socket ? "socket" : "service");
+
+ if (rc < 0)
+ ERROR("can't get the wants target for %s", desc->name);
+
+ return rc;
+}
+
+static int do_send_reload(const struct generatedesc *desc)
+{
+ int i;
+ int reloadsys, reloadusr;
+ const struct unitdesc *u;
+
+ reloadsys = reloadusr = 0;
+ for (i = 0 ; i < desc->nunits ; i++) {
+ u = &desc->units[i];
+ if (u->wanted_by != NULL) {
+ switch (u->scope) {
+ case unitscope_user:
+ reloadusr = 1;
+ break;
+ case unitscope_system:
+ reloadsys = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (reloadusr)
+ reloadusr = systemd_daemon_reload(1);
+ if (reloadsys)
+ reloadsys = systemd_daemon_reload(0);
+ return 0;
+}
+
+static int do_uninstall_units(void *closure, const struct generatedesc *desc)
+{
+ int rc, rc2;
+ int i;
+ char path[PATH_MAX];
+ const struct unitdesc *u;
+
+ rc = 0;
+ for (i = 0 ; i < desc->nunits ; i++) {
+ u = &desc->units[i];
+ rc2 = check_unit_desc(u, 0);
+ if (rc2 == 0) {
+ rc2 = get_unit_path(path, sizeof path, u);
+ if (rc2 >= 0) {
+ rc2 = unlink(path);
+ }
+ if (rc2 < 0 && rc == 0)
+ rc = rc2;
+ if (u->wanted_by != NULL) {
+ rc2 = get_wants_path(path, sizeof path, u);
+ if (rc2 >= 0)
+ rc2 = unlink(path);
+ }
+ }
+ if (rc2 < 0 && rc == 0)
+ rc = rc2;
+ }
+ rc2 = do_send_reload(desc);
+ if (rc2 < 0 && rc == 0)
+ rc = rc2;
+ return rc;
+}
+
+static int do_install_units(void *closure, const struct generatedesc *desc)
+{
+ int rc;
+ int i;
+ char path[PATH_MAX + 1], target[PATH_MAX + 1];
+ const struct unitdesc *u;
+
+ i = 0;
+ while (i < desc->nunits) {
+ u = &desc->units[i];
+ rc = check_unit_desc(u, 1);
+ if (!rc) {
+ rc = get_unit_path(path, sizeof path, u);
+ if (rc >= 0) {
+ rc = putfile(path, u->content, u->content_length);
+ if (rc >= 0 && u->wanted_by != NULL) {
+ rc = get_wants_path(path, sizeof path, u);
+ if (rc >= 0) {
+ rc = get_wants_target(target, sizeof target, u);
+ if (rc >= 0) {
+ unlink(path); /* TODO? check? */
+ rc = symlink(target, path);
+ }
+ }
+ }
+ i++;
+ }
+ }
+ if (rc < 0)
+ goto error;