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 #6199
Closes #6207
  • Loading branch information
bagder committed Dec 20, 2020
1 parent 6e2392f commit 5c5d146
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 104 deletions.
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 5c5d146

Please sign in to comment.