#include "tool_writeout.h"
#include "tool_xattr.h"
#include "tool_vms.h"
+#include "tool_help.h"
+#include "tool_hugehelp.h"
#include "memdebug.h" /* keep this as LAST include */
"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;
}
#ifdef __VMS
}
#endif /* __VMS */
-
-int operate(struct Configurable *config, int argc, argv_item_t argv[])
+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.config = config;
/*
- ** Initialize curl library - do not call any libcurl functions before
- ** this point.
- */
- 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
-
- 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++) {
- char *orig_opt = argv[i];
-
- if(stillflags &&
- ('-' == argv[i][0])) {
- char *nextarg;
- bool passarg;
- 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 && 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) {
- 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(config->userpwd && !config->xoauth2_bearer) {
- res = checkpasswd("host", &config->userpwd);
- if(res)
- goto quit_curl;
- }
-
- if(config->proxyuserpwd) {
- res = checkpasswd("proxy", &config->proxyuserpwd);
- 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.
*/
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;
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;
}
else {
if(urls) {
- res = glob_next_url(&this_url, urls);
+ res = (CURLcode) glob_next_url(&this_url, urls);
if(res)
goto show_error;
}
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;
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;
}
if((infd == -1) || fstat(infd, &fileinfo))
#endif
{
- helpf(config->errors, "Can't open '%s'!\n", uploadfile);
+ 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[%lu/%lu]: %s --> %s\n",
+ 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);
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(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?1L:0L);
+ my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L);
if(config->no_body) {
my_setopt(curl, CURLOPT_NOBODY, 1L);
my_setopt(curl, CURLOPT_HEADER, 1L);
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);
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?1L:0L);
+ /* 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_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_XFERINFOFUNCTION, tool_progress_cb);
/* disable it */
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, 1L);
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 */
#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++);
- main_free(); /* cleanup */
+ operation = operation->next;
+ }
- return res;
+ /* Set the current operation pointer */
+ config->current = config->first;
+
+ /* 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;
}