Showing with 65 additions and 36 deletions.
  1. +54 −11 lib/tpm2_options.c
  2. +10 −0 lib/tpm2_options.h
  3. +1 −25 tools/tpm2_tool.c
65 changes: 54 additions & 11 deletions lib/tpm2_options.c
Expand Up @@ -37,6 +37,9 @@
#include <getopt.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/wait.h>

#include "log.h"
#include "tpm2_options.h"
#include "tpm2_util.h"
Expand Down Expand Up @@ -199,17 +202,31 @@ static char *tcti_get_opts(char *optstr) {
return &split[1];
}

static void execute_man (char *prog_name, char *envp[]) {
static bool execute_man(char *prog_name) {

char *manpage = basename(prog_name);
char *argv[] = {
"/man", // ARGv[0] needs to be something.
manpage,
NULL
};
execvpe ("man", argv, envp);
LOG_ERR("Could not execute \"man %s\" error: %s", manpage,
strerror(errno));
pid_t pid;
int status;

if ((pid = fork()) < 0) {
LOG_ERR("Could not fork process to execute man, error: %s",
strerror(errno));
return false;
}

if (pid == 0) {
char *manpage = basename(prog_name);
execlp("man", "man", manpage, NULL);
} else {
if ((pid = waitpid(pid, &status, 0)) == -1) {
LOG_ERR("Waiting for child process that executes man failed, error: %s",
strerror(errno));
return false;
}

return WEXITSTATUS(status) == 0;
}

return true;
}

static void show_version (const char *name) {
Expand All @@ -236,6 +253,30 @@ static void show_version (const char *name) {
tcti_conf);
}

void tpm2_print_usage(const char *command, struct tpm2_options *tool_opts) {
unsigned int i;

printf("usage: %s%s%s\n", command,
tool_opts->callbacks.on_opt ? " [OPTIONS]" : "",
tool_opts->callbacks.on_arg ? " ARGUMENTS" : "");

if (tool_opts->callbacks.on_opt) {
for (i = 0; i < tool_opts->len; i++) {
struct option *opt = &tool_opts->long_opts[i];
printf("[ -%c | --%s%s]", opt->val, opt->name,
opt->has_arg ? "=VALUE" : "");
if ((i + 1) % 4 == 0) {
printf("\n");
} else {
printf(" ");
}
}
if (i % 4 != 0) {
printf("\n");
}
}
}

tpm2_option_code tpm2_handle_options (int argc, char **argv, char **envp,
tpm2_options *tool_opts, tpm2_option_flags *flags,
TSS2_TCTI_CONTEXT **tcti) {
Expand Down Expand Up @@ -291,7 +332,9 @@ tpm2_option_code tpm2_handle_options (int argc, char **argv, char **envp,
tcti_opts = tcti_get_opts(optarg);
break;
case 'h':
execute_man(argv[0], envp);
if (!execute_man(argv[0])) {
tpm2_print_usage(argv[0], tool_opts);
}
show_help = false;
goto out;
break;
Expand Down
10 changes: 10 additions & 0 deletions lib/tpm2_options.h
Expand Up @@ -186,4 +186,14 @@ tpm2_option_code tpm2_handle_options (int argc, char **argv, char **envp,
tpm2_options *tool_opts, tpm2_option_flags *flags,
TSS2_TCTI_CONTEXT **tcti);

/**
* Print usage summary for a given tpm2 tool.
*
* @param command
* The command to print its usage summary text.
* @param tool_opts
* The tpm2_options array that contains the tool options to print as a summary.
*/
void tpm2_print_usage(const char *command, struct tpm2_options *tool_opts);

#endif /* OPTIONS_H */
26 changes: 1 addition & 25 deletions tools/tpm2_tool.c
Expand Up @@ -93,30 +93,6 @@ static TSS2_SYS_CONTEXT* sapi_ctx_init(TSS2_TCTI_CONTEXT *tcti_ctx) {
return sapi_ctx;
}

void print_usage(const char *command, struct tpm2_options *tool_opts) {
unsigned int i;

tpm2_tool_output("usage: %s%s%s\n", command,
tool_opts->callbacks.on_opt ? " [OPTIONS]" : "",
tool_opts->callbacks.on_arg ? " ARGUMENTS" : "");

if (tool_opts->callbacks.on_opt) {
for (i = 0; i < tool_opts->len; i++) {
struct option *opt = &tool_opts->long_opts[i];
tpm2_tool_output("[ -%c | --%s%s]", opt->val, opt->name,
opt->has_arg ? "=VALUE" : "");
if ((i + 1) % 4 == 0) {
tpm2_tool_output("\n");
} else {
tpm2_tool_output(" ");
}
}
if (i % 4 != 0) {
tpm2_tool_output("\n");
}
}
}

/*
* This program is a template for TPM2 tools that use the SAPI. It does
* nothing more than parsing command line options that allow the caller to
Expand All @@ -136,7 +112,7 @@ int main(int argc, char *argv[], char *envp[]) {
}

if (argc == 1 && tool_opts && tool_opts->show_usage) {
print_usage(argv[0], tool_opts);
tpm2_print_usage(argv[0], tool_opts);
return ret;
}

Expand Down