X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fservice.c;h=116e539d951df7303039759645589b54b0e49342;hb=1ddff895f3ad85ec79c4923ba8c882a283826f42;hp=cf5edd2b9b1c71931d81a094356680aa4bf272a6;hpb=a7d3cc26f9694053712458615006ea79cd7a7cb4;p=elogind.git diff --git a/src/service.c b/src/service.c index cf5edd2b9..116e539d9 100644 --- a/src/service.c +++ b/src/service.c @@ -178,11 +178,11 @@ static void service_close_socket_fd(Service *s) { static void service_connection_unref(Service *s) { assert(s); - if (!s->socket) + if (!s->accept_socket) return; - socket_connection_unref(s->socket); - s->socket = NULL; + socket_connection_unref(s->accept_socket); + s->accept_socket = NULL; } static void service_done(Unit *u) { @@ -222,6 +222,8 @@ static void service_done(Unit *u) { service_close_socket_fd(s); service_connection_unref(s); + set_free(s->configured_sockets); + unit_unwatch_timer(u, &s->timer_watch); } @@ -250,7 +252,7 @@ static char *sysv_translate_name(const char *name) { 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 @@ -289,28 +291,39 @@ static int sysv_translate_facility(const char *name, char **_r) { unsigned i; char *r; + const char *n; - for (i = 0; i < ELEMENTSOF(table); i += 2) + assert(name); + assert(_r); - if (streq(table[i], name) || - (*name == '$' && streq(table[i], name+1))) { + n = *name == '$' ? name + 1 : name; - if (!table[i+1]) - return 0; + for (i = 0; i < ELEMENTSOF(table); i += 2) { - if (!(r = strdup(table[i+1]))) - return -ENOMEM; + if (!streq(table[i], n)) + continue; - goto finish; - } + 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; @@ -432,6 +445,7 @@ static int service_load_sysv_path(Service *s, const char *path) { LSB, LSB_DESCRIPTION } state = NORMAL; + char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL, *description; assert(s); assert(path); @@ -522,24 +536,27 @@ static int service_load_sysv_path(Service *s, const char *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:")) { @@ -568,21 +585,29 @@ static int service_load_sysv_path(Service *s, const char *path) { * 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; - free(u->meta.description); - u->meta.description = d; + if (chkconfig_description) + asprintf(&d, "%s %s", chkconfig_description, j); + else + d = strdup(j); + + if (!d) { + r = -ENOMEM; + goto finish; + } + + free(chkconfig_description); + chkconfig_description = d; + } } else if (state == LSB || state == LSB_DESCRIPTION) { @@ -600,12 +625,7 @@ static int service_load_sysv_path(Service *s, const char *path) { goto finish; } - if (streq(n, file_name_from_path(path))) { - free(n); - continue; - } - - r = sysv_translate_facility(n, &m); + r = sysv_translate_facility(n, file_name_from_path(path), &m); free(n); if (r < 0) @@ -650,12 +670,7 @@ static int service_load_sysv_path(Service *s, const char *path) { goto finish; } - if (streq(n, file_name_from_path(path))) { - free(n); - continue; - } - - r = sysv_translate_facility(n, &m); + r = sysv_translate_facility(n, file_name_from_path(path), &m); free(n); if (r < 0) @@ -688,35 +703,37 @@ static int service_load_sysv_path(Service *s, const char *path) { 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; @@ -734,16 +751,25 @@ static int service_load_sysv_path(Service *s, const char *path) { } 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; } @@ -769,12 +795,35 @@ static int service_load_sysv_path(Service *s, const char *path) { /* Special setting for all SysV services */ s->type = SERVICE_FORKING; s->remain_after_exit = true; - s->restart = SERVICE_ONCE; + s->restart = SERVICE_RESTART_NO; s->exec_context.std_output = (s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY) ? 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; @@ -783,6 +832,10 @@ finish: if (f) fclose(f); + free(short_description); + free(long_description); + free(chkconfig_description); + return r; } @@ -1126,6 +1179,9 @@ static int service_get_sockets(Service *s, Set **_set) { if (s->socket_fd >= 0) return 0; + if (!set_isempty(s->configured_sockets)) + return 0; + /* Collects all Socket objects that belong to this * service. Note that a service might have multiple sockets * via multiple names. */ @@ -1165,23 +1221,30 @@ fail: static int service_notify_sockets_dead(Service *s) { Iterator i; - Set *set; + Set *set, *free_set = NULL; Socket *sock; int r; assert(s); + /* Notifies all our sockets when we die */ + if (s->socket_fd >= 0) return 0; - /* Notifies all our sockets when we die */ - if ((r = service_get_sockets(s, &set)) < 0) - return r; + if (!set_isempty(s->configured_sockets)) + set = s->configured_sockets; + else { + if ((r = service_get_sockets(s, &free_set)) < 0) + return r; + + set = free_set; + } SET_FOREACH(sock, set, i) socket_notify_service_dead(sock); - set_free(set); + set_free(free_set); return 0; } @@ -1339,7 +1402,7 @@ static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) { int r; int *rfds = NULL; unsigned rn_fds = 0; - Set *set; + Set *set, *free_set = NULL; Socket *sock; assert(s); @@ -1349,8 +1412,14 @@ static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) { if (s->socket_fd >= 0) return 0; - if ((r = service_get_sockets(s, &set)) < 0) - return r; + if (!set_isempty(s->configured_sockets)) + set = s->configured_sockets; + else { + if ((r = service_get_sockets(s, &free_set)) < 0) + return r; + + set = free_set; + } SET_FOREACH(sock, set, i) { int *cfds; @@ -1387,7 +1456,7 @@ static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) { *fds = rfds; *n_fds = rn_fds; - set_free(set); + set_free(free_set); return 0; @@ -2033,14 +2102,6 @@ static int service_start(Unit *u) { return -ECANCELED; } - if ((s->exec_context.std_input == EXEC_INPUT_SOCKET || - s->exec_context.std_output == EXEC_OUTPUT_SOCKET || - s->exec_context.std_error == EXEC_OUTPUT_SOCKET) && - s->socket_fd < 0) { - log_warning("%s can only be started with a per-connection socket.", u->meta.id); - return -EINVAL; - } - s->failure = false; s->main_pid_known = false; s->forbid_restart = false; @@ -2745,6 +2806,7 @@ static int service_enumerate(Manager *m) { STRV_FOREACH(p, arch_daemons_split) { free(name); + name = NULL; if (**p == '!') /* daemons prefixed with ! are disabled, so ignore them */ continue; @@ -3010,7 +3072,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock) { s->socket_fd = fd; s->got_socket_fd = true; - s->socket = sock; + s->accept_socket = sock; return 0; } @@ -3047,9 +3109,9 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState); static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { - [SERVICE_ONCE] = "once", - [SERVICE_RESTART_ON_SUCCESS] = "restart-on-success", - [SERVICE_RESTART_ALWAYS] = "restart-always", + [SERVICE_RESTART_NO] = "no", + [SERVICE_RESTART_ON_SUCCESS] = "on-success", + [SERVICE_RESTART_ALWAYS] = "always", }; DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart);