mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +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:
parent
09e917ea4d
commit
43e48a4738
@ -13,8 +13,8 @@ static int check_unit_generic(int code, const UnitActiveState good_states[], int
|
|||||||
_cleanup_strv_free_ char **names = NULL;
|
_cleanup_strv_free_ char **names = NULL;
|
||||||
UnitActiveState active_state;
|
UnitActiveState active_state;
|
||||||
sd_bus *bus;
|
sd_bus *bus;
|
||||||
|
bool not_found = true, ok = false;
|
||||||
int r;
|
int r;
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
r = acquire_bus(BUS_MANAGER, &bus);
|
r = acquire_bus(BUS_MANAGER, &bus);
|
||||||
if (r < 0)
|
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");
|
return log_error_errno(r, "Failed to expand names: %m");
|
||||||
|
|
||||||
STRV_FOREACH(name, names) {
|
STRV_FOREACH(name, names) {
|
||||||
|
_cleanup_free_ char *load_state = NULL;
|
||||||
|
|
||||||
r = get_state_one_unit(bus, *name, &active_state);
|
r = get_state_one_unit(bus, *name, &active_state);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = unit_load_state(bus, *name, &load_state);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (!arg_quiet)
|
if (!arg_quiet)
|
||||||
puts(unit_active_state_to_string(active_state));
|
puts(unit_active_state_to_string(active_state));
|
||||||
|
|
||||||
for (int i = 0; i < nb_states; ++i)
|
for (int i = 0; i < nb_states; ++i)
|
||||||
if (good_states[i] == active_state)
|
if (good_states[i] == active_state) {
|
||||||
found = true;
|
ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!streq(load_state, "not-found"))
|
||||||
|
not_found = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use the given return code for the case that we won't find
|
/* We use LSB code 4 ("program or service status is unknown")
|
||||||
* any unit which matches the list */
|
* when the corresponding unit file doesn't exist. */
|
||||||
return found ? 0 : code;
|
return ok ? EXIT_SUCCESS : not_found ? EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN : code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int verb_is_active(int argc, char *argv[], void *userdata) {
|
int verb_is_active(int argc, char *argv[], void *userdata) {
|
||||||
|
@ -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) {
|
int verb_is_enabled(int argc, char *argv[], void *userdata) {
|
||||||
_cleanup_strv_free_ char **names = NULL;
|
_cleanup_strv_free_ char **names = NULL;
|
||||||
bool enabled;
|
bool not_found, enabled;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = mangle_names("to check", strv_skip(argv, 1), &names);
|
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)
|
if (r < 0)
|
||||||
return r;
|
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()) {
|
if (install_client_side()) {
|
||||||
STRV_FOREACH(name, names) {
|
STRV_FOREACH(name, names) {
|
||||||
UnitFileState state;
|
UnitFileState state;
|
||||||
|
|
||||||
r = unit_file_get_state(arg_scope, arg_root, *name, &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);
|
return log_error_errno(r, "Failed to get unit file state for %s: %m", *name);
|
||||||
|
else
|
||||||
|
not_found = false;
|
||||||
|
|
||||||
if (IN_SET(state,
|
if (IN_SET(state,
|
||||||
UNIT_FILE_ENABLED,
|
UNIT_FILE_ENABLED,
|
||||||
@ -112,8 +119,19 @@ int verb_is_enabled(int argc, char *argv[], void *userdata) {
|
|||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileState", &error, &reply, "s", *name);
|
r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileState", &error, &reply, "s", *name);
|
||||||
if (r < 0)
|
if (r == -ENOENT) {
|
||||||
return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
|
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);
|
r = sd_bus_message_read(reply, "s", &s);
|
||||||
if (r < 0)
|
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;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,7 @@ int enable_sysv_units(const char *verb, char **args) {
|
|||||||
#if HAVE_SYSV_COMPAT
|
#if HAVE_SYSV_COMPAT
|
||||||
_cleanup_(lookup_paths_free) LookupPaths paths = {};
|
_cleanup_(lookup_paths_free) LookupPaths paths = {};
|
||||||
unsigned f = 0;
|
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 */
|
/* 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 (j == EXIT_SUCCESS) {
|
||||||
if (!arg_quiet)
|
if (!arg_quiet)
|
||||||
puts("enabled");
|
puts("enabled");
|
||||||
r = 1;
|
enable_state = SYSV_UNIT_ENABLED;
|
||||||
} else {
|
} else {
|
||||||
if (!arg_quiet)
|
if (!arg_quiet)
|
||||||
puts("disabled");
|
puts("disabled");
|
||||||
|
if (enable_state != SYSV_UNIT_ENABLED)
|
||||||
|
enable_state = SYSV_UNIT_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (j != EXIT_SUCCESS)
|
} else if (j != EXIT_SUCCESS)
|
||||||
@ -245,6 +248,8 @@ int enable_sysv_units(const char *verb, char **args) {
|
|||||||
strv_remove(args + f, name);
|
strv_remove(args + f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (streq(verb, "is-enabled"))
|
||||||
|
return enable_state;
|
||||||
#endif
|
#endif
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,12 @@ enum {
|
|||||||
EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
|
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 enable_sysv_units(const char *verb, char **args);
|
||||||
|
|
||||||
int action_to_runlevel(void) _pure_;
|
int action_to_runlevel(void) _pure_;
|
||||||
|
Loading…
Reference in New Issue
Block a user