SHA256
1
0
forked from pool/s390-tools
s390-tools/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch
2017-02-21 11:14:26 +00:00

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;
+}