/* Drop Debian-style .sh suffix */
strcpy(stpcpy(r, name) - 3, ".service");
#ifdef TARGET_ARCH
- else if (startswith(name, "@"))
- /* Drop Arch-style background prefix */
- strcpy(stpcpy(r, name + 1), ".service");
+ else if (startswith(name, "@"))
+ /* Drop Arch-style background prefix */
+ strcpy(stpcpy(r, name + 1), ".service");
#endif
else
/* Normal init scripts */
return r;
}
-static int sysv_translate_facility(const char *name, char **_r) {
+static int sysv_translate_facility(const char *name, const char *filename, char **_r) {
+
+ /* We silently ignore the $ prefix here. According to the LSB
+ * spec it simply indicates whether something is a
+ * standardized name or a distribution-specific one. Since we
+ * just follow what already exists and do not introduce new
+ * uses or names we don't care who introduced a new name. */
static const char * const table[] = {
/* LSB defined facilities */
- "$local_fs", SPECIAL_LOCAL_FS_TARGET,
- "$network", SPECIAL_NETWORK_TARGET,
- "$named", SPECIAL_NSS_LOOKUP_TARGET,
- "$portmap", SPECIAL_RPCBIND_TARGET,
- "$remote_fs", SPECIAL_REMOTE_FS_TARGET,
- "$syslog", SPECIAL_SYSLOG_TARGET,
- "$time", SPECIAL_RTC_SET_TARGET,
+ "local_fs", SPECIAL_LOCAL_FS_TARGET,
+ "network", SPECIAL_NETWORK_TARGET,
+ "named", SPECIAL_NSS_LOOKUP_TARGET,
+ "portmap", SPECIAL_RPCBIND_TARGET,
+ "remote_fs", SPECIAL_REMOTE_FS_TARGET,
+ "syslog", SPECIAL_SYSLOG_TARGET,
+ "time", SPECIAL_RTC_SET_TARGET,
/* Debian extensions */
#ifdef TARGET_DEBIAN
- "$mail-transport-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+ "mail-transport-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
#endif
- "$mail-transfer-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
- "$x-display-manager", SPECIAL_DISPLAY_MANAGER_SERVICE,
+ "mail-transfer-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+ "x-display-manager", SPECIAL_DISPLAY_MANAGER_SERVICE,
#ifdef TARGET_FEDORA
- /* Fedora extensions, lacking the $ prefix */
- "MTA", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
- "smtpdaemon", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
- "httpd", SPECIAL_HTTP_DAEMON_TARGET,
+ /* Fedora extensions */
+ "MTA", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+ "smtpdaemon", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+ "httpd", SPECIAL_HTTP_DAEMON_TARGET,
#endif
+
+ /* SuSE extensions */
+ "null", NULL
+
};
unsigned i;
char *r;
+ const char *n;
- for (i = 0; i < ELEMENTSOF(table); i += 2)
- if (streq(table[i], name)) {
- if (!(r = strdup(table[i+1])))
- return -ENOMEM;
+ assert(name);
+ assert(_r);
- goto finish;
- }
+ n = *name == '$' ? name + 1 : name;
+
+ for (i = 0; i < ELEMENTSOF(table); i += 2) {
+
+ if (!streq(table[i], n))
+ continue;
+
+ if (!table[i+1])
+ return 0;
+
+ if (!(r = strdup(table[i+1])))
+ return -ENOMEM;
+
+ goto finish;
+ }
+
+ /* If we don't know this name, fallback heuristics to figure
+ * out whether something is a target or an service alias. */
if (*name == '$')
- r = unit_name_build(name+1, NULL, ".target");
+ /* Facilities starting with $ are most likely targets */
+ r = unit_name_build(n, NULL, ".target");
+ else if (filename && streq(name, filename))
+ /* Names equalling the file name of the services are redundant */
+ return 0;
else
- r = sysv_translate_name(name);
+ /* Everything else we assume to be normal service names */
+ r = sysv_translate_name(n);
if (!r)
return -ENOMEM;
if (s == t)
continue;
+ if (t->meta.load_state != UNIT_LOADED)
+ continue;
+
if (t->sysv_start_priority < 0)
continue;
LSB,
LSB_DESCRIPTION
} state = NORMAL;
+ char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL, *description;
assert(s);
assert(path);
s->sysv_runlevels = d;
}
- } else if (startswith_no_case(t, "description:") &&
- !u->meta.description) {
+ } else if (startswith_no_case(t, "description:")) {
size_t k = strlen(t);
char *d;
+ const char *j;
if (t[k-1] == '\\') {
state = DESCRIPTION;
t[k-1] = 0;
}
- if (!(d = strappend("LSB: ", strstrip(t+12)))) {
- r = -ENOMEM;
- goto finish;
- }
+ if ((j = strstrip(t+12)) && *j) {
+ if (!(d = strdup(j))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+ } else
+ d = NULL;
- free(u->meta.description);
- u->meta.description = d;
+ free(chkconfig_description);
+ chkconfig_description = d;
} else if (startswith_no_case(t, "pidfile:")) {
* continuation */
size_t k = strlen(t);
- char *d;
+ char *j;
if (t[k-1] == '\\')
t[k-1] = 0;
else
state = NORMAL;
- assert(u->meta.description);
- if (asprintf(&d, "%s %s", u->meta.description, strstrip(t)) < 0) {
- r = -ENOMEM;
- goto finish;
- }
+ if ((j = strstrip(t)) && *j) {
+ char *d = NULL;
+
+ if (chkconfig_description)
+ asprintf(&d, "%s %s", chkconfig_description, j);
+ else
+ d = strdup(j);
+
+ if (!d) {
+ r = -ENOMEM;
+ goto finish;
+ }
- free(u->meta.description);
- u->meta.description = d;
+ free(chkconfig_description);
+ chkconfig_description = d;
+ }
} else if (state == LSB || state == LSB_DESCRIPTION) {
goto finish;
}
- r = sysv_translate_facility(n, &m);
+ r = sysv_translate_facility(n, file_name_from_path(path), &m);
free(n);
if (r < 0)
goto finish;
}
- r = sysv_translate_facility(n, &m);
+ r = sysv_translate_facility(n, file_name_from_path(path), &m);
free(n);
if (r < 0)
s->sysv_runlevels = d;
}
- } else if (startswith_no_case(t, "Description:") &&
- !u->meta.description) {
- char *d;
-
- /* We use the long description only if
- * no short description is set. */
+ } else if (startswith_no_case(t, "Description:")) {
+ char *d, *j;
state = LSB_DESCRIPTION;
- if (!(d = strappend("LSB: ", strstrip(t+12)))) {
- r = -ENOMEM;
- goto finish;
- }
+ if ((j = strstrip(t+12)) && *j) {
+ if (!(d = strdup(j))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+ } else
+ d = NULL;
- free(u->meta.description);
- u->meta.description = d;
+ free(long_description);
+ long_description = d;
} else if (startswith_no_case(t, "Short-Description:")) {
- char *d;
+ char *d, *j;
state = LSB;
- if (!(d = strappend("LSB: ", strstrip(t+18)))) {
- r = -ENOMEM;
- goto finish;
- }
+ if ((j = strstrip(t+18)) && *j) {
+ if (!(d = strdup(j))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+ } else
+ d = NULL;
- free(u->meta.description);
- u->meta.description = d;
+ free(short_description);
+ short_description = d;
} else if (startswith_no_case(t, "X-Interactive:")) {
int b;
} else if (state == LSB_DESCRIPTION) {
if (startswith(l, "#\t") || startswith(l, "# ")) {
- char *d;
+ char *j;
- assert(u->meta.description);
- if (asprintf(&d, "%s %s", u->meta.description, t) < 0) {
- r = -ENOMEM;
- goto finish;
+ if ((j = strstrip(t)) && *j) {
+ char *d = NULL;
+
+ if (long_description)
+ asprintf(&d, "%s %s", long_description, t);
+ else
+ d = strdup(j);
+
+ if (!d) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ free(long_description);
+ long_description = d;
}
- free(u->meta.description);
- u->meta.description = d;
} else
state = LSB;
}
? EXEC_OUTPUT_TTY : EXEC_OUTPUT_NULL;
s->exec_context.kill_mode = KILL_PROCESS_GROUP;
+ /* We use the long description only if
+ * no short description is set. */
+
+ if (short_description)
+ description = short_description;
+ else if (chkconfig_description)
+ description = chkconfig_description;
+ else if (long_description)
+ description = long_description;
+ else
+ description = NULL;
+
+ if (description) {
+ char *d;
+
+ if (!(d = strappend("LSB: ", description))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ u->meta.description = d;
+ }
+
u->meta.load_state = UNIT_LOADED;
r = 0;
if (f)
fclose(f);
+ free(short_description);
+ free(long_description);
+ free(chkconfig_description);
+
return r;
}
STRV_FOREACH(p, arch_daemons_split) {
free(name);
+ name = NULL;
if (**p == '!') /* daemons prefixed with ! are disabled, so ignore them */
continue;