X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=usage.c;h=1868a24f7a5148b1714dc4a9730f343339e61dce;hb=a78305ffbca58e49a7cdad901df0ae779bbed8fb;hp=cc803336bd5e6761b7fd50c33dba5aa9f734c4ba;hpb=6933c978eb629810114dfc1badf6575c9bc6223b;p=platform%2Fupstream%2Fgit.git diff --git a/usage.c b/usage.c index cc80333..1868a24 100644 --- a/usage.c +++ b/usage.c @@ -9,35 +9,84 @@ void vreportf(const char *prefix, const char *err, va_list params) { char msg[4096]; - char *p; + char *p, *pend = msg + sizeof(msg); + size_t prefix_len = strlen(prefix); - vsnprintf(msg, sizeof(msg), err, params); - for (p = msg; *p; p++) { + if (sizeof(msg) <= prefix_len) { + fprintf(stderr, "BUG!!! too long a prefix '%s'\n", prefix); + abort(); + } + memcpy(msg, prefix, prefix_len); + p = msg + prefix_len; + if (vsnprintf(p, pend - p, err, params) < 0) + *p = '\0'; /* vsnprintf() failed, clip at prefix */ + + for (; p != pend - 1 && *p; p++) { if (iscntrl(*p) && *p != '\t' && *p != '\n') *p = '?'; } - fprintf(stderr, "%s%s\n", prefix, msg); + + *(p++) = '\n'; /* we no longer need a NUL */ + fflush(stderr); + write_in_full(2, msg, p - msg); } static NORETURN void usage_builtin(const char *err, va_list params) { vreportf("usage: ", err, params); + + /* + * When we detect a usage error *before* the command dispatch in + * cmd_main(), we don't know what verb to report. Force it to this + * to facilitate post-processing. + */ + trace2_cmd_name("_usage_"); + + /* + * Currently, the (err, params) are usually just the static usage + * string which isn't very useful here. Usually, the call site + * manually calls fprintf(stderr,...) with the actual detailed + * syntax error before calling usage(). + * + * TODO It would be nice to update the call sites to pass both + * the static usage string and the detailed error message. + */ + exit(129); } static NORETURN void die_builtin(const char *err, va_list params) { + /* + * We call this trace2 function first and expect it to va_copy 'params' + * before using it (because an 'ap' can only be walked once). + */ + trace2_cmd_error_va(err, params); + vreportf("fatal: ", err, params); + exit(128); } static void error_builtin(const char *err, va_list params) { + /* + * We call this trace2 function first and expect it to va_copy 'params' + * before using it (because an 'ap' can only be walked once). + */ + trace2_cmd_error_va(err, params); + vreportf("error: ", err, params); } static void warn_builtin(const char *warn, va_list params) { + /* + * We call this trace2 function first and expect it to va_copy 'params' + * before using it (because an 'ap' can only be walked once). + */ + trace2_cmd_error_va(warn, params); + vreportf("warning: ", warn, params); } @@ -65,33 +114,33 @@ static int die_is_recursing_builtin(void) /* If we are in a dlopen()ed .so write to a global variable would segfault * (ugh), so keep things static. */ -static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = usage_builtin; -static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin; -static void (*error_routine)(const char *err, va_list params) = error_builtin; -static void (*warn_routine)(const char *err, va_list params) = warn_builtin; +static NORETURN_PTR report_fn usage_routine = usage_builtin; +static NORETURN_PTR report_fn die_routine = die_builtin; +static report_fn error_routine = error_builtin; +static report_fn warn_routine = warn_builtin; static int (*die_is_recursing)(void) = die_is_recursing_builtin; -void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params)) +void set_die_routine(NORETURN_PTR report_fn routine) { die_routine = routine; } -void set_error_routine(void (*routine)(const char *err, va_list params)) +void set_error_routine(report_fn routine) { error_routine = routine; } -void (*get_error_routine(void))(const char *err, va_list params) +report_fn get_error_routine(void) { return error_routine; } -void set_warn_routine(void (*routine)(const char *warn, va_list params)) +void set_warn_routine(report_fn routine) { warn_routine = routine; } -void (*get_warn_routine(void))(const char *warn, va_list params) +report_fn get_warn_routine(void) { return warn_routine; }