mirror of
https://github.com/curl/curl.git
synced 2026-05-30 02:37:28 +03:00
curl: support repeated use of the verbose option; -vv etc
- make mentioning `-v` on the curl command line increase the verbosity of the trace output - related discussion https://github.com/curl/curl/discussions/13810 - make a single -v revert all previous -v+ changes - make --no-verbose also reset all trace configs Closes #13977
This commit is contained in:
parent
53146dd262
commit
06c5829dab
5 changed files with 175 additions and 56 deletions
|
|
@ -28,8 +28,28 @@ and a line starting with * means additional info provided by curl.
|
|||
If you only want HTTP headers in the output, --include or --dump-header might
|
||||
be more suitable options.
|
||||
|
||||
If you think this option still does not give you enough details, consider using
|
||||
--trace or --trace-ascii instead.
|
||||
Since curl 8.10, mentioning this option several times in the same argument
|
||||
increases the level of the trace output. However, as before,
|
||||
a single `-v`, `--verbose` or `--no-verbose` reverts any additions by
|
||||
previous `-vv` again. This means that `-vv -v` is equivalent to `-v`. This
|
||||
avoids unwanted verbosity when the option is mentioned in the command line
|
||||
*and* curl config files.
|
||||
|
||||
Using it twice, e.g. `-vv`, outputs time (`--trace-time`) and transfer
|
||||
ids (`--trace-ids`), as well as enable tracing for all protocols
|
||||
(`--trace-config protocol`).
|
||||
|
||||
Adding a third verbose outputs transfer content (`--trace-ascii %`) and
|
||||
enable tracing of more components (`--trace-config read,write,ssl`).
|
||||
|
||||
A forth time adds tracing of all network components.
|
||||
(`--trace-config network`).
|
||||
|
||||
Any addition of the verbose option after that has no effect.
|
||||
|
||||
If you think this option does not give you the right details, consider using
|
||||
--trace or --trace-ascii instead. Or use it only once and use `--trace-config`
|
||||
to trace the specific components you wish to see.
|
||||
|
||||
Note that verbose output of curl activities and network traffic might contain
|
||||
sensitive data, including usernames, credentials or secret data content. Be
|
||||
|
|
|
|||
|
|
@ -109,6 +109,27 @@ Traces reading of upload data from the application in order to send it to the se
|
|||
|
||||
Traces writing of download data, received from the server, to the application.
|
||||
|
||||
# TRACE GROUPS
|
||||
|
||||
Besides the specific component names there are the following group names
|
||||
defined:
|
||||
|
||||
## `all`
|
||||
|
||||
## `network`
|
||||
|
||||
All components involved in bare network I/O, including the SSL layer.
|
||||
|
||||
All components that your libcurl is built with.
|
||||
|
||||
## `protocol`
|
||||
|
||||
All components involved in transfer protocols, such as 'ftp' and 'http/2'.
|
||||
|
||||
## `proxy`
|
||||
|
||||
All components involved in use of proxies.
|
||||
|
||||
# %PROTOCOLS%
|
||||
|
||||
# EXAMPLE
|
||||
|
|
|
|||
134
lib/curl_trc.c
134
lib/curl_trc.c
|
|
@ -53,6 +53,9 @@
|
|||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
|
|
@ -218,58 +221,102 @@ void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
|
|||
}
|
||||
#endif /* !CURL_DISABLE_FTP */
|
||||
|
||||
static struct curl_trc_feat *trc_feats[] = {
|
||||
&Curl_trc_feat_read,
|
||||
&Curl_trc_feat_write,
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
&Curl_trc_feat_ftp,
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
&Curl_doh_trc,
|
||||
#endif
|
||||
NULL,
|
||||
#define TRC_CT_NONE (0)
|
||||
#define TRC_CT_PROTOCOL (1<<(0))
|
||||
#define TRC_CT_NETWORK (1<<(1))
|
||||
#define TRC_CT_PROXY (1<<(2))
|
||||
|
||||
struct trc_feat_def {
|
||||
struct curl_trc_feat *feat;
|
||||
unsigned int category;
|
||||
};
|
||||
|
||||
static struct Curl_cftype *cf_types[] = {
|
||||
&Curl_cft_tcp,
|
||||
&Curl_cft_udp,
|
||||
&Curl_cft_unix,
|
||||
&Curl_cft_tcp_accept,
|
||||
&Curl_cft_happy_eyeballs,
|
||||
&Curl_cft_setup,
|
||||
static struct trc_feat_def trc_feats[] = {
|
||||
{ &Curl_trc_feat_read, TRC_CT_NONE },
|
||||
{ &Curl_trc_feat_write, TRC_CT_NONE },
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
{ &Curl_trc_feat_ftp, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
{ &Curl_doh_trc, TRC_CT_NETWORK },
|
||||
#endif
|
||||
};
|
||||
|
||||
struct trc_cft_def {
|
||||
struct Curl_cftype *cft;
|
||||
unsigned int category;
|
||||
};
|
||||
|
||||
static struct trc_cft_def trc_cfts[] = {
|
||||
{ &Curl_cft_tcp, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_udp, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_unix, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_tcp_accept, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_happy_eyeballs, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_setup, TRC_CT_PROTOCOL },
|
||||
#ifdef USE_NGHTTP2
|
||||
&Curl_cft_nghttp2,
|
||||
{ &Curl_cft_nghttp2, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#ifdef USE_SSL
|
||||
&Curl_cft_ssl,
|
||||
{ &Curl_cft_ssl, TRC_CT_NETWORK },
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
&Curl_cft_ssl_proxy,
|
||||
{ &Curl_cft_ssl_proxy, TRC_CT_PROXY },
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_PROXY)
|
||||
#if !defined(CURL_DISABLE_HTTP)
|
||||
&Curl_cft_h1_proxy,
|
||||
{ &Curl_cft_h1_proxy, TRC_CT_PROXY },
|
||||
#ifdef USE_NGHTTP2
|
||||
&Curl_cft_h2_proxy,
|
||||
{ &Curl_cft_h2_proxy, TRC_CT_PROXY },
|
||||
#endif
|
||||
&Curl_cft_http_proxy,
|
||||
{ &Curl_cft_http_proxy, TRC_CT_PROXY },
|
||||
#endif /* !CURL_DISABLE_HTTP */
|
||||
&Curl_cft_haproxy,
|
||||
&Curl_cft_socks_proxy,
|
||||
{ &Curl_cft_haproxy, TRC_CT_PROXY },
|
||||
{ &Curl_cft_socks_proxy, TRC_CT_PROXY },
|
||||
#endif /* !CURL_DISABLE_PROXY */
|
||||
#ifdef USE_HTTP3
|
||||
&Curl_cft_http3,
|
||||
{ &Curl_cft_http3, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
|
||||
&Curl_cft_http_connect,
|
||||
{ &Curl_cft_http_connect, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void trc_apply_level_by_name(const char * const token, int lvl)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
|
||||
if(strcasecompare(token, trc_cfts[i].cft->name)) {
|
||||
trc_cfts[i].cft->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
|
||||
if(strcasecompare(token, trc_feats[i].feat->name)) {
|
||||
trc_feats[i].feat->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void trc_apply_level_by_category(int category, int lvl)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
|
||||
if(!category || (trc_cfts[i].category & category))
|
||||
trc_cfts[i].cft->log_level = lvl;
|
||||
}
|
||||
for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
|
||||
if(!category || (trc_feats[i].category & category))
|
||||
trc_feats[i].feat->log_level = lvl;
|
||||
}
|
||||
}
|
||||
|
||||
CURLcode Curl_trc_opt(const char *config)
|
||||
{
|
||||
char *token, *tok_buf, *tmp;
|
||||
size_t i;
|
||||
int lvl;
|
||||
|
||||
tmp = strdup(config);
|
||||
|
|
@ -291,24 +338,17 @@ CURLcode Curl_trc_opt(const char *config)
|
|||
lvl = CURL_LOG_LVL_INFO;
|
||||
break;
|
||||
}
|
||||
for(i = 0; cf_types[i]; ++i) {
|
||||
if(strcasecompare(token, "all")) {
|
||||
cf_types[i]->log_level = lvl;
|
||||
}
|
||||
else if(strcasecompare(token, cf_types[i]->name)) {
|
||||
cf_types[i]->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; trc_feats[i]; ++i) {
|
||||
if(strcasecompare(token, "all")) {
|
||||
trc_feats[i]->log_level = lvl;
|
||||
}
|
||||
else if(strcasecompare(token, trc_feats[i]->name)) {
|
||||
trc_feats[i]->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(strcasecompare(token, "all"))
|
||||
trc_apply_level_by_category(TRC_CT_NONE, lvl);
|
||||
else if(strcasecompare(token, "protocol"))
|
||||
trc_apply_level_by_category(TRC_CT_PROTOCOL, lvl);
|
||||
else if(strcasecompare(token, "network"))
|
||||
trc_apply_level_by_category(TRC_CT_NETWORK, lvl);
|
||||
else if(strcasecompare(token, "proxy"))
|
||||
trc_apply_level_by_category(TRC_CT_PROXY, lvl);
|
||||
else
|
||||
trc_apply_level_by_name(token, lvl);
|
||||
|
||||
token = strtok_r(NULL, ", ", &tok_buf);
|
||||
}
|
||||
free(tmp);
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ struct GlobalConfig {
|
|||
bool silent; /* do not show messages, --silent given */
|
||||
bool noprogress; /* do not show progress bar */
|
||||
bool isatty; /* Updated internally if output is a tty */
|
||||
unsigned char verbosity; /* How verbose we should be */
|
||||
char *trace_dump; /* file to dump the network trace to */
|
||||
FILE *trace_stream;
|
||||
bool trace_fopened;
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|||
time_t now;
|
||||
bool longopt = FALSE;
|
||||
bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
|
||||
size_t nopts = 0; /* options processed in `flag`*/
|
||||
ParameterError err = PARAM_OK;
|
||||
bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
|
||||
by using --OPTION or --no-OPTION */
|
||||
|
|
@ -2490,8 +2491,27 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|||
cleanarg(clearthis);
|
||||
break;
|
||||
case C_VERBOSE: /* --verbose */
|
||||
if(toggle) {
|
||||
/* the '%' thing here will cause the trace get sent to stderr */
|
||||
/* This option is a super-boolean with side effect when applied
|
||||
* more than once in the same argument flag, like `-vvv`. */
|
||||
if(!toggle) {
|
||||
global->verbosity = 0;
|
||||
if(set_trace_config(global, "-all"))
|
||||
err = PARAM_NO_MEM;
|
||||
global->tracetype = TRACE_NONE;
|
||||
break;
|
||||
}
|
||||
else if(!nopts) {
|
||||
/* fist `-v` in an argument resets to base verbosity */
|
||||
global->verbosity = 0;
|
||||
if(set_trace_config(global, "-all")) {
|
||||
err = PARAM_NO_MEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* the '%' thing here will cause the trace get sent to stderr */
|
||||
switch(global->verbosity) {
|
||||
case 0:
|
||||
global->verbosity = 1;
|
||||
Curl_safefree(global->trace_dump);
|
||||
global->trace_dump = strdup("%");
|
||||
if(!global->trace_dump)
|
||||
|
|
@ -2499,13 +2519,30 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|||
else {
|
||||
if(global->tracetype && (global->tracetype != TRACE_PLAIN))
|
||||
warnf(global,
|
||||
"-v, --verbose overrides an earlier trace/verbose option");
|
||||
"-v, --verbose overrides an earlier trace option");
|
||||
global->tracetype = TRACE_PLAIN;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
global->verbosity = 2;
|
||||
if(set_trace_config(global, "ids,time,protocol"))
|
||||
err = PARAM_NO_MEM;
|
||||
break;
|
||||
case 2:
|
||||
global->verbosity = 3;
|
||||
global->tracetype = TRACE_ASCII;
|
||||
if(set_trace_config(global, "ssl,read,write"))
|
||||
err = PARAM_NO_MEM;
|
||||
break;
|
||||
case 3:
|
||||
global->verbosity = 4;
|
||||
if(set_trace_config(global, "network"))
|
||||
err = PARAM_NO_MEM;
|
||||
break;
|
||||
default:
|
||||
/* no effect for now */
|
||||
break;
|
||||
}
|
||||
else
|
||||
/* verbose is disabled here */
|
||||
global->tracetype = TRACE_NONE;
|
||||
break;
|
||||
case C_VERSION: /* --version */
|
||||
if(toggle) /* --no-version yields no output! */
|
||||
|
|
@ -2634,7 +2671,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|||
break;
|
||||
}
|
||||
a = NULL;
|
||||
|
||||
++nopts; /* processed one option from `flag` input, loop for more */
|
||||
} while(!longopt && !singleopt && *++parse && !*usedarg && !err);
|
||||
|
||||
error:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue