systemd-verify: check man pages

This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2014-07-20 18:23:53 -04:00
parent 8b835fccda
commit 78002a6781
4 changed files with 104 additions and 45 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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) {

View file

@ -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;