* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
# include <netinet/tcp.h>
#endif
-#include "curl_rawstr.h"
+#ifdef __VMS
+# include <fabdef.h>
+#endif
+
+#include "rawstr.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "tool_msgs.h"
#include "tool_operate.h"
#include "tool_operhlp.h"
+#include "tool_paramhlp.h"
#include "tool_parsecfg.h"
#include "tool_setopt.h"
#include "tool_sleep.h"
#include "tool_writeenv.h"
#include "tool_writeout.h"
#include "tool_xattr.h"
+#include "tool_vms.h"
+#include "tool_help.h"
+#include "tool_hugehelp.h"
-#include "curl_memdebug.h" /* keep this as LAST include */
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef CURLDEBUG
+/* libcurl's debug builds provide an extra function */
+CURLcode curl_easy_perform_ev(CURL *easy);
+#endif
#define CURLseparator "--_curl_--"
"If you'd like to turn off curl's verification of the certificate, use\n" \
" the -k (or --insecure) option.\n"
-static int is_fatal_error(int code)
+static bool is_fatal_error(CURLcode code)
{
switch(code) {
/* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
case CURLE_FUNCTION_NOT_FOUND:
case CURLE_BAD_FUNCTION_ARGUMENT:
/* critical error */
- return 1;
+ return TRUE;
default:
break;
}
+
/* no error or not critical */
- return 0;
+ return FALSE;
}
-int operate(struct Configurable *config, int argc, argv_item_t argv[])
+#ifdef __VMS
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+static curl_off_t vms_realfilesize(const char * name,
+ const struct_stat * stat_buf)
+{
+ char buffer[8192];
+ curl_off_t count;
+ int ret_stat;
+ FILE * file;
+
+ file = fopen(name, "r");
+ if(file == NULL) {
+ return 0;
+ }
+ count = 0;
+ ret_stat = 1;
+ while(ret_stat > 0) {
+ ret_stat = fread(buffer, 1, sizeof(buffer), file);
+ if(ret_stat != 0)
+ count += ret_stat;
+ }
+ fclose(file);
+
+ return count;
+}
+
+/*
+ *
+ * VmsSpecialSize checks to see if the stat st_size can be trusted and
+ * if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char * name,
+ const struct_stat * stat_buf)
+{
+ switch(stat_buf->st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ return vms_realfilesize(name, stat_buf);
+ break;
+ default:
+ return stat_buf->st_size;
+ }
+}
+#endif /* __VMS */
+
+static CURLcode operate_do(struct GlobalConfig *global,
+ struct OperationConfig *config)
{
char errorbuffer[CURL_ERROR_SIZE];
struct ProgressData progressbar;
metalinkfile *mlfile_last = NULL;
- CURL *curl = NULL;
+ CURL *curl = config->easy;
char *httpgetfields = NULL;
- bool stillflags;
- int res = 0;
- int i;
+ CURLcode res = CURLE_OK;
+ unsigned long li;
- bool orig_noprogress;
- bool orig_isatty;
+ /* Save the values of noprogress and isatty to restore them later on */
+ bool orig_noprogress = global->noprogress;
+ bool orig_isatty = global->isatty;
errorbuffer[0] = '\0';
+
/* default headers output stream is stdout */
memset(&hdrcbdata, 0, sizeof(struct HdrCbData));
memset(&heads, 0, sizeof(struct OutStruct));
heads.stream = stdout;
heads.config = config;
- memory_tracking_init();
-
- /*
- ** Initialize curl library - do not call any libcurl functions before
- ** this point. Note that the memory_tracking_init() magic above is an
- ** exception, but then that's not part of the official public API.
- */
- if(main_init() != CURLE_OK) {
- helpf(config->errors, "error initializing curl library\n");
- return CURLE_FAILED_INIT;
- }
-
- /* Get libcurl info right away */
- if(get_libcurl_info() != CURLE_OK) {
- helpf(config->errors, "error retrieving curl library information\n");
- main_free();
- return CURLE_FAILED_INIT;
- }
-
- /* Get a curl handle to use for all forthcoming curl transfers */
- curl = curl_easy_init();
- if(!curl) {
- helpf(config->errors, "error initializing curl easy handle\n");
- main_free();
- return CURLE_FAILED_INIT;
- }
- config->easy = curl;
-
/*
** Beyond this point no return'ing from this function allowed.
** Jump to label 'quit_curl' in order to abandon this function
** from outside of nested loops further down below.
*/
- /* setup proper locale from environment */
-#ifdef HAVE_SETLOCALE
- setlocale(LC_ALL, "");
-#endif
-
- /* inits */
- config->postfieldsize = -1;
- config->showerror = -1; /* will show errors */
- config->use_httpget = FALSE;
- config->create_dirs = FALSE;
- config->maxredirs = DEFAULT_MAXREDIRS;
- config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
- config->proto_present = FALSE;
- config->proto_redir =
- CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
- config->proto_redir_present = FALSE;
-
- if((argc > 1) &&
- (!curlx_strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
- strchr(argv[1], 'q')) {
- /*
- * The first flag, that is not a verbose name, but a shortname
- * and it includes the 'q' flag!
- */
- ;
- }
- else {
- parseconfig(NULL, config); /* ignore possible failure */
- }
-
- if((argc < 2) && !config->url_list) {
- helpf(config->errors, NULL);
+ /* Check we have a url */
+ if(!config->url_list || !config->url_list->url) {
+ helpf(global->errors, "no URL specified!\n");
res = CURLE_FAILED_INIT;
goto quit_curl;
}
- /* Parse options */
- for(i = 1, stillflags = TRUE; i < argc; i++) {
- if(stillflags &&
- ('-' == argv[i][0])) {
- char *nextarg;
- bool passarg;
- char *orig_opt = argv[i];
-
- char *flag = argv[i];
-
- if(curlx_strequal("--", argv[i]))
- /* this indicates the end of the flags and thus enables the
- following (URL) argument to start with -. */
- stillflags = FALSE;
- else {
- nextarg = (i < (argc-1)) ? argv[i+1] : NULL;
-
- res = getparameter(flag, nextarg, &passarg, config);
- if(res) {
- int retval = CURLE_OK;
- if(res != PARAM_HELP_REQUESTED) {
- const char *reason = param2text(res);
- helpf(config->errors, "option %s: %s\n", orig_opt, reason);
- retval = CURLE_FAILED_INIT;
- }
- res = retval;
- goto quit_curl;
- }
-
- if(passarg) /* we're supposed to skip this */
- i++;
- }
- }
- else {
- bool used;
- /* just add the URL please */
- res = getparameter((char *)"--url", argv[i], &used, config);
- if(res)
- goto quit_curl;
- }
- }
-
- if((!config->url_list || !config->url_list->url) && !config->list_engines) {
- helpf(config->errors, "no URL specified!\n");
- res = CURLE_FAILED_INIT;
- goto quit_curl;
- }
-
- if(!config->useragent)
- config->useragent = my_useragent();
- if(!config->useragent) {
- helpf(config->errors, "out of memory\n");
- res = CURLE_OUT_OF_MEMORY;
- goto quit_curl;
- }
-
/* On WIN32 we can't set the path to curl-ca-bundle.crt
* at compile time. So we look here for the file in two ways:
* 1: look at the environment variable CURL_CA_BUNDLE for a path
config->cacert = strdup(env);
if(!config->cacert) {
curl_free(env);
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
res = CURLE_OUT_OF_MEMORY;
goto quit_curl;
}
config->capath = strdup(env);
if(!config->capath) {
curl_free(env);
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
res = CURLE_OUT_OF_MEMORY;
goto quit_curl;
}
config->cacert = strdup(env);
if(!config->cacert) {
curl_free(env);
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
res = CURLE_OUT_OF_MEMORY;
goto quit_curl;
}
httpgetfields = strdup(config->postfields);
Curl_safefree(config->postfields);
if(!httpgetfields) {
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
res = CURLE_OUT_OF_MEMORY;
goto quit_curl;
}
if(SetHTTPrequest(config,
(config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
&config->httpreq)) {
- res = PARAM_BAD_USE;
+ res = CURLE_FAILED_INIT;
goto quit_curl;
}
}
else {
if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) {
- res = PARAM_BAD_USE;
+ res = CURLE_FAILED_INIT;
goto quit_curl;
}
}
}
-#ifndef CURL_DISABLE_LIBCURL_OPTION
- res = easysrc_init();
- if(res) {
- helpf(config->errors, "out of memory\n");
- goto quit_curl;
- }
-#endif
-
- if(config->list_engines) {
- struct curl_slist *engines = NULL;
- curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
- list_engines(engines);
- curl_slist_free_all(engines);
- res = CURLE_OK;
- goto quit_curl;
- }
-
/* Single header file for all URLs */
if(config->headerfile) {
/* open file for output: */
heads.stream = newfile;
}
}
+ else {
+ /* always use binary mode for protocol header output */
+ set_binmode(heads.stream);
+ }
}
- /* save the values of noprogress and isatty to restore them later on */
- orig_noprogress = config->noprogress;
- orig_isatty = config->isatty;
-
/*
** Nested loops start here.
*/
for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
- int up; /* upload file counter within a single upload glob */
+ unsigned long up; /* upload file counter within a single upload glob */
char *infiles; /* might be a glob pattern */
char *outfiles;
- int infilenum;
+ unsigned long infilenum;
URLGlob *inglob;
int metalink = 0; /* nonzero for metalink download. */
if(urlnode->outfile) {
outfiles = strdup(urlnode->outfile);
if(!outfiles) {
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
res = CURLE_OUT_OF_MEMORY;
break;
}
if(!config->globoff && infiles) {
/* Unless explicitly shut off */
- res = glob_url(&inglob, infiles, &infilenum,
- config->showerror?config->errors:NULL);
+ res = (CURLcode) glob_url(&inglob, infiles, &infilenum,
+ global->showerror?global->errors:NULL);
if(res) {
Curl_safefree(outfiles);
break;
char *uploadfile; /* a single file, never a glob */
int separator;
URLGlob *urls;
- int urlnum;
+ unsigned long urlnum;
uploadfile = NULL;
urls = NULL;
Curl_nop_stmt;
else {
if(inglob) {
- res = glob_next_url(&uploadfile, inglob);
+ res = (CURLcode) glob_next_url(&uploadfile, inglob);
if(res == CURLE_OUT_OF_MEMORY)
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
}
else if(!up) {
uploadfile = strdup(infiles);
if(!uploadfile) {
- helpf(config->errors, "out of memory\n");
+ helpf(global->errors, "out of memory\n");
res = CURLE_OUT_OF_MEMORY;
}
}
if(!config->globoff) {
/* Unless explicitly shut off, we expand '{...}' and '[...]'
expressions and return total number of URLs in pattern set */
- res = glob_url(&urls, urlnode->url, &urlnum,
- config->showerror?config->errors:NULL);
+ res = (CURLcode) glob_url(&urls, urlnode->url, &urlnum,
+ global->showerror?global->errors:NULL);
if(res) {
Curl_safefree(uploadfile);
break;
separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
/* Here's looping around each globbed URL */
- for(i = 0 ; i < urlnum; i++) {
+ for(li = 0 ; li < urlnum; li++) {
int infd;
bool infdopen;
long retry_numretries;
long retry_sleep_default;
long retry_sleep;
- char *this_url;
+ char *this_url = NULL;
int metalink_next_res = 0;
outfile = NULL;
}
else {
if(urls) {
- res = glob_next_url(&this_url, urls);
+ res = (CURLcode) glob_next_url(&this_url, urls);
if(res)
goto show_error;
}
- else if(!i) {
+ else if(!li) {
this_url = strdup(urlnode->url);
if(!this_url) {
res = CURLE_OUT_OF_MEMORY;
if(res)
goto show_error;
if((!outfile || !*outfile) && !config->content_disposition) {
- helpf(config->errors, "Remote file name has no length!\n");
+ helpf(global->errors, "Remote file name has no length!\n");
res = CURLE_WRITE_ERROR;
goto quit_urls;
}
else if(urls) {
/* fill '#1' ... '#9' terms from URL pattern */
char *storefile = outfile;
- res = glob_match_url(&outfile, storefile, urls);
+ res = (CURLcode) glob_match_url(&outfile, storefile, urls);
Curl_safefree(storefile);
if(res) {
/* bad globbing */
file output call */
if(config->create_dirs || metalink) {
- res = create_dir_hierarchy(outfile, config->errors);
+ res = create_dir_hierarchy(outfile, global->errors);
/* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
if(res == CURLE_WRITE_ERROR)
goto quit_urls;
}
if(config->resume_from) {
+#ifdef __VMS
+ /* open file for output, forcing VMS output format into stream
+ mode which is needed for stat() call above to always work. */
+ FILE *file = fopen(outfile, config->resume_from?"ab":"wb",
+ "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0");
+#else
/* open file for output: */
FILE *file = fopen(outfile, config->resume_from?"ab":"wb");
+#endif
if(!file) {
- helpf(config->errors, "Can't open '%s'!\n", outfile);
+ helpf(global->errors, "Can't open '%s'!\n", outfile);
res = CURLE_WRITE_ERROR;
goto quit_urls;
}
* header for VARIABLE header files only the bare record data needs
* to be considered with one appended if implied CC
*/
-
+#ifdef __VMS
+ /* Calculate the real upload site for VMS */
+ infd = -1;
+ if(stat(uploadfile, &fileinfo) == 0) {
+ fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo);
+ switch (fileinfo.st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ case FAB$C_STMCR:
+ infd = open(uploadfile, O_RDONLY | O_BINARY);
+ break;
+ default:
+ infd = open(uploadfile, O_RDONLY | O_BINARY,
+ "rfm=stmlf", "ctx=stm");
+ }
+ }
+ if(infd == -1)
+#else
infd = open(uploadfile, O_RDONLY | O_BINARY);
- if((infd == -1) || fstat(infd, &fileinfo)) {
- helpf(config->errors, "Can't open '%s'!\n", uploadfile);
+ if((infd == -1) || fstat(infd, &fileinfo))
+#endif
+ {
+ helpf(global->errors, "Can't open '%s'!\n", uploadfile);
if(infd != -1) {
close(infd);
infd = STDIN_FILENO;
if(uploadfile && config->resume_from_current)
config->resume_from = -1; /* -1 will then force get-it-yourself */
- if(output_expected(this_url, uploadfile)
- && outs.stream && isatty(fileno(outs.stream)))
+ if(output_expected(this_url, uploadfile) && outs.stream &&
+ isatty(fileno(outs.stream)))
/* we send the output to a tty, therefore we switch off the progress
meter */
- config->noprogress = config->isatty = TRUE;
+ global->noprogress = global->isatty = TRUE;
else {
/* progress meter is per download, so restore config
values */
- config->noprogress = orig_noprogress;
- config->isatty = orig_isatty;
+ global->noprogress = orig_noprogress;
+ global->isatty = orig_isatty;
}
- if(urlnum > 1 && !(config->mute)) {
- fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
- i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
+ if(urlnum > 1 && !global->mute) {
+ fprintf(global->errors, "\n[%lu/%lu]: %s --> %s\n",
+ li+1, urlnum, this_url, outfile ? outfile : "<stdout>");
if(separator)
printf("%s%s\n", CURLseparator, this_url);
}
/*
* Then append ? followed by the get fields to the url.
*/
- urlbuffer = malloc(strlen(this_url) + strlen(httpgetfields) + 3);
- if(!urlbuffer) {
- res = CURLE_OUT_OF_MEMORY;
- goto show_error;
- }
if(pc)
- sprintf(urlbuffer, "%s%c%s", this_url, sep, httpgetfields);
+ urlbuffer = aprintf("%s%c%s", this_url, sep, httpgetfields);
else
/* Append / before the ? to create a well-formed url
if the url contains a hostname only
*/
- sprintf(urlbuffer, "%s/?%s", this_url, httpgetfields);
+ urlbuffer = aprintf("%s/?%s", this_url, httpgetfields);
+
+ if(!urlbuffer) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
Curl_safefree(this_url); /* free previous URL */
this_url = urlbuffer; /* use our new URL instead! */
}
- if(!config->errors)
- config->errors = stderr;
+ if(!global->errors)
+ global->errors = stderr;
if((!outfile || !strcmp(outfile, "-")) && !config->use_ascii) {
/* We get the output to stdout and we have not got the ASCII/text
}
if(config->tcp_nodelay)
- my_setopt(curl, CURLOPT_TCP_NODELAY, 1);
+ my_setopt(curl, CURLOPT_TCP_NODELAY, 1L);
/* where to store */
my_setopt(curl, CURLOPT_WRITEDATA, &outs);
input.fd = infd;
input.config = config;
/* Note that if CURLOPT_READFUNCTION is fread (the default), then
- * lib/curl_telnet.c will Curl_poll() on the input file descriptor
+ * lib/telnet.c will Curl_poll() on the input file descriptor
* rather then calling the READFUNCTION at regular intervals.
* The circumstances in which it is preferable to enable this
* behaviour, by omitting to set the READFUNCTION & READDATA options,
if(config->recvpersecond)
/* tell libcurl to use a smaller sized buffer as it allows us to
make better sleeps! 7.9.9 stuff! */
- my_setopt(curl, CURLOPT_BUFFERSIZE, config->recvpersecond);
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
/* size of uploaded file: */
if(uploadfilesize != -1)
my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
my_setopt_str(curl, CURLOPT_URL, this_url); /* what to fetch */
- my_setopt(curl, CURLOPT_NOPROGRESS, config->noprogress);
+ my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L);
if(config->no_body) {
- my_setopt(curl, CURLOPT_NOBODY, 1);
- my_setopt(curl, CURLOPT_HEADER, 1);
+ my_setopt(curl, CURLOPT_NOBODY, 1L);
+ my_setopt(curl, CURLOPT_HEADER, 1L);
}
/* If --metalink is used, we ignore --include (headers in
output) option because mixing headers to the body will
confuse XML parser and/or hash check will fail. */
else if(!config->use_metalink)
- my_setopt(curl, CURLOPT_HEADER, config->include_headers);
+ my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L);
+
+ if(config->xoauth2_bearer)
+ my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->xoauth2_bearer);
#if !defined(CURL_DISABLE_PROXY)
{
my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
/* new in libcurl 7.3 */
- my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
+ my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel?1L:0L);
/* new in libcurl 7.5 */
if(config->proxy)
- my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
+ my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->proxyver);
/* new in libcurl 7.10 */
if(config->socksproxy) {
my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
- my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->socksver);
+ my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->socksver);
}
/* new in libcurl 7.10.6 */
if(config->proxyanyauth)
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
- (long) CURLAUTH_ANY);
+ (long)CURLAUTH_ANY);
else if(config->proxynegotiate)
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
- (long) CURLAUTH_GSSNEGOTIATE);
+ (long)CURLAUTH_GSSNEGOTIATE);
else if(config->proxyntlm)
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
- (long) CURLAUTH_NTLM);
+ (long)CURLAUTH_NTLM);
else if(config->proxydigest)
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
- (long) CURLAUTH_DIGEST);
+ (long)CURLAUTH_DIGEST);
else if(config->proxybasic)
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
- (long) CURLAUTH_BASIC);
+ (long)CURLAUTH_BASIC);
/* new in libcurl 7.19.4 */
my_setopt(curl, CURLOPT_NOPROXY, config->noproxy);
}
#endif
- my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror);
- my_setopt(curl, CURLOPT_UPLOAD, uploadfile?TRUE:FALSE);
- my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
- my_setopt(curl, CURLOPT_APPEND, config->ftp_append);
+ my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror?1L:0L);
+ my_setopt(curl, CURLOPT_UPLOAD, uploadfile?1L:0L);
+ my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly?1L:0L);
+ my_setopt(curl, CURLOPT_APPEND, config->ftp_append?1L:0L);
if(config->netrc_opt)
- my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL);
else if(config->netrc || config->netrc_file)
- my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED);
else
- my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_IGNORED);
if(config->netrc_file)
my_setopt(curl, CURLOPT_NETRC_FILE, config->netrc_file);
- my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
+ my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L);
+ if(config->login_options)
+ my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
my_setopt_str(curl, CURLOPT_RANGE, config->range);
my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
- my_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
+ my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
if(built_in_protos & CURLPROTO_HTTP) {
long postRedir = 0;
my_setopt(curl, CURLOPT_FOLLOWLOCATION,
- config->followlocation);
+ config->followlocation?1L:0L);
my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
- config->unrestricted_auth);
+ config->unrestricted_auth?1L:0L);
switch(config->httpreq) {
case HTTPREQ_SIMPLEPOST:
}
my_setopt_str(curl, CURLOPT_REFERER, config->referer);
- my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer);
+ my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L);
my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
+ /* new in libcurl 7.36.0 */
+ if(config->proxyheaders) {
+ my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
+ my_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
+ }
+
/* new in libcurl 7.5 */
my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
/* new in libcurl 7.10.6 (default is Basic) */
if(config->authtype)
- my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long) config->authtype);
+ my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
/* curl 7.19.1 (the 301 version existed in 7.18.2),
303 was added in 7.26.0 */
/* new in libcurl 7.21.6 */
if(config->tr_encoding)
- my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1);
+ my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
} /* (built_in_protos & CURLPROTO_HTTP) */
config->sendpersecond);
my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
config->recvpersecond);
- my_setopt(curl, CURLOPT_RESUME_FROM_LARGE,
- config->use_resume?config->resume_from:0);
- my_setopt(curl, CURLOPT_SSLCERT, config->cert);
+ if(config->use_resume)
+ my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
+ else
+ my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
+
+ my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
- my_setopt(curl, CURLOPT_SSLKEY, config->key);
+ my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
if(config->no_body || config->remote_time) {
/* no body or use remote time */
- my_setopt(curl, CURLOPT_FILETIME, TRUE);
+ my_setopt(curl, CURLOPT_FILETIME, 1L);
}
- my_setopt(curl, CURLOPT_CRLF, config->crlf);
+ my_setopt(curl, CURLOPT_CRLF, config->crlf?1L:0L);
my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
- {
- /* TODO: Make this a run-time check instead of compile-time one. */
+ if(config->cookie)
+ my_setopt_str(curl, CURLOPT_COOKIE, config->cookie);
- if(config->cookie)
- my_setopt_str(curl, CURLOPT_COOKIE, config->cookie);
+ if(config->cookiefile)
+ my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile);
- if(config->cookiefile)
- my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile);
+ /* new in libcurl 7.9 */
+ if(config->cookiejar)
+ my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
- /* new in libcurl 7.9 */
- if(config->cookiejar)
- my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
-
- /* new in libcurl 7.9.7 */
- my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession);
+ /* new in libcurl 7.9.7 */
+ my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession?1L:0L);
+#else
+ if(config->cookie || config->cookiefile || config->cookiejar) {
+ warnf(config, "cookie option(s) used even though cookie support "
+ "is disabled!\n");
+ return CURLE_NOT_BUILT_IN;
}
#endif
my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
- my_setopt_enum(curl, CURLOPT_TIMECONDITION, config->timecond);
- my_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
+ my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond);
+ my_setopt(curl, CURLOPT_TIMEVALUE, (long)config->condtime);
my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
- my_setopt(curl, CURLOPT_STDERR, config->errors);
+ my_setopt(curl, CURLOPT_STDERR, global->errors);
/* three new ones in libcurl 7.3: */
my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
progressbarinit(&progressbar, config);
- if((config->progressmode == CURL_PROGRESS_BAR) &&
- !config->noprogress && !config->mute) {
+ if((global->progressmode == CURL_PROGRESS_BAR) &&
+ !global->noprogress && !global->mute) {
/* we want the alternative style, then we have to implement it
ourselves! */
- my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb);
- my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
+ my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
+ my_setopt(curl, CURLOPT_XFERINFODATA, &progressbar);
}
+ /* new in libcurl 7.24.0: */
+ if(config->dns_servers)
+ my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
+
+ /* new in libcurl 7.33.0: */
+ if(config->dns_interface)
+ my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
+ if(config->dns_ipv4_addr)
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
+ if(config->dns_ipv6_addr)
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
+
/* new in libcurl 7.6.2: */
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
/* new in libcurl 7.7: */
my_setopt_str(curl, CURLOPT_RANDOM_FILE, config->random_file);
- my_setopt(curl, CURLOPT_EGDSOCKET, config->egd_file);
- my_setopt(curl, CURLOPT_CONNECTTIMEOUT, config->connecttimeout);
+ my_setopt_str(curl, CURLOPT_EGDSOCKET, config->egd_file);
+ my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
+ (long)(config->connecttimeout * 1000));
if(config->cipher_list)
my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
/* new in libcurl 7.9.2: */
if(config->disable_epsv)
/* disable it */
- my_setopt(curl, CURLOPT_FTP_USE_EPSV, FALSE);
+ my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
/* new in libcurl 7.10.5 */
if(config->disable_eprt)
/* disable it */
- my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
+ my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
- if(config->tracetype != TRACE_NONE) {
+ if(global->tracetype != TRACE_NONE) {
my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
my_setopt(curl, CURLOPT_DEBUGDATA, config);
- my_setopt(curl, CURLOPT_VERBOSE, TRUE);
+ my_setopt(curl, CURLOPT_VERBOSE, 1L);
}
/* new in curl 7.9.3 */
res = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
if(res)
goto show_error;
- my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
+ my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
}
/* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
- config->ftp_create_dirs);
+ config->ftp_create_dirs?1L:0L);
/* new in curl 7.10.8 */
if(config->max_filesize)
/* new in curl 7.15.5 */
if(config->ftp_ssl_reqd)
- my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
/* new in curl 7.11.0 */
else if(config->ftp_ssl)
- my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
/* new in curl 7.16.0 */
else if(config->ftp_ssl_control)
- my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL);
/* new in curl 7.16.1 */
if(config->ftp_ssl_ccc)
- my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
+ my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC,
+ (long)config->ftp_ssl_ccc_mode);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
{
/* curl 7.13.0 */
my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
- my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
+ my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl?1L:0L);
/* curl 7.14.2 */
- my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
+ my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L);
/* curl 7.15.1 */
- my_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
+ my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod);
/* curl 7.15.2 */
if(config->localport) {
- my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
+ my_setopt(curl, CURLOPT_LOCALPORT, (long)config->localport);
my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
- config->localportrange);
+ (long)config->localportrange);
}
/* curl 7.15.5 */
/* curl 7.16.0 */
if(config->disable_sessionid)
- my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE,
- !config->disable_sessionid);
+ /* disable it */
+ my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
/* curl 7.16.2 */
if(config->raw) {
- my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, FALSE);
- my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, FALSE);
+ my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
+ my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
}
/* curl 7.17.1 */
/* curl 7.20.x */
if(config->ftp_pret)
- my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
+ my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
if(config->proto_present)
my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
+ /* new in 7.31.0 */
+ if(config->sasl_ir)
+ my_setopt(curl, CURLOPT_SASL_IR, 1L);
+
+ if(config->nonpn) {
+ my_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 0L);
+ }
+
+ if(config->noalpn) {
+ my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
+ }
+
/* initialize retry vars for loop below */
retry_sleep_default = (config->retry_delay) ?
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
res = CURLE_OUT_OF_MEMORY;
goto show_error;
}
- fprintf(config->errors, "Metalink: parsing (%s) metalink/XML...\n",
- this_url);
+ fprintf(config->global->errors,
+ "Metalink: parsing (%s) metalink/XML...\n", this_url);
}
else if(metalink)
- fprintf(config->errors, "Metalink: fetching (%s) from (%s)...\n",
+ fprintf(config->global->errors,
+ "Metalink: fetching (%s) from (%s)...\n",
mlfile->filename, this_url);
#endif /* USE_METALINK */
+#ifdef CURLDEBUG
+ if(config->test_event_based)
+ res = curl_easy_perform_ev(curl);
+ else
+#endif
res = curl_easy_perform(curl);
- if(outs.is_cd_filename && outs.stream && !config->mute &&
+ if(outs.is_cd_filename && outs.stream && !global->mute &&
outs.filename)
printf("curl: Saved to filename '%s'\n", outs.filename);
if(outs.bytes && outs.filename) {
/* We have written data to a output file, we truncate file
*/
- if(!config->mute)
- fprintf(config->errors, "Throwing away %"
+ if(!global->mute)
+ fprintf(global->errors, "Throwing away %"
CURL_FORMAT_CURL_OFF_T " bytes\n",
outs.bytes);
fflush(outs.stream);
if(ftruncate( fileno(outs.stream), outs.init)) {
/* when truncate fails, we can't just append as then we'll
create something strange, bail out */
- if(!config->mute)
- fprintf(config->errors,
+ if(!global->mute)
+ fprintf(global->errors,
"failed to truncate, exiting\n");
res = CURLE_WRITE_ERROR;
goto quit_urls;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
if(response != 200 && response != 206) {
metalink_next_res = 1;
- fprintf(config->errors,
+ fprintf(global->errors,
"Metalink: fetching (%s) from (%s) FAILED "
"(HTTP status code %d)\n",
mlfile->filename, this_url, response);
}
else {
metalink_next_res = 1;
- fprintf(config->errors,
+ fprintf(global->errors,
"Metalink: fetching (%s) from (%s) FAILED (%s)\n",
mlfile->filename, this_url,
(errorbuffer[0]) ?
}
}
if(metalink && !metalink_next_res)
- fprintf(config->errors, "Metalink: fetching (%s) from (%s) OK\n",
+ fprintf(global->errors, "Metalink: fetching (%s) from (%s) OK\n",
mlfile->filename, this_url);
/* In all ordinary cases, just break out of loop here */
}
- if((config->progressmode == CURL_PROGRESS_BAR) &&
+ if((global->progressmode == CURL_PROGRESS_BAR) &&
progressbar.calls)
/* if the custom progress bar has been displayed, we output a
newline here */
#ifdef __VMS
if(is_vms_shell()) {
/* VMS DCL shell behavior */
- if(!config->showerror)
+ if(!global->showerror)
vms_show = VMSSTS_HIDE;
}
else
#endif
- if(res && config->showerror) {
- fprintf(config->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
+ if(res && global->showerror) {
+ fprintf(global->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
errorbuffer : curl_easy_strerror((CURLcode)res));
if(res == CURLE_SSL_CACERT)
- fprintf(config->errors, "%s%s",
+ fprintf(global->errors, "%s%s",
CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
}
if(!res && rc) {
/* something went wrong in the writing process */
res = CURLE_WRITE_ERROR;
- fprintf(config->errors, "(%d) Failed writing body\n", res);
+ fprintf(global->errors, "(%d) Failed writing body\n", res);
}
}
else if(!outs.s_isreg && outs.stream) {
if(!res && rc) {
/* something went wrong in the writing process */
res = CURLE_WRITE_ERROR;
- fprintf(config->errors, "(%d) Failed writing body\n", res);
+ fprintf(global->errors, "(%d) Failed writing body\n", res);
}
}
if(!metalink && config->use_metalink && res == CURLE_OK) {
int rv = parse_metalink(config, &outs, this_url);
if(rv == 0)
- fprintf(config->errors, "Metalink: parsing (%s) OK\n", this_url);
+ fprintf(config->global->errors, "Metalink: parsing (%s) OK\n",
+ this_url);
else if(rv == -1)
- fprintf(config->errors, "Metalink: parsing (%s) FAILED\n",
+ fprintf(config->global->errors, "Metalink: parsing (%s) FAILED\n",
this_url);
}
else if(metalink && res == CURLE_OK && !metalink_next_res) {
- int rv = metalink_check_hash(config, mlfile, outs.filename);
+ int rv = metalink_check_hash(global, mlfile, outs.filename);
if(rv == 0) {
metalink_next_res = 1;
}
quit_curl:
+ /* Reset the global config variables */
+ global->noprogress = orig_noprogress;
+ global->isatty = orig_isatty;
+
/* Free function-local referenced allocated memory */
Curl_safefree(httpgetfields);
/* Free list of given URLs */
clean_getout(config);
- /* Cleanup the curl handle now that our
- progressbar struct is still in scope */
- if(curl) {
- curl_easy_cleanup(curl);
- config->easy = curl = NULL;
- }
-#ifndef CURL_DISABLE_LIBCURL_OPTION
- easysrc_cleanup();
-#endif
-
hdrcbdata.heads = NULL;
/* Close function-local opened file descriptors */
-
if(heads.fopened && heads.stream)
fclose(heads.stream);
+
if(heads.alloc_filename)
Curl_safefree(heads.filename);
- if(config->trace_fopened && config->trace_stream)
- fclose(config->trace_stream);
+ /* Release metalink related resources here */
+ clean_metalink(config);
+
+ return res;
+}
+
+CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[])
+{
+ CURLcode result = CURLE_OK;
+ /* Setup proper locale from environment */
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_ALL, "");
+#endif
+
+ /* Parse .curlrc if necessary */
+ if((argc == 1) || (!curlx_strequal(argv[1], "-q"))) {
+ parseconfig(NULL, config); /* ignore possible failure */
+
+ /* If we had no arguments then make sure a url was specified in .curlrc */
+ if((argc < 2) && (!config->first->url_list)) {
+ helpf(config->errors, NULL);
+ result = CURLE_FAILED_INIT;
+ }
+ }
+
+ if(!result) {
+ /* Parse the command line arguments */
+ ParameterError res = parse_args(config, argc, argv);
+ if(res) {
+ result = CURLE_OK;
+
+ /* Check if we were asked for the help */
+ if(res == PARAM_HELP_REQUESTED)
+ tool_help();
+ /* Check if we were asked for the manual */
+ else if(res == PARAM_MANUAL_REQUESTED)
+ hugehelp();
+ /* Check if we were asked for the version information */
+ else if(res == PARAM_VERSION_INFO_REQUESTED)
+ tool_version_info();
+ /* Check if we were asked to list the SSL engines */
+ else if(res == PARAM_ENGINES_REQUESTED)
+ tool_list_engines(config->easy);
+ else
+ result = CURLE_FAILED_INIT;
+ }
+ else {
#ifndef CURL_DISABLE_LIBCURL_OPTION
- /* Dump the libcurl code if previously enabled.
- NOTE: that this function relies on config->errors amongst other things
- so not everything can be closed and cleaned before this is called */
- dumpeasysrc(config);
+ /* Initialise the libcurl source output */
+ result = easysrc_init();
#endif
- if(config->errors_fopened && config->errors)
- fclose(config->errors);
+ /* Perform the main operations */
+ if(!result) {
+ size_t count = 0;
+ struct OperationConfig *operation = config->first;
- /* Release metalink related resources here */
- clean_metalink(config);
+ /* Get the required aguments for each operation */
+ while(!result && operation) {
+ result = get_args(operation, count++);
+
+ operation = operation->next;
+ }
- main_free(); /* cleanup */
+ /* Set the current operation pointer */
+ config->current = config->first;
- return res;
-}
+ /* Perform each operation */
+ while(!result && config->current) {
+ result = operate_do(config, config->current);
+
+ config->current = config->current->next;
+ }
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ /* Cleanup the libcurl source output */
+ easysrc_cleanup();
+
+ /* Dump the libcurl code if previously enabled */
+ dumpeasysrc(config);
+#endif
+ }
+ else
+ helpf(config->errors, "out of memory\n");
+ }
+ }
+
+ return result;
+}