usage.con commit Revert "vreportf: avoid intermediate buffer" (b5a9e43)
   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
   9static FILE *error_handle;
  10
  11void vreportf(const char *prefix, const char *err, va_list params)
  12{
  13        char msg[4096];
  14        FILE *fh = error_handle ? error_handle : stderr;
  15        vsnprintf(msg, sizeof(msg), err, params);
  16        fprintf(fh, "%s%s\n", prefix, msg);
  17}
  18
  19static NORETURN void usage_builtin(const char *err, va_list params)
  20{
  21        vreportf("usage: ", err, params);
  22        exit(129);
  23}
  24
  25static NORETURN void die_builtin(const char *err, va_list params)
  26{
  27        vreportf("fatal: ", err, params);
  28        exit(128);
  29}
  30
  31static void error_builtin(const char *err, va_list params)
  32{
  33        vreportf("error: ", err, params);
  34}
  35
  36static void warn_builtin(const char *warn, va_list params)
  37{
  38        vreportf("warning: ", warn, params);
  39}
  40
  41static int die_is_recursing_builtin(void)
  42{
  43        static int dying;
  44        return dying++;
  45}
  46
  47/* If we are in a dlopen()ed .so write to a global variable would segfault
  48 * (ugh), so keep things static. */
  49static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = usage_builtin;
  50static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin;
  51static void (*error_routine)(const char *err, va_list params) = error_builtin;
  52static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
  53static int (*die_is_recursing)(void) = die_is_recursing_builtin;
  54
  55void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params))
  56{
  57        die_routine = routine;
  58}
  59
  60void set_error_routine(void (*routine)(const char *err, va_list params))
  61{
  62        error_routine = routine;
  63}
  64
  65void set_die_is_recursing_routine(int (*routine)(void))
  66{
  67        die_is_recursing = routine;
  68}
  69
  70void set_error_handle(FILE *fh)
  71{
  72        error_handle = fh;
  73}
  74
  75void NORETURN usagef(const char *err, ...)
  76{
  77        va_list params;
  78
  79        va_start(params, err);
  80        usage_routine(err, params);
  81        va_end(params);
  82}
  83
  84void NORETURN usage(const char *err)
  85{
  86        usagef("%s", err);
  87}
  88
  89void NORETURN die(const char *err, ...)
  90{
  91        va_list params;
  92
  93        if (die_is_recursing()) {
  94                fputs("fatal: recursion detected in die handler\n", stderr);
  95                exit(128);
  96        }
  97
  98        va_start(params, err);
  99        die_routine(err, params);
 100        va_end(params);
 101}
 102
 103void NORETURN die_errno(const char *fmt, ...)
 104{
 105        va_list params;
 106        char fmt_with_err[1024];
 107        char str_error[256], *err;
 108        int i, j;
 109
 110        if (die_is_recursing()) {
 111                fputs("fatal: recursion detected in die_errno handler\n",
 112                        stderr);
 113                exit(128);
 114        }
 115
 116        err = strerror(errno);
 117        for (i = j = 0; err[i] && j < sizeof(str_error) - 1; ) {
 118                if ((str_error[j++] = err[i++]) != '%')
 119                        continue;
 120                if (j < sizeof(str_error) - 1) {
 121                        str_error[j++] = '%';
 122                } else {
 123                        /* No room to double the '%', so we overwrite it with
 124                         * '\0' below */
 125                        j--;
 126                        break;
 127                }
 128        }
 129        str_error[j] = 0;
 130        snprintf(fmt_with_err, sizeof(fmt_with_err), "%s: %s", fmt, str_error);
 131
 132        va_start(params, fmt);
 133        die_routine(fmt_with_err, params);
 134        va_end(params);
 135}
 136
 137#undef error
 138int error(const char *err, ...)
 139{
 140        va_list params;
 141
 142        va_start(params, err);
 143        error_routine(err, params);
 144        va_end(params);
 145        return -1;
 146}
 147
 148void warning(const char *warn, ...)
 149{
 150        va_list params;
 151
 152        va_start(params, warn);
 153        warn_routine(warn, params);
 154        va_end(params);
 155}