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