mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
systemd-verify: check man pages
This commit is contained in:
parent
8b835fccda
commit
78002a6781
@ -150,3 +150,56 @@ void pager_close(void) {
|
||||
bool pager_have(void) {
|
||||
return pager_pid > 0;
|
||||
}
|
||||
|
||||
int show_man_page(const char *desc, bool null_stdio) {
|
||||
const char *args[4] = { "man", NULL, NULL, NULL };
|
||||
char *e = NULL;
|
||||
pid_t pid;
|
||||
size_t k;
|
||||
int r;
|
||||
siginfo_t status;
|
||||
|
||||
k = strlen(desc);
|
||||
|
||||
if (desc[k-1] == ')')
|
||||
e = strrchr(desc, '(');
|
||||
|
||||
if (e) {
|
||||
char *page = NULL, *section = NULL;
|
||||
|
||||
page = strndupa(desc, e - desc);
|
||||
section = strndupa(e + 1, desc + k - e - 2);
|
||||
|
||||
args[1] = section;
|
||||
args[2] = page;
|
||||
} else
|
||||
args[1] = desc;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Failed to fork: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child */
|
||||
if (null_stdio) {
|
||||
r = make_null_stdio();
|
||||
if (r < 0) {
|
||||
log_error("Failed to kill stdio: %s", strerror(-r));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
execvp(args[0], (char**) args);
|
||||
log_error("Failed to execute man: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = wait_for_terminate(pid, &status);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("Exit code %i status %i", status.si_code, status.si_status);
|
||||
return status.si_status;
|
||||
}
|
||||
|
@ -28,3 +28,5 @@
|
||||
int pager_open(bool jump_to_end);
|
||||
void pager_close(void);
|
||||
bool pager_have(void) _pure_;
|
||||
|
||||
int show_man_page(const char *page, bool null_stdio);
|
||||
|
@ -3503,50 +3503,11 @@ static void show_unit_help(UnitStatusInfo *i) {
|
||||
return;
|
||||
}
|
||||
|
||||
STRV_FOREACH(p, i->documentation) {
|
||||
|
||||
if (startswith(*p, "man:")) {
|
||||
const char *args[4] = { "man", NULL, NULL, NULL };
|
||||
_cleanup_free_ char *page = NULL, *section = NULL;
|
||||
char *e = NULL;
|
||||
pid_t pid;
|
||||
size_t k;
|
||||
|
||||
k = strlen(*p);
|
||||
|
||||
if ((*p)[k-1] == ')')
|
||||
e = strrchr(*p, '(');
|
||||
|
||||
if (e) {
|
||||
page = strndup((*p) + 4, e - *p - 4);
|
||||
section = strndup(e + 1, *p + k - e - 2);
|
||||
if (!page || !section) {
|
||||
log_oom();
|
||||
return;
|
||||
}
|
||||
|
||||
args[1] = section;
|
||||
args[2] = page;
|
||||
} else
|
||||
args[1] = *p + 4;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Failed to fork: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child */
|
||||
execvp(args[0], (char**) args);
|
||||
log_error("Failed to execute man: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
wait_for_terminate(pid, NULL);
|
||||
} else
|
||||
STRV_FOREACH(p, i->documentation)
|
||||
if (startswith(*p, "man:"))
|
||||
show_man_page(*p + 4, false);
|
||||
else
|
||||
log_info("Can't show: %s", *p);
|
||||
}
|
||||
}
|
||||
|
||||
static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
|
||||
|
@ -27,8 +27,10 @@
|
||||
#include "log.h"
|
||||
#include "strv.h"
|
||||
#include "build.h"
|
||||
#include "pager.h"
|
||||
|
||||
SystemdRunningAs arg_running_as = SYSTEMD_SYSTEM;
|
||||
bool arg_no_man = false;
|
||||
|
||||
static int generate_path(char **var, char **filenames) {
|
||||
char **filename;
|
||||
@ -140,6 +142,37 @@ static int verify_executables(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int verify_documentation(Unit *u) {
|
||||
char **p;
|
||||
int r = 0, k;
|
||||
|
||||
if (arg_no_man)
|
||||
return 0;
|
||||
|
||||
STRV_FOREACH(p, u->documentation) {
|
||||
log_debug_unit(u->id, "%s: found documentation item %s.", u->id, *p);
|
||||
if (startswith(*p, "man:")) {
|
||||
k = show_man_page(*p + 4, true);
|
||||
if (k != 0) {
|
||||
if (k < 0)
|
||||
log_error_unit(u->id, "%s: can't show %s: %s",
|
||||
u->id, *p, strerror(-r));
|
||||
else {
|
||||
log_error_unit(u->id, "%s: man %s command failed with code %d",
|
||||
u->id, *p + 4, k);
|
||||
k = -ENOEXEC;
|
||||
}
|
||||
if (r == 0)
|
||||
r = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check remote URLs? */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_unit(Unit *u) {
|
||||
_cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
|
||||
Job *j;
|
||||
@ -167,6 +200,10 @@ static int test_unit(Unit *u) {
|
||||
if (k < 0 && r == 0)
|
||||
r = k;
|
||||
|
||||
k = verify_documentation(u);
|
||||
if (k < 0 && r == 0)
|
||||
r = k;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -242,8 +279,9 @@ static void help(void) {
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --system Connect to system manager\n"
|
||||
" --user Connect to user service manager\n",
|
||||
program_invocation_short_name);
|
||||
" --user Connect to user service manager\n"
|
||||
" --no-man Do not check for existence of man pages\n"
|
||||
, program_invocation_short_name);
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
@ -251,6 +289,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_USER,
|
||||
ARG_SYSTEM,
|
||||
ARG_NO_MAN,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -288,6 +327,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_running_as = SYSTEMD_SYSTEM;
|
||||
break;
|
||||
|
||||
case ARG_NO_MAN:
|
||||
arg_no_man = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
log_error("Unknown option %s.", argv[optind-1]);
|
||||
return -EINVAL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user