Skip to content

Commit

Permalink
curl: add variables to --write-out
Browse files Browse the repository at this point in the history
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 curl#6199
Closes curl#6207
  • Loading branch information
bagder committed Dec 21, 2020
1 parent ebdb5f2 commit 7a90ddf
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 104 deletions.
16 changes: 16 additions & 0 deletions docs/cmdline-opts/write-out.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion src/tool_operate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/tool_operate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/tool_paramhlp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions src/tool_sdecls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
147 changes: 72 additions & 75 deletions src/tool_writeout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 */
Expand All @@ -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))
Expand Down Expand Up @@ -392,5 +390,4 @@ void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo)
ptr++;
}
}

}
62 changes: 34 additions & 28 deletions src/tool_writeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 */

0 comments on commit 7a90ddf

Please sign in to comment.