1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

systemctl: is-*: return correct code when no unit is found

According to systemctl(1), we should use LSB return code 4
(EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN) when the state
is "no such unit" for is-{active,failed,enabled} verbs.

Fixes #25680
This commit is contained in:
Mike Yuan 2022-12-10 20:55:42 +08:00
parent 09e917ea4d
commit 43e48a4738
No known key found for this signature in database
GPG Key ID: 5A6360D78C6092C3
4 changed files with 53 additions and 13 deletions

View File

@ -13,8 +13,8 @@ static int check_unit_generic(int code, const UnitActiveState good_states[], int
_cleanup_strv_free_ char **names = NULL;
UnitActiveState active_state;
sd_bus *bus;
bool not_found = true, ok = false;
int r;
bool found = false;
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@ -25,21 +25,32 @@ static int check_unit_generic(int code, const UnitActiveState good_states[], int
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
_cleanup_free_ char *load_state = NULL;
r = get_state_one_unit(bus, *name, &active_state);
if (r < 0)
return r;
r = unit_load_state(bus, *name, &load_state);
if (r < 0)
return r;
if (!arg_quiet)
puts(unit_active_state_to_string(active_state));
for (int i = 0; i < nb_states; ++i)
if (good_states[i] == active_state)
found = true;
if (good_states[i] == active_state) {
ok = true;
break;
}
/* use the given return code for the case that we won't find
* any unit which matches the list */
return found ? 0 : code;
if (!streq(load_state, "not-found"))
not_found = false;
}
/* We use LSB code 4 ("program or service status is unknown")
* when the corresponding unit file doesn't exist. */
return ok ? EXIT_SUCCESS : not_found ? EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN : code;
}
int verb_is_active(int argc, char *argv[], void *userdata) {

View File

@ -58,7 +58,7 @@ static int show_installation_targets(sd_bus *bus, const char *name) {
int verb_is_enabled(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **names = NULL;
bool enabled;
bool not_found, enabled;
int r;
r = mangle_names("to check", strv_skip(argv, 1), &names);
@ -69,15 +69,22 @@ int verb_is_enabled(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
enabled = r > 0;
not_found = r == 0; /* Doesn't have SysV support or SYSV_UNIT_NOT_FOUND */
enabled = r == SYSV_UNIT_ENABLED;
if (install_client_side()) {
STRV_FOREACH(name, names) {
UnitFileState state;
r = unit_file_get_state(arg_scope, arg_root, *name, &state);
if (r < 0)
if (r == -ENOENT) {
if (!arg_quiet)
puts("not-found");
continue;
} else if (r < 0)
return log_error_errno(r, "Failed to get unit file state for %s: %m", *name);
else
not_found = false;
if (IN_SET(state,
UNIT_FILE_ENABLED,
@ -112,8 +119,19 @@ int verb_is_enabled(int argc, char *argv[], void *userdata) {
const char *s;
r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileState", &error, &reply, "s", *name);
if (r < 0)
return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
if (r == -ENOENT) {
sd_bus_error_free(&error);
if (!arg_quiet)
puts("not-found");
continue;
} else if (r < 0)
return log_error_errno(r,
"Failed to get unit file state for %s: %s",
*name,
bus_error_message(&error, r));
else
not_found = false;
r = sd_bus_message_read(reply, "s", &s);
if (r < 0)
@ -133,5 +151,5 @@ int verb_is_enabled(int argc, char *argv[], void *userdata) {
}
}
return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
return enabled ? EXIT_SUCCESS : not_found ? EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN : EXIT_FAILURE;
}

View File

@ -113,6 +113,7 @@ int enable_sysv_units(const char *verb, char **args) {
#if HAVE_SYSV_COMPAT
_cleanup_(lookup_paths_free) LookupPaths paths = {};
unsigned f = 0;
SysVUnitEnableState enable_state = SYSV_UNIT_NOT_FOUND;
/* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
@ -226,10 +227,12 @@ int enable_sysv_units(const char *verb, char **args) {
if (j == EXIT_SUCCESS) {
if (!arg_quiet)
puts("enabled");
r = 1;
enable_state = SYSV_UNIT_ENABLED;
} else {
if (!arg_quiet)
puts("disabled");
if (enable_state != SYSV_UNIT_ENABLED)
enable_state = SYSV_UNIT_DISABLED;
}
} else if (j != EXIT_SUCCESS)
@ -245,6 +248,8 @@ int enable_sysv_units(const char *verb, char **args) {
strv_remove(args + f, name);
}
if (streq(verb, "is-enabled"))
return enable_state;
#endif
return r;
}

View File

@ -30,6 +30,12 @@ enum {
EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
};
typedef enum SysVUnitEnableState {
SYSV_UNIT_NOT_FOUND = 0,
SYSV_UNIT_DISABLED,
SYSV_UNIT_ENABLED,
} SysVUnitEnableState;
int enable_sysv_units(const char *verb, char **args);
int action_to_runlevel(void) _pure_;