diff options
author | Nikola Pajkovsky <npajkovs@redhat.com> | 2010-10-04 16:08:58 +0200 |
---|---|---|
committer | Nikola Pajkovsky <npajkovs@redhat.com> | 2010-10-04 16:08:58 +0200 |
commit | aacc4082c747557a04627b304fce07ca7cdae8b2 (patch) | |
tree | 9ad3fad4ff72e31f35019c7453aa84a805fb3f83 | |
parent | 1ae327bd0df1eb621fc6a9b4d8b81f10bf7f019d (diff) | |
parent | 97ced498a972810547d2e87cbbce932593b1bc40 (diff) | |
download | abrt-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.h | 1 | ||||
-rw-r--r-- | lib/utils/Makefile.am | 3 | ||||
-rw-r--r-- | lib/utils/parse_options.c | 130 | ||||
-rw-r--r-- | lib/utils/parse_options.h | 37 | ||||
-rw-r--r-- | lib/utils/xfuncs.c | 8 | ||||
-rw-r--r-- | src/daemon/Daemon.cpp | 65 |
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)); |