|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* Copyright (c) 2011, Collabora Ltd.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
3749ba |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
3749ba |
* are met:
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* * Redistributions of source code must retain the above
|
|
Packit Service |
3749ba |
* copyright notice, this list of conditions and the
|
|
Packit Service |
3749ba |
* following disclaimer.
|
|
Packit Service |
3749ba |
* * Redistributions in binary form must reproduce the
|
|
Packit Service |
3749ba |
* above copyright notice, this list of conditions and
|
|
Packit Service |
3749ba |
* the following disclaimer in the documentation and/or
|
|
Packit Service |
3749ba |
* other materials provided with the distribution.
|
|
Packit Service |
3749ba |
* * The names of contributors to this software may not be
|
|
Packit Service |
3749ba |
* used to endorse or promote products derived from this
|
|
Packit Service |
3749ba |
* software without specific prior written permission.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit Service |
3749ba |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit Service |
3749ba |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
Packit Service |
3749ba |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
Packit Service |
3749ba |
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
Packit Service |
3749ba |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
Packit Service |
3749ba |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
Packit Service |
3749ba |
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
Packit Service |
3749ba |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit Service |
3749ba |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
Packit Service |
3749ba |
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
Packit Service |
3749ba |
* DAMAGE.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* Author: Stef Walter <stefw@collabora.co.uk>
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "config.h"
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "buffer.h"
|
|
Packit Service |
3749ba |
#include "compat.h"
|
|
Packit Service |
3749ba |
#include "debug.h"
|
|
Packit Service |
3749ba |
#include "message.h"
|
|
Packit Service |
3749ba |
#include "path.h"
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include <assert.h>
|
|
Packit Service |
3749ba |
#include <ctype.h>
|
|
Packit Service |
3749ba |
#include <getopt.h>
|
|
Packit Service |
3749ba |
#include <string.h>
|
|
Packit Service |
3749ba |
#include <stdio.h>
|
|
Packit Service |
3749ba |
#include <stdlib.h>
|
|
Packit Service |
3749ba |
#include <unistd.h>
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "tool.h"
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static char
|
|
Packit Service |
3749ba |
short_option (int opt)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
if (isalpha (opt) || isdigit (opt))
|
|
Packit Service |
3749ba |
return (char)opt;
|
|
Packit Service |
3749ba |
return 0;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static const struct option *
|
|
Packit Service |
3749ba |
find_option (const struct option *longopts,
|
|
Packit Service |
3749ba |
int opt)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (i = 0; longopts[i].name != NULL; i++) {
|
|
Packit Service |
3749ba |
if (longopts[i].val == opt)
|
|
Packit Service |
3749ba |
return longopts + i;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return NULL;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
void
|
|
Packit Service |
3749ba |
p11_tool_usage (const p11_tool_desc *usages,
|
|
Packit Service |
3749ba |
const struct option *longopts)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
const struct option *longopt;
|
|
Packit Service |
3749ba |
const int indent = 22;
|
|
Packit Service |
3749ba |
const char *long_name;
|
|
Packit Service |
3749ba |
const char *description;
|
|
Packit Service |
3749ba |
const char *next;
|
|
Packit Service |
3749ba |
char short_name;
|
|
Packit Service |
3749ba |
int spaces;
|
|
Packit Service |
3749ba |
int len;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (i = 0; usages[i].text != NULL; i++) {
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* If no option, then this is a heading */
|
|
Packit Service |
3749ba |
if (!usages[i].option) {
|
|
Packit Service |
3749ba |
printf ("%s\n\n", usages[i].text);
|
|
Packit Service |
3749ba |
continue;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
longopt = find_option (longopts, usages[i].option);
|
|
Packit Service |
3749ba |
long_name = longopt ? longopt->name : NULL;
|
|
Packit Service |
3749ba |
short_name = short_option (usages[i].option);
|
|
Packit Service |
3749ba |
description = usages[i].text;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (short_name && long_name)
|
|
Packit Service |
3749ba |
len = printf (" -%c, --%s", (int)short_name, long_name);
|
|
Packit Service |
3749ba |
else if (long_name)
|
|
Packit Service |
3749ba |
len = printf (" --%s", long_name);
|
|
Packit Service |
3749ba |
else
|
|
Packit Service |
3749ba |
len = printf (" -%c", (int)short_name);
|
|
Packit Service |
3749ba |
if (longopt && longopt->has_arg)
|
|
Packit Service |
3749ba |
len += printf ("%s<%s>",
|
|
Packit Service |
3749ba |
long_name ? "=" : " ",
|
|
Packit Service |
3749ba |
usages[i].arg ? usages[i].arg : "...");
|
|
Packit Service |
3749ba |
if (len < indent) {
|
|
Packit Service |
3749ba |
spaces = indent - len;
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
printf ("\n");
|
|
Packit Service |
3749ba |
spaces = indent;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
while (description) {
|
|
Packit Service |
3749ba |
while (spaces-- > 0)
|
|
Packit Service |
3749ba |
fputc (' ', stdout);
|
|
Packit Service |
3749ba |
next = strchr (description, '\n');
|
|
Packit Service |
3749ba |
if (next) {
|
|
Packit Service |
3749ba |
next += 1;
|
|
Packit Service |
3749ba |
printf ("%.*s", (int)(next - description), description);
|
|
Packit Service |
3749ba |
description = next;
|
|
Packit Service |
3749ba |
spaces = indent;
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
printf ("%s\n", description);
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_tool_getopt (int argc,
|
|
Packit Service |
3749ba |
char *argv[],
|
|
Packit Service |
3749ba |
const struct option *longopts)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_buffer buf;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
char opt;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (!p11_buffer_init_null (&buf, 64))
|
|
Packit Service |
3749ba |
return_val_if_reached (-1);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (i = 0; longopts[i].name != NULL; i++) {
|
|
Packit Service |
3749ba |
opt = short_option (longopts[i].val);
|
|
Packit Service |
3749ba |
if (opt != 0) {
|
|
Packit Service |
3749ba |
p11_buffer_add (&buf, &opt, 1);
|
|
Packit Service |
3749ba |
assert (longopts[i].has_arg != optional_argument);
|
|
Packit Service |
3749ba |
if (longopts[i].has_arg == required_argument)
|
|
Packit Service |
3749ba |
p11_buffer_add (&buf, ":", 1);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = getopt_long (argc, argv, buf.data, longopts, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_buffer_uninit (&buf;;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return ret;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
command_usage (const p11_tool_command *commands)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
const char *progname;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
progname = getprogname ();
|
|
Packit Service |
3749ba |
printf ("usage: %s command <args>...\n", progname);
|
|
Packit Service |
3749ba |
printf ("\nCommon %s commands are:\n", progname);
|
|
Packit Service |
3749ba |
for (i = 0; commands[i].name != NULL; i++) {
|
|
Packit Service |
3749ba |
if (strcmp (commands[i].name, P11_TOOL_FALLBACK) != 0)
|
|
Packit Service |
3749ba |
printf (" %-15s %s\n", commands[i].name, commands[i].text);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
printf ("\nSee '%s <command> --help' for more information\n", progname);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
verbose_arg (void)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
setenv ("P11_KIT_DEBUG", "tool", 0);
|
|
Packit Service |
3749ba |
p11_message_loud ();
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
quiet_arg (void)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
setenv ("P11_KIT_DEBUG", "", 1);
|
|
Packit Service |
3749ba |
p11_message_quiet ();
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_tool_main (int argc,
|
|
Packit Service |
3749ba |
char *argv[],
|
|
Packit Service |
3749ba |
const p11_tool_command *commands)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
const p11_tool_command *fallback = NULL;
|
|
Packit Service |
3749ba |
char *command = NULL;
|
|
Packit Service |
3749ba |
bool want_help = false;
|
|
Packit Service |
3749ba |
bool skip;
|
|
Packit Service |
3749ba |
int in, out;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Print messages by default. */
|
|
Packit Service |
3749ba |
p11_message_loud ();
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* Parse the global options. We rearrange the options as
|
|
Packit Service |
3749ba |
* necessary, in order to pass relevant options through
|
|
Packit Service |
3749ba |
* to the commands, but also have them take effect globally.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (in = 1, out = 1; in < argc; in++, out++) {
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* The non-option is the command, take it out of the arguments */
|
|
Packit Service |
3749ba |
if (argv[in][0] != '-') {
|
|
Packit Service |
3749ba |
if (!command) {
|
|
Packit Service |
3749ba |
skip = true;
|
|
Packit Service |
3749ba |
command = argv[in];
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
skip = false;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* The global long options */
|
|
Packit Service |
3749ba |
} else if (argv[in][1] == '-') {
|
|
Packit Service |
3749ba |
skip = false;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (strcmp (argv[in], "--") == 0) {
|
|
Packit Service |
3749ba |
if (!command) {
|
|
Packit Service |
3749ba |
p11_message ("no command specified");
|
|
Packit Service |
3749ba |
return 2;
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else if (strcmp (argv[in], "--verbose") == 0) {
|
|
Packit Service |
3749ba |
verbose_arg ();
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else if (strcmp (argv[in], "--quiet") == 0) {
|
|
Packit Service |
3749ba |
quiet_arg ();
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else if (strcmp (argv[in], "--help") == 0) {
|
|
Packit Service |
3749ba |
want_help = true;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else if (!command) {
|
|
Packit Service |
3749ba |
p11_message ("unknown global option: %s", argv[in]);
|
|
Packit Service |
3749ba |
return 2;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* The global short options */
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
skip = false;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (i = 1; argv[in][i] != '\0'; i++) {
|
|
Packit Service |
3749ba |
switch (argv[in][i]) {
|
|
Packit Service |
3749ba |
case 'h':
|
|
Packit Service |
3749ba |
want_help = true;
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Compatibility option */
|
|
Packit Service |
3749ba |
case 'l':
|
|
Packit Service |
3749ba |
command = "list-modules";
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
case 'v':
|
|
Packit Service |
3749ba |
verbose_arg ();
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
case 'q':
|
|
Packit Service |
3749ba |
quiet_arg ();
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
default:
|
|
Packit Service |
3749ba |
if (!command) {
|
|
Packit Service |
3749ba |
p11_message ("unknown global option: -%c", (int)argv[in][i]);
|
|
Packit Service |
3749ba |
return 2;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Skipping this argument? */
|
|
Packit Service |
3749ba |
if (skip)
|
|
Packit Service |
3749ba |
out--;
|
|
Packit Service |
3749ba |
else
|
|
Packit Service |
3749ba |
argv[out] = argv[in];
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Initialize tool's debugging after setting env vars above */
|
|
Packit Service |
3749ba |
p11_debug_init ();
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (command == NULL) {
|
|
Packit Service |
3749ba |
/* As a special favor if someone just typed the command, help them out */
|
|
Packit Service |
3749ba |
if (argc == 1) {
|
|
Packit Service |
3749ba |
command_usage (commands);
|
|
Packit Service |
3749ba |
return 2;
|
|
Packit Service |
3749ba |
} else if (want_help) {
|
|
Packit Service |
3749ba |
command_usage (commands);
|
|
Packit Service |
3749ba |
return 0;
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
p11_message ("no command specified");
|
|
Packit Service |
3749ba |
return 2;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
argc = out;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Look for the command */
|
|
Packit Service |
3749ba |
for (i = 0; commands[i].name != NULL; i++) {
|
|
Packit Service |
3749ba |
if (strcmp (commands[i].name, P11_TOOL_FALLBACK) == 0) {
|
|
Packit Service |
3749ba |
fallback = commands + i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else if (strcmp (commands[i].name, command) == 0) {
|
|
Packit Service |
3749ba |
argv[0] = command;
|
|
Packit Service |
3749ba |
return (commands[i].function) (argc, argv);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Got here because no command matched */
|
|
Packit Service |
3749ba |
if (fallback != NULL) {
|
|
Packit Service |
3749ba |
argv[0] = command;
|
|
Packit Service |
3749ba |
return (fallback->function) (argc, argv);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* At this point we have no command */
|
|
Packit Service |
3749ba |
p11_message ("'%s' is not a valid command. See '%s --help'",
|
|
Packit Service |
3749ba |
command, getprogname ());
|
|
Packit Service |
3749ba |
return 2;
|
|
Packit Service |
3749ba |
}
|