|
Packit Service |
779887 |
/*
|
|
Packit Service |
779887 |
Copyright (C) 2010 ABRT team
|
|
Packit Service |
779887 |
Copyright (C) 2010 RedHat Inc
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
779887 |
it under the terms of the GNU General Public License as published by
|
|
Packit Service |
779887 |
the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
779887 |
(at your option) any later version.
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
This program is distributed in the hope that it will be useful,
|
|
Packit Service |
779887 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
779887 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
779887 |
GNU General Public License for more details.
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
You should have received a copy of the GNU General Public License along
|
|
Packit Service |
779887 |
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit Service |
779887 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
779887 |
*/
|
|
Packit Service |
779887 |
#include <getopt.h>
|
|
Packit Service |
779887 |
#include "internal_libreport.h"
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
#define USAGE_OPTS_WIDTH 30
|
|
Packit Service |
779887 |
#define USAGE_GAP 2
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
const char *g_progname;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
const char *abrt_init(char **argv)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
if (!load_global_configuration())
|
|
Packit Service |
779887 |
error_msg_and_die("Cannot continue without libreport global configuration.");
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
char *env_verbose = getenv("ABRT_VERBOSE");
|
|
Packit Service |
779887 |
if (env_verbose)
|
|
Packit Service |
779887 |
g_verbose = atoi(env_verbose);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
g_progname = strrchr(argv[0], '/');
|
|
Packit Service |
779887 |
if (g_progname)
|
|
Packit Service |
779887 |
g_progname++;
|
|
Packit Service |
779887 |
else
|
|
Packit Service |
779887 |
g_progname = argv[0];
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
char *pfx = getenv("ABRT_PROG_PREFIX");
|
|
Packit Service |
779887 |
if (pfx && string_to_bool(pfx))
|
|
Packit Service |
779887 |
msg_prefix = g_progname;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
return g_progname;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
void export_abrt_envvars(int pfx)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
|
|
Packit Service |
779887 |
if (pfx)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
putenv((char*)"ABRT_PROG_PREFIX=1");
|
|
Packit Service |
779887 |
msg_prefix = g_progname;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
void show_usage_and_die(const char *usage, const struct options *opt)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
INITIALIZE_LIBREPORT();
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
fputs(_("Usage: "), stderr);
|
|
Packit Service |
779887 |
while (*usage)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
int len = strchrnul(usage, '&') - usage;
|
|
Packit Service |
779887 |
if (len > 0)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
fprintf(stderr, "%.*s", len, usage);
|
|
Packit Service |
779887 |
usage += len;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
if (*usage == '&')
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
/* Only '&' *followed by whitespace* is substituted
|
|
Packit Service |
779887 |
* with program name - all other &'s are printed literally.
|
|
Packit Service |
779887 |
*/
|
|
Packit Service |
779887 |
if (usage[1] == '\0' || isspace(usage[1]))
|
|
Packit Service |
779887 |
fputs(g_progname, stderr);
|
|
Packit Service |
779887 |
else
|
|
Packit Service |
779887 |
fputc('&', stderr);
|
|
Packit Service |
779887 |
usage++;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
fputs("\n\n", stderr);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
for (; opt->type != OPTION_END; opt++)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
size_t pos;
|
|
Packit Service |
779887 |
int pad;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (opt->type == OPTION_GROUP)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
fputc('\n', stderr);
|
|
Packit Service |
779887 |
if (*opt->help)
|
|
Packit Service |
779887 |
fprintf(stderr, "%s\n", opt->help);
|
|
Packit Service |
779887 |
continue;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
pos = fprintf(stderr, " ");
|
|
Packit Service |
779887 |
if (opt->short_name)
|
|
Packit Service |
779887 |
pos += fprintf(stderr, "-%c", opt->short_name);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (opt->short_name && opt->long_name)
|
|
Packit Service |
779887 |
pos += fprintf(stderr, ", ");
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (opt->long_name)
|
|
Packit Service |
779887 |
pos += fprintf(stderr, "--%s", opt->long_name);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (opt->argh)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
const char *fmt = " %s";
|
|
Packit Service |
779887 |
if (opt->type == OPTION_OPTSTRING)
|
|
Packit Service |
779887 |
fmt = "[%s]";
|
|
Packit Service |
779887 |
pos += fprintf(stderr, fmt, opt->argh);
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (pos <= USAGE_OPTS_WIDTH)
|
|
Packit Service |
779887 |
pad = USAGE_OPTS_WIDTH - pos;
|
|
Packit Service |
779887 |
else
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
fputc('\n', stderr);
|
|
Packit Service |
779887 |
pad = USAGE_OPTS_WIDTH;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opt->help);
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
fputc('\n', stderr);
|
|
Packit Service |
779887 |
xfunc_die();
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
static int parse_opt_size(const struct options *opt)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
unsigned size = 0;
|
|
Packit Service |
779887 |
for (; opt->type != OPTION_END; opt++)
|
|
Packit Service |
779887 |
size++;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
return size;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
unsigned parse_opts(int argc, char **argv, const struct options *opt,
|
|
Packit Service |
779887 |
const char *usage)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
int help = 0;
|
|
Packit Service |
779887 |
int size = parse_opt_size(opt);
|
|
Packit Service |
779887 |
const int LONGOPT_OFFSET = 256;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
struct strbuf *shortopts = strbuf_new();
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
struct option *longopts = xzalloc(sizeof(longopts[0]) * (size+2));
|
|
Packit Service |
779887 |
struct option *curopt = longopts;
|
|
Packit Service |
779887 |
int ii;
|
|
Packit Service |
779887 |
for (ii = 0; ii < size; ++ii)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
curopt->name = opt[ii].long_name;
|
|
Packit Service |
779887 |
/*curopt->flag = 0; - xzalloc did it */
|
|
Packit Service |
779887 |
if (opt[ii].short_name)
|
|
Packit Service |
779887 |
curopt->val = opt[ii].short_name;
|
|
Packit Service |
779887 |
else
|
|
Packit Service |
779887 |
curopt->val = LONGOPT_OFFSET + ii;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
switch (opt[ii].type)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
case OPTION_BOOL:
|
|
Packit Service |
779887 |
curopt->has_arg = no_argument;
|
|
Packit Service |
779887 |
if (opt[ii].short_name)
|
|
Packit Service |
779887 |
strbuf_append_char(shortopts, opt[ii].short_name);
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_INTEGER:
|
|
Packit Service |
779887 |
case OPTION_STRING:
|
|
Packit Service |
779887 |
case OPTION_LIST:
|
|
Packit Service |
779887 |
curopt->has_arg = required_argument;
|
|
Packit Service |
779887 |
if (opt[ii].short_name)
|
|
Packit Service |
779887 |
strbuf_append_strf(shortopts, "%c:", opt[ii].short_name);
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_OPTSTRING:
|
|
Packit Service |
779887 |
curopt->has_arg = optional_argument;
|
|
Packit Service |
779887 |
if (opt[ii].short_name)
|
|
Packit Service |
779887 |
strbuf_append_strf(shortopts, "%c::", opt[ii].short_name);
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_GROUP:
|
|
Packit Service |
779887 |
case OPTION_END:
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
//log_warning("curopt[%d].name:'%s' .has_arg:%d .flag:%p .val:%d", (int)(curopt-longopts),
|
|
Packit Service |
779887 |
// curopt->name, curopt->has_arg, curopt->flag, curopt->val);
|
|
Packit Service |
779887 |
/*
|
|
Packit Service |
779887 |
* getopt_long() thinks that NULL name marks the end of longopts.
|
|
Packit Service |
779887 |
* Example:
|
|
Packit Service |
779887 |
* [0] name:'verbose' val:'v'
|
|
Packit Service |
779887 |
* [1] name:NULL val:'c'
|
|
Packit Service |
779887 |
* [2] name:'force' val:'f'
|
|
Packit Service |
779887 |
* ... ... ...
|
|
Packit Service |
779887 |
* In this case, --force won't be accepted!
|
|
Packit Service |
779887 |
* Therefore we can only advance if name is not NULL.
|
|
Packit Service |
779887 |
*/
|
|
Packit Service |
779887 |
if (curopt->name)
|
|
Packit Service |
779887 |
curopt++;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
curopt->name = "help";
|
|
Packit Service |
779887 |
curopt->has_arg = no_argument;
|
|
Packit Service |
779887 |
curopt->flag = &help;
|
|
Packit Service |
779887 |
curopt->val = 1;
|
|
Packit Service |
779887 |
/* xzalloc did it already:
|
|
Packit Service |
779887 |
curopt++;
|
|
Packit Service |
779887 |
curopt->name = NULL;
|
|
Packit Service |
779887 |
curopt->has_arg = 0;
|
|
Packit Service |
779887 |
curopt->flag = NULL;
|
|
Packit Service |
779887 |
curopt->val = 0;
|
|
Packit Service |
779887 |
*/
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
unsigned retval = 0;
|
|
Packit Service |
779887 |
while (1)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
int c = getopt_long(argc, argv, shortopts->buf, longopts, NULL);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (c == -1)
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (c == '?' || help)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
free(longopts);
|
|
Packit Service |
779887 |
strbuf_free(shortopts);
|
|
Packit Service |
779887 |
xfunc_error_retval = 0; /* this isn't error, exit code = 0 */
|
|
Packit Service |
779887 |
show_usage_and_die(usage, opt);
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
for (ii = 0; ii < size; ++ii)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
if (opt[ii].short_name == c || LONGOPT_OFFSET + ii == c)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
if (ii < sizeof(retval)*8)
|
|
Packit Service |
779887 |
retval |= (1 << ii);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
if (opt[ii].value != NULL) switch (opt[ii].type)
|
|
Packit Service |
779887 |
{
|
|
Packit Service |
779887 |
case OPTION_BOOL:
|
|
Packit Service |
779887 |
*(int*)(opt[ii].value) += 1;
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_INTEGER:
|
|
Packit Service |
779887 |
*(int*)(opt[ii].value) = xatoi(optarg);
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_STRING:
|
|
Packit Service |
779887 |
case OPTION_OPTSTRING:
|
|
Packit Service |
779887 |
if (optarg)
|
|
Packit Service |
779887 |
*(char**)(opt[ii].value) = (char*)optarg;
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_LIST:
|
|
Packit Service |
779887 |
*(GList**)(opt[ii].value) = g_list_append(*(GList**)(opt[ii].value), optarg);
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
case OPTION_GROUP:
|
|
Packit Service |
779887 |
case OPTION_END:
|
|
Packit Service |
779887 |
break;
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
}
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
free(longopts);
|
|
Packit Service |
779887 |
strbuf_free(shortopts);
|
|
Packit Service |
779887 |
|
|
Packit Service |
779887 |
return retval;
|
|
Packit Service |
779887 |
}
|