summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/Makefile.am9
-rw-r--r--tools/list.c (renamed from tools/p11-kit.c)99
-rw-r--r--tools/tool.c337
-rw-r--r--tools/tool.h56
4 files changed, 459 insertions, 42 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 44b8432..43adf56 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -6,17 +6,22 @@ INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/common \
-I$(top_srcdir)/p11-kit \
- -DSRCDIR=\"$(srcdir)\"
+ -DSRCDIR=\"$(srcdir)\" \
+ -DPKGDATADIR=\"$(pkgdatadir)\" \
+ -DP11_KIT_FUTURE_UNSTABLE_API \
+ $(NULL)
bin_PROGRAMS = \
p11-kit
p11_kit_SOURCES = \
- p11-kit.c \
+ list.c \
+ tool.c tool.h \
$(NULL)
p11_kit_LDADD = \
$(top_builddir)/p11-kit/libp11-kit.la \
+ $(top_builddir)/common/libp11-library.la \
$(top_builddir)/common/libp11-compat.la \
$(LTLIBINTL) \
$(NULL)
diff --git a/tools/p11-kit.c b/tools/list.c
index f789fb8..8430d78 100644
--- a/tools/p11-kit.c
+++ b/tools/list.c
@@ -35,6 +35,7 @@
#include "config.h"
#include "compat.h"
+#include "debug.h"
#include <assert.h>
#include <ctype.h>
@@ -43,20 +44,14 @@
#include <stdlib.h>
#include <unistd.h>
-#include "p11-kit/p11-kit.h"
-#include "p11-kit/uri.h"
+#include "library.h"
+#include "p11-kit.h"
+#include "tool.h"
+#include "uri.h"
typedef int (*operation) (int argc, char *argv[]);
bool verbose = false;
-static void
-usage (void)
-{
- fprintf (stderr, "usage: p11-kit [-v] -l\n");
- fprintf (stderr, " p11-kit -h\n");
- exit (2);
-}
-
static const char HEXC_LOWER[] = "0123456789abcdef";
static char *
@@ -106,7 +101,7 @@ print_token_info (CK_FUNCTION_LIST_PTR module, CK_SLOT_ID slot_id)
rv = (module->C_GetTokenInfo) (slot_id, &info);
if (rv != CKR_OK) {
- warnx ("couldn't load module info: %s", p11_kit_strerror (rv));
+ p11_message ("couldn't load module info: %s", p11_kit_strerror (rv));
return;
}
@@ -173,7 +168,7 @@ print_module_info (CK_FUNCTION_LIST_PTR module)
rv = (module->C_GetInfo) (&info);
if (rv != CKR_OK) {
- warnx ("couldn't load module info: %s", p11_kit_strerror (rv));
+ p11_message ("couldn't load module info: %s", p11_kit_strerror (rv));
return;
}
@@ -194,7 +189,7 @@ print_module_info (CK_FUNCTION_LIST_PTR module)
count = sizeof (slot_list) / sizeof (slot_list[0]);
rv = (module->C_GetSlotList) (CK_TRUE, slot_list, &count);
if (rv != CKR_OK) {
- warnx ("couldn't load module info: %s", p11_kit_strerror (rv));
+ p11_message ("couldn't load module info: %s", p11_kit_strerror (rv));
return;
}
@@ -203,7 +198,7 @@ print_module_info (CK_FUNCTION_LIST_PTR module)
}
static int
-list_modules (int argc, char *argv[])
+print_modules (void)
{
CK_FUNCTION_LIST_PTR *module_list;
char *name;
@@ -211,13 +206,12 @@ list_modules (int argc, char *argv[])
CK_RV rv;
int i;
- if (argc != 0)
- usage ();
-
rv = p11_kit_initialize_registered ();
- if (rv != CKR_OK)
- errx (1, "couldn't initialize registered modules: %s",
- p11_kit_strerror (rv));
+ if (rv != CKR_OK) {
+ p11_message ("couldn't initialize registered modules: %s",
+ p11_kit_strerror (rv));
+ return 1;
+ }
module_list = p11_kit_registered_modules ();
for (i = 0; module_list[i]; i++) {
@@ -225,8 +219,8 @@ list_modules (int argc, char *argv[])
path = p11_kit_registered_option (module_list[i], "module");
printf ("%s: %s\n",
- name ? name : "(null)",
- path ? path : "(null)");
+ name ? name : "(null)",
+ path ? path : "(null)");
print_module_info (module_list[i]);
free (name);
@@ -235,39 +229,64 @@ list_modules (int argc, char *argv[])
free (module_list);
p11_kit_finalize_registered ();
-
return 0;
}
int
-main (int argc, char *argv[])
+p11_tool_list_modules (int argc,
+ char *argv[])
{
- operation oper = NULL;
int opt;
- while ((opt = getopt (argc, argv, "hlv")) != -1) {
+ enum {
+ opt_verbose = 'v',
+ opt_quiet = 'q',
+ opt_list = 'l',
+ opt_help = 'h',
+ };
+
+ struct option options[] = {
+ { "verbose", no_argument, NULL, opt_verbose },
+ { "quiet", no_argument, NULL, opt_quiet },
+ { "list", no_argument, NULL, opt_list },
+ { "help", no_argument, NULL, opt_help },
+ { 0 },
+ };
+
+ p11_tool_desc usages[] = {
+ { 0, "usage: p11-kit list" },
+ { opt_verbose, "show verbose debug output", },
+ { opt_quiet, "supress command output", },
+ { 0 },
+ };
+
+ while ((opt = p11_tool_getopt (argc, argv, options)) != -1) {
switch (opt) {
- case 'l':
- if (oper != NULL)
- usage ();
- oper = list_modules;
- break;
- case 'v':
- verbose = true;
- putenv ("P11_KIT_DEBUG=all");
+
+ /* Ignore these options, already handled */
+ case opt_verbose:
+ case opt_quiet:
+ case opt_list:
break;
- case 'h':
+
+ case opt_help:
+ p11_tool_usage (usages, options);
+ return 0;
case '?':
- usage();
+ return 2;
+ default:
+ assert_not_reached ();
break;
}
}
- if (!oper)
- usage ();
-
argc -= optind;
argv += optind;
- return (oper) (argc, argv);
+ if (argc != 0) {
+ p11_message ("extra arguments specified");
+ return 2;
+ }
+
+ return print_modules ();
}
diff --git a/tools/tool.c b/tools/tool.c
new file mode 100644
index 0000000..92c5e70
--- /dev/null
+++ b/tools/tool.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2011, Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "buffer.h"
+#include "compat.h"
+#include "debug.h"
+#include "library.h"
+#include "p11-kit.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tool.h"
+
+struct {
+ const char *name;
+ int (*function) (int, char*[]);
+ const char *text;
+} commands[] = {
+ { "list-modules", p11_tool_list_modules, "List modules and tokens"},
+ { 0, }
+};
+
+static char
+short_option (int opt)
+{
+ if (isalpha (opt) || isdigit (opt))
+ return (char)opt;
+ return 0;
+}
+
+static const struct option *
+find_option (const struct option *longopts,
+ int opt)
+{
+ int i;
+
+ for (i = 0; longopts[i].name != NULL; i++) {
+ if (longopts[i].val == opt)
+ return longopts + i;
+ }
+
+ return NULL;
+}
+
+void
+p11_tool_usage (const p11_tool_desc *usages,
+ const struct option *longopts)
+{
+ const struct option *longopt;
+ const int indent = 22;
+ const char *long_name;
+ const char *description;
+ const char *next;
+ char short_name;
+ int spaces;
+ int len;
+ int i;
+
+ for (i = 0; usages[i].text != NULL; i++) {
+
+ /* If no option, then this is a heading */
+ if (!usages[i].option) {
+ printf ("%s\n\n", usages[i].text);
+ continue;
+ }
+
+ longopt = find_option (longopts, usages[i].option);
+ long_name = longopt ? longopt->name : NULL;
+ short_name = short_option (usages[i].option);
+ description = usages[i].text;
+
+ if (short_name && long_name)
+ len = printf (" -%c, --%s", (int)short_name, long_name);
+ else if (long_name)
+ len = printf (" --%s", long_name);
+ else
+ len = printf (" -%c", (int)short_name);
+ if (longopt->has_arg)
+ len += printf ("%s<%s>",
+ long_name ? "=" : " ",
+ usages[i].arg ? usages[i].arg : "...");
+ if (len < indent) {
+ spaces = indent - len;
+ } else {
+ printf ("\n");
+ spaces = indent;
+ }
+ while (description) {
+ while (spaces-- > 0)
+ fputc (' ', stdout);
+ next = strchr (description, '\n');
+ if (next) {
+ next += 1;
+ printf ("%.*s", (int)(next - description), description);
+ description = next;
+ spaces = indent;
+ } else {
+ printf ("%s\n", description);
+ break;
+ }
+ }
+
+ }
+}
+
+int
+p11_tool_getopt (int argc,
+ char *argv[],
+ const struct option *longopts)
+{
+ p11_buffer buf;
+ int ret;
+ char opt;
+ int i;
+
+ if (!p11_buffer_init_null (&buf, 64))
+ return_val_if_reached (-1);
+
+ for (i = 0; longopts[i].name != NULL; i++) {
+ opt = short_option (longopts[i].val);
+ if (opt != 0) {
+ p11_buffer_add (&buf, &opt, 1);
+ assert (longopts[i].has_arg != optional_argument);
+ if (longopts[i].has_arg == required_argument)
+ p11_buffer_add (&buf, ":", 1);
+ }
+ }
+
+ ret = getopt_long (argc, argv, buf.data, longopts, NULL);
+
+ p11_buffer_uninit (&buf);
+
+ return ret;
+}
+
+static void
+command_usage (void)
+{
+ int i;
+
+ printf ("usage: p11-kit command <args>...\n");
+ printf ("\nCommon p11-kit commands are:\n");
+ for (i = 0; commands[i].name != NULL; i++)
+ printf (" %-15s %s\n", commands[i].name, commands[i].text);
+ printf ("\nSee 'p11-kit <command> --help' for more information\n");
+}
+
+static void
+exec_external (const char *command,
+ int argc,
+ char *argv[])
+{
+ char *filename;
+ const char *path;
+ char *env;
+
+ if (!asprintf (&filename, "p11-kit-%s", command) < 0)
+ return_if_reached ();
+
+ /* Add our libexec directory to the path */
+ path = getenv ("PATH");
+ if (!asprintf (&env, "PATH=%s%s%s", path ? path : "", path ? ":" : "", PKGDATADIR))
+ return_if_reached ();
+ printf ("%s\n", env);
+ putenv (env);
+
+ argv[0] = filename;
+ execvp (filename, argv);
+}
+
+static void
+verbose_arg (void)
+{
+ putenv ("P11_KIT_DEBUG=all");
+ p11_kit_be_loud ();
+ p11_message_loud ();
+}
+
+static void
+quiet_arg (void)
+{
+ putenv ("P11_KIT_DEBUG=");
+ p11_kit_be_quiet ();
+ p11_message_quiet ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *command = NULL;
+ bool skip;
+ int in, out;
+ int i;
+
+ /*
+ * Parse the global options. We rearrange the options as
+ * necessary, in order to pass relevant options through
+ * to the commands, but also have them take effect globally.
+ */
+
+ for (in = 1, out = 1; in < argc; in++, out++) {
+ skip = false;
+
+ /* Already seen the command, keep the arguments */
+ if (command) {
+ skip = false;
+
+ /* The non-option is the command, take it out of the arguments */
+ } else if (argv[in][0] != '-') {
+ skip = true;
+ command = argv[in];
+
+ /* The global long options */
+ } else if (argv[in][1] == '-') {
+ skip = false;
+
+ if (strcmp (argv[in], "--") == 0) {
+ p11_message ("no command specified");
+ return 2;
+
+ } else if (strcmp (argv[in], "--verbose") == 0) {
+ verbose_arg ();
+
+ } else if (strcmp (argv[in], "--quiet") == 0) {
+ quiet_arg ();
+
+ } else if (strcmp (argv[in], "--help") == 0) {
+ command_usage ();
+ return 0;
+
+ } else {
+ p11_message ("unknown option: %s", argv[in]);
+ return 2;
+ }
+
+ /* The global short options */
+ } else {
+ skip = false;
+
+ for (i = 1; argv[in][i] != '\0'; i++) {
+ switch (argv[in][i]) {
+ case 'h':
+ command_usage ();
+ return 0;
+
+ /* Compatibility option */
+ case 'l':
+ command = "list-modules";
+ break;
+
+ case 'v':
+ verbose_arg ();
+ break;
+
+ case 'q':
+ quiet_arg ();
+ break;
+
+ default:
+ p11_message ("unknown option: -%c", (int)argv[in][i]);
+ return 2;
+ }
+ }
+ }
+
+ /* Skipping this argument? */
+ if (skip)
+ out--;
+ else
+ argv[out] = argv[in];
+ }
+
+ if (command == NULL) {
+ /* As a special favor if someone just typed 'p11-kit', help them out */
+ if (argc == 1)
+ command_usage ();
+ else
+ p11_message ("no command specified");
+ return 2;
+ }
+
+ argc = out;
+
+ /* Look for the command */
+ for (i = 0; commands[i].name != NULL; i++) {
+ if (strcmp (commands[i].name, command) == 0) {
+ argv[0] = command;
+ return (commands[i].function) (argc, argv);
+ }
+ }
+
+ /* Got here because no command matched */
+ exec_external (command, argc, argv);
+
+ /* At this point we have no command */
+ p11_message ("'%s' is not a valid p11-kit command. See 'p11-kit --help'", command);
+ return 2;
+}
diff --git a/tools/tool.h b/tools/tool.h
new file mode 100644
index 0000000..709e668
--- /dev/null
+++ b/tools/tool.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#ifndef P11_TOOL_H_
+#define P11_TOOL_H_
+
+#include <getopt.h>
+
+typedef struct {
+ int option;
+ const char *text;
+ const char *arg;
+} p11_tool_desc;
+
+int p11_tool_getopt (int argc,
+ char *argv[],
+ const struct option *longopts);
+
+void p11_tool_usage (const p11_tool_desc *usages,
+ const struct option *longopts);
+
+int p11_tool_list_modules (int argc,
+ char *argv[]);
+
+#endif /* P11_TOOL_H_ */