forked from pool/s390-tools
Marcus Meissner
9b729e2acc
New package per "Factory first" policy. Please list me as bug owner and maintainer, if possible. OBS-URL: https://build.opensuse.org/request/show/459343 OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=1
1054 lines
25 KiB
Diff
1054 lines
25 KiB
Diff
Subject: [PATCH] [FEAT RTL1601] libutil: Add utility functions
|
|
From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
|
|
|
|
Summary: libutil: Add utility functions
|
|
Description: Introduce utility functions for use by s390-tools.
|
|
Upstream-ID: -
|
|
Problem-ID: RTL1601
|
|
|
|
Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
|
|
---
|
|
include/util_base.h | 2
|
|
include/util_libc.h | 125 +++++++++++++++++++
|
|
include/util_opt.h | 82 ++++++++++++
|
|
include/util_panic.h | 45 ++++++
|
|
include/util_prg.h | 55 ++++++++
|
|
libutil/Makefile | 11 +
|
|
libutil/util_libc.c | 155 +++++++++++++++++++++++
|
|
libutil/util_opt.c | 281 +++++++++++++++++++++++++++++++++++++++++++
|
|
libutil/util_panic.c | 119 ++++++++++++++++++
|
|
libutil/util_prg.c | 111 ++++++++++++++++
|
|
10 files changed, 985 insertions(+), 1 deletion(-)
|
|
|
|
--- a/include/util_base.h
|
|
+++ b/include/util_base.h
|
|
@@ -15,4 +15,6 @@ void util_hexdump(FILE *fh, const char *
|
|
void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group,
|
|
int cnt, int indent);
|
|
|
|
+#define UTIL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
|
+
|
|
#endif /* UTIL_BASE_H */
|
|
--- /dev/null
|
|
+++ b/include/util_libc.h
|
|
@@ -0,0 +1,125 @@
|
|
+/**
|
|
+ * @defgroup util_libc_h util_libc: Libc wrapper interface
|
|
+ * @{
|
|
+ * @brief Handle standard errors for libc functions
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#ifndef UTIL_LIBC_H
|
|
+#define UTIL_LIBC_H
|
|
+
|
|
+#include <stdio.h>
|
|
+
|
|
+/**
|
|
+ * Allocate memory or panic in case of failure
|
|
+ *
|
|
+ * @param[in] size Number of bytes to be allocated
|
|
+ *
|
|
+ * @returns Pointer to allocated memory buffer
|
|
+ */
|
|
+#define util_malloc(size) \
|
|
+ __util_malloc(__func__, __FILE__, __LINE__, size)
|
|
+
|
|
+void *__util_malloc(const char *func, const char *file, int line, size_t size);
|
|
+
|
|
+/**
|
|
+ * Allocate zero-initialized memory or panic in case of failure
|
|
+ *
|
|
+ * @param[in] size Number of bytes to be allocated
|
|
+ *
|
|
+ * @returns Pointer to allocated memory buffer initialized with zeroes
|
|
+ */
|
|
+#define util_zalloc(size) \
|
|
+ __util_zalloc(__func__, __FILE__, __LINE__, size)
|
|
+
|
|
+void *__util_zalloc(const char *func, const char *file, int line, size_t size);
|
|
+
|
|
+
|
|
+/**
|
|
+ * Re-allocate memory or exit in case of failure
|
|
+ *
|
|
+ * @param[in] ptr Pointer ot old memory buffer
|
|
+ * @param[in] size Number of bytes to be allocated
|
|
+ *
|
|
+ * @returns Pointer to allocated memory buffer
|
|
+ */
|
|
+#define util_realloc(ptr, size) \
|
|
+ __util_realloc(__func__, __FILE__, __LINE__, ptr, size)
|
|
+
|
|
+void *__util_realloc(const char *func, const char *file, int line,
|
|
+ void *ptr, size_t size);
|
|
+
|
|
+/**
|
|
+ * Duplicate a string buffer or exit in case of failure
|
|
+ *
|
|
+ * @param[in] str String to be duplicated
|
|
+ *
|
|
+ * @returns Pointer to newly allocated and copied string
|
|
+ */
|
|
+#define util_strdup(str) \
|
|
+ __util_strdup(__func__, __FILE__, __LINE__, str)
|
|
+
|
|
+void *__util_strdup(const char *func, const char *file, int line,
|
|
+ const char *str);
|
|
+
|
|
+/**
|
|
+ * Print to allocated string or exit in case of failure
|
|
+ *
|
|
+ * @param[in] strp String to be allocated
|
|
+ * @param[in] fmt Format string for generation of string
|
|
+ * @param[in] ap Parameters for format string
|
|
+ *
|
|
+ * @returns num Number of formatted characters
|
|
+ */
|
|
+#define util_vasprintf(strp, fmt, ap) \
|
|
+ __util_vasprintf(__func__, __FILE__, __LINE__, strp, fmt, ap)
|
|
+
|
|
+#define UTIL_VASPRINTF(strp, fmt, ap) \
|
|
+do { \
|
|
+ va_start(ap, fmt); \
|
|
+ util_vasprintf(strp, fmt, ap); \
|
|
+ va_end(ap); \
|
|
+} while (0)
|
|
+
|
|
+int __util_vasprintf(const char *func, const char *file, int line,
|
|
+ char **strp, const char *fmt, va_list ap);
|
|
+
|
|
+/**
|
|
+ * Print to newly allocated string or exit in case of failure
|
|
+ *
|
|
+ * @param[in] strp String to be allocated
|
|
+ * @param[in] ... Format string and parameters for format string
|
|
+ *
|
|
+ * @returns num Number of formatted characters
|
|
+ */
|
|
+#define util_asprintf(strp, ...) \
|
|
+ __util_asprintf(__func__, __FILE__, __LINE__, strp, ##__VA_ARGS__)
|
|
+
|
|
+int __util_asprintf(const char *func, const char *file, int line,
|
|
+ char **strp, const char *fmt, ...);
|
|
+
|
|
+
|
|
+/**
|
|
+ * Print to string buffer or exit in case of failure
|
|
+ *
|
|
+ * @param[in] str String buffer
|
|
+ * @param[in] fmt Format string for generation of string
|
|
+ * @param[in] ap Parameters for format string
|
|
+ *
|
|
+ * @returns num Number of formatted characters
|
|
+ */
|
|
+#define util_vsprintf(str, fmt, ap) \
|
|
+ __util_vsprintf(__func__, __FILE__, __LINE__, str, fmt, ap)
|
|
+
|
|
+#define UTIL_VSPRINTF(str, fmt, ap) \
|
|
+do { \
|
|
+ va_start(ap, fmt); \
|
|
+ util_vsprintf(str, fmt, ap); \
|
|
+ va_end(ap); \
|
|
+} while (0)
|
|
+
|
|
+int __util_vsprintf(const char *func, const char *file, int line,
|
|
+ char *str, const char *fmt, va_list ap);
|
|
+
|
|
+#endif /** UTIL_LIBC_H @} */
|
|
--- /dev/null
|
|
+++ b/include/util_opt.h
|
|
@@ -0,0 +1,82 @@
|
|
+/**
|
|
+ * @defgroup util_opt_h util_opt: Command line options interface
|
|
+ * @{
|
|
+ * @brief Parse the command line options
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#ifndef UTIL_OPT_H
|
|
+#define UTIL_OPT_H
|
|
+
|
|
+#include <getopt.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+/* Flag indicating that an option does not have a short form */
|
|
+#define UTIL_OPT_FLAG_NOSHORT 1
|
|
+
|
|
+/* Flag indicating that an option does not have a long form */
|
|
+#define UTIL_OPT_FLAG_NOLONG 2
|
|
+
|
|
+/* Flag indicating that this is a section heading */
|
|
+#define UTIL_OPT_FLAG_SECTION 4
|
|
+
|
|
+/**
|
|
+ * Command line option
|
|
+ */
|
|
+struct util_opt {
|
|
+ /** Defined by getopt.h, see "man getopt_long" */
|
|
+ struct option option;
|
|
+ /** For options with arguments: Argument name */
|
|
+ char *argument;
|
|
+ /** Description displayed for --help */
|
|
+ char *desc;
|
|
+ /** Flags for this option */
|
|
+ int flags;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Standard option: --help
|
|
+ */
|
|
+#define UTIL_OPT_HELP \
|
|
+{ \
|
|
+ .option = { "help", 0, NULL, 'h' }, \
|
|
+ .desc = "Print this help, then exit", \
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Standard option: --version
|
|
+ */
|
|
+#define UTIL_OPT_VERSION \
|
|
+{ \
|
|
+ .option = { "version", 0, NULL, 'v' }, \
|
|
+ .desc = "Print version information, then exit", \
|
|
+}
|
|
+
|
|
+/**
|
|
+ * End-marker for the option pointer vector
|
|
+ */
|
|
+#define UTIL_OPT_END \
|
|
+{ \
|
|
+ .option = { NULL, 0, NULL, 0 }, \
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Section header
|
|
+ */
|
|
+#define UTIL_OPT_SECTION(title) \
|
|
+{ \
|
|
+ .desc = (title), \
|
|
+ .flags = UTIL_OPT_FLAG_SECTION, \
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Option functions
|
|
+ */
|
|
+void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix);
|
|
+int util_opt_getopt_long(int argc, char *argv[]);
|
|
+void util_opt_print_help(void);
|
|
+void util_opt_print_indented(const char *opt, const char *desc);
|
|
+void util_opt_print_parse_error(char opt, char *argv[]);
|
|
+
|
|
+#endif /** UTIL_OPT_H @} */
|
|
--- /dev/null
|
|
+++ b/include/util_panic.h
|
|
@@ -0,0 +1,45 @@
|
|
+/**
|
|
+ * @defgroup util_panic_h util_panic: Panic interface
|
|
+ * @{
|
|
+ * @brief Collect FFDC data for unexpected errors
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#ifndef UTIL_PANIC_H
|
|
+#define UTIL_PANIC_H
|
|
+
|
|
+#include "zt_common.h"
|
|
+
|
|
+#ifndef __noreturn
|
|
+#define __noreturn
|
|
+#endif
|
|
+
|
|
+/**
|
|
+ * Write message, print backtrace and then call the abort() function
|
|
+ *
|
|
+ * @param[in] ... Format string and parameters describing the panic reason
|
|
+ */
|
|
+#define util_panic(...) \
|
|
+ __util_panic(__func__, __FILE__, __LINE__, ##__VA_ARGS__)
|
|
+
|
|
+void __util_panic(const char *func, const char *file, int line,
|
|
+ const char *fmt, ...) __noreturn;
|
|
+
|
|
+/**
|
|
+ * Ensure that assumption is not true, otherwise panic
|
|
+ *
|
|
+ * Example: util_assert(ptr == NULL, "The ptr must be NULL, but is %p", ptr)
|
|
+ *
|
|
+ * @param[in] assumption This assumption has to be true
|
|
+ * @param[in] ... Format string and parameters describing the assumption
|
|
+ */
|
|
+#define util_assert(assumption, ...) \
|
|
+ __util_assert(#assumption, __func__, __FILE__, __LINE__, \
|
|
+ assumption, ##__VA_ARGS__)
|
|
+
|
|
+void __util_assert(const char *assertion_string,
|
|
+ const char *func, const char *file, int line,
|
|
+ int assumption, const char *fmt, ...);
|
|
+
|
|
+#endif /** UTIL_PANIC_H @} */
|
|
--- /dev/null
|
|
+++ b/include/util_prg.h
|
|
@@ -0,0 +1,55 @@
|
|
+/**
|
|
+ * @defgroup util_prg_h util_prg: Program interface
|
|
+ * @{
|
|
+ * @brief Print standard program messages
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#ifndef UTIL_PRG_H
|
|
+#define UTIL_PRG_H
|
|
+
|
|
+#include <err.h>
|
|
+#include <limits.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+
|
|
+/**
|
|
+ * Copyright description
|
|
+ */
|
|
+struct util_prg_copyright {
|
|
+ /** Name of the copyright owner, e.g. IBM */
|
|
+ const char *owner;
|
|
+ /** Year of first publishing */
|
|
+ int pub_first;
|
|
+ /** Year of last major changes */
|
|
+ int pub_last;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * @brief Coypright end marker
|
|
+ */
|
|
+#define UTIL_PRG_COPYRIGHT_END {NULL, 0, 0}
|
|
+
|
|
+/**
|
|
+ * Program description
|
|
+ */
|
|
+struct util_prg {
|
|
+ /** Description for help */
|
|
+ const char *desc;
|
|
+ /** Positional arguments */
|
|
+ const char *args;
|
|
+ /** Copyright list */
|
|
+ struct util_prg_copyright copyright_vec[];
|
|
+};
|
|
+
|
|
+void util_prg_init(const struct util_prg *prg);
|
|
+void util_prg_print_parse_error(void);
|
|
+void util_prg_print_required_arg(const char *option);
|
|
+void util_prg_print_invalid_option(const char *option);
|
|
+void util_prg_print_arg_error(const char *arg_name);
|
|
+void util_prg_print_version(void);
|
|
+void util_prg_print_help(void);
|
|
+
|
|
+#endif /** UTIL_PRG_H @} */
|
|
--- a/libutil/Makefile
|
|
+++ b/libutil/Makefile
|
|
@@ -2,12 +2,21 @@ include ../common.mak
|
|
|
|
CPPFLAGS += -I../include
|
|
|
|
-all: util_base.o util_list.o util_part.o util_proc.o
|
|
+all: util_base.o util_list.o util_part.o util_proc.o util_libc.o util_opt.o \
|
|
+ util_panic.o util_prg.o
|
|
|
|
util_list.o: util_list.c ../include/util.h
|
|
|
|
util_proc.o: util_proc.c ../include/util_proc.h
|
|
|
|
+util_libc.o: util_libc.c ../include/util_libc.h
|
|
+
|
|
+util_opt.o: util_opt.c ../include/util_opt.h
|
|
+
|
|
+util_panic.o: util_panic.c ../include/util_panic.h
|
|
+
|
|
+util_prg.o: util_prg.c ../include/util_prg.h
|
|
+
|
|
install: all
|
|
|
|
clean:
|
|
--- /dev/null
|
|
+++ b/libutil/util_libc.c
|
|
@@ -0,0 +1,155 @@
|
|
+/*
|
|
+ * util - Utility function library
|
|
+ *
|
|
+ * Handle standard errors for libc functions
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#define _GNU_SOURCE /* for program_invocation_short_name */
|
|
+
|
|
+#include <errno.h>
|
|
+#include <stdarg.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include "util_base.h"
|
|
+#include "util_panic.h"
|
|
+#include "util_libc.h"
|
|
+
|
|
+/*
|
|
+ * Return size as string of largest unit, e.g. 1025 = "1 KiB"
|
|
+ */
|
|
+static void format_size(char *str, size_t size)
|
|
+{
|
|
+ static const char * const unit_vec[] =
|
|
+ {"byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < UTIL_ARRAY_SIZE(unit_vec); i++) {
|
|
+ if (size / 1024 == 0) {
|
|
+ sprintf(str, "%zu %s", size, unit_vec[i]);
|
|
+ return;
|
|
+ }
|
|
+ size /= 1024;
|
|
+ }
|
|
+ sprintf(str, "huge");
|
|
+}
|
|
+
|
|
+static void __util_oom(const char *func, const char *file, int line,
|
|
+ size_t size)
|
|
+{
|
|
+ char size_str[256];
|
|
+
|
|
+ fprintf(stderr, "%s: Failed to allocate memory",
|
|
+ program_invocation_short_name);
|
|
+ if (size > 0) {
|
|
+ format_size(size_str, size);
|
|
+ fprintf(stderr, " (%s)", size_str);
|
|
+ }
|
|
+ fprintf(stderr, " at %s:%d %s()\n", file, line, func);
|
|
+ exit(EXIT_FAILURE);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Allocate memory or exit in case of failure
|
|
+ */
|
|
+void *__util_malloc(const char *func, const char *file, int line, size_t size)
|
|
+{
|
|
+ void *buf;
|
|
+
|
|
+ buf = malloc(size);
|
|
+
|
|
+ if (buf == NULL)
|
|
+ __util_oom(func, file, line, size);
|
|
+
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Allocate zero-initialized memory or exit in case of failure
|
|
+ */
|
|
+void *__util_zalloc(const char *func, const char *file, int line, size_t size)
|
|
+{
|
|
+ void *buf = __util_malloc(func, file, line, size);
|
|
+
|
|
+ memset(buf, 0, size);
|
|
+
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Re-allocate memory or exit in case of failure
|
|
+ */
|
|
+void *__util_realloc(const char *func, const char *file, int line,
|
|
+ void *ptr, size_t size)
|
|
+{
|
|
+ void *buf;
|
|
+
|
|
+ buf = realloc(ptr, size);
|
|
+
|
|
+ if (buf == NULL)
|
|
+ __util_oom(func, file, line, size);
|
|
+
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Duplicate a string buffer or exit in case of failure
|
|
+ */
|
|
+void *__util_strdup(const char *func, const char *file, int line,
|
|
+ const char *str)
|
|
+{
|
|
+ void *buf = strdup(str);
|
|
+
|
|
+ if (buf == NULL)
|
|
+ __util_oom(func, file, line, strlen(str) + 1);
|
|
+
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print to newly allocated string or exit in case of failure
|
|
+ */
|
|
+int __util_vasprintf(const char *func, const char *file, int line,
|
|
+ char **strp, const char *fmt, va_list ap)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = vasprintf(strp, fmt, ap);
|
|
+ if (rc == -1)
|
|
+ __util_oom(func, file, line, 0);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print to newly allocated string or exit in case of failure
|
|
+ */
|
|
+int __util_asprintf(const char *func, const char *file, int line,
|
|
+ char **strp, const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+ int rc;
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ rc = __util_vasprintf(func, file, line, strp, fmt, ap);
|
|
+ va_end(ap);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print to string buffer or exit in case of failure
|
|
+ */
|
|
+int __util_vsprintf(const char *func, const char *file, int line,
|
|
+ char *str, const char *fmt, va_list ap)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = vsprintf(str, fmt, ap);
|
|
+ if (rc == -1)
|
|
+ __util_assert("rc != -1", func, file, line,
|
|
+ rc != -1, "Could not format string\n");
|
|
+ return rc;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/libutil/util_opt.c
|
|
@@ -0,0 +1,281 @@
|
|
+/*
|
|
+ * util - Utility function library
|
|
+ *
|
|
+ * Parse the command line options
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#include <argz.h>
|
|
+#include <libgen.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include "util_base.h"
|
|
+#include "util_libc.h"
|
|
+#include "util_opt.h"
|
|
+#include "util_panic.h"
|
|
+#include "util_prg.h"
|
|
+
|
|
+/*
|
|
+ * Private data
|
|
+ */
|
|
+/// @cond
|
|
+static struct util_opt_l {
|
|
+ /* Option character string for getopt_long() */
|
|
+ char *opt_str;
|
|
+ /* Option array for getopt_long() */
|
|
+ struct option *option_vec;
|
|
+ /* Original util_opt array */
|
|
+ struct util_opt *opt_vec;
|
|
+ /* Length of longest option string */
|
|
+ int opt_max;
|
|
+} l;
|
|
+
|
|
+struct util_opt_l *util_opt_l = &l;
|
|
+/// @endcond
|
|
+
|
|
+#define util_opt_iterate(opt) \
|
|
+ for (opt = &l.opt_vec[0]; opt->desc != NULL; opt++)
|
|
+
|
|
+#define MAX(x, y) ((x) < (y) ? (y) : (x))
|
|
+#define MAX_OPTLEN 256
|
|
+
|
|
+static int opt_max_len(void);
|
|
+
|
|
+/**
|
|
+ * Initialize the command line options
|
|
+ *
|
|
+ * Build short option string and long option array to be used for getopt_long().
|
|
+ * The ":" prefix is added to the short option string for handling of "missing
|
|
+ * required arguments".
|
|
+ *
|
|
+ * @param[in] opt_vec Option array
|
|
+ * @param[in] opt_prefix Optional option string prefix
|
|
+ */
|
|
+void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix)
|
|
+{
|
|
+ int i, j, count;
|
|
+ char *str;
|
|
+ size_t prefix_len = opt_prefix ? strlen(opt_prefix) : 0;
|
|
+
|
|
+ opterr = 0;
|
|
+ /* Get number of options */
|
|
+ for (count = 0; opt_vec[count].desc != NULL; count++);
|
|
+ /*
|
|
+ * Allocate short option string for worst case when all options have
|
|
+ * optional parameters e.g "x::" and long option string.
|
|
+ */
|
|
+ l.opt_str = util_malloc(sizeof(char) * count * 3 + 2 + prefix_len);
|
|
+ l.option_vec = util_malloc(sizeof(struct option) * (count + 1));
|
|
+ l.opt_vec = opt_vec;
|
|
+
|
|
+ str = l.opt_str;
|
|
+ if (opt_prefix) {
|
|
+ strcpy(str, opt_prefix);
|
|
+ str += prefix_len;
|
|
+ }
|
|
+ /* Force getopt_long() to return ':' for missing required arguments */
|
|
+ *str++ = ':';
|
|
+ /* Construction of input structures for getopt_long() function. */
|
|
+ for (i = 0, j = 0; i < count; i++) {
|
|
+ if (opt_vec[i].flags & UTIL_OPT_FLAG_SECTION)
|
|
+ continue;
|
|
+ memcpy(&l.option_vec[j++], &opt_vec[i].option,
|
|
+ sizeof(struct option));
|
|
+ if (opt_vec[i].flags & UTIL_OPT_FLAG_NOSHORT)
|
|
+ continue;
|
|
+ *str++ = opt_vec[i].option.val;
|
|
+ switch (opt_vec[i].option.has_arg) {
|
|
+ case no_argument:
|
|
+ break;
|
|
+ case required_argument:
|
|
+ *str++ = ':';
|
|
+ break;
|
|
+ case optional_argument:
|
|
+ *str++ = ':';
|
|
+ *str++ = ':';
|
|
+ break;
|
|
+ default:
|
|
+ util_panic("Unexpected \"has_arg\" parameter: %d\n",
|
|
+ opt_vec[i].option.has_arg);
|
|
+ }
|
|
+ }
|
|
+ /* Add end marker to option array and short option string */
|
|
+ memset(&l.option_vec[j], 0, sizeof(struct option));
|
|
+ *str = '\0';
|
|
+
|
|
+ l.opt_max = opt_max_len();
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Wrapper for getopt_long
|
|
+ *
|
|
+ * @param[in] argc Count of command line parameters
|
|
+ * @param[in] argv Array of command line parameters
|
|
+ */
|
|
+int util_opt_getopt_long(int argc, char *argv[])
|
|
+{
|
|
+ return getopt_long(argc, argv, l.opt_str, l.option_vec, NULL);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Format option name: Add short, long option and argument (as applicable)
|
|
+ */
|
|
+static void format_opt(char *buf, size_t maxlen, const struct util_opt *opt)
|
|
+{
|
|
+ int has_arg, flags, rc;
|
|
+ char val, *arg_str;
|
|
+ const char *name;
|
|
+
|
|
+ has_arg = opt->option.has_arg;
|
|
+ name = opt->option.name;
|
|
+ val = opt->option.val;
|
|
+ flags = opt->flags;
|
|
+
|
|
+ /* Prepare potential option argument string */
|
|
+ if (has_arg == optional_argument) {
|
|
+ if (flags & UTIL_OPT_FLAG_NOLONG)
|
|
+ util_asprintf(&arg_str, "[%s]", opt->argument);
|
|
+ else
|
|
+ util_asprintf(&arg_str, "[=%s]", opt->argument);
|
|
+ } else if (has_arg == required_argument) {
|
|
+ util_asprintf(&arg_str, " %s", opt->argument);
|
|
+ } else {
|
|
+ util_asprintf(&arg_str, "");
|
|
+ }
|
|
+
|
|
+ /* Format the option */
|
|
+ if (flags & UTIL_OPT_FLAG_NOLONG)
|
|
+ rc = snprintf(buf, maxlen, "-%c%s", val, arg_str);
|
|
+ else if (flags & UTIL_OPT_FLAG_NOSHORT)
|
|
+ rc = snprintf(buf, maxlen, " --%s%s", name, arg_str);
|
|
+ else
|
|
+ rc = snprintf(buf, maxlen, "-%c, --%s%s", val, name, arg_str);
|
|
+
|
|
+ util_assert(rc < (int)maxlen, "Option too long: %s\n", name);
|
|
+ free(arg_str);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Return size of the longest formatted option
|
|
+ */
|
|
+static int opt_max_len(void)
|
|
+{
|
|
+ const struct util_opt *opt;
|
|
+ unsigned int max = 0;
|
|
+ char opt_str[MAX_OPTLEN];
|
|
+
|
|
+ util_opt_iterate(opt) {
|
|
+ if (opt->flags & UTIL_OPT_FLAG_SECTION)
|
|
+ continue;
|
|
+ format_opt(opt_str, MAX_OPTLEN, opt);
|
|
+ max = MAX(max, strlen(opt_str));
|
|
+ }
|
|
+ return max;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print option description with indentation
|
|
+ */
|
|
+static void print_opt_description(const char *desc_in, int indent)
|
|
+{
|
|
+ char *word, *line, *desc, *desc_ptr;
|
|
+ int word_len, pos = indent;
|
|
+
|
|
+ desc = desc_ptr = util_strdup(desc_in);
|
|
+ line = strsep(&desc, "\n");
|
|
+ while (line) {
|
|
+ word = strsep(&line, " ");
|
|
+ pos = indent;
|
|
+ while (word) {
|
|
+ word_len = strlen(word);
|
|
+ if (pos + word_len + 1 > 80) {
|
|
+ printf("\n%*s", indent, " ");
|
|
+ pos = indent;
|
|
+ }
|
|
+ printf(" %s", word);
|
|
+ pos += word_len + 1;
|
|
+ word = strsep(&line, " ");
|
|
+ }
|
|
+ if (desc)
|
|
+ printf("\n%*s", indent, " ");
|
|
+ line = strsep(&desc, "\n");
|
|
+ }
|
|
+ printf("\n");
|
|
+ free(desc_ptr);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Print an option name, followed by a description indented to fit the
|
|
+ * longest option name
|
|
+ */
|
|
+void util_opt_print_indented(const char *opt, const char *desc)
|
|
+{
|
|
+ printf(" %-*s ", l.opt_max, opt);
|
|
+ print_opt_description(desc, 2 + l.opt_max);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Print the usage of the command line options to the console
|
|
+ */
|
|
+void util_opt_print_help(void)
|
|
+{
|
|
+ char opt_str[MAX_OPTLEN];
|
|
+ struct util_opt *opt;
|
|
+ int first = 1;
|
|
+
|
|
+ /*
|
|
+ * Create format string: " -%c, --%-<long opt size>s %s"
|
|
+ *
|
|
+ * Example:
|
|
+ *
|
|
+ * -p, --print STRING Print STRING to console
|
|
+ */
|
|
+ util_opt_iterate(opt) {
|
|
+ if (opt->flags & UTIL_OPT_FLAG_SECTION) {
|
|
+ printf("%s%s\n", first ? "" : "\n", opt->desc);
|
|
+ first = 0;
|
|
+ continue;
|
|
+ }
|
|
+ format_opt(opt_str, MAX_OPTLEN, opt);
|
|
+ util_opt_print_indented(opt_str, opt->desc);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Print option parsing error message
|
|
+ *
|
|
+ * This function should be used when the return code of the
|
|
+ * util_opt_getopt_long() function returns a character that does
|
|
+ * not match any of the expected options.
|
|
+ *
|
|
+ * @param[in] opt Short option returned by getopt_long()
|
|
+ * @param[in] argv Option array
|
|
+ */
|
|
+void util_opt_print_parse_error(char opt, char *argv[])
|
|
+{
|
|
+ char optopt_str[3];
|
|
+
|
|
+ switch (opt) {
|
|
+ case ':':
|
|
+ /* A required option argument has not been specified */
|
|
+ util_prg_print_required_arg(argv[optind - 1]);
|
|
+ break;
|
|
+ case '?':
|
|
+ /* An invalid option has been specified */
|
|
+ if (optopt) {
|
|
+ /* Short option */
|
|
+ sprintf(optopt_str, "-%c", optopt);
|
|
+ util_prg_print_invalid_option(optopt_str);
|
|
+ } else {
|
|
+ /* Long option */
|
|
+ util_prg_print_invalid_option(argv[optind - 1]);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ util_panic("Option '%c' should not be handled here\n", opt);
|
|
+ }
|
|
+}
|
|
+
|
|
--- /dev/null
|
|
+++ b/libutil/util_panic.c
|
|
@@ -0,0 +1,119 @@
|
|
+/*
|
|
+ * util - Utility function library
|
|
+ *
|
|
+ * Collect FFDC data for unexpected errors
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#include <sys/resource.h>
|
|
+#include <sys/time.h>
|
|
+
|
|
+#include <execinfo.h>
|
|
+#include <stdarg.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+
|
|
+#include "util_base.h"
|
|
+#include "util_panic.h"
|
|
+
|
|
+/*
|
|
+ * Obtain a backtrace and print it to stderr
|
|
+ *
|
|
+ * To get symbols, compile the code with "-rdynamic".
|
|
+ */
|
|
+static void print_backtrace(void)
|
|
+{
|
|
+ void *array[256];
|
|
+ size_t i, size;
|
|
+ char **strings;
|
|
+
|
|
+ fprintf(stderr, "Backtrace:\n\n");
|
|
+ size = backtrace(array, UTIL_ARRAY_SIZE(array));
|
|
+ strings = backtrace_symbols(array, size);
|
|
+ if (strings == NULL) {
|
|
+ fprintf(stderr, " Could not obtain backtrace (ENOMEM)\n");
|
|
+ return;
|
|
+ }
|
|
+ for (i = 0; i < size; i++)
|
|
+ fprintf(stderr, " %s\n", strings[i]);
|
|
+
|
|
+ free(strings);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Check for core ulimit
|
|
+ */
|
|
+static void ulimit_core_check(void)
|
|
+{
|
|
+ struct rlimit limit;
|
|
+
|
|
+ if (getrlimit(RLIMIT_CORE, &limit) != 0)
|
|
+ return;
|
|
+ if (limit.rlim_cur != 0)
|
|
+ return;
|
|
+ fprintf(stderr, "Core dump size is zero. To get a full core dump use 'ulimit -c unlimited'.\n");
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print FFDC data and then abort
|
|
+ */
|
|
+static void panic_finish(const char *func, const char *file, int line,
|
|
+ const char *fmt, va_list ap)
|
|
+{
|
|
+ /* Write panic error string */
|
|
+ fprintf(stderr, "\n");
|
|
+ fprintf(stderr, "Error string:\n");
|
|
+ fprintf(stderr, "\n");
|
|
+ fprintf(stderr, " ");
|
|
+ vfprintf(stderr, fmt, ap);
|
|
+ fprintf(stderr, "\n");
|
|
+ /* Write file, line number, and function name */
|
|
+ fprintf(stderr, "Location:\n\n");
|
|
+ fprintf(stderr, " %s:%d: %s()\n", file, line, func);
|
|
+ fprintf(stderr, "\n");
|
|
+
|
|
+ /* Print the function backtrace */
|
|
+ print_backtrace();
|
|
+ fprintf(stderr, "\n");
|
|
+
|
|
+ ulimit_core_check();
|
|
+ fprintf(stderr, "----------------------------------------------------------------------->8-----\n");
|
|
+ abort();
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Do panic processing if the assumption is not true
|
|
+ */
|
|
+void __util_assert(const char *assertion_str,
|
|
+ const char *func, const char *file, int line,
|
|
+ int assumption, const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+ if (assumption)
|
|
+ return;
|
|
+ va_start(ap, fmt);
|
|
+ fprintf(stderr, "---8<-------------------------------------------------------------------------\n");
|
|
+ fprintf(stderr, "ASSERTION FAILED: The application terminated due to an internal or OS error\n");
|
|
+ fprintf(stderr, "\n");
|
|
+ fprintf(stderr, "The following assumption was *not* true:\n");
|
|
+ fprintf(stderr, "\n");
|
|
+ fprintf(stderr, " %s\n", assertion_str);
|
|
+ panic_finish(func, file, line, fmt, ap);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Do panic processing
|
|
+ */
|
|
+void __util_panic(const char *func, const char *file, int line,
|
|
+ const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ fprintf(stderr, "---8<-------------------------------------------------------------------------\n");
|
|
+ fprintf(stderr, "PANIC: The application terminated due to an unrecoverable error\n");
|
|
+ panic_finish(func, file, line, fmt, ap);
|
|
+ while(1);
|
|
+}
|
|
--- /dev/null
|
|
+++ b/libutil/util_prg.c
|
|
@@ -0,0 +1,111 @@
|
|
+/*
|
|
+ * util - Utility function library
|
|
+ *
|
|
+ * Print standard program messages
|
|
+ *
|
|
+ * Copyright IBM Corp. 2016
|
|
+ */
|
|
+
|
|
+#define _GNU_SOURCE /* for program_invocation_short_name */
|
|
+
|
|
+#include <errno.h>
|
|
+#include <stdio.h>
|
|
+
|
|
+#include "util_prg.h"
|
|
+#include "zt_common.h"
|
|
+
|
|
+/*
|
|
+ * Private data
|
|
+ */
|
|
+static struct util_prg_l {
|
|
+ const struct util_prg *prg;
|
|
+} l;
|
|
+
|
|
+struct util_prg_l *util_prg_l = &l;
|
|
+
|
|
+/**
|
|
+ * Print program usage information for the --help option
|
|
+ */
|
|
+void util_prg_print_help(void)
|
|
+{
|
|
+ printf("Usage: %s [OPTIONS]", program_invocation_short_name);
|
|
+ if (l.prg->args)
|
|
+ printf(" %s", l.prg->args);
|
|
+ printf("\n\n%s\n\n", l.prg->desc);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Print program version information for the --version option
|
|
+ */
|
|
+void util_prg_print_version(void)
|
|
+{
|
|
+ const struct util_prg_copyright *copyright;
|
|
+
|
|
+ printf("%s version %s\n", program_invocation_short_name,
|
|
+ RELEASE_STRING);
|
|
+ copyright = l.prg->copyright_vec;
|
|
+ while (copyright->owner) {
|
|
+ if (copyright->pub_first == copyright->pub_last)
|
|
+ printf("Copyright %s %d\n", copyright->owner,
|
|
+ copyright->pub_first);
|
|
+ else
|
|
+ printf("Copyright %s %d, %d\n", copyright->owner,
|
|
+ copyright->pub_first, copyright->pub_last);
|
|
+ copyright++;
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Ask user to use the --help option
|
|
+ */
|
|
+void util_prg_print_parse_error(void)
|
|
+{
|
|
+ fprintf(stderr, "Try '%s --help' for more information.\n",
|
|
+ program_invocation_short_name);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * An option has been specified that is not supported
|
|
+ *
|
|
+ * @param[in] option Option string (short or long)
|
|
+ */
|
|
+void util_prg_print_invalid_option(const char *opt_name)
|
|
+{
|
|
+ fprintf(stderr, "%s: Invalid option '%s'\n",
|
|
+ program_invocation_short_name, opt_name);
|
|
+ util_prg_print_parse_error();
|
|
+}
|
|
+
|
|
+/**
|
|
+ * A required argument for an option is missing
|
|
+ *
|
|
+ * @param[in] option Option string
|
|
+ */
|
|
+void util_prg_print_required_arg(const char *opt_name)
|
|
+{
|
|
+ fprintf(stderr, "%s: Option '%s' requires an argument\n",
|
|
+ program_invocation_short_name, opt_name);
|
|
+ util_prg_print_parse_error();
|
|
+}
|
|
+
|
|
+/**
|
|
+ * A superfluous invalid positional argument has been specified
|
|
+ *
|
|
+ * @param[in] arg_name Name of the invalid argument
|
|
+ */
|
|
+void util_prg_print_arg_error(const char *arg_name)
|
|
+{
|
|
+ fprintf(stderr, "%s: Invalid argument '%s'\n",
|
|
+ program_invocation_short_name, arg_name);
|
|
+ util_prg_print_parse_error();
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Initialize the program module
|
|
+ *
|
|
+ * @param[in] prg Program description
|
|
+ */
|
|
+void util_prg_init(const struct util_prg *prg)
|
|
+{
|
|
+ l.prg = prg;
|
|
+}
|