#define COMMENTS "#;\n"
#define NEWLINES "\n\r"
+#ifdef HAVE_SYSV_COMPAT
typedef enum RunlevelType {
RUNLEVEL_UP,
RUNLEVEL_DOWN,
#define RUNLEVELS_UP "12345"
/* #define RUNLEVELS_DOWN "06" */
/* #define RUNLEVELS_BOOT "bBsS" */
+#endif
static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
[SERVICE_DEAD] = UNIT_INACTIVE,
s->timeout_usec = DEFAULT_TIMEOUT_USEC;
s->restart_usec = DEFAULT_RESTART_USEC;
s->timer_watch.type = WATCH_INVALID;
+#ifdef HAVE_SYSV_COMPAT
s->sysv_start_priority = -1;
+#endif
s->socket_fd = -1;
exec_context_init(&s->exec_context);
free(s->pid_file);
s->pid_file = NULL;
+#ifdef HAVE_SYSV_COMPAT
free(s->sysv_path);
s->sysv_path = NULL;
free(s->sysv_runlevels);
s->sysv_runlevels = NULL;
+#endif
free(s->status_text);
s->status_text = NULL;
unit_unwatch_timer(u, &s->timer_watch);
}
+#ifdef HAVE_SYSV_COMPAT
static char *sysv_translate_name(const char *name) {
char *r;
/* 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 */
static int sysv_translate_facility(const char *name, 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;
for (i = 0; i < ELEMENTSOF(table); i += 2)
- if (streq(table[i], name)) {
+
+ if (streq(table[i], name) ||
+ (*name == '$' && streq(table[i], name+1))) {
+
+ 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");
else
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;
}
+ if (streq(n, file_name_from_path(path))) {
+ free(n);
+ continue;
+ }
+
r = sysv_translate_facility(n, &m);
free(n);
goto finish;
}
+ if (streq(n, file_name_from_path(path))) {
+ free(n);
+ continue;
+ }
+
r = sysv_translate_facility(n, &m);
free(n);
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;
}
return 0;
}
+#endif
static int service_verify(Service *s) {
assert(s);
if ((r = unit_load_fragment(u)) < 0)
return r;
+#ifdef HAVE_SYSV_COMPAT
/* Load a classic init script as a fallback, if we couldn't find anything */
if (u->meta.load_state == UNIT_STUB)
if ((r = service_load_sysv(s)) < 0)
return r;
+#endif
/* Still nothing found? Then let's give up */
if (u->meta.load_state == UNIT_STUB)
if ((r = unit_add_default_cgroup(u)) < 0)
return r;
+#ifdef HAVE_SYSV_COMPAT
if ((r = sysv_fix_order(s)) < 0)
return r;
+#endif
if (s->bus_name)
if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
exec_command_dump_list(s->exec_command[c], f, prefix2);
}
+#ifdef HAVE_SYSV_COMPAT
if (s->sysv_path)
fprintf(f,
"%sSysV Init Script Path: %s\n"
if (s->sysv_runlevels)
fprintf(f, "%sSysVRunLevels: %s\n",
prefix, s->sysv_runlevels);
+#endif
if (s->status_text)
fprintf(f, "%sStatus Text: %s\n",
return service_state_to_string(SERVICE(u)->state);
}
+#ifdef HAVE_SYSV_COMPAT
static bool service_check_gc(Unit *u) {
Service *s = SERVICE(u);
return !!s->sysv_path;
}
+#endif
static bool service_check_snapshot(Unit *u) {
Service *s = SERVICE(u);
unit_add_to_dbus_queue(u);
}
+#ifdef HAVE_SYSV_COMPAT
static int service_enumerate(Manager *m) {
char **p;
unsigned i;
STRV_FOREACH(p, arch_daemons_split) {
free(name);
+ name = NULL;
if (**p == '!') /* daemons prefixed with ! are disabled, so ignore them */
continue;
return r;
}
+#endif
static void service_bus_name_owner_change(
Unit *u,
.active_state = service_active_state,
.sub_state_to_string = service_sub_state_to_string,
+#ifdef HAVE_SYSV_COMPAT
.check_gc = service_check_gc,
+#endif
.check_snapshot = service_check_snapshot,
.sigchld_event = service_sigchld_event,
.bus_message_handler = bus_service_message_handler,
.bus_invalidating_properties = bus_service_invalidating_properties,
+#ifdef HAVE_SYSV_COMPAT
.enumerate = service_enumerate
+#endif
};