2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
6 #include "git-compat-util.h"
9 void vreportf(const char *prefix
, const char *err
, va_list params
)
14 vsnprintf(msg
, sizeof(msg
), err
, params
);
15 for (p
= msg
; *p
; p
++) {
16 if (iscntrl(*p
) && *p
!= '\t' && *p
!= '\n')
19 fprintf(stderr
, "%s%s\n", prefix
, msg
);
22 static NORETURN
void usage_builtin(const char *err
, va_list params
)
24 vreportf("usage: ", err
, params
);
27 * When we detect a usage error *before* the command dispatch in
28 * cmd_main(), we don't know what verb to report. Force it to this
29 * to facilitate post-processing.
31 trace2_cmd_name("_usage_");
34 * Currently, the (err, params) are usually just the static usage
35 * string which isn't very useful here. Usually, the call site
36 * manually calls fprintf(stderr,...) with the actual detailed
37 * syntax error before calling usage().
39 * TODO It would be nice to update the call sites to pass both
40 * the static usage string and the detailed error message.
46 static NORETURN
void die_builtin(const char *err
, va_list params
)
49 * We call this trace2 function first and expect it to va_copy 'params'
50 * before using it (because an 'ap' can only be walked once).
52 trace2_cmd_error_va(err
, params
);
54 vreportf("fatal: ", err
, params
);
59 static void error_builtin(const char *err
, va_list params
)
62 * We call this trace2 function first and expect it to va_copy 'params'
63 * before using it (because an 'ap' can only be walked once).
65 trace2_cmd_error_va(err
, params
);
67 vreportf("error: ", err
, params
);
70 static void warn_builtin(const char *warn
, va_list params
)
72 vreportf("warning: ", warn
, params
);
75 static int die_is_recursing_builtin(void)
79 * Just an arbitrary number X where "a < x < b" where "a" is
80 * "maximum number of pthreads we'll ever plausibly spawn" and
81 * "b" is "something less than Inf", since the point is to
82 * prevent infinite recursion.
84 static const int recursion_limit
= 1024;
87 if (dying
> recursion_limit
) {
89 } else if (dying
== 2) {
90 warning("die() called many times. Recursion error or racy threaded death!");
97 /* If we are in a dlopen()ed .so write to a global variable would segfault
98 * (ugh), so keep things static. */
99 static NORETURN_PTR
void (*usage_routine
)(const char *err
, va_list params
) = usage_builtin
;
100 static NORETURN_PTR
void (*die_routine
)(const char *err
, va_list params
) = die_builtin
;
101 static void (*error_routine
)(const char *err
, va_list params
) = error_builtin
;
102 static void (*warn_routine
)(const char *err
, va_list params
) = warn_builtin
;
103 static int (*die_is_recursing
)(void) = die_is_recursing_builtin
;
105 void set_die_routine(NORETURN_PTR
void (*routine
)(const char *err
, va_list params
))
107 die_routine
= routine
;
110 void set_error_routine(void (*routine
)(const char *err
, va_list params
))
112 error_routine
= routine
;
115 void (*get_error_routine(void))(const char *err
, va_list params
)
117 return error_routine
;
120 void set_warn_routine(void (*routine
)(const char *warn
, va_list params
))
122 warn_routine
= routine
;
125 void (*get_warn_routine(void))(const char *warn
, va_list params
)
130 void set_die_is_recursing_routine(int (*routine
)(void))
132 die_is_recursing
= routine
;
135 void NORETURN
usagef(const char *err
, ...)
139 va_start(params
, err
);
140 usage_routine(err
, params
);
144 void NORETURN
usage(const char *err
)
149 void NORETURN
die(const char *err
, ...)
153 if (die_is_recursing()) {
154 fputs("fatal: recursion detected in die handler\n", stderr
);
158 va_start(params
, err
);
159 die_routine(err
, params
);
163 static const char *fmt_with_err(char *buf
, int n
, const char *fmt
)
165 char str_error
[256], *err
;
168 err
= strerror(errno
);
169 for (i
= j
= 0; err
[i
] && j
< sizeof(str_error
) - 1; ) {
170 if ((str_error
[j
++] = err
[i
++]) != '%')
172 if (j
< sizeof(str_error
) - 1) {
173 str_error
[j
++] = '%';
175 /* No room to double the '%', so we overwrite it with
182 /* Truncation is acceptable here */
183 snprintf(buf
, n
, "%s: %s", fmt
, str_error
);
187 void NORETURN
die_errno(const char *fmt
, ...)
192 if (die_is_recursing()) {
193 fputs("fatal: recursion detected in die_errno handler\n",
198 va_start(params
, fmt
);
199 die_routine(fmt_with_err(buf
, sizeof(buf
), fmt
), params
);
204 int error_errno(const char *fmt
, ...)
209 va_start(params
, fmt
);
210 error_routine(fmt_with_err(buf
, sizeof(buf
), fmt
), params
);
216 int error(const char *err
, ...)
220 va_start(params
, err
);
221 error_routine(err
, params
);
226 void warning_errno(const char *warn
, ...)
231 va_start(params
, warn
);
232 warn_routine(fmt_with_err(buf
, sizeof(buf
), warn
), params
);
236 void warning(const char *warn
, ...)
240 va_start(params
, warn
);
241 warn_routine(warn
, params
);
245 /* Only set this, ever, from t/helper/, when verifying that bugs are caught. */
248 static NORETURN
void BUG_vfl(const char *file
, int line
, const char *fmt
, va_list params
)
252 /* truncation via snprintf is OK here */
254 snprintf(prefix
, sizeof(prefix
), "BUG: %s:%d: ", file
, line
);
256 snprintf(prefix
, sizeof(prefix
), "BUG: ");
258 vreportf(prefix
, fmt
, params
);
264 #ifdef HAVE_VARIADIC_MACROS
265 NORETURN
void BUG_fl(const char *file
, int line
, const char *fmt
, ...)
269 BUG_vfl(file
, line
, fmt
, ap
);
273 NORETURN
void BUG(const char *fmt
, ...)
277 BUG_vfl(NULL
, 0, fmt
, ap
);
282 #ifdef SUPPRESS_ANNOTATED_LEAKS
283 void unleak_memory(const void *ptr
, size_t len
)
285 static struct suppressed_leak_root
{
286 struct suppressed_leak_root
*next
;
287 char data
[FLEX_ARRAY
];
289 struct suppressed_leak_root
*root
;
291 FLEX_ALLOC_MEM(root
, data
, ptr
, len
);
292 root
->next
= suppressed_leaks
;
293 suppressed_leaks
= root
;