summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikola Pajkovsky <npajkovs@redhat.com>2010-10-04 16:08:58 +0200
committerNikola Pajkovsky <npajkovs@redhat.com>2010-10-04 16:08:58 +0200
commitaacc4082c747557a04627b304fce07ca7cdae8b2 (patch)
tree9ad3fad4ff72e31f35019c7453aa84a805fb3f83
parent1ae327bd0df1eb621fc6a9b4d8b81f10bf7f019d (diff)
parent97ced498a972810547d2e87cbbce932593b1bc40 (diff)
downloadabrt-aacc4082c747557a04627b304fce07ca7cdae8b2.tar.gz
abrt-aacc4082c747557a04627b304fce07ca7cdae8b2.tar.xz
abrt-aacc4082c747557a04627b304fce07ca7cdae8b2.zip
Merge branch 'new-parser'
* new-parser: Daemon.cpp: remove getopt and use parse_opts instead new args parser xfunc.c: add new funtion xcalloc
-rw-r--r--inc/xfuncs.h1
-rw-r--r--lib/utils/Makefile.am3
-rw-r--r--lib/utils/parse_options.c130
-rw-r--r--lib/utils/parse_options.h37
-rw-r--r--lib/utils/xfuncs.c8
-rw-r--r--src/daemon/Daemon.cpp65
6 files changed, 212 insertions, 32 deletions
diff --git a/inc/xfuncs.h b/inc/xfuncs.h
index 0be1f801..20284564 100644
--- a/inc/xfuncs.h
+++ b/inc/xfuncs.h
@@ -33,6 +33,7 @@ int ndelay_on(int fd);
int ndelay_off(int fd);
int close_on_exec_on(int fd);
+void* xcalloc(size_t nmemb, size_t size);
void* xmalloc(size_t size);
void* xrealloc(void *ptr, size_t size);
void* xzalloc(size_t size);
diff --git a/lib/utils/Makefile.am b/lib/utils/Makefile.am
index 1e104821..ac5f4837 100644
--- a/lib/utils/Makefile.am
+++ b/lib/utils/Makefile.am
@@ -33,7 +33,8 @@ libABRTUtils_la_SOURCES = \
abrt_packages.c abrt_packages.h \
hooklib.c hooklib.h \
sha1.c sha1.h \
- database.c
+ database.c \
+ parse_options.c parse_options.h
libABRTUtils_la_CPPFLAGS = \
-Wall -Werror \
-I$(srcdir)/../../inc \
diff --git a/lib/utils/parse_options.c b/lib/utils/parse_options.c
new file mode 100644
index 00000000..6928e481
--- /dev/null
+++ b/lib/utils/parse_options.c
@@ -0,0 +1,130 @@
+
+#include <getopt.h>
+#include "abrtlib.h"
+#include "parse_options.h"
+
+static int parse_opt_size(const struct options *opt)
+{
+ unsigned size = 1;
+ for (; opt->type != OPTION_END; opt++)
+ size++;
+
+ return size;
+}
+
+#define USAGE_OPTS_WIDTH 24
+#define USAGE_GAP 2
+
+void parse_usage_and_die(const char * const * usage, const struct options *opt)
+{
+ fprintf(stderr, _("usage: %s\n"), *usage++);
+
+ while (*usage && **usage)
+ fprintf(stderr, _(" or: %s\n"), *usage++);
+
+ fputc('\n', stderr);
+
+ for (; opt->type != OPTION_END; opt++)
+ {
+ size_t pos;
+ int pad;
+
+ pos = fprintf(stderr, " ");
+ if (opt->short_name)
+ pos += fprintf(stderr, "-%c", opt->short_name);
+
+ if (opt->short_name && opt->long_name)
+ pos += fprintf(stderr, ", ");
+
+ if (opt->long_name)
+ pos += fprintf(stderr, "--%s", opt->long_name);
+
+ if (pos <= USAGE_OPTS_WIDTH)
+ pad = USAGE_OPTS_WIDTH - pos;
+ else
+ {
+ fputc('\n', stderr);
+ pad = USAGE_OPTS_WIDTH;
+ }
+ fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opt->help);
+ }
+ fputc('\n', stderr);
+ exit(1);
+}
+
+void parse_opts(int argc, char **argv, const struct options *opt,
+ const char * const usage[])
+{
+ int size = parse_opt_size(opt);
+
+ struct strbuf *shortopts = strbuf_new();
+
+ struct option *longopts = xcalloc(sizeof(struct options), size);
+ int ii;
+ for (ii = 0; ii < size - 1; ++ii)
+ {
+ longopts[ii].name = opt[ii].long_name;
+
+ switch (opt[ii].type)
+ {
+ case OPTION_BOOL:
+ longopts[ii].has_arg = no_argument;
+ if (opt[ii].short_name)
+ strbuf_append_char(shortopts, opt[ii].short_name);
+ break;
+ case OPTION_STRING:
+ longopts[ii].has_arg = required_argument;
+ if (opt[ii].short_name)
+ strbuf_append_strf(shortopts, "%c:", opt[ii].short_name);
+ break;
+ case OPTION_END:
+ break;
+ }
+ longopts[ii].flag = 0;
+ longopts[ii].val = opt[ii].short_name;
+ }
+
+ longopts[ii].name = 0;
+ longopts[ii].has_arg = 0;
+ longopts[ii].flag = 0;
+ longopts[ii].val = 0;
+
+ int option_index = 0;
+ while (1)
+ {
+ int c = getopt_long(argc, argv, shortopts->buf, longopts, &option_index);
+
+ if (c == -1)
+ break;
+
+ if (c == '?')
+ {
+ free(longopts);
+ strbuf_free(shortopts);
+ parse_usage_and_die(usage, opt);
+ }
+
+ for (ii = 0; ii < size - 1; ++ii)
+ {
+ if (opt[ii].short_name == c)
+ {
+
+ switch (opt[ii].type)
+ {
+ case OPTION_BOOL:
+ *(int*)opt[ii].value += 1;
+ break;
+ case OPTION_STRING:
+ if (optarg)
+ *(char**)opt[ii].value = (char*)optarg;
+ break;
+ case OPTION_END:
+ break;
+ }
+ }
+ }
+ }
+
+ free(longopts);
+ strbuf_free(shortopts);
+}
diff --git a/lib/utils/parse_options.h b/lib/utils/parse_options.h
new file mode 100644
index 00000000..fe76a7f3
--- /dev/null
+++ b/lib/utils/parse_options.h
@@ -0,0 +1,37 @@
+
+#ifndef PARSE_OPTIONS_H
+#define PARSE_OPTIONS_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum parse_opt_type {
+ OPTION_BOOL,
+ OPTION_STRING,
+ OPTION_END,
+};
+
+struct options {
+ enum parse_opt_type type;
+ int short_name;
+ const char *long_name;
+ void *value;
+ const char *help;
+};
+
+#define OPT_END() { OPTION_END }
+#define OPT_BOOL(s, l, v, h) { OPTION_BOOL, (s), (l), (v), (h) }
+#define OPT_STRING(s, l, v, h) { OPTION_STRING, (s), (l), (v), (h) }
+
+void parse_opts(int argc, char **argv, const struct options *opt,
+ const char * const usage[]);
+
+void parse_usage_and_die(const char * const * usage, const struct options *opt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/utils/xfuncs.c b/lib/utils/xfuncs.c
index 71796371..214ce426 100644
--- a/lib/utils/xfuncs.c
+++ b/lib/utils/xfuncs.c
@@ -39,6 +39,14 @@ int close_on_exec_on(int fd)
return fcntl(fd, F_SETFD, FD_CLOEXEC);
}
+void *xcalloc(size_t nmemb, size_t size)
+{
+ void *ptr = calloc(nmemb, size);
+ if (!ptr && nmemb && size)
+ die_out_of_memory();
+ return ptr;
+}
+
// Die if we can't allocate size bytes of memory.
void* xmalloc(size_t size)
{
diff --git a/src/daemon/Daemon.cpp b/src/daemon/Daemon.cpp
index f54acde0..85c984f3 100644
--- a/src/daemon/Daemon.cpp
+++ b/src/daemon/Daemon.cpp
@@ -33,6 +33,7 @@
#include "abrt_exception.h"
#include "CrashWatcher.h"
#include "Daemon.h"
+#include "parse_options.h"
using namespace std;
@@ -84,6 +85,10 @@ using namespace std;
* Both are sent as unicast to last client set by set_client_name(name).
* If set_client_name(NULL) was done, they are not sent.
*/
+static const char * const abrtd_usage[] = {
+ _("abrtd [options]"),
+ NULL
+};
CCommLayerServer* g_pCommLayer;
@@ -854,9 +859,20 @@ static void sanitize_dump_dir_rights()
ensure_writable_dir(VAR_RUN"/abrt", 0755, "root");
}
+static int daemonize_opt, syslog_opt, help_opt;
+static char *timeout_opt;
+
+static struct options abrtd_options[] = {
+ OPT_BOOL( 'h' , "help", &help_opt, _("Show this help message")),
+ OPT_BOOL( 'd' , 0, &daemonize_opt, _("Do not daemonize")),
+ OPT_BOOL( 's' , 0, &syslog_opt, _("Log to syslog even with -d")),
+ OPT_STRING( 't' , 0, &timeout_opt, _("Exit after SEC seconds of inactivity")),
+ OPT_BOOL( 'v' , 0, &g_verbose, _("Verbose")),
+ OPT_END()
+};
+
int main(int argc, char** argv)
{
- int opt;
int parent_pid = getpid();
setlocale(LC_ALL, "");
@@ -873,38 +889,25 @@ int main(int argc, char** argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
- while ((opt = getopt(argc, argv, "dsvt:")) != -1)
+ parse_opts(argc, argv, abrtd_options, abrtd_usage);
+
+ if (help_opt)
+ parse_usage_and_die(abrtd_usage, abrtd_options);
+
+ if (daemonize_opt)
+ daemonize = false;
+
+ if (syslog_opt)
+ start_syslog_logging();
+
+ if (timeout_opt)
{
unsigned long ul;
-
- switch (opt)
- {
- case 'd':
- daemonize = false;
- break;
- case 's':
- start_syslog_logging();
- break;
- case 'v':
- g_verbose++;
- break;
- case 't':
- char *end;
- errno = 0;
- s_timeout = ul = strtoul(optarg, &end, 0);
- if (errno == 0 && *end == '\0' && ul <= INT_MAX)
- break;
- /* fall through to error */
- default:
- error_msg_and_die(
- "Usage: abrtd [-dsv] [-t SEC]\n"
- "\nOptions:"
- "\n\t-d\tDo not daemonize"
- "\n\t-s\tLog to syslog even with -d"
- "\n\t-t SEC\tExit after SEC seconds of inactivity"
- "\n\t-v\tVerbose"
- );
- }
+ char *end;
+ errno = 0;
+ s_timeout = ul = strtoul(timeout_opt, &end, 0);
+ if (!(errno == 0 && *end == '\0' && ul <= INT_MAX))
+ parse_usage_and_die(abrtd_usage, abrtd_options);
}
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));