summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2020-12-14 10:09:51 +0100
committerDaniel Stenberg <daniel@haxx.se>2020-12-21 16:38:48 +0100
commit7a90ddf88f5a1b313ecd28e1ec064d8351b0ddf2 (patch)
tree0b0b2a7df6ae8039b6eb61ca75d9f7eb2eaea76f
parentebdb5f23ccb0b658263f212ecbb52b10a03187dd (diff)
downloadcurl-7a90ddf88f5a1b313ecd28e1ec064d8351b0ddf2.tar.gz
curl: add variables to --write-out
In particular, these ones can help a user to create its own error message when one or transfers fail. writeout: add 'onerror', 'url', 'urlnum', 'exitcode', 'errormsg' onerror - lets a user only show the rest on non-zero exit codes url - the input URL used for this transfer urlnum - the numerical URL counter (0 indexed) for this transfer exitcode - the numerical exit code for the transfer errormsg - obvious Reported-by: Earnestly on github Fixes #6199 Closes #6207
-rw-r--r--docs/cmdline-opts/write-out.d16
-rw-r--r--src/tool_operate.c3
-rw-r--r--src/tool_operate.h1
-rw-r--r--src/tool_paramhlp.c2
-rw-r--r--src/tool_sdecls.h1
-rw-r--r--src/tool_writeout.c147
-rw-r--r--src/tool_writeout.h62
7 files changed, 128 insertions, 104 deletions
diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d
index 28b9a13a9..af5d0cf22 100644
--- a/docs/cmdline-opts/write-out.d
+++ b/docs/cmdline-opts/write-out.d
@@ -29,6 +29,12 @@ The variables available are:
.B content_type
The Content-Type of the requested document, if there was any.
.TP
+.B errormsg
+The error message. (Added in 7.75.0)
+.TP
+.B exitcode
+The numerical exitcode. (Added in 7.75.0)
+.TP
.B filename_effective
The ultimate filename that curl writes out to. This is only meaningful if curl
is told to write to a file with the --remote-name or --output
@@ -74,6 +80,10 @@ The number of response headers in the most recent request (restarted at each
.B num_redirects
Number of redirects that were followed in the request. (Added in 7.12.3)
.TP
+.B onerror
+The rest of the output is only shown if the transfer returned a non-zero error
+(Added in 7.75.0)
+.TP
.B proxy_ssl_verify_result
The result of the HTTPS proxy's SSL peer certificate verification that was
requested. 0 means the verification was successful. (Added in 7.52.0)
@@ -161,6 +171,12 @@ server needed to calculate the result.
.B time_total
The total time, in seconds, that the full operation lasted.
.TP
+.B url
+The URL that was fetched. (Added in 7.75.0)
+.TP
+.B urlnum
+The URL index number of this transfer, 0-indexed. (Added in 7.75.0)
+.TP
.B url_effective
The URL that was fetched last. This is most meaningful if you've told curl
to follow location: headers.
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 82a03f829..23dfa635e 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -628,7 +628,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
fputs("\n", per->progressbar.out);
if(config->writeout)
- ourWriteOut(per->curl, per, config->writeout);
+ ourWriteOut(per->curl, per, config->writeout, result);
/* Close the outs file */
if(outs->fopened && outs->stream) {
@@ -873,6 +873,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
*added = TRUE;
per->config = config;
per->curl = curl;
+ per->urlnum = urlnode->num;
/* default headers output stream is stdout */
heads = &per->heads;
diff --git a/src/tool_operate.h b/src/tool_operate.h
index fae978dff..2739301ce 100644
--- a/src/tool_operate.h
+++ b/src/tool_operate.h
@@ -41,6 +41,7 @@ struct per_transfer {
struct metalinkfile *mlfile;
struct metalink_resource *mlres;
char *this_url;
+ unsigned int urlnum; /* the index of the given URL */
char *outfile;
bool infdopen; /* TRUE if infd needs closing */
int infd;
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index a2f20cb17..461474644 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -40,6 +40,7 @@
struct getout *new_getout(struct OperationConfig *config)
{
+ static int outnum = 0;
struct getout *node = calloc(1, sizeof(struct getout));
struct getout *last = config->url_last;
if(node) {
@@ -53,6 +54,7 @@ struct getout *new_getout(struct OperationConfig *config)
config->url_last = node;
node->flags = config->default_node_flags;
+ node->num = outnum++;
}
return node;
}
diff --git a/src/tool_sdecls.h b/src/tool_sdecls.h
index 5b251657a..39e63093a 100644
--- a/src/tool_sdecls.h
+++ b/src/tool_sdecls.h
@@ -105,6 +105,7 @@ struct getout {
char *outfile; /* where to store the output */
char *infile; /* file to upload, if GETOUT_UPLOAD is set */
int flags; /* options - composed of GETOUT_* bits */
+ int num; /* which URL number in an invocation */
};
#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
diff --git a/src/tool_writeout.c b/src/tool_writeout.c
index 8b9f59005..8b465db2d 100644
--- a/src/tool_writeout.c
+++ b/src/tool_writeout.c
@@ -30,80 +30,58 @@
#include "memdebug.h" /* keep this as LAST include */
static const struct writeoutvar variables[] = {
- {"url_effective", VAR_EFFECTIVE_URL, 0,
- CURLINFO_EFFECTIVE_URL, JSON_STRING},
- {"method", VAR_EFFECTIVE_METHOD, 0,
- CURLINFO_EFFECTIVE_METHOD, JSON_STRING},
- {"http_code", VAR_HTTP_CODE, 0,
- CURLINFO_RESPONSE_CODE, JSON_LONG},
- {"response_code", VAR_HTTP_CODE, 0,
- CURLINFO_RESPONSE_CODE, JSON_LONG},
- {"num_headers", VAR_NUM_HEADERS, 0,
- 0, JSON_LONG},
- {"http_connect", VAR_HTTP_CODE_PROXY, 0,
- CURLINFO_HTTP_CONNECTCODE, JSON_LONG},
- {"time_total", VAR_TOTAL_TIME, 0,
- CURLINFO_TOTAL_TIME_T, JSON_TIME},
- {"time_namelookup", VAR_NAMELOOKUP_TIME, 0,
- CURLINFO_NAMELOOKUP_TIME_T, JSON_TIME},
- {"time_connect", VAR_CONNECT_TIME, 0,
- CURLINFO_CONNECT_TIME_T, JSON_TIME},
- {"time_appconnect", VAR_APPCONNECT_TIME, 0,
- CURLINFO_APPCONNECT_TIME_T, JSON_TIME},
- {"time_pretransfer", VAR_PRETRANSFER_TIME, 0,
- CURLINFO_PRETRANSFER_TIME_T, JSON_TIME},
- {"time_starttransfer", VAR_STARTTRANSFER_TIME, 0,
- CURLINFO_STARTTRANSFER_TIME_T, JSON_TIME},
- {"size_header", VAR_HEADER_SIZE, 0,
- CURLINFO_HEADER_SIZE, JSON_LONG},
- {"size_request", VAR_REQUEST_SIZE, 0,
- CURLINFO_REQUEST_SIZE, JSON_LONG},
- {"size_download", VAR_SIZE_DOWNLOAD, 0,
- CURLINFO_SIZE_DOWNLOAD_T, JSON_OFFSET},
- {"size_upload", VAR_SIZE_UPLOAD, 0,
- CURLINFO_SIZE_UPLOAD_T, JSON_OFFSET},
- {"speed_download", VAR_SPEED_DOWNLOAD, 0,
- CURLINFO_SPEED_DOWNLOAD_T, JSON_OFFSET},
- {"speed_upload", VAR_SPEED_UPLOAD, 0,
- CURLINFO_SPEED_UPLOAD_T, JSON_OFFSET},
- {"content_type", VAR_CONTENT_TYPE, 0,
- CURLINFO_CONTENT_TYPE, JSON_STRING},
- {"num_connects", VAR_NUM_CONNECTS, 0,
- CURLINFO_NUM_CONNECTS, JSON_LONG},
- {"time_redirect", VAR_REDIRECT_TIME, 0,
- CURLINFO_REDIRECT_TIME_T, JSON_TIME},
- {"num_redirects", VAR_REDIRECT_COUNT, 0,
- CURLINFO_REDIRECT_COUNT, JSON_LONG},
- {"ftp_entry_path", VAR_FTP_ENTRY_PATH, 0,
- CURLINFO_FTP_ENTRY_PATH, JSON_STRING},
- {"redirect_url", VAR_REDIRECT_URL, 0,
- CURLINFO_REDIRECT_URL, JSON_STRING},
- {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, 0,
- CURLINFO_SSL_VERIFYRESULT, JSON_LONG},
+ {"content_type", VAR_CONTENT_TYPE, 0, CURLINFO_CONTENT_TYPE, JSON_STRING},
+ {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, 0, JSON_FILENAME},
+ {"exitcode", VAR_EXITCODE, 0, 0, JSON_LONG},
+ {"errormsg", VAR_ERRORMSG, 0, 0, JSON_STRING},
+ {"ftp_entry_path", VAR_FTP_ENTRY_PATH, 0, CURLINFO_FTP_ENTRY_PATH,
+ JSON_STRING},
+ {"http_code", VAR_HTTP_CODE, 0, CURLINFO_RESPONSE_CODE, JSON_LONG},
+ {"http_connect", VAR_HTTP_CODE_PROXY, 0, CURLINFO_HTTP_CONNECTCODE,
+ JSON_LONG},
+ {"http_version", VAR_HTTP_VERSION, 0, CURLINFO_HTTP_VERSION, JSON_VERSION},
+ {"json", VAR_JSON, 1, 0, JSON_NONE},
+ {"local_ip", VAR_LOCAL_IP, 0, CURLINFO_LOCAL_IP, JSON_STRING},
+ {"local_port", VAR_LOCAL_PORT, 0, CURLINFO_LOCAL_PORT, JSON_LONG},
+ {"method", VAR_EFFECTIVE_METHOD, 0, CURLINFO_EFFECTIVE_METHOD, JSON_STRING},
+ {"num_connects", VAR_NUM_CONNECTS, 0, CURLINFO_NUM_CONNECTS, JSON_LONG},
+ {"num_headers", VAR_NUM_HEADERS, 0, 0, JSON_LONG},
+ {"num_redirects", VAR_REDIRECT_COUNT, 0, CURLINFO_REDIRECT_COUNT, JSON_LONG},
+ {"onerror", VAR_ONERROR, 1, 0, JSON_NONE},
{"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT, 0,
CURLINFO_PROXY_SSL_VERIFYRESULT, JSON_LONG},
- {"filename_effective", VAR_EFFECTIVE_FILENAME, 0,
- 0, JSON_FILENAME},
- {"remote_ip", VAR_PRIMARY_IP, 0,
- CURLINFO_PRIMARY_IP, JSON_STRING},
- {"remote_port", VAR_PRIMARY_PORT, 0,
- CURLINFO_PRIMARY_PORT, JSON_LONG},
- {"local_ip", VAR_LOCAL_IP, 0,
- CURLINFO_LOCAL_IP, JSON_STRING},
- {"local_port", VAR_LOCAL_PORT, 0,
- CURLINFO_LOCAL_PORT, JSON_LONG},
- {"http_version", VAR_HTTP_VERSION, 0,
- CURLINFO_HTTP_VERSION, JSON_VERSION},
- {"scheme", VAR_SCHEME, 0,
- CURLINFO_SCHEME, JSON_STRING},
- {"stdout", VAR_STDOUT, 1,
- 0, JSON_NONE},
- {"stderr", VAR_STDERR, 1,
- 0, JSON_NONE},
- {"json", VAR_JSON, 1,
- 0, JSON_NONE},
- {NULL, VAR_NONE, 1,
- 0, JSON_NONE}
+ {"redirect_url", VAR_REDIRECT_URL, 0, CURLINFO_REDIRECT_URL, JSON_STRING},
+ {"remote_ip", VAR_PRIMARY_IP, 0, CURLINFO_PRIMARY_IP, JSON_STRING},
+ {"remote_port", VAR_PRIMARY_PORT, 0, CURLINFO_PRIMARY_PORT, JSON_LONG},
+ {"response_code", VAR_HTTP_CODE, 0, CURLINFO_RESPONSE_CODE, JSON_LONG},
+ {"scheme", VAR_SCHEME, 0, CURLINFO_SCHEME, JSON_STRING},
+ {"size_download", VAR_SIZE_DOWNLOAD, 0, CURLINFO_SIZE_DOWNLOAD_T,
+ JSON_OFFSET},
+ {"size_header", VAR_HEADER_SIZE, 0, CURLINFO_HEADER_SIZE, JSON_LONG},
+ {"size_request", VAR_REQUEST_SIZE, 0, CURLINFO_REQUEST_SIZE, JSON_LONG},
+ {"size_upload", VAR_SIZE_UPLOAD, 0, CURLINFO_SIZE_UPLOAD_T, JSON_OFFSET},
+ {"speed_download", VAR_SPEED_DOWNLOAD, 0, CURLINFO_SPEED_DOWNLOAD_T,
+ JSON_OFFSET},
+ {"speed_upload", VAR_SPEED_UPLOAD, 0, CURLINFO_SPEED_UPLOAD_T, JSON_OFFSET},
+ {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, 0, CURLINFO_SSL_VERIFYRESULT,
+ JSON_LONG},
+ {"stderr", VAR_STDERR, 1, 0, JSON_NONE},
+ {"stdout", VAR_STDOUT, 1, 0, JSON_NONE},
+ {"time_appconnect", VAR_APPCONNECT_TIME, 0, CURLINFO_APPCONNECT_TIME_T,
+ JSON_TIME},
+ {"time_connect", VAR_CONNECT_TIME, 0, CURLINFO_CONNECT_TIME_T, JSON_TIME},
+ {"time_namelookup", VAR_NAMELOOKUP_TIME, 0, CURLINFO_NAMELOOKUP_TIME_T,
+ JSON_TIME},
+ {"time_pretransfer", VAR_PRETRANSFER_TIME, 0, CURLINFO_PRETRANSFER_TIME_T,
+ JSON_TIME},
+ {"time_redirect", VAR_REDIRECT_TIME, 0, CURLINFO_REDIRECT_TIME_T, JSON_TIME},
+ {"time_starttransfer", VAR_STARTTRANSFER_TIME, 0,
+ CURLINFO_STARTTRANSFER_TIME_T, JSON_TIME},
+ {"time_total", VAR_TOTAL_TIME, 0, CURLINFO_TOTAL_TIME_T, JSON_TIME},
+ {"url", VAR_INPUT_URL, 0, 0, JSON_STRING},
+ {"url_effective", VAR_EFFECTIVE_URL, 0, CURLINFO_EFFECTIVE_URL, JSON_STRING},
+ {"urlnum", VAR_URLNUM, 0, 0, JSON_LONG},
+ {NULL, VAR_NONE, 1, 0, JSON_NONE}
};
static void us2sec(FILE *stream, curl_off_t us)
@@ -114,15 +92,17 @@ static void us2sec(FILE *stream, curl_off_t us)
secs, us);
}
-void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo)
+void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo,
+ CURLcode result)
{
FILE *stream = stdout;
const char *ptr = writeinfo;
char *stringp = NULL;
long longinfo;
curl_off_t offinfo;
+ bool done = FALSE;
- while(ptr && *ptr) {
+ while(ptr && *ptr && !done) {
if('%' == *ptr && ptr[1]) {
if('%' == ptr[1]) {
/* an escaped %-letter */
@@ -148,6 +128,24 @@ void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo)
if(curl_strequal(ptr, variables[i].name)) {
match = TRUE;
switch(variables[i].id) {
+ case VAR_ONERROR:
+ if(result == CURLE_OK)
+ /* this isn't error so skip the rest */
+ done = TRUE;
+ break;
+ case VAR_EXITCODE:
+ fprintf(stream, "%d", (int)result);
+ break;
+ case VAR_ERRORMSG:
+ fputs(per->errorbuffer[0] ? per->errorbuffer :
+ curl_easy_strerror(result), stream);
+ break;
+ case VAR_INPUT_URL:
+ fputs(per->this_url, stream);
+ break;
+ case VAR_URLNUM:
+ fprintf(stream, "%u", per->urlnum);
+ break;
case VAR_EFFECTIVE_URL:
if((CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp))
@@ -392,5 +390,4 @@ void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo)
ptr++;
}
}
-
}
diff --git a/src/tool_writeout.h b/src/tool_writeout.h
index 9fb4e167a..02858d8c1 100644
--- a/src/tool_writeout.h
+++ b/src/tool_writeout.h
@@ -26,41 +26,46 @@
typedef enum {
VAR_NONE, /* must be the first */
- VAR_TOTAL_TIME,
- VAR_NAMELOOKUP_TIME,
- VAR_CONNECT_TIME,
VAR_APPCONNECT_TIME,
- VAR_PRETRANSFER_TIME,
- VAR_STARTTRANSFER_TIME,
- VAR_SIZE_DOWNLOAD,
- VAR_SIZE_UPLOAD,
- VAR_SPEED_DOWNLOAD,
- VAR_SPEED_UPLOAD,
- VAR_HTTP_CODE,
- VAR_HTTP_CODE_PROXY,
- VAR_HEADER_SIZE,
- VAR_NUM_HEADERS,
- VAR_REQUEST_SIZE,
+ VAR_CONNECT_TIME,
+ VAR_CONTENT_TYPE,
+ VAR_EFFECTIVE_FILENAME,
VAR_EFFECTIVE_METHOD,
VAR_EFFECTIVE_URL,
- VAR_CONTENT_TYPE,
- VAR_NUM_CONNECTS,
- VAR_REDIRECT_TIME,
- VAR_REDIRECT_COUNT,
+ VAR_ERRORMSG,
+ VAR_EXITCODE,
VAR_FTP_ENTRY_PATH,
- VAR_REDIRECT_URL,
- VAR_SSL_VERIFY_RESULT,
- VAR_PROXY_SSL_VERIFY_RESULT,
- VAR_EFFECTIVE_FILENAME,
- VAR_PRIMARY_IP,
- VAR_PRIMARY_PORT,
+ VAR_HEADER_SIZE,
+ VAR_HTTP_CODE,
+ VAR_HTTP_CODE_PROXY,
+ VAR_HTTP_VERSION,
+ VAR_INPUT_URL,
+ VAR_JSON,
VAR_LOCAL_IP,
VAR_LOCAL_PORT,
- VAR_HTTP_VERSION,
+ VAR_NAMELOOKUP_TIME,
+ VAR_NUM_CONNECTS,
+ VAR_NUM_HEADERS,
+ VAR_ONERROR,
+ VAR_PRETRANSFER_TIME,
+ VAR_PRIMARY_IP,
+ VAR_PRIMARY_PORT,
+ VAR_PROXY_SSL_VERIFY_RESULT,
+ VAR_REDIRECT_COUNT,
+ VAR_REDIRECT_TIME,
+ VAR_REDIRECT_URL,
+ VAR_REQUEST_SIZE,
VAR_SCHEME,
- VAR_STDOUT,
+ VAR_SIZE_DOWNLOAD,
+ VAR_SIZE_UPLOAD,
+ VAR_SPEED_DOWNLOAD,
+ VAR_SPEED_UPLOAD,
+ VAR_SSL_VERIFY_RESULT,
+ VAR_STARTTRANSFER_TIME,
VAR_STDERR,
- VAR_JSON,
+ VAR_STDOUT,
+ VAR_TOTAL_TIME,
+ VAR_URLNUM,
VAR_NUM_OF_VARS /* must be the last */
} writeoutid;
@@ -82,6 +87,7 @@ struct writeoutvar {
jsontype jsontype;
};
-void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo);
+void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo,
+ CURLcode exitcode);
#endif /* HEADER_CURL_TOOL_WRITEOUT_H */