usage.con commit am: fix signoff when other trailers are present (735285b)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "git-compat-util.h"
   7#include "cache.h"
   8
   9void vreportf(const char *prefix, const char *err, va_list params)
  10{
  11        char msg[4096];
  12        char *p;
  13
  14        vsnprintf(msg, sizeof(msg), err, params);
  15        for (p = msg; *p; p++) {
  16                if (iscntrl(*p) && *p != '\t' && *p != '\n')
  17                        *p = '?';
  18        }
  19        fprintf(stderr, "%s%s\n", prefix, msg);
  20}
  21
  22static NORETURN void usage_builtin(const char *err, va_list params)
  23{
  24        vreportf("usage: ", err, params);
  25        exit(129);
  26}
  27
  28static NORETURN void die_builtin(const char *err, va_list params)
  29{
  30        vreportf("fatal: ", err, params);
  31        exit(128);
  32}
  33
  34static void error_builtin(const char *err, va_list params)
  35{
  36        vreportf("error: ", err, params);
  37}
  38
  39static void warn_builtin(const char *warn, va_list params)
  40{
  41        vreportf("warning: ", warn, params);
  42}
  43
  44static int die_is_recursing_builtin(void)
  45{
  46        static int dying;
  47        return dying++;
  48}
  49
  50/* If we are in a dlopen()ed .so write to a global variable would segfault
  51 * (ugh), so keep things static. */
  52static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = usage_builtin;
  53static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin;
  54static void (*error_routine)(const char *err, va_list params) = error_builtin;
  55static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
  56static int (*die_is_recursing)(void) = die_is_recursing_builtin;
  57
  58void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params))
  59{
  60        die_routine = routine;
  61}
  62
  63void set_error_routine(void (*routine)(const char *err, va_list params))
  64{
  65        error_routine = routine;
  66}
  67
  68void (*get_error_routine(void))(const char *err, va_list params)
  69{
  70        return error_routine;
  71}
  72
  73void set_warn_routine(void (*routine)(const char *warn, va_list params))
  74{
  75        warn_routine = routine;
  76}
  77
  78void (*get_warn_routine(void))(const char *warn, va_list params)
  79{
  80        return warn_routine;
  81}
  82
  83void set_die_is_recursing_routine(int (*routine)(void))
  84{
  85        die_is_recursing = routine;
  86}
  87
  88void NORETURN usagef(const char *err, ...)
  89{
  90        va_list params;
  91
  92        va_start(params, err);
  93        usage_routine(err, params);
  94        va_end(params);
  95}
  96
  97void NORETURN usage(const char *err)
  98{
  99        usagef("%s", err);
 100}
 101
 102void NORETURN die(const char *err, ...)
 103{
 104        va_list params;
 105
 106        if (die_is_recursing()) {
 107                fputs("fatal: recursion detected in die handler\n", stderr);
 108                exit(128);
 109        }
 110
 111        va_start(params, err);
 112        die_routine(err, params);
 113        va_end(params);
 114}
 115
 116static const char *fmt_with_err(char *buf, int n, const char *fmt)
 117{
 118        char str_error[256], *err;
 119        int i, j;
 120
 121        err = strerror(errno);
 122        for (i = j = 0; err[i] && j < sizeof(str_error) - 1; ) {
 123                if ((str_error[j++] = err[i++]) != '%')
 124                        continue;
 125                if (j < sizeof(str_error) - 1) {
 126                        str_error[j++] = '%';
 127                } else {
 128                        /* No room to double the '%', so we overwrite it with
 129                         * '\0' below */
 130                        j--;
 131                        break;
 132                }
 133        }
 134        str_error[j] = 0;
 135        snprintf(buf, n, "%s: %s", fmt, str_error);
 136        return buf;
 137}
 138
 139void NORETURN die_errno(const char *fmt, ...)
 140{
 141        char buf[1024];
 142        va_list params;
 143
 144        if (die_is_recursing()) {
 145                fputs("fatal: recursion detected in die_errno handler\n",
 146                        stderr);
 147                exit(128);
 148        }
 149
 150        va_start(params, fmt);
 151        die_routine(fmt_with_err(buf, sizeof(buf), fmt), params);
 152        va_end(params);
 153}
 154
 155#undef error_errno
 156int error_errno(const char *fmt, ...)
 157{
 158        char buf[1024];
 159        va_list params;
 160
 161        va_start(params, fmt);
 162        error_routine(fmt_with_err(buf, sizeof(buf), fmt), params);
 163        va_end(params);
 164        return -1;
 165}
 166
 167#undef error
 168int error(const char *err, ...)
 169{
 170        va_list params;
 171
 172        va_start(params, err);
 173        error_routine(err, params);
 174        va_end(params);
 175        return -1;
 176}
 177
 178void warning_errno(const char *warn, ...)
 179{
 180        char buf[1024];
 181        va_list params;
 182
 183        va_start(params, warn);
 184        warn_routine(fmt_with_err(buf, sizeof(buf), warn), params);
 185        va_end(params);
 186}
 187
 188void warning(const char *warn, ...)
 189{
 190        va_list params;
 191
 192        va_start(params, warn);
 193        warn_routine(warn, params);
 194        va_end(params);
 195}
 196
 197static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)
 198{
 199        char prefix[256];
 200
 201        /* truncation via snprintf is OK here */
 202        if (file)
 203                snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line);
 204        else
 205                snprintf(prefix, sizeof(prefix), "BUG: ");
 206
 207        vreportf(prefix, fmt, params);
 208        abort();
 209}
 210
 211#ifdef HAVE_VARIADIC_MACROS
 212NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...)
 213{
 214        va_list ap;
 215        va_start(ap, fmt);
 216        BUG_vfl(file, line, fmt, ap);
 217        va_end(ap);
 218}
 219#else
 220NORETURN void BUG(const char *fmt, ...)
 221{
 222        va_list ap;
 223        va_start(ap, fmt);
 224        BUG_vfl(NULL, 0, fmt, ap);
 225        va_end(ap);
 226}
 227#endif