curl tool: code moved to tool_*.[ch] files
authorYang Tse <yangsita@gmail.com>
Tue, 4 Oct 2011 22:03:20 +0000 (00:03 +0200)
committerYang Tse <yangsita@gmail.com>
Tue, 4 Oct 2011 22:03:58 +0000 (00:03 +0200)
29 files changed:
buildconf
packages/Symbian/group/curl.mmp
src/Makefile.inc
src/Makefile.vc6
src/main.c [deleted file]
src/tool_doswin.c
src/tool_doswin.h
src/tool_easysrc.h
src/tool_getparam.c [new file with mode: 0644]
src/tool_getparam.h [new file with mode: 0644]
src/tool_help.c [new file with mode: 0644]
src/tool_help.h [moved from src/tool_myfunc.h with 88% similarity]
src/tool_helpers.c [new file with mode: 0644]
src/tool_helpers.h [new file with mode: 0644]
src/tool_main.c [new file with mode: 0644]
src/tool_main.h [new file with mode: 0644]
src/tool_operate.c [new file with mode: 0644]
src/tool_operate.h [new file with mode: 0644]
src/tool_operhlp.c [new file with mode: 0644]
src/tool_operhlp.h [new file with mode: 0644]
src/tool_panykey.c [moved from src/tool_myfunc.c with 70% similarity]
src/tool_panykey.h [new file with mode: 0644]
src/tool_paramhlp.c [new file with mode: 0644]
src/tool_paramhlp.h [new file with mode: 0644]
src/tool_parsecfg.c [new file with mode: 0644]
src/tool_parsecfg.h [new file with mode: 0644]
src/tool_sleep.c [new file with mode: 0644]
src/tool_sleep.h [new file with mode: 0644]
src/vc6curlsrc.dsp

index 8083c2b..dda2a1d 100755 (executable)
--- a/buildconf
+++ b/buildconf
@@ -80,7 +80,7 @@ removethis(){
 # Ensure that buildconf runs from the subdirectory where configure.ac lives
 #
 if test ! -f configure.ac ||
-  test ! -f src/main.c ||
+  test ! -f src/tool_main.c ||
   test ! -f lib/urldata.h ||
   test ! -f include/curl/curl.h; then
   echo "Can not run buildconf from outside of curl's source subdirectory!"
index ab20f7f..0f548c6 100644 (file)
@@ -8,7 +8,7 @@ UID           0x00000000 0xF0206442
 
 SOURCEPATH  ../../../src
 SOURCE \
-    main.c hugehelp.c urlglob.c writeout.c writeenv.c \
+    hugehelp.c urlglob.c writeout.c writeenv.c \
     getpass.c homedir.c curlutil.c xattr.c \
     tool_binmode.c \
     tool_bname.c \
@@ -25,11 +25,20 @@ SOURCE \
     tool_doswin.c \
     tool_easysrc.c \
     tool_formparse.c \
+    tool_getparam.c \
+    tool_help.c \
+    tool_helpers.c \
     tool_libinfo.c \
+    tool_main.c \
     tool_mfiles.c \
     tool_msgs.c \
-    tool_myfunc.c \
+    tool_operate.c \
+    tool_operhlp.c \
+    tool_panykey.c \
+    tool_paramhlp.c \
+    tool_parsecfg.c \
     tool_setopt.c \
+    tool_sleep.c \
     tool_vms.c
 
 SOURCEPATH  ../../../lib
index 640fd63..af6f6b4 100644 (file)
@@ -14,7 +14,7 @@ CURLX_ONES = $(top_srcdir)/lib/strtoofft.c \
        $(top_srcdir)/lib/rawstr.c \
        $(top_srcdir)/lib/nonblock.c
 
-CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
+CURL_CFILES = hugehelp.c urlglob.c writeout.c writeenv.c \
        getpass.c homedir.c curlutil.c xattr.c \
        tool_binmode.c \
        tool_bname.c \
@@ -31,11 +31,20 @@ CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
        tool_doswin.c \
        tool_easysrc.c \
        tool_formparse.c \
+       tool_getparam.c \
+       tool_help.c \
+       tool_helpers.c \
        tool_libinfo.c \
+       tool_main.c \
        tool_mfiles.c \
        tool_msgs.c \
-       tool_myfunc.c \
+       tool_operate.c \
+       tool_operhlp.c \
+       tool_panykey.c \
+       tool_paramhlp.c \
+       tool_parsecfg.c \
        tool_setopt.c \
+       tool_sleep.c \
        tool_vms.c
 
 CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \
@@ -56,12 +65,21 @@ CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \
        tool_doswin.h \
        tool_easysrc.h \
        tool_formparse.h \
+       tool_getparam.h \
+       tool_help.h \
+       tool_helpers.h \
        tool_libinfo.h \
+       tool_main.h \
        tool_mfiles.h \
        tool_msgs.h \
-       tool_myfunc.h \
+       tool_operate.h \
+       tool_operhlp.h \
+       tool_panykey.h \
+       tool_paramhlp.h \
+       tool_parsecfg.h \
        tool_sdecls.h \
        tool_setopt.h \
+       tool_sleep.h \
        tool_vms.h
 
 curl_SOURCES = $(CURL_CFILES) $(CURLX_ONES) $(CURL_HFILES)
index 9d6ea26..5cec77a 100644 (file)
@@ -42,7 +42,7 @@ PROGRAM_NAME = curl.exe
 # Verify that current subdir is curl's 'src'\r
 # -------------------------------------------\r
 \r
-!IF ! EXIST(.\main.c)\r
+!IF ! EXIST(.\tool_main.c)\r
 !  MESSAGE Can not process this makefile from outside of curl's 'src' subdirectory.\r
 !  MESSAGE Change to curl's 'src' subdirectory, and try again.\r
 !  ERROR   See previous message.\r
@@ -137,7 +137,6 @@ RELEASE_OBJS= \
        getpassr.obj \\r
        homedirr.obj \\r
        hugehelpr.obj \\r
-       mainr.obj \\r
        nonblockr.obj \\r
        rawstrr.obj \\r
        strtoofftr.obj \\r
@@ -156,11 +155,20 @@ RELEASE_OBJS= \
        tool_doswinr.obj \\r
        tool_easysrcr.obj \\r
        tool_formparser.obj \\r
+       tool_getparamr.obj \\r
+       tool_helpr.obj \\r
+       tool_helpersr.obj \\r
        tool_libinfor.obj \\r
+       tool_mainr.obj \\r
        tool_mfilesr.obj \\r
        tool_msgsr.obj \\r
-       tool_myfuncr.obj \\r
+       tool_operater.obj \\r
+       tool_operhlpr.obj \\r
+       tool_panykeyr.obj \\r
+       tool_paramhlpr.obj \\r
+       tool_parsecfgr.obj \\r
        tool_setoptr.obj \\r
+       tool_sleepr.obj \\r
        tool_vmsr.obj \\r
        urlglobr.obj \\r
        writeoutr.obj \\r
@@ -172,7 +180,6 @@ DEBUG_OBJS= \
        getpassd.obj \\r
        homedird.obj \\r
        hugehelpd.obj \\r
-       maind.obj \\r
        nonblockd.obj \\r
        rawstrd.obj \\r
        strtoofftd.obj \\r
@@ -191,11 +198,20 @@ DEBUG_OBJS= \
        tool_doswind.obj \\r
        tool_easysrcd.obj \\r
        tool_formparsed.obj \\r
+       tool_getparamd.obj \\r
+       tool_helpd.obj \\r
+       tool_helpersd.obj \\r
        tool_libinfod.obj \\r
+       tool_maind.obj \\r
        tool_mfilesd.obj \\r
        tool_msgsd.obj \\r
-       tool_myfuncd.obj \\r
+       tool_operated.obj \\r
+       tool_operhlpd.obj \\r
+       tool_panykeyd.obj \\r
+       tool_paramhlpd.obj \\r
+       tool_parsecfgd.obj \\r
        tool_setoptd.obj \\r
+       tool_sleepd.obj \\r
        tool_vmsd.obj \\r
        urlglobd.obj \\r
        writeoutd.obj \\r
@@ -370,22 +386,38 @@ tool_easysrcr.obj: tool_easysrc.c
        $(CCR) $(CFLAGS) /Fo"$@" tool_easysrc.c\r
 tool_formparser.obj: tool_formparse.c\r
        $(CCR) $(CFLAGS) /Fo"$@" tool_formparse.c\r
+tool_getparamr.obj: tool_getparam.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_getparam.c\r
+tool_helpr.obj: tool_help.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_help.c\r
+tool_helpersr.obj: tool_helpers.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_helpers.c\r
 tool_libinfor.obj: tool_libinfo.c\r
        $(CCR) $(CFLAGS) /Fo"$@" tool_libinfo.c\r
+tool_mainr.obj: tool_main.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_main.c\r
 tool_mfilesr.obj: tool_mfiles.c\r
        $(CCR) $(CFLAGS) /Fo"$@" tool_mfiles.c\r
 tool_msgsr.obj: tool_msgs.c\r
        $(CCR) $(CFLAGS) /Fo"$@" tool_msgs.c\r
-tool_myfuncr.obj: tool_myfunc.c\r
-       $(CCR) $(CFLAGS) /Fo"$@" tool_myfunc.c\r
+tool_operater.obj: tool_operate.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_operate.c\r
+tool_operhlpr.obj: tool_operhlp.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_operhlp.c\r
+tool_panykeyr.obj: tool_panykey.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_panykey.c\r
+tool_paramhlpr.obj: tool_paramhlp.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_paramhlp.c\r
+tool_parsecfgr.obj: tool_parsecfg.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_parsecfg.c\r
 tool_setoptr.obj: tool_setopt.c\r
        $(CCR) $(CFLAGS) /Fo"$@" tool_setopt.c\r
+tool_sleepr.obj: tool_sleep.c\r
+       $(CCR) $(CFLAGS) /Fo"$@" tool_sleep.c\r
 tool_vmsr.obj: tool_vms.c\r
        $(CCR) $(CFLAGS) /Fo"$@" tool_vms.c\r
 xattrr.obj: xattr.c\r
        $(CCR) $(CFLAGS) /Fo"$@" xattr.c\r
-mainr.obj: main.c\r
-       $(CCR) $(CFLAGS) /Fo"$@" main.c\r
 curlr.res : curl.rc\r
        $(RCR) $(RESFLAGS) /Fo"$@" curl.rc\r
 \r
@@ -438,22 +470,38 @@ tool_easysrcd.obj: tool_easysrc.c
        $(CCD) $(CFLAGS) /Fo"$@" tool_easysrc.c\r
 tool_formparsed.obj: tool_formparse.c\r
        $(CCD) $(CFLAGS) /Fo"$@" tool_formparse.c\r
+tool_getparamd.obj: tool_getparam.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_getparam.c\r
+tool_helpd.obj: tool_help.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_help.c\r
+tool_helpersd.obj: tool_helpers.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_helpers.c\r
 tool_libinfod.obj: tool_libinfo.c\r
        $(CCD) $(CFLAGS) /Fo"$@" tool_libinfo.c\r
+tool_maind.obj: tool_main.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_main.c\r
 tool_mfilesd.obj: tool_mfiles.c\r
        $(CCD) $(CFLAGS) /Fo"$@" tool_mfiles.c\r
 tool_msgsd.obj: tool_msgs.c\r
        $(CCD) $(CFLAGS) /Fo"$@" tool_msgs.c\r
-tool_myfuncd.obj: tool_myfunc.c\r
-       $(CCD) $(CFLAGS) /Fo"$@" tool_myfunc.c\r
+tool_operated.obj: tool_operate.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_operate.c\r
+tool_operhlpd.obj: tool_operhlp.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_operhlp.c\r
+tool_panykeyd.obj: tool_panykey.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_panykey.c\r
+tool_paramhlpd.obj: tool_paramhlp.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_paramhlp.c\r
+tool_parsecfgd.obj: tool_parsecfg.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_parsecfg.c\r
 tool_setoptd.obj: tool_setopt.c\r
        $(CCD) $(CFLAGS) /Fo"$@" tool_setopt.c\r
+tool_sleepd.obj: tool_sleep.c\r
+       $(CCD) $(CFLAGS) /Fo"$@" tool_sleep.c\r
 tool_vmsd.obj: tool_vms.c\r
        $(CCD) $(CFLAGS) /Fo"$@" tool_vms.c\r
 xattrd.obj: xattr.c\r
        $(CCD) $(CFLAGS) /Fo"$@" xattr.c\r
-maind.obj: main.c\r
-       $(CCD) $(CFLAGS) /Fo"$@" main.c\r
 curld.res : curl.rc\r
        $(RCD) $(RESFLAGS) /Fo"$@" curl.rc\r
 \r
diff --git a/src/main.c b/src/main.c
deleted file mode 100644 (file)
index f331e4d..0000000
+++ /dev/null
@@ -1,4309 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, 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
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-#include "setup.h"
-
-#include <curl/curl.h>
-
-/*
-** system headers
-*/
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef NETWARE
-#  ifdef __NOVELL_LIBC__
-#    include <screen.h>
-#  else
-#    include <nwconio.h>
-#  endif
-#endif
-
-#ifdef HAVE_IO_H
-#  include <io.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#  include <fcntl.h>
-#endif
-
-#ifdef HAVE_UTIME_H
-#  include <utime.h>
-#elif defined(HAVE_SYS_UTIME_H)
-#  include <sys/utime.h>
-#endif
-
-#ifdef HAVE_LIMITS_H
-#  include <limits.h>
-#endif
-
-#ifdef HAVE_SYS_POLL_H
-#  include <sys/poll.h>
-#elif defined(HAVE_POLL_H)
-#  include <poll.h>
-#endif
-
-#ifdef HAVE_LOCALE_H
-#  include <locale.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#  include <netinet/in.h>
-#endif
-
-#ifdef HAVE_NETINET_TCP_H
-#  include <netinet/tcp.h>
-#endif
-
-#ifdef MSDOS
-#  include <dos.h>
-#endif
-
-/*
-** src subdirectory headers
-*/
-
-#include "urlglob.h"
-#include "writeout.h"
-#include "getpass.h"
-#include "homedir.h"
-#include "curlutil.h"
-#include "version.h"
-#include "xattr.h"
-#include "tool_cfgable.h"
-#include "tool_convert.h"
-#include "tool_dirhie.h"
-#include "tool_doswin.h"
-#include "tool_easysrc.h"
-#include "tool_libinfo.h"
-#include "tool_mfiles.h"
-#include "tool_msgs.h"
-#include "tool_myfunc.h"
-#include "tool_cb_prg.h"
-#include "tool_setopt.h"
-#include "tool_vms.h"
-
-#include "tool_cb_rea.h"
-#include "tool_cb_wrt.h"
-#include "tool_cb_see.h"
-#include "tool_cb_skt.h"
-#include "tool_cb_hdr.h"
-#include "tool_cb_dbg.h"
-
-#include "tool_binmode.h"
-#include "tool_formparse.h"
-
-#ifdef USE_MANUAL
-#  include "hugehelp.h"
-#endif
-#ifdef USE_ENVIRONMENT
-#  include "writeenv.h"
-#endif
-
-/*
-** libcurl subdirectory headers
-*/
-
-#include "rawstr.h"
-
-#define ENABLE_CURLX_PRINTF
-/* make the curlx header define all printf() functions to use the curlx_*
-   versions instead */
-#include "curlx.h"
-
-/* This is low-level hard-hacking memory leak tracking and similar. Using
-   the library level code from this client-side is ugly, but we do this
-   anyway for convenience. */
-#include "memdebug.h" /* keep this as LAST include */
-
-#ifdef __VMS
-static int vms_show = 0;
-#endif
-
-#if defined(NETWARE)
-#define PRINT_LINES_PAUSE 23
-#endif
-
-#if defined(__SYMBIAN32__)
-#define PRINT_LINES_PAUSE 16
-#define pressanykey() getchar()
-#endif
-
-#define DEFAULT_MAXREDIRS  50L
-
-#ifndef O_BINARY
-/* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
-   source code but yet it doesn't ruin anything */
-#define O_BINARY 0
-#endif
-
-#ifdef MSDOS
-#define USE_WATT32
-#ifdef DJGPP
-/* we want to glob our own argv[] */
-char **__crt0_glob_function (char *arg)
-{
-  (void)arg;
-  return (char**)0;
-}
-#endif /* __DJGPP__ */
-#endif /* MSDOS */
-
-#ifndef STDIN_FILENO
-#define STDIN_FILENO  fileno(stdin)
-#endif
-
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO  fileno(stdout)
-#endif
-
-#ifndef STDERR_FILENO
-#define STDERR_FILENO  fileno(stderr)
-#endif
-
-#define CURLseparator   "--_curl_--"
-
-#define CURL_CA_CERT_ERRORMSG1                                          \
-  "More details here: http://curl.haxx.se/docs/sslcerts.html\n\n"       \
-  "curl performs SSL certificate verification by default, "             \
-  "using a \"bundle\"\n"                                                \
-  " of Certificate Authority (CA) public keys (CA certs). If the default\n" \
-  " bundle file isn't adequate, you can specify an alternate file\n"    \
-  " using the --cacert option.\n"
-
-#define CURL_CA_CERT_ERRORMSG2                                          \
-  "If this HTTPS server uses a certificate signed by a CA represented in\n" \
-  " the bundle, the certificate verification probably failed due to a\n" \
-  " problem with the certificate (it might be expired, or the name might\n" \
-  " not match the domain name in the URL).\n"                           \
-  "If you'd like to turn off curl's verification of the certificate, use\n" \
-  " the -k (or --insecure) option.\n"
-
-/*
- * This is the main global constructor for the app. Call this before
- * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
- * used, or havoc may be the result.
- */
-static CURLcode main_init(void)
-{
-#ifdef DJGPP
-  /* stop stat() wasting time */
-  _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
-#endif
-
-  return curl_global_init(CURL_GLOBAL_DEFAULT);
-}
-
-/*
- * This is the main global destructor for the app. Call this after
- * _all_ libcurl usage is done.
- */
-static void main_free(void)
-{
-  curl_global_cleanup();
-  convert_cleanup();
-}
-
-static int SetHTTPrequest(struct Configurable *config,
-                          HttpReq req, HttpReq *store)
-{
-  if((*store == HTTPREQ_UNSPEC) ||
-     (*store == req)) {
-    *store = req;
-    return 0;
-  }
-  warnf(config, "You can only select one HTTP request!\n");
-  return 1;
-}
-
-static void help(void)
-{
-  int i;
-  /* A few of these source lines are >80 columns wide, but that's only because
-     breaking the strings narrower makes this chunk look even worse!
-
-     Starting with 7.18.0, this list of command line options is sorted based
-     on the long option name. It is not done automatically, although a command
-     line like the following can help out:
-
-     curl --help | cut -c5- | grep "^-" | sort
-  */
-  static const char * const helptext[]={
-    "Usage: curl [options...] <url>",
-    "Options: (H) means HTTP/HTTPS only, (F) means FTP only",
-    "     --anyauth       Pick \"any\" authentication method (H)",
-    " -a, --append        Append to target file when uploading (F/SFTP)",
-    "     --basic         Use HTTP Basic Authentication (H)",
-    "     --cacert FILE   CA certificate to verify peer against (SSL)",
-    "     --capath DIR    CA directory to verify peer against (SSL)",
-    " -E, --cert CERT[:PASSWD] Client certificate file and password (SSL)",
-    "     --cert-type TYPE Certificate file type (DER/PEM/ENG) (SSL)",
-    "     --ciphers LIST  SSL ciphers to use (SSL)",
-    "     --compressed    Request compressed response (using deflate or gzip)",
-    " -K, --config FILE   Specify which config file to read",
-    "     --connect-timeout SECONDS  Maximum time allowed for connection",
-    " -C, --continue-at OFFSET  Resumed transfer offset",
-    " -b, --cookie STRING/FILE  String or file to read cookies from (H)",
-    " -c, --cookie-jar FILE  Write cookies to this file after operation (H)",
-    "     --create-dirs   Create necessary local directory hierarchy",
-    "     --crlf          Convert LF to CRLF in upload",
-    "     --crlfile FILE  Get a CRL list in PEM format from the given file",
-    " -d, --data DATA     HTTP POST data (H)",
-    "     --data-ascii DATA  HTTP POST ASCII data (H)",
-    "     --data-binary DATA  HTTP POST binary data (H)",
-    "     --data-urlencode DATA  HTTP POST data url encoded (H)",
-    "     --delegation STRING GSS-API delegation permission",
-    "     --digest        Use HTTP Digest Authentication (H)",
-    "     --disable-eprt  Inhibit using EPRT or LPRT (F)",
-    "     --disable-epsv  Inhibit using EPSV (F)",
-    " -D, --dump-header FILE  Write the headers to this file",
-    "     --egd-file FILE  EGD socket path for random data (SSL)",
-    "     --engine ENGINGE  Crypto engine (SSL). \"--engine list\" for list",
-#ifdef USE_ENVIRONMENT
-    "     --environment   Write results to environment variables (RISC OS)",
-#endif
-    " -f, --fail          Fail silently (no output at all) on HTTP errors (H)",
-    " -F, --form CONTENT  Specify HTTP multipart POST data (H)",
-    "     --form-string STRING  Specify HTTP multipart POST data (H)",
-    "     --ftp-account DATA  Account data string (F)",
-    "     --ftp-alternative-to-user COMMAND  "
-    "String to replace \"USER [name]\" (F)",
-    "     --ftp-create-dirs  Create the remote dirs if not present (F)",
-    "     --ftp-method [MULTICWD/NOCWD/SINGLECWD] Control CWD usage (F)",
-    "     --ftp-pasv      Use PASV/EPSV instead of PORT (F)",
-    " -P, --ftp-port ADR  Use PORT with given address instead of PASV (F)",
-    "     --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
-    "     --ftp-pret      Send PRET before PASV (for drftpd) (F)",
-    "     --ftp-ssl-ccc   Send CCC after authenticating (F)",
-    "     --ftp-ssl-ccc-mode ACTIVE/PASSIVE  Set CCC mode (F)",
-    "     --ftp-ssl-control Require SSL/TLS for ftp login, "
-    "clear for transfer (F)",
-    " -G, --get           Send the -d data with a HTTP GET (H)",
-    " -g, --globoff       Disable URL sequences and ranges using {} and []",
-    " -H, --header LINE   Custom header to pass to server (H)",
-    " -I, --head          Show document info only",
-    " -h, --help          This help text",
-    "     --hostpubmd5 MD5  "
-    "Hex encoded MD5 string of the host public key. (SSH)",
-    " -0, --http1.0       Use HTTP 1.0 (H)",
-    "     --ignore-content-length  Ignore the HTTP Content-Length header",
-    " -i, --include       Include protocol headers in the output (H/F)",
-    " -k, --insecure      Allow connections to SSL sites without certs (H)",
-    "     --interface INTERFACE  Specify network interface/address to use",
-    " -4, --ipv4          Resolve name to IPv4 address",
-    " -6, --ipv6          Resolve name to IPv6 address",
-    " -j, --junk-session-cookies Ignore session cookies read from file (H)",
-    "     --keepalive-time SECONDS  Interval between keepalive probes",
-    "     --key KEY       Private key file name (SSL/SSH)",
-    "     --key-type TYPE Private key file type (DER/PEM/ENG) (SSL)",
-    "     --krb LEVEL     Enable Kerberos with specified security level (F)",
-    "     --libcurl FILE  Dump libcurl equivalent code of this command line",
-    "     --limit-rate RATE  Limit transfer speed to this rate",
-    " -l, --list-only     List only names of an FTP directory (F)",
-    "     --local-port RANGE  Force use of these local port numbers",
-    " -L, --location      Follow redirects (H)",
-    "     --location-trusted like --location and send auth to other hosts (H)",
-    " -M, --manual        Display the full manual",
-    "     --mail-from FROM  Mail from this address",
-    "     --mail-rcpt TO  Mail to this receiver(s)",
-    "     --max-filesize BYTES  Maximum file size to download (H/F)",
-    "     --max-redirs NUM  Maximum number of redirects allowed (H)",
-    " -m, --max-time SECONDS  Maximum time allowed for the transfer",
-    "     --negotiate     Use HTTP Negotiate Authentication (H)",
-    " -n, --netrc         Must read .netrc for user name and password",
-    "     --netrc-optional Use either .netrc or URL; overrides -n",
-    "     --netrc-file FILE  Set up the netrc filename to use",
-    " -N, --no-buffer     Disable buffering of the output stream",
-    "     --no-keepalive  Disable keepalive use on the connection",
-    "     --no-sessionid  Disable SSL session-ID reusing (SSL)",
-    "     --noproxy       List of hosts which do not use proxy",
-    "     --ntlm          Use HTTP NTLM authentication (H)",
-    " -o, --output FILE   Write output to <file> instead of stdout",
-    "     --pass PASS     Pass phrase for the private key (SSL/SSH)",
-    "     --post301       "
-    "Do not switch to GET after following a 301 redirect (H)",
-    "     --post302       "
-    "Do not switch to GET after following a 302 redirect (H)",
-    " -#, --progress-bar  Display transfer progress as a progress bar",
-    "     --proto PROTOCOLS  Enable/disable specified protocols",
-    "     --proto-redir PROTOCOLS  "
-    "Enable/disable specified protocols on redirect",
-    " -x, --proxy [PROTOCOL://]HOST[:PORT] Use proxy on given port",
-    "     --proxy-anyauth Pick \"any\" proxy authentication method (H)",
-    "     --proxy-basic   Use Basic authentication on the proxy (H)",
-    "     --proxy-digest  Use Digest authentication on the proxy (H)",
-    "     --proxy-negotiate Use Negotiate authentication on the proxy (H)",
-    "     --proxy-ntlm    Use NTLM authentication on the proxy (H)",
-    " -U, --proxy-user USER[:PASSWORD]  Proxy user and password",
-    "     --proxy1.0 HOST[:PORT]  Use HTTP/1.0 proxy on given port",
-    " -p, --proxytunnel   Operate through a HTTP proxy tunnel (using CONNECT)",
-    "     --pubkey KEY    Public key file name (SSH)",
-    " -Q, --quote CMD     Send command(s) to server before transfer (F/SFTP)",
-    "     --random-file FILE  File for reading random data from (SSL)",
-    " -r, --range RANGE   Retrieve only the bytes within a range",
-    "     --raw           Do HTTP \"raw\", without any transfer decoding (H)",
-    " -e, --referer       Referer URL (H)",
-    " -J, --remote-header-name Use the header-provided filename (H)",
-    " -O, --remote-name   Write output to a file named as the remote file",
-    "     --remote-name-all Use the remote file name for all URLs",
-    " -R, --remote-time   Set the remote file's time on the local output",
-    " -X, --request COMMAND  Specify request command to use",
-    "     --resolve HOST:PORT:ADDRESS  Force resolve of HOST:PORT to ADDRESS",
-    "     --retry NUM   "
-    "Retry request NUM times if transient problems occur",
-    "     --retry-delay SECONDS "
-    "When retrying, wait this many seconds between each",
-    "     --retry-max-time SECONDS  Retry only within this period",
-    " -S, --show-error    "
-    "Show error. With -s, make curl show errors when they occur",
-    " -s, --silent        Silent mode. Don't output anything",
-    "     --socks4 HOST[:PORT]  SOCKS4 proxy on given host + port",
-    "     --socks4a HOST[:PORT]  SOCKS4a proxy on given host + port",
-    "     --socks5 HOST[:PORT]  SOCKS5 proxy on given host + port",
-    "     --socks5-hostname HOST[:PORT] "
-    "SOCKS5 proxy, pass host name to proxy",
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-    "     --socks5-gssapi-service NAME  SOCKS5 proxy service name for gssapi",
-    "     --socks5-gssapi-nec  Compatibility with NEC SOCKS5 server",
-#endif
-    " -Y, --speed-limit RATE  "
-    "Stop transfers below speed-limit for 'speed-time' secs",
-    " -y, --speed-time SECONDS  "
-    "Time for trig speed-limit abort. Defaults to 30",
-    "     --ssl           Try SSL/TLS (FTP, IMAP, POP3, SMTP)",
-    "     --ssl-reqd      Require SSL/TLS (FTP, IMAP, POP3, SMTP)",
-    " -2, --sslv2         Use SSLv2 (SSL)",
-    " -3, --sslv3         Use SSLv3 (SSL)",
-    "     --stderr FILE   Where to redirect stderr. - means stdout",
-    "     --tcp-nodelay   Use the TCP_NODELAY option",
-    " -t, --telnet-option OPT=VAL  Set telnet option",
-    "     --tftp-blksize VALUE  Set TFTP BLKSIZE option (must be >512)",
-    " -z, --time-cond TIME  Transfer based on a time condition",
-    " -1, --tlsv1         Use TLSv1 (SSL)",
-    "     --trace FILE    Write a debug trace to the given file",
-    "     --trace-ascii FILE  Like --trace but without the hex output",
-    "     --trace-time    Add time stamps to trace/verbose output",
-    "     --tr-encoding   Request compressed transfer encoding (H)",
-    " -T, --upload-file FILE  Transfer FILE to destination",
-    "     --url URL       URL to work with",
-    " -B, --use-ascii     Use ASCII/text transfer",
-    " -u, --user USER[:PASSWORD]  Server user and password",
-    "     --tlsuser USER  TLS username",
-    "     --tlspassword STRING TLS password",
-    "     --tlsauthtype STRING  TLS authentication type (default SRP)",
-    " -A, --user-agent STRING  User-Agent to send to server (H)",
-    " -v, --verbose       Make the operation more talkative",
-    " -V, --version       Show version number and quit",
-
-#ifdef USE_WATT32
-    "     --wdebug        Turn on Watt-32 debugging",
-#endif
-    " -w, --write-out FORMAT  What to output after completion",
-    "     --xattr        Store metadata in extended file attributes",
-    " -q                 If used as the first parameter disables .curlrc",
-    NULL
-  };
-  for(i=0; helptext[i]; i++) {
-    puts(helptext[i]);
-#ifdef PRINT_LINES_PAUSE
-    if(i && ((i % PRINT_LINES_PAUSE) == 0))
-      pressanykey();
-#endif
-  }
-}
-
-struct LongShort {
-  const char *letter;
-  const char *lname;
-  bool extraparam;
-};
-
-static int parseconfig(const char *filename,
-                       struct Configurable *config);
-static char *my_get_line(FILE *fp);
-
-#define GetStr(str,val) \
-do { \
-  if(*(str)) { \
-    free(*(str)); \
-    *(str) = NULL; \
-  } \
-  if((val)) \
-    *(str) = strdup((val)); \
-  if(!*(str)) \
-    return PARAM_NO_MEM; \
-} WHILE_FALSE
-
-static void clean_getout(struct Configurable *config)
-{
-  struct getout *next;
-  struct getout *node = config->url_list;
-
-  while(node) {
-    next = node->next;
-    Curl_safefree(node->url);
-    Curl_safefree(node->outfile);
-    Curl_safefree(node->infile);
-    Curl_safefree(node);
-    node = next;
-  }
-  config->url_list = NULL;
-}
-
-static struct getout *new_getout(struct Configurable *config)
-{
-  struct getout *node =malloc(sizeof(struct getout));
-  struct getout *last= config->url_last;
-  if(node) {
-    /* clear the struct */
-    memset(node, 0, sizeof(struct getout));
-
-    /* append this new node last in the list */
-    if(last)
-      last->next = node;
-    else
-      config->url_list = node; /* first node */
-
-    /* move the last pointer */
-    config->url_last = node;
-
-    node->flags = config->default_node_flags;
-  }
-  return node;
-}
-
-/* Print list of OpenSSL engines supported.
- */
-static void list_engines(const struct curl_slist *engines)
-{
-  puts("Build-time engines:");
-  if(!engines) {
-    puts("  <none>");
-    return;
-  }
-  for(; engines; engines = engines->next)
-    printf("  %s\n", engines->data);
-}
-
-typedef enum {
-  PARAM_OK,
-  PARAM_OPTION_AMBIGUOUS,
-  PARAM_OPTION_UNKNOWN,
-  PARAM_REQUIRES_PARAMETER,
-  PARAM_BAD_USE,
-  PARAM_HELP_REQUESTED,
-  PARAM_GOT_EXTRA_PARAMETER,
-  PARAM_BAD_NUMERIC,
-  PARAM_LIBCURL_DOESNT_SUPPORT,
-  PARAM_NO_MEM,
-  PARAM_LAST
-} ParameterError;
-
-static const char *param2text(int res)
-{
-  ParameterError error = (ParameterError)res;
-  switch(error) {
-  case PARAM_GOT_EXTRA_PARAMETER:
-    return "had unsupported trailing garbage";
-  case PARAM_OPTION_UNKNOWN:
-    return "is unknown";
-  case PARAM_OPTION_AMBIGUOUS:
-    return "is ambiguous";
-  case PARAM_REQUIRES_PARAMETER:
-    return "requires parameter";
-  case PARAM_BAD_USE:
-    return "is badly used here";
-  case PARAM_BAD_NUMERIC:
-    return "expected a proper numerical parameter";
-  case PARAM_LIBCURL_DOESNT_SUPPORT:
-    return "the installed libcurl version doesn't support this";
-  case PARAM_NO_MEM:
-    return "out of memory";
-  default:
-    return "unknown error";
-  }
-}
-
-static ParameterError file2string(char **bufp, FILE *file)
-{
-  char buffer[256];
-  char *ptr;
-  char *string = NULL;
-  size_t stringlen = 0;
-  size_t buflen;
-
-  if(file) {
-    while(fgets(buffer, sizeof(buffer), file)) {
-      if((ptr = strchr(buffer, '\r')) != NULL)
-        *ptr = '\0';
-      if((ptr = strchr(buffer, '\n')) != NULL)
-        *ptr = '\0';
-      buflen = strlen(buffer);
-      if((ptr = realloc(string, stringlen+buflen+1)) == NULL) {
-        Curl_safefree(string);
-        return PARAM_NO_MEM;
-      }
-      string = ptr;
-      strcpy(string+stringlen, buffer);
-      stringlen += buflen;
-    }
-  }
-  *bufp = string;
-  return PARAM_OK;
-}
-
-static ParameterError file2memory(char **bufp, size_t *size, FILE *file)
-{
-  char *newbuf;
-  char *buffer = NULL;
-  size_t alloc = 512;
-  size_t nused = 0;
-  size_t nread;
-
-  if(file) {
-    do {
-      if(!buffer || (alloc == nused)) {
-        /* size_t overflow detection for huge files */
-        if(alloc+1 > ((size_t)-1)/2) {
-          Curl_safefree(buffer);
-          return PARAM_NO_MEM;
-        }
-        alloc *= 2;
-        /* allocate an extra char, reserved space, for null termination */
-        if((newbuf = realloc(buffer, alloc+1)) == NULL) {
-          Curl_safefree(buffer);
-          return PARAM_NO_MEM;
-        }
-        buffer = newbuf;
-      }
-      nread = fread(buffer+nused, 1, alloc-nused, file);
-      nused += nread;
-    } while(nread);
-    /* null terminate the buffer in case it's used as a string later */
-    buffer[nused] = '\0';
-    /* free trailing slack space, if possible */
-    if(alloc != nused) {
-      if((newbuf = realloc(buffer, nused+1)) != NULL)
-        buffer = newbuf;
-    }
-    /* discard buffer if nothing was read */
-    if(!nused) {
-      Curl_safefree(buffer); /* no string */
-    }
-  }
-  *size = nused;
-  *bufp = buffer;
-  return PARAM_OK;
-}
-
-static void cleanarg(char *str)
-{
-#ifdef HAVE_WRITABLE_ARGV
-  /* now that GetStr has copied the contents of nextarg, wipe the next
-   * argument out so that the username:password isn't displayed in the
-   * system process list */
-  if(str) {
-    size_t len = strlen(str);
-    memset(str, ' ', len);
-  }
-#else
-  (void)str;
-#endif
-}
-
-/*
- * Parse the string and write the integer in the given address. Return
- * non-zero on failure, zero on success.
- *
- * The string must start with a digit to be valid.
- *
- * Since this function gets called with the 'nextarg' pointer from within the
- * getparameter a lot, we must check it for NULL before accessing the str
- * data.
- */
-
-static int str2num(long *val, const char *str)
-{
-  if(str && ISDIGIT(*str)) {
-    char *endptr;
-    long num = strtol(str, &endptr, 10);
-    if((endptr != str) && (endptr == str + strlen(str))) {
-      *val = num;
-      return 0;  /* Ok */
-    }
-  }
-  return 1; /* badness */
-}
-
-/*
- * Parse the string and modify the long in the given address. Return
- * non-zero on failure, zero on success.
- *
- * The string is a list of protocols
- *
- * Since this function gets called with the 'nextarg' pointer from within the
- * getparameter a lot, we must check it for NULL before accessing the str
- * data.
- */
-
-static long proto2num(struct Configurable *config, long *val, const char *str)
-{
-  char *buffer;
-  const char *sep = ",";
-  char *token;
-
-  static struct sprotos {
-    const char *name;
-    long bit;
-  } const protos[] = {
-    { "all", CURLPROTO_ALL },
-    { "http", CURLPROTO_HTTP },
-    { "https", CURLPROTO_HTTPS },
-    { "ftp", CURLPROTO_FTP },
-    { "ftps", CURLPROTO_FTPS },
-    { "scp", CURLPROTO_SCP },
-    { "sftp", CURLPROTO_SFTP },
-    { "telnet", CURLPROTO_TELNET },
-    { "ldap", CURLPROTO_LDAP },
-    { "ldaps", CURLPROTO_LDAPS },
-    { "dict", CURLPROTO_DICT },
-    { "file", CURLPROTO_FILE },
-    { "tftp", CURLPROTO_TFTP },
-    { "imap", CURLPROTO_IMAP },
-    { "imaps", CURLPROTO_IMAPS },
-    { "pop3", CURLPROTO_POP3 },
-    { "pop3s", CURLPROTO_POP3S },
-    { "smtp", CURLPROTO_SMTP },
-    { "smtps", CURLPROTO_SMTPS },
-    { "rtsp", CURLPROTO_RTSP },
-    { "gopher", CURLPROTO_GOPHER },
-    { NULL, 0 }
-  };
-
-  if(!str)
-    return 1;
-
-  buffer = strdup(str); /* because strtok corrupts it */
-
-  for(token = strtok(buffer, sep);
-      token;
-      token = strtok(NULL, sep)) {
-    enum e_action { allow, deny, set } action = allow;
-
-    struct sprotos const *pp;
-
-    /* Process token modifiers */
-    while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
-      switch (*token++) {
-      case '=':
-        action = set;
-        break;
-      case '-':
-        action = deny;
-        break;
-      case '+':
-        action = allow;
-        break;
-      default: /* Includes case of terminating NULL */
-        Curl_safefree(buffer);
-        return 1;
-      }
-    }
-
-    for(pp=protos; pp->name; pp++) {
-      if(curlx_raw_equal(token, pp->name)) {
-        switch (action) {
-        case deny:
-          *val &= ~(pp->bit);
-          break;
-        case allow:
-          *val |= pp->bit;
-          break;
-        case set:
-          *val = pp->bit;
-          break;
-        }
-        break;
-      }
-    }
-
-    if(!(pp->name)) { /* unknown protocol */
-      /* If they have specified only this protocol, we say treat it as
-         if no protocols are allowed */
-      if(action == set)
-        *val = 0;
-      warnf(config, "unrecognized protocol '%s'\n", token);
-    }
-  }
-  Curl_safefree(buffer);
-  return 0;
-}
-
-/**
- * Parses the given string looking for an offset (which may be
- * a larger-than-integer value).
- *
- * @param val  the offset to populate
- * @param str  the buffer containing the offset
- * @return zero if successful, non-zero if failure.
- */
-static int str2offset(curl_off_t *val, const char *str)
-{
-#if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
-  *val = curlx_strtoofft(str, NULL, 0);
-  if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE))
-    return 1;
-#else
-  *val = strtol(str, NULL, 0);
-  if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE)
-    return 1;
-#endif
-  return 0;
-}
-
-static void checkpasswd(const char *kind, /* for what purpose */
-                        char **userpwd) /* pointer to allocated string */
-{
-  char *ptr;
-  if(!*userpwd)
-    return;
-
-  ptr = strchr(*userpwd, ':');
-  if(!ptr) {
-    /* no password present, prompt for one */
-    char passwd[256]="";
-    char prompt[256];
-    size_t passwdlen;
-    size_t userlen = strlen(*userpwd);
-    char *passptr;
-
-    /* build a nice-looking prompt */
-    curlx_msnprintf(prompt, sizeof(prompt),
-                    "Enter %s password for user '%s':",
-                    kind, *userpwd);
-
-    /* get password */
-    getpass_r(prompt, passwd, sizeof(passwd));
-    passwdlen = strlen(passwd);
-
-    /* extend the allocated memory area to fit the password too */
-    passptr = realloc(*userpwd,
-                      passwdlen + 1 + /* an extra for the colon */
-                      userlen + 1);   /* an extra for the zero */
-
-    if(passptr) {
-      /* append the password separated with a colon */
-      passptr[userlen]=':';
-      memcpy(&passptr[userlen+1], passwd, passwdlen+1);
-      *userpwd = passptr;
-    }
-  }
-}
-
-static ParameterError add2list(struct curl_slist **list,
-                               const char *ptr)
-{
-  struct curl_slist *newlist = curl_slist_append(*list, ptr);
-  if(newlist)
-    *list = newlist;
-  else
-    return PARAM_NO_MEM;
-
-  return PARAM_OK;
-}
-
-static int ftpfilemethod(struct Configurable *config, const char *str)
-{
-  if(curlx_raw_equal("singlecwd", str))
-    return CURLFTPMETHOD_SINGLECWD;
-  if(curlx_raw_equal("nocwd", str))
-    return CURLFTPMETHOD_NOCWD;
-  if(curlx_raw_equal("multicwd", str))
-    return CURLFTPMETHOD_MULTICWD;
-  warnf(config, "unrecognized ftp file method '%s', using default\n", str);
-  return CURLFTPMETHOD_MULTICWD;
-}
-
-static int ftpcccmethod(struct Configurable *config, const char *str)
-{
-  if(curlx_raw_equal("passive", str))
-    return CURLFTPSSL_CCC_PASSIVE;
-  if(curlx_raw_equal("active", str))
-    return CURLFTPSSL_CCC_ACTIVE;
-  warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
-  return CURLFTPSSL_CCC_PASSIVE;
-}
-
-static long delegation(struct Configurable *config,
-                       char *str)
-{
-  if(curlx_raw_equal("none", str))
-    return CURLGSSAPI_DELEGATION_NONE;
-  if(curlx_raw_equal("policy", str))
-    return CURLGSSAPI_DELEGATION_POLICY_FLAG;
-  if(curlx_raw_equal("always", str))
-    return CURLGSSAPI_DELEGATION_FLAG;
-  warnf(config, "unrecognized delegation method '%s', using none\n", str);
-  return CURLGSSAPI_DELEGATION_NONE;
-}
-
-static ParameterError getparameter(char *flag, /* f or -long-flag */
-                                   char *nextarg, /* NULL if unset */
-                                   bool *usedarg, /* set to TRUE if the arg
-                                                     has been used */
-                                   struct Configurable *config)
-{
-  char letter;
-  char subletter=0; /* subletters can only occur on long options */
-  int rc; /* generic return code variable */
-  const char *parse=NULL;
-  unsigned int j;
-  time_t now;
-  int hit=-1;
-  bool longopt=FALSE;
-  bool singleopt=FALSE; /* when true means '-o foo' used '-ofoo' */
-  ParameterError err;
-  bool toggle=TRUE; /* how to switch boolean options, on or off. Controlled
-                       by using --OPTION or --no-OPTION */
-
-  /* single-letter,
-     long-name,
-     boolean whether it takes an additional argument
-  */
-  static const struct LongShort aliases[]= {
-    /* all these ones, starting with "*" or "$" as a short-option have *no*
-       short option to mention. */
-    {"*", "url",         TRUE},
-    {"*a", "random-file", TRUE},
-    {"*b", "egd-file",   TRUE},
-    {"*c", "connect-timeout", TRUE},
-    {"*d", "ciphers",    TRUE},
-    {"*e", "disable-epsv", FALSE},
-    {"*E", "epsv", FALSE}, /* made like this to make --no-epsv and --epsv to
-                              work although --disable-epsv is the documented
-                              option */
-#ifdef USE_ENVIRONMENT
-    {"*f", "environment", FALSE},
-#endif
-    {"*g", "trace",      TRUE},
-    {"*h", "trace-ascii", TRUE},
-    {"*i", "limit-rate", TRUE},
-    {"*j", "compressed",  FALSE},
-    {"*J", "tr-encoding",  FALSE},
-    {"*k", "digest",     FALSE},
-    {"*l", "negotiate",  FALSE},
-    {"*m", "ntlm",       FALSE},
-    {"*M", "ntlm-wb",    FALSE},
-    {"*n", "basic",      FALSE},
-    {"*o", "anyauth",    FALSE},
-#ifdef USE_WATT32
-    {"*p", "wdebug",     FALSE},
-#endif
-    {"*q", "ftp-create-dirs", FALSE},
-    {"*r", "create-dirs", FALSE},
-    {"*s", "max-redirs",   TRUE},
-    {"*t", "proxy-ntlm",   FALSE},
-    {"*u", "crlf",        FALSE},
-    {"*v", "stderr",      TRUE},
-    {"*w", "interface",   TRUE},
-    {"*x", "krb" ,        TRUE},
-    {"*x", "krb4" ,       TRUE}, /* this is the previous name */
-    {"*y", "max-filesize", TRUE},
-    {"*z", "disable-eprt", FALSE},
-    {"*Z", "eprt", FALSE}, /* made like this to make --no-eprt and --eprt to
-                              work although --disable-eprt is the documented
-                              option */
-    {"$a", "ftp-ssl",    FALSE}, /* deprecated name since 7.20.0 */
-    {"$a", "ssl",        FALSE}, /* new option name in 7.20.0, previously this
-                                    was ftp-ssl */
-    {"$b", "ftp-pasv",   FALSE},
-    {"$c", "socks5",   TRUE},
-    {"$c", "socks",      TRUE}, /* this is how the option once was documented
-                                   but we prefer the --socks5 version for
-                                   explicit version */
-    {"$d", "tcp-nodelay",FALSE},
-    {"$e", "proxy-digest", FALSE},
-    {"$f", "proxy-basic", FALSE},
-    {"$g", "retry",      TRUE},
-    {"$h", "retry-delay", TRUE},
-    {"$i", "retry-max-time", TRUE},
-    {"$k", "proxy-negotiate",   FALSE},
-    {"$m", "ftp-account", TRUE},
-    {"$n", "proxy-anyauth", FALSE},
-    {"$o", "trace-time", FALSE},
-    {"$p", "ignore-content-length", FALSE},
-    {"$q", "ftp-skip-pasv-ip", FALSE},
-    {"$r", "ftp-method", TRUE},
-    {"$s", "local-port", TRUE},
-    {"$t", "socks4",     TRUE},
-    {"$T", "socks4a",    TRUE},
-    {"$u", "ftp-alternative-to-user", TRUE},
-    {"$v", "ftp-ssl-reqd", FALSE}, /* deprecated name since 7.20.0 */
-    {"$v", "ssl-reqd", FALSE},  /* new option name in 7.20.0, previously this
-                                   was ftp-ssl-reqd */
-    {"$w", "sessionid", FALSE}, /* listed as --no-sessionid in the help */
-    {"$x", "ftp-ssl-control", FALSE},
-    {"$y", "ftp-ssl-ccc", FALSE},
-    {"$j", "ftp-ssl-ccc-mode", TRUE},
-    {"$z", "libcurl",    TRUE},
-    {"$#", "raw",        FALSE},
-    {"$0", "post301",    FALSE},
-    {"$1", "keepalive",   FALSE}, /* listed as --no-keepalive in the help */
-    {"$2", "socks5-hostname", TRUE},
-    {"$3", "keepalive-time",  TRUE},
-    {"$4", "post302",    FALSE},
-    {"$5", "noproxy",    TRUE},
-
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-    {"$6", "socks5-gssapi-service",  TRUE},
-    {"$7", "socks5-gssapi-nec",  FALSE},
-#endif
-    {"$8", "proxy1.0",   TRUE},
-    {"$9", "tftp-blksize", TRUE},
-    {"$A", "mail-from", TRUE},
-    {"$B", "mail-rcpt", TRUE},
-    {"$C", "ftp-pret",   FALSE},
-    {"$D", "proto",      TRUE},
-    {"$E", "proto-redir", TRUE},
-    {"$F", "resolve",    TRUE},
-    {"$G", "delegation", TRUE},
-    {"0", "http1.0",     FALSE},
-    {"1", "tlsv1",       FALSE},
-    {"2", "sslv2",       FALSE},
-    {"3", "sslv3",       FALSE},
-    {"4", "ipv4",       FALSE},
-    {"6", "ipv6",       FALSE},
-    {"a", "append",      FALSE},
-    {"A", "user-agent",  TRUE},
-    {"b", "cookie",      TRUE},
-    {"B", "use-ascii",   FALSE},
-    {"c", "cookie-jar",  TRUE},
-    {"C", "continue-at", TRUE},
-    {"d", "data",        TRUE},
-    {"da", "data-ascii", TRUE},
-    {"db", "data-binary", TRUE},
-    {"de", "data-urlencode", TRUE},
-    {"D", "dump-header", TRUE},
-    {"e", "referer",     TRUE},
-    {"E", "cert",        TRUE},
-    {"Ea", "cacert",     TRUE},
-    {"Eb","cert-type",   TRUE},
-    {"Ec","key",         TRUE},
-    {"Ed","key-type",    TRUE},
-    {"Ee","pass",        TRUE},
-    {"Ef","engine",      TRUE},
-    {"Eg","capath ",     TRUE},
-    {"Eh","pubkey",      TRUE},
-    {"Ei", "hostpubmd5", TRUE},
-    {"Ej","crlfile",     TRUE},
-    {"Ek","tlsuser",     TRUE},
-    {"El","tlspassword", TRUE},
-    {"Em","tlsauthtype", TRUE},
-    {"f", "fail",        FALSE},
-    {"F", "form",        TRUE},
-    {"Fs","form-string", TRUE},
-    {"g", "globoff",     FALSE},
-    {"G", "get",         FALSE},
-    {"h", "help",        FALSE},
-    {"H", "header",      TRUE},
-    {"i", "include",     FALSE},
-    {"I", "head",        FALSE},
-    {"j", "junk-session-cookies", FALSE},
-    {"J", "remote-header-name", FALSE},
-    {"k", "insecure",    FALSE},
-    {"K", "config",      TRUE},
-    {"l", "list-only",   FALSE},
-    {"L", "location",    FALSE},
-    {"Lt", "location-trusted", FALSE},
-    {"m", "max-time",    TRUE},
-    {"M", "manual",      FALSE},
-    {"n", "netrc",       FALSE},
-    {"no", "netrc-optional", FALSE},
-    {"ne", "netrc-file", TRUE},
-    {"N", "buffer",   FALSE}, /* listed as --no-buffer in the help */
-    {"o", "output",      TRUE},
-    {"O",  "remote-name", FALSE},
-    {"Oa", "remote-name-all", FALSE},
-    {"p", "proxytunnel", FALSE},
-    {"P", "ftpport",     TRUE}, /* older version */
-    {"P", "ftp-port",    TRUE},
-    {"q", "disable",     FALSE},
-    {"Q", "quote",       TRUE},
-    {"r", "range",       TRUE},
-    {"R", "remote-time", FALSE},
-    {"s", "silent",      FALSE},
-    {"S", "show-error",  FALSE},
-    {"t", "telnet-options", TRUE}, /* this is documented as telnet-option */
-    {"T", "upload-file", TRUE},
-    {"u", "user",        TRUE},
-    {"U", "proxy-user",  TRUE},
-    {"v", "verbose",     FALSE},
-    {"V", "version",     FALSE},
-    {"w", "write-out",   TRUE},
-    {"x", "proxy",       TRUE},
-    {"X", "request",     TRUE},
-    {"X", "http-request", TRUE}, /* OBSOLETE VERSION */
-    {"Y", "speed-limit",  TRUE},
-    {"y", "speed-time", TRUE},
-    {"z", "time-cond",   TRUE},
-    {"#", "progress-bar",FALSE},
-    {"~", "xattr",FALSE},
-  };
-
-  if(('-' != flag[0]) ||
-     (('-' == flag[0]) && ('-' == flag[1]))) {
-    /* this should be a long name */
-    char *word=('-' == flag[0])?flag+2:flag;
-    size_t fnam=strlen(word);
-    int numhits=0;
-
-    if(!strncmp(word, "no-", 3)) {
-      /* disable this option but ignore the "no-" part when looking for it */
-      word += 3;
-      toggle = FALSE;
-    }
-
-    for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
-      if(curlx_strnequal(aliases[j].lname, word, fnam)) {
-        longopt = TRUE;
-        numhits++;
-        if(curlx_raw_equal(aliases[j].lname, word)) {
-          parse = aliases[j].letter;
-          hit = j;
-          numhits = 1; /* a single unique hit */
-          break;
-        }
-        parse = aliases[j].letter;
-        hit = j;
-      }
-    }
-    if(numhits>1) {
-      /* this is at least the second match! */
-      return PARAM_OPTION_AMBIGUOUS;
-    }
-    if(hit < 0) {
-      return PARAM_OPTION_UNKNOWN;
-    }
-  }
-  else {
-    flag++; /* prefixed with one dash, pass it */
-    hit=-1;
-    parse = flag;
-  }
-
-  do {
-    /* we can loop here if we have multiple single-letters */
-
-    if(!longopt) {
-      if(NULL != parse) {
-        letter = (char)*parse;
-      }
-      else {
-        letter = '\0';
-      }
-      subletter='\0';
-    }
-    else {
-      letter = parse[0];
-      subletter = parse[1];
-    }
-    *usedarg = FALSE; /* default is that we don't use the arg */
-
-    if(hit < 0) {
-      for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
-        if(letter == aliases[j].letter[0]) {
-          hit = j;
-          break;
-        }
-      }
-      if(hit < 0) {
-        return PARAM_OPTION_UNKNOWN;
-      }
-    }
-
-    if(aliases[hit].extraparam) {
-      /* this option requires an extra parameter */
-      if(!longopt && parse[1]) {
-        nextarg=(char *)&parse[1]; /* this is the actual extra parameter */
-        singleopt=TRUE;   /* don't loop anymore after this */
-      }
-      else if(!nextarg)
-        return PARAM_REQUIRES_PARAMETER;
-      else
-        *usedarg = TRUE; /* mark it as used */
-    }
-
-    switch(letter) {
-    case '*': /* options without a short option */
-      switch(subletter) {
-      case 'a': /* random-file */
-        GetStr(&config->random_file, nextarg);
-        break;
-      case 'b': /* egd-file */
-        GetStr(&config->egd_file, nextarg);
-        break;
-      case 'c': /* connect-timeout */
-        if(str2num(&config->connecttimeout, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-      case 'd': /* ciphers */
-        GetStr(&config->cipher_list, nextarg);
-        break;
-      case 'e': /* --disable-epsv */
-        config->disable_epsv = toggle;
-        break;
-      case 'E': /* --epsv */
-        config->disable_epsv = (!toggle)?TRUE:FALSE;
-        break;
-#ifdef USE_ENVIRONMENT
-      case 'f':
-        config->writeenv = toggle;
-        break;
-#endif
-      case 'g': /* --trace */
-        GetStr(&config->trace_dump, nextarg);
-        if(config->tracetype && (config->tracetype != TRACE_BIN))
-          warnf(config, "--trace overrides an earlier trace/verbose option\n");
-        config->tracetype = TRACE_BIN;
-        break;
-      case 'h': /* --trace-ascii */
-        GetStr(&config->trace_dump, nextarg);
-        if(config->tracetype && (config->tracetype != TRACE_ASCII))
-          warnf(config,
-                "--trace-ascii overrides an earlier trace/verbose option\n");
-        config->tracetype = TRACE_ASCII;
-        break;
-      case 'i': /* --limit-rate */
-      {
-        /* We support G, M, K too */
-        char *unit;
-        curl_off_t value = curlx_strtoofft(nextarg, &unit, 0);
-
-        if(!*unit)
-          unit=(char *)"b";
-        else if(strlen(unit) > 1)
-          unit=(char *)"w"; /* unsupported */
-
-        switch(*unit) {
-        case 'G':
-        case 'g':
-          value *= 1024*1024*1024;
-          break;
-        case 'M':
-        case 'm':
-          value *= 1024*1024;
-          break;
-        case 'K':
-        case 'k':
-          value *= 1024;
-          break;
-        case 'b':
-        case 'B':
-          /* for plain bytes, leave as-is */
-          break;
-        default:
-          warnf(config, "unsupported rate unit. Use G, M, K or B!\n");
-          return PARAM_BAD_USE;
-        }
-        config->recvpersecond = value;
-        config->sendpersecond = value;
-      }
-      break;
-
-      case 'j': /* --compressed */
-        if(toggle && !(curlinfo->features & CURL_VERSION_LIBZ))
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        config->encoding = toggle;
-        break;
-
-      case 'J': /* --tr-encoding */
-        config->tr_encoding = toggle;
-        break;
-
-      case 'k': /* --digest */
-        if(toggle)
-          config->authtype |= CURLAUTH_DIGEST;
-        else
-          config->authtype &= ~CURLAUTH_DIGEST;
-        break;
-
-      case 'l': /* --negotiate */
-        if(toggle) {
-          if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
-            config->authtype |= CURLAUTH_GSSNEGOTIATE;
-          else
-            return PARAM_LIBCURL_DOESNT_SUPPORT;
-        }
-        else
-          config->authtype &= ~CURLAUTH_GSSNEGOTIATE;
-        break;
-
-      case 'm': /* --ntlm */
-        if(toggle) {
-          if(curlinfo->features & CURL_VERSION_NTLM)
-            config->authtype |= CURLAUTH_NTLM;
-          else
-            return PARAM_LIBCURL_DOESNT_SUPPORT;
-        }
-        else
-          config->authtype &= ~CURLAUTH_NTLM;
-        break;
-
-      case 'M': /* --ntlm-wb */
-        if(toggle) {
-          if(curlinfo->features & CURL_VERSION_NTLM_WB)
-            config->authtype |= CURLAUTH_NTLM_WB;
-          else
-            return PARAM_LIBCURL_DOESNT_SUPPORT;
-        }
-        else
-          config->authtype &= ~CURLAUTH_NTLM_WB;
-        break;
-
-      case 'n': /* --basic for completeness */
-        if(toggle)
-          config->authtype |= CURLAUTH_BASIC;
-        else
-          config->authtype &= ~CURLAUTH_BASIC;
-        break;
-
-      case 'o': /* --anyauth, let libcurl pick it */
-        if(toggle)
-          config->authtype = CURLAUTH_ANY;
-        /* --no-anyauth simply doesn't touch it */
-        break;
-
-#ifdef USE_WATT32
-      case 'p': /* --wdebug */
-        dbug_init();
-        break;
-#endif
-      case 'q': /* --ftp-create-dirs */
-        config->ftp_create_dirs = toggle;
-        break;
-
-      case 'r': /* --create-dirs */
-        config->create_dirs = TRUE;
-        break;
-
-      case 's': /* --max-redirs */
-        /* specified max no of redirects (http(s)) */
-        if(str2num(&config->maxredirs, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-
-      case 't': /* --proxy-ntlm */
-        if(curlinfo->features & CURL_VERSION_NTLM)
-          config->proxyntlm = toggle;
-        else
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        break;
-
-      case 'u': /* --crlf */
-        /* LF -> CRLF conversion? */
-        config->crlf = TRUE;
-        break;
-
-      case 'v': /* --stderr */
-        if(strcmp(nextarg, "-")) {
-          FILE *newfile = fopen(nextarg, "wt");
-          if(!newfile)
-            warnf(config, "Failed to open %s!\n", nextarg);
-          else {
-            if(config->errors_fopened)
-              fclose(config->errors);
-            config->errors = newfile;
-            config->errors_fopened = TRUE;
-          }
-        }
-        else
-          config->errors = stdout;
-        break;
-      case 'w': /* --interface */
-        /* interface */
-        GetStr(&config->iface, nextarg);
-        break;
-      case 'x': /* --krb */
-        /* kerberos level string */
-        if(curlinfo->features & (CURL_VERSION_KERBEROS4 |
-                                 CURL_VERSION_GSSNEGOTIATE))
-          GetStr(&config->krblevel, nextarg);
-        else
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        break;
-      case 'y': /* --max-filesize */
-        if(str2offset(&config->max_filesize, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-      case 'z': /* --disable-eprt */
-        config->disable_eprt = toggle;
-        break;
-      case 'Z': /* --eprt */
-        config->disable_eprt = (!toggle)?TRUE:FALSE;
-        break;
-
-      default: /* the URL! */
-      {
-        struct getout *url;
-        if(config->url_get || ((config->url_get = config->url_list) != NULL)) {
-          /* there's a node here, if it already is filled-in continue to find
-             an "empty" node */
-          while(config->url_get && (config->url_get->flags&GETOUT_URL))
-            config->url_get = config->url_get->next;
-        }
-
-        /* now there might or might not be an available node to fill in! */
-
-        if(config->url_get)
-          /* existing node */
-          url = config->url_get;
-        else
-          /* there was no free node, create one! */
-          url=new_getout(config);
-
-        if(url) {
-          /* fill in the URL */
-          GetStr(&url->url, nextarg);
-          url->flags |= GETOUT_URL;
-        }
-      }
-      }
-      break;
-    case '$': /* more options without a short option */
-      switch(subletter) {
-      case 'a': /* --ftp-ssl */
-        if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        config->ftp_ssl = toggle;
-        break;
-      case 'b': /* --ftp-pasv */
-        Curl_safefree(config->ftpport);
-        break;
-      case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
-                   the name locally and passes on the resolved address */
-        GetStr(&config->socksproxy, nextarg);
-        config->socksver = CURLPROXY_SOCKS5;
-        break;
-      case 't': /* --socks4 specifies a socks4 proxy to use */
-        GetStr(&config->socksproxy, nextarg);
-        config->socksver = CURLPROXY_SOCKS4;
-        break;
-      case 'T': /* --socks4a specifies a socks4a proxy to use */
-        GetStr(&config->socksproxy, nextarg);
-        config->socksver = CURLPROXY_SOCKS4A;
-        break;
-      case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
-                   resolving with the proxy */
-        GetStr(&config->socksproxy, nextarg);
-        config->socksver = CURLPROXY_SOCKS5_HOSTNAME;
-        break;
-      case 'd': /* --tcp-nodelay option */
-        config->tcp_nodelay = toggle;
-        break;
-      case 'e': /* --proxy-digest */
-        config->proxydigest = toggle;
-        break;
-      case 'f': /* --proxy-basic */
-        config->proxybasic = toggle;
-        break;
-      case 'g': /* --retry */
-        if(str2num(&config->req_retry, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-      case 'h': /* --retry-delay */
-        if(str2num(&config->retry_delay, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-      case 'i': /* --retry-max-time */
-        if(str2num(&config->retry_maxtime, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-
-      case 'k': /* --proxy-negotiate */
-        if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
-          config->proxynegotiate = toggle;
-        else
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        break;
-      case 'm': /* --ftp-account */
-        GetStr(&config->ftp_account, nextarg);
-        break;
-      case 'n': /* --proxy-anyauth */
-        config->proxyanyauth = toggle;
-        break;
-      case 'o': /* --trace-time */
-        config->tracetime = toggle;
-        break;
-      case 'p': /* --ignore-content-length */
-        config->ignorecl = toggle;
-        break;
-      case 'q': /* --ftp-skip-pasv-ip */
-        config->ftp_skip_ip = toggle;
-        break;
-      case 'r': /* --ftp-method (undocumented at this point) */
-        config->ftp_filemethod = ftpfilemethod(config, nextarg);
-        break;
-      case 's': /* --local-port */
-        rc = sscanf(nextarg, "%d - %d",
-                    &config->localport,
-                    &config->localportrange);
-        if(!rc)
-          return PARAM_BAD_USE;
-        else if(rc == 1)
-          config->localportrange = 1; /* default number of ports to try */
-        else {
-          config->localportrange -= config->localport;
-          if(config->localportrange < 1) {
-            warnf(config, "bad range input\n");
-            return PARAM_BAD_USE;
-          }
-        }
-        break;
-      case 'u': /* --ftp-alternative-to-user */
-        GetStr(&config->ftp_alternative_to_user, nextarg);
-        break;
-      case 'v': /* --ftp-ssl-reqd */
-        if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        config->ftp_ssl_reqd = toggle;
-        break;
-      case 'w': /* --no-sessionid */
-        config->disable_sessionid = (!toggle)?TRUE:FALSE;
-        break;
-      case 'x': /* --ftp-ssl-control */
-        if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        config->ftp_ssl_control = toggle;
-        break;
-      case 'y': /* --ftp-ssl-ccc */
-        config->ftp_ssl_ccc = toggle;
-        if(!config->ftp_ssl_ccc_mode)
-          config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
-        break;
-      case 'j': /* --ftp-ssl-ccc-mode */
-        config->ftp_ssl_ccc = TRUE;
-        config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
-        break;
-      case 'z': /* --libcurl */
-        GetStr(&config->libcurl, nextarg);
-        break;
-      case '#': /* --raw */
-        config->raw = toggle;
-        break;
-      case '0': /* --post301 */
-        config->post301 = toggle;
-        break;
-      case '1': /* --no-keepalive */
-        config->nokeepalive = (!toggle)?TRUE:FALSE;
-        break;
-      case '3': /* --keepalive-time */
-        if(str2num(&config->alivetime, nextarg))
-          return PARAM_BAD_NUMERIC;
-        break;
-      case '4': /* --post302 */
-        config->post302 = toggle;
-        break;
-      case '5': /* --noproxy */
-        /* This specifies the noproxy list */
-        GetStr(&config->noproxy, nextarg);
-        break;
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-      case '6': /* --socks5-gssapi-service */
-        GetStr(&config->socks5_gssapi_service, nextarg);
-        break;
-      case '7': /* --socks5-gssapi-nec*/
-        config->socks5_gssapi_nec = TRUE;
-        break;
-#endif
-      case '8': /* --proxy1.0 */
-        /* http 1.0 proxy */
-        GetStr(&config->proxy, nextarg);
-        config->proxyver = CURLPROXY_HTTP_1_0;
-        break;
-      case '9': /* --tftp-blksize */
-        str2num(&config->tftp_blksize, nextarg);
-        break;
-      case 'A': /* --mail-from */
-        GetStr(&config->mail_from, nextarg);
-        break;
-      case 'B': /* --mail-rcpt */
-        /* append receiver to a list */
-        err = add2list(&config->mail_rcpt, nextarg);
-        if(err)
-          return err;
-        break;
-      case 'C': /* --ftp-pret */
-        config->ftp_pret = toggle;
-        break;
-      case 'D': /* --proto */
-        config->proto_present = TRUE;
-        if(proto2num(config, &config->proto, nextarg))
-          return PARAM_BAD_USE;
-        break;
-      case 'E': /* --proto-redir */
-        config->proto_redir_present = TRUE;
-        if(proto2num(config, &config->proto_redir, nextarg))
-          return PARAM_BAD_USE;
-        break;
-      case 'F': /* --resolve */
-        err = add2list(&config->resolve, nextarg);
-        if(err)
-          return err;
-        break;
-      case 'G': /* --delegation LEVEL */
-        config->gssapi_delegation = delegation(config, nextarg);
-        break;
-      }
-      break;
-    case '#': /* --progress-bar */
-      if(toggle)
-        config->progressmode = CURL_PROGRESS_BAR;
-      else
-        config->progressmode = CURL_PROGRESS_STATS;
-      break;
-    case '~': /* --xattr */
-      config->xattr = toggle;
-      break;
-    case '0':
-      /* HTTP version 1.0 */
-      config->httpversion = CURL_HTTP_VERSION_1_0;
-      break;
-    case '1':
-      /* TLS version 1 */
-      config->ssl_version = CURL_SSLVERSION_TLSv1;
-      break;
-    case '2':
-      /* SSL version 2 */
-      config->ssl_version = CURL_SSLVERSION_SSLv2;
-      break;
-    case '3':
-      /* SSL version 3 */
-      config->ssl_version = CURL_SSLVERSION_SSLv3;
-      break;
-    case '4':
-      /* IPv4 */
-      config->ip_version = 4;
-      break;
-    case '6':
-      /* IPv6 */
-      config->ip_version = 6;
-      break;
-    case 'a':
-      /* This makes the FTP sessions use APPE instead of STOR */
-      config->ftp_append = toggle;
-      break;
-    case 'A':
-      /* This specifies the User-Agent name */
-      GetStr(&config->useragent, nextarg);
-      break;
-    case 'b': /* cookie string coming up: */
-      if(nextarg[0] == '@') {
-        nextarg++;
-      }
-      else if(strchr(nextarg, '=')) {
-        /* A cookie string must have a =-letter */
-        GetStr(&config->cookie, nextarg);
-        break;
-      }
-      /* We have a cookie file to read from! */
-      GetStr(&config->cookiefile, nextarg);
-      break;
-    case 'B':
-      /* use ASCII/text when transferring */
-      config->use_ascii = toggle;
-      break;
-    case 'c':
-      /* get the file name to dump all cookies in */
-      GetStr(&config->cookiejar, nextarg);
-      break;
-    case 'C':
-      /* This makes us continue an ftp transfer at given position */
-      if(!curlx_strequal(nextarg, "-")) {
-        if(str2offset(&config->resume_from, nextarg))
-          return PARAM_BAD_NUMERIC;
-        config->resume_from_current = FALSE;
-      }
-      else {
-        config->resume_from_current = TRUE;
-        config->resume_from = 0;
-      }
-      config->use_resume=TRUE;
-      break;
-    case 'd':
-      /* postfield data */
-    {
-      char *postdata=NULL;
-      FILE *file;
-      size_t size = 0;
-
-      if(subletter == 'e') { /* --data-urlencode*/
-        /* [name]=[content], we encode the content part only
-         * [name]@[file name]
-         *
-         * Case 2: we first load the file using that name and then encode
-         * the content.
-         */
-        const char *p = strchr(nextarg, '=');
-        size_t nlen;
-        char is_file;
-        if(!p)
-          /* there was no '=' letter, check for a '@' instead */
-          p = strchr(nextarg, '@');
-        if(p) {
-          nlen = p - nextarg; /* length of the name part */
-          is_file = *p++; /* pass the separator */
-        }
-        else {
-          /* neither @ nor =, so no name and it isn't a file */
-          nlen = is_file = 0;
-          p = nextarg;
-        }
-        if('@' == is_file) {
-          /* a '@' letter, it means that a file name or - (stdin) follows */
-
-          if(curlx_strequal("-", p)) {
-            file = stdin;
-            set_binmode(stdin);
-          }
-          else {
-            file = fopen(p, "rb");
-            if(!file)
-              warnf(config,
-                    "Couldn't read data from file \"%s\", this makes "
-                    "an empty POST.\n", nextarg);
-          }
-
-          err = file2memory(&postdata, &size, file);
-
-          if(file && (file != stdin))
-            fclose(file);
-          if(err)
-            return err;
-        }
-        else {
-          GetStr(&postdata, p);
-          size = strlen(postdata);
-        }
-
-        if(!postdata) {
-          /* no data from the file, point to a zero byte string to make this
-             get sent as a POST anyway */
-          postdata=strdup("");
-          size = 0;
-        }
-        else {
-          char *enc = curl_easy_escape(config->easy, postdata, (int)size);
-          Curl_safefree(postdata); /* no matter if it worked or not */
-          if(enc) {
-            /* now make a string with the name from above and append the
-               encoded string */
-            size_t outlen = nlen + strlen(enc) + 2;
-            char *n = malloc(outlen);
-            if(!n) {
-              curl_free(enc);
-              return PARAM_NO_MEM;
-            }
-            if(nlen > 0) { /* only append '=' if we have a name */
-              snprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
-              size = outlen-1;
-            }
-            else {
-              strcpy(n, enc);
-              size = outlen-2; /* since no '=' was inserted */
-            }
-            curl_free(enc);
-            postdata = n;
-          }
-          else
-            return PARAM_NO_MEM;
-        }
-      }
-      else if('@' == *nextarg) {
-        /* the data begins with a '@' letter, it means that a file name
-           or - (stdin) follows */
-        nextarg++; /* pass the @ */
-
-        if(curlx_strequal("-", nextarg)) {
-          file = stdin;
-          if(subletter == 'b') /* forced data-binary */
-            set_binmode(stdin);
-        }
-        else {
-          file = fopen(nextarg, "rb");
-          if(!file)
-            warnf(config, "Couldn't read data from file \"%s\", this makes "
-                  "an empty POST.\n", nextarg);
-        }
-
-        if(subletter == 'b')
-          /* forced binary */
-          err = file2memory(&postdata, &size, file);
-        else {
-          err = file2string(&postdata, file);
-          if(postdata)
-            size = strlen(postdata);
-        }
-
-        if(file && (file != stdin))
-          fclose(file);
-        if(err)
-          return err;
-
-        if(!postdata) {
-          /* no data from the file, point to a zero byte string to make this
-             get sent as a POST anyway */
-          postdata=strdup("");
-        }
-      }
-      else {
-        GetStr(&postdata, nextarg);
-        size=strlen(postdata);
-      }
-
-#ifdef CURL_DOES_CONVERSIONS
-      if(subletter != 'b') { /* NOT forced binary, convert to ASCII */
-        convert_to_network(postdata, strlen(postdata));
-      }
-#endif
-
-      if(config->postfields) {
-        /* we already have a string, we append this one with a separating
-           &-letter */
-        char *oldpost=config->postfields;
-        curl_off_t oldlen = config->postfieldsize;
-        curl_off_t newlen = oldlen + size + 2;
-        config->postfields=malloc((size_t)newlen);
-        if(!config->postfields) {
-          Curl_safefree(postdata);
-          return PARAM_NO_MEM;
-        }
-        memcpy(config->postfields, oldpost, (size_t)oldlen);
-        /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
-        config->postfields[oldlen]='\x26';
-        memcpy(&config->postfields[oldlen+1], postdata, size);
-        config->postfields[oldlen+1+size]=0;
-        Curl_safefree(oldpost);
-        Curl_safefree(postdata);
-        config->postfieldsize += size+1;
-      }
-      else {
-        config->postfields=postdata;
-        config->postfieldsize = size;
-      }
-    }
-    /*
-      We can't set the request type here, as this data might be used in
-      a simple GET if -G is used. Already or soon.
-
-      if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
-      return PARAM_BAD_USE;
-    */
-    break;
-    case 'D':
-      /* dump-header to given file name */
-      GetStr(&config->headerfile, nextarg);
-      break;
-    case 'e':
-    {
-      char *ptr = strstr(nextarg, ";auto");
-      if(ptr) {
-        /* Automatic referer requested, this may be combined with a
-           set initial one */
-        config->autoreferer = TRUE;
-        *ptr = 0; /* zero terminate here */
-      }
-      else
-        config->autoreferer = FALSE;
-      GetStr(&config->referer, nextarg);
-    }
-    break;
-    case 'E':
-      switch(subletter) {
-      case 'a': /* CA info PEM file */
-        /* CA info PEM file */
-        GetStr(&config->cacert, nextarg);
-        break;
-      case 'b': /* cert file type */
-        GetStr(&config->cert_type, nextarg);
-        break;
-      case 'c': /* private key file */
-        GetStr(&config->key, nextarg);
-        break;
-      case 'd': /* private key file type */
-        GetStr(&config->key_type, nextarg);
-        break;
-      case 'e': /* private key passphrase */
-        GetStr(&config->key_passwd, nextarg);
-        cleanarg(nextarg);
-        break;
-      case 'f': /* crypto engine */
-        GetStr(&config->engine, nextarg);
-        if(config->engine && curlx_raw_equal(config->engine,"list"))
-          config->list_engines = TRUE;
-        break;
-      case 'g': /* CA info PEM file */
-        /* CA cert directory */
-        GetStr(&config->capath, nextarg);
-        break;
-      case 'h': /* --pubkey public key file */
-        GetStr(&config->pubkey, nextarg);
-        break;
-      case 'i': /* --hostpubmd5 md5 of the host public key */
-        GetStr(&config->hostpubmd5, nextarg);
-        if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
-          return PARAM_BAD_USE;
-        break;
-      case 'j': /* CRL info PEM file */
-        /* CRL file */
-        GetStr(&config->crlfile, nextarg);
-        break;
-      case 'k': /* TLS username */
-        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
-          GetStr(&config->tls_username, nextarg);
-        else
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        break;
-      case 'l': /* TLS password */
-        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
-          GetStr(&config->tls_password, nextarg);
-        else
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        break;
-      case 'm': /* TLS authentication type */
-        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
-          GetStr(&config->tls_authtype, nextarg);
-          if(!strequal(config->tls_authtype, "SRP"))
-            return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
-        }
-        else
-          return PARAM_LIBCURL_DOESNT_SUPPORT;
-        break;
-      default: /* certificate file */
-      {
-        char *ptr = strchr(nextarg, ':');
-        /* Since we live in a world of weirdness and confusion, the win32
-           dudes can use : when using drive letters and thus
-           c:\file:password needs to work. In order not to break
-           compatibility, we still use : as separator, but we try to detect
-           when it is used for a file name! On windows. */
-#ifdef WIN32
-        if(ptr &&
-           (ptr == &nextarg[1]) &&
-           (nextarg[2] == '\\' || nextarg[2] == '/') &&
-           (ISALPHA(nextarg[0])) )
-          /* colon in the second column, followed by a backslash, and the
-             first character is an alphabetic letter:
-
-             this is a drive letter colon */
-          ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
-#endif
-        if(ptr) {
-          /* we have a password too */
-          *ptr=0;
-          ptr++;
-          GetStr(&config->key_passwd, ptr);
-        }
-        GetStr(&config->cert, nextarg);
-        cleanarg(nextarg);
-      }
-      }
-      break;
-    case 'f':
-      /* fail hard on errors  */
-      config->failonerror = toggle;
-      break;
-    case 'F':
-      /* "form data" simulation, this is a little advanced so lets do our best
-         to sort this out slowly and carefully */
-      if(formparse(config,
-                   nextarg,
-                   &config->httppost,
-                   &config->last_post,
-                   (subletter=='s')?TRUE:FALSE)) /* 's' means literal string */
-        return PARAM_BAD_USE;
-      if(SetHTTPrequest(config, HTTPREQ_POST, &config->httpreq))
-        return PARAM_BAD_USE;
-      break;
-
-    case 'g': /* g disables URLglobbing */
-      config->globoff = toggle;
-      break;
-
-    case 'G': /* HTTP GET */
-      config->use_httpget = TRUE;
-      break;
-
-    case 'h': /* h for help */
-      if(toggle) {
-        help();
-        return PARAM_HELP_REQUESTED;
-      }
-      /* we now actually support --no-help too! */
-      break;
-    case 'H':
-      /* A custom header to append to a list */
-      err = add2list(&config->headers, nextarg);
-      if(err)
-        return err;
-      break;
-    case 'i':
-      config->include_headers = toggle; /* include the headers as well in the
-                                           general output stream */
-      break;
-    case 'j':
-      config->cookiesession = toggle;
-      break;
-    case 'I':
-      /*
-       * no_body will imply include_headers later on
-       */
-      config->no_body = toggle;
-      if(SetHTTPrequest(config,
-                        (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
-                        &config->httpreq))
-        return PARAM_BAD_USE;
-      break;
-    case 'J': /* --remote-header-name */
-      if(config->include_headers) {
-        warnf(config,
-              "--include and --remote-header-name cannot be combined.\n");
-        return PARAM_BAD_USE;
-      }
-      config->content_disposition = toggle;
-      break;
-    case 'k': /* allow insecure SSL connects */
-      config->insecure_ok = toggle;
-      break;
-    case 'K': /* parse config file */
-      if(parseconfig(nextarg, config))
-        warnf(config, "error trying read config from the '%s' file\n",
-              nextarg);
-      break;
-    case 'l':
-      config->dirlistonly = toggle; /* only list the names of the FTP dir */
-      break;
-    case 'L':
-      config->followlocation = toggle; /* Follow Location: HTTP headers */
-      switch (subletter) {
-      case 't':
-        /* Continue to send authentication (user+password) when following
-         * locations, even when hostname changed */
-        config->unrestricted_auth = toggle;
-        break;
-      }
-      break;
-    case 'm':
-      /* specified max time */
-      if(str2num(&config->timeout, nextarg))
-        return PARAM_BAD_NUMERIC;
-      break;
-    case 'M': /* M for manual, huge help */
-      if(toggle) { /* --no-manual shows no manual... */
-#ifdef USE_MANUAL
-        hugehelp();
-        return PARAM_HELP_REQUESTED;
-#else
-        warnf(config,
-              "built-in manual was disabled at build-time!\n");
-        return PARAM_OPTION_UNKNOWN;
-#endif
-      }
-      break;
-    case 'n':
-      switch(subletter) {
-      case 'o': /* CA info PEM file */
-        /* use .netrc or URL */
-        config->netrc_opt = toggle;
-        break;
-      case 'e': /* netrc-file */
-        GetStr(&config->netrc_file, nextarg);
-        break;
-      default:
-        /* pick info from .netrc, if this is used for http, curl will
-           automatically enfore user+password with the request */
-        config->netrc = toggle;
-        break;
-      }
-      break;
-    case 'N':
-      /* disable the output I/O buffering. note that the option is called
-         --buffer but is mostly used in the negative form: --no-buffer */
-      if(longopt)
-        config->nobuffer = (!toggle)?TRUE:FALSE;
-      else
-        config->nobuffer = toggle;
-      break;
-    case 'O': /* --remote-name */
-      if(subletter == 'a') { /* --remote-name-all */
-        config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
-        break;
-      }
-      /* fall-through! */
-    case 'o': /* --output */
-      /* output file */
-    {
-      struct getout *url;
-      if(config->url_out || ((config->url_out = config->url_list) != NULL)) {
-        /* there's a node here, if it already is filled-in continue to find
-           an "empty" node */
-        while(config->url_out && (config->url_out->flags&GETOUT_OUTFILE))
-          config->url_out = config->url_out->next;
-      }
-
-      /* now there might or might not be an available node to fill in! */
-
-      if(config->url_out)
-        /* existing node */
-        url = config->url_out;
-      else
-        /* there was no free node, create one! */
-        url=new_getout(config);
-
-      if(url) {
-        /* fill in the outfile */
-        if('o' == letter) {
-          GetStr(&url->outfile, nextarg);
-          url->flags &= ~GETOUT_USEREMOTE; /* switch off */
-        }
-        else {
-          url->outfile=NULL; /* leave it */
-          if(toggle)
-            url->flags |= GETOUT_USEREMOTE;  /* switch on */
-          else
-            url->flags &= ~GETOUT_USEREMOTE; /* switch off */
-        }
-        url->flags |= GETOUT_OUTFILE;
-      }
-    }
-    break;
-    case 'P':
-      /* This makes the FTP sessions use PORT instead of PASV */
-      /* use <eth0> or <192.168.10.10> style addresses. Anything except
-         this will make us try to get the "default" address.
-         NOTE: this is a changed behaviour since the released 4.1!
-      */
-      GetStr(&config->ftpport, nextarg);
-      break;
-    case 'p':
-      /* proxy tunnel for non-http protocols */
-      config->proxytunnel = toggle;
-      break;
-
-    case 'q': /* if used first, already taken care of, we do it like
-                 this so we don't cause an error! */
-      break;
-    case 'Q':
-      /* QUOTE command to send to FTP server */
-      switch(nextarg[0]) {
-      case '-':
-        /* prefixed with a dash makes it a POST TRANSFER one */
-        nextarg++;
-        err = add2list(&config->postquote, nextarg);
-        break;
-      case '+':
-        /* prefixed with a plus makes it a just-before-transfer one */
-        nextarg++;
-        err = add2list(&config->prequote, nextarg);
-        break;
-      default:
-        err = add2list(&config->quote, nextarg);
-        break;
-      }
-      if(err)
-        return err;
-      break;
-    case 'r':
-      /* Specifying a range WITHOUT A DASH will create an illegal HTTP range
-         (and won't actually be range by definition). The man page previously
-         claimed that to be a good way, why this code is added to work-around
-         it. */
-      if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
-        char buffer[32];
-        curl_off_t off;
-        warnf(config,
-              "A specified range MUST include at least one dash (-). "
-              "Appending one for you!\n");
-        off = curlx_strtoofft(nextarg, NULL, 10);
-        snprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
-        Curl_safefree(config->range);
-        config->range = strdup(buffer);
-      }
-      {
-        /* byte range requested */
-        char* tmp_range;
-        tmp_range=nextarg;
-        while(*tmp_range != '\0') {
-          if(!ISDIGIT(*tmp_range)&&*tmp_range!='-'&&*tmp_range!=',') {
-            warnf(config,"Invalid character is found in given range. "
-                  "A specified range MUST have only digits in "
-                  "\'start\'-\'stop\'. The server's response to this "
-                  "request is uncertain.\n");
-            break;
-          }
-          tmp_range++;
-        }
-        /* byte range requested */
-        GetStr(&config->range, nextarg);
-      }
-      break;
-    case 'R':
-      /* use remote file's time */
-      config->remote_time = toggle;
-      break;
-    case 's':
-      /* don't show progress meter, don't show errors : */
-      if(toggle)
-        config->mute = config->noprogress = TRUE;
-      else
-        config->mute = config->noprogress = FALSE;
-      config->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
-      break;
-    case 'S':
-      /* show errors */
-      config->showerror = toggle; /* toggle on if used with -s */
-      break;
-    case 't':
-      /* Telnet options */
-      err = add2list(&config->telnet_options, nextarg);
-      if(err)
-        return err;
-      break;
-    case 'T':
-      /* we are uploading */
-    {
-      struct getout *url;
-      if(config->url_out || ((config->url_out = config->url_list) != NULL)) {
-        /* there's a node here, if it already is filled-in continue to find
-           an "empty" node */
-        while(config->url_out && (config->url_out->flags&GETOUT_UPLOAD))
-          config->url_out = config->url_out->next;
-      }
-
-      /* now there might or might not be an available node to fill in! */
-
-      if(config->url_out)
-        /* existing node */
-        url = config->url_out;
-      else
-        /* there was no free node, create one! */
-        url=new_getout(config);
-
-      if(url) {
-        url->flags |= GETOUT_UPLOAD; /* mark -T used */
-        if(!*nextarg)
-          url->flags |= GETOUT_NOUPLOAD;
-        else {
-          /* "-" equals stdin, but keep the string around for now */
-          GetStr(&url->infile, nextarg);
-        }
-      }
-    }
-    break;
-    case 'u':
-      /* user:password  */
-      GetStr(&config->userpwd, nextarg);
-      cleanarg(nextarg);
-      checkpasswd("host", &config->userpwd);
-      break;
-    case 'U':
-      /* Proxy user:password  */
-      GetStr(&config->proxyuserpwd, nextarg);
-      cleanarg(nextarg);
-      checkpasswd("proxy", &config->proxyuserpwd);
-      break;
-    case 'v':
-      if(toggle) {
-        /* the '%' thing here will cause the trace get sent to stderr */
-        Curl_safefree(config->trace_dump);
-        config->trace_dump = strdup("%");
-        if(config->tracetype && (config->tracetype != TRACE_PLAIN))
-          warnf(config,
-                "-v, --verbose overrides an earlier trace/verbose option\n");
-        config->tracetype = TRACE_PLAIN;
-      }
-      else
-        /* verbose is disabled here */
-        config->tracetype = TRACE_NONE;
-      break;
-    case 'V':
-    {
-      const char * const *proto;
-
-      if(!toggle)
-        /* --no-version yields no output! */
-        break;
-
-      printf(CURL_ID "%s\n", curl_version());
-      if(curlinfo->protocols) {
-        printf("Protocols: ");
-        for(proto=curlinfo->protocols; *proto; ++proto) {
-          printf("%s ", *proto);
-        }
-        puts(""); /* newline */
-      }
-      if(curlinfo->features) {
-        unsigned int i;
-        struct feat {
-          const char *name;
-          int bitmask;
-        };
-        static const struct feat feats[] = {
-          {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
-          {"Debug", CURL_VERSION_DEBUG},
-          {"TrackMemory", CURL_VERSION_CURLDEBUG},
-          {"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
-          {"IDN", CURL_VERSION_IDN},
-          {"IPv6", CURL_VERSION_IPV6},
-          {"Largefile", CURL_VERSION_LARGEFILE},
-          {"NTLM", CURL_VERSION_NTLM},
-          {"NTLM_WB", CURL_VERSION_NTLM_WB},
-          {"SPNEGO", CURL_VERSION_SPNEGO},
-          {"SSL",  CURL_VERSION_SSL},
-          {"SSPI",  CURL_VERSION_SSPI},
-          {"krb4", CURL_VERSION_KERBEROS4},
-          {"libz", CURL_VERSION_LIBZ},
-          {"CharConv", CURL_VERSION_CONV},
-          {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
-        };
-        printf("Features: ");
-        for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
-          if(curlinfo->features & feats[i].bitmask)
-            printf("%s ", feats[i].name);
-        }
-        puts(""); /* newline */
-      }
-    }
-    return PARAM_HELP_REQUESTED;
-    case 'w':
-      /* get the output string */
-      if('@' == *nextarg) {
-        /* the data begins with a '@' letter, it means that a file name
-           or - (stdin) follows */
-        FILE *file;
-        const char *fname;
-        nextarg++; /* pass the @ */
-        if(curlx_strequal("-", nextarg)) {
-          fname = "<stdin>";
-          file = stdin;
-        }
-        else {
-          fname = nextarg;
-          file = fopen(nextarg, "r");
-        }
-        err = file2string(&config->writeout, file);
-        if(file && (file != stdin))
-          fclose(file);
-        if(err)
-          return err;
-        if(!config->writeout)
-          warnf(config, "Failed to read %s", fname);
-      }
-      else
-        GetStr(&config->writeout, nextarg);
-      break;
-    case 'x':
-      /* proxy */
-      GetStr(&config->proxy, nextarg);
-      config->proxyver = CURLPROXY_HTTP;
-      break;
-    case 'X':
-      /* set custom request */
-      GetStr(&config->customrequest, nextarg);
-      break;
-    case 'y':
-      /* low speed time */
-      if(str2num(&config->low_speed_time, nextarg))
-        return PARAM_BAD_NUMERIC;
-      if(!config->low_speed_limit)
-        config->low_speed_limit = 1;
-      break;
-    case 'Y':
-      /* low speed limit */
-      if(str2num(&config->low_speed_limit, nextarg))
-        return PARAM_BAD_NUMERIC;
-      if(!config->low_speed_time)
-        config->low_speed_time=30;
-      break;
-    case 'z': /* time condition coming up */
-      switch(*nextarg) {
-      case '+':
-        nextarg++;
-      default:
-        /* If-Modified-Since: (section 14.28 in RFC2068) */
-        config->timecond = CURL_TIMECOND_IFMODSINCE;
-        break;
-      case '-':
-        /* If-Unmodified-Since:  (section 14.24 in RFC2068) */
-        config->timecond = CURL_TIMECOND_IFUNMODSINCE;
-        nextarg++;
-        break;
-      case '=':
-        /* Last-Modified:  (section 14.29 in RFC2068) */
-        config->timecond = CURL_TIMECOND_LASTMOD;
-        nextarg++;
-        break;
-      }
-      now=time(NULL);
-      config->condtime=curl_getdate(nextarg, &now);
-      if(-1 == (int)config->condtime) {
-        /* now let's see if it is a file name to get the time from instead! */
-        struct_stat statbuf;
-        if(-1 == stat(nextarg, &statbuf)) {
-          /* failed, remove time condition */
-          config->timecond = CURL_TIMECOND_NONE;
-          warnf(config,
-                "Illegal date format for -z, --timecond (and not "
-                "a file name). Disabling time condition. "
-                "See curl_getdate(3) for valid date syntax.\n");
-        }
-        else {
-          /* pull the time out from the file */
-          config->condtime = statbuf.st_mtime;
-        }
-      }
-      break;
-    default: /* unknown flag */
-      return PARAM_OPTION_UNKNOWN;
-    }
-    hit = -1;
-
-  } while(!longopt && !singleopt && *++parse && !*usedarg);
-
-  return PARAM_OK;
-}
-
-/*
- * Copies the string from line to the buffer at param, unquoting
- * backslash-quoted characters and NUL-terminating the output string.
- * Stops at the first non-backslash-quoted double quote character or the
- * end of the input string. param must be at least as long as the input
- * string.  Returns the pointer after the last handled input character.
- */
-static const char *unslashquote(const char *line, char *param)
-{
-  while(*line && (*line != '\"')) {
-    if(*line == '\\') {
-      char out;
-      line++;
-
-      /* default is to output the letter after the backslash */
-      switch(out = *line) {
-      case '\0':
-        continue; /* this'll break out of the loop */
-      case 't':
-        out='\t';
-        break;
-      case 'n':
-        out='\n';
-        break;
-      case 'r':
-        out='\r';
-        break;
-      case 'v':
-        out='\v';
-        break;
-      }
-      *param++=out;
-      line++;
-    }
-    else
-      *param++=*line++;
-  }
-  *param=0; /* always zero terminate */
-  return line;
-}
-
-/* return 0 on everything-is-fine, and non-zero otherwise */
-static int parseconfig(const char *filename,
-                       struct Configurable *config)
-{
-  int res;
-  FILE *file;
-  char filebuffer[512];
-  bool usedarg;
-  char *home;
-  int rc = 0;
-
-  if(!filename || !*filename) {
-    /* NULL or no file name attempts to load .curlrc from the homedir! */
-
-#define CURLRC DOT_CHAR "curlrc"
-
-#ifndef __AMIGA__
-    filename = CURLRC;   /* sensible default */
-    home = homedir();    /* portable homedir finder */
-    if(home) {
-      if(strlen(home)<(sizeof(filebuffer)-strlen(CURLRC))) {
-        snprintf(filebuffer, sizeof(filebuffer),
-                 "%s%s%s", home, DIR_CHAR, CURLRC);
-
-#ifdef WIN32
-        /* Check if the file exists - if not, try CURLRC in the same
-         * directory as our executable
-         */
-        file = fopen(filebuffer, "r");
-        if(file != NULL) {
-          fclose(file);
-          filename = filebuffer;
-        }
-        else {
-          /* Get the filename of our executable. GetModuleFileName is
-           * already declared via inclusions done in setup header file.
-           * We assume that we are using the ASCII version here.
-           */
-          int n = GetModuleFileName(0, filebuffer, sizeof(filebuffer));
-          if(n > 0 && n < (int)sizeof(filebuffer)) {
-            /* We got a valid filename - get the directory part */
-            char *lastdirchar = strrchr(filebuffer, '\\');
-            if(lastdirchar) {
-              size_t remaining;
-              *lastdirchar = 0;
-              /* If we have enough space, build the RC filename */
-              remaining = sizeof(filebuffer) - strlen(filebuffer);
-              if(strlen(CURLRC) < remaining - 1) {
-                snprintf(lastdirchar, remaining,
-                         "%s%s", DIR_CHAR, CURLRC);
-                /* Don't bother checking if it exists - we do
-                 * that later
-                 */
-                filename = filebuffer;
-              }
-            }
-          }
-        }
-#else /* WIN32 */
-        filename = filebuffer;
-#endif /* WIN32 */
-      }
-      Curl_safefree(home); /* we've used it, now free it */
-    }
-
-# else /* __AMIGA__ */
-    /* On AmigaOS all the config files are into env:
-     */
-    filename = "ENV:" CURLRC;
-
-#endif
-  }
-
-  if(strcmp(filename,"-"))
-    file = fopen(filename, "r");
-  else
-    file = stdin;
-
-  if(file) {
-    char *line;
-    char *aline;
-    char *option;
-    char *param;
-    int lineno=0;
-    bool alloced_param;
-
-#define ISSEP(x) (((x)=='=') || ((x) == ':'))
-
-    while(NULL != (aline = my_get_line(file))) {
-      lineno++;
-      line = aline;
-      alloced_param=FALSE;
-
-      /* line with # in the first non-blank column is a comment! */
-      while(*line && ISSPACE(*line))
-        line++;
-
-      switch(*line) {
-      case '#':
-      case '/':
-      case '\r':
-      case '\n':
-      case '*':
-      case '\0':
-        Curl_safefree(aline);
-        continue;
-      }
-
-      /* the option keywords starts here */
-      option = line;
-      while(*line && !ISSPACE(*line) && !ISSEP(*line))
-        line++;
-      /* ... and has ended here */
-
-      if(*line)
-        *line++=0; /* zero terminate, we have a local copy of the data */
-
-#ifdef DEBUG_CONFIG
-      fprintf(stderr, "GOT: %s\n", option);
-#endif
-
-      /* pass spaces and separator(s) */
-      while(*line && (ISSPACE(*line) || ISSEP(*line)))
-        line++;
-
-      /* the parameter starts here (unless quoted) */
-      if(*line == '\"') {
-        /* quoted parameter, do the quote dance */
-        line++;
-        param=malloc(strlen(line)+1); /* parameter */
-        if(!param) {
-          /* out of memory */
-          Curl_safefree(aline);
-          rc = 1;
-          break;
-        }
-        alloced_param=TRUE;
-        (void)unslashquote(line, param);
-      }
-      else {
-        param=line; /* parameter starts here */
-        while(*line && !ISSPACE(*line))
-          line++;
-        *line=0; /* zero terminate */
-      }
-
-      if(param && !*param) {
-        /* do this so getparameter can check for required parameters.
-           Otherwise it always thinks there's a parameter. */
-        if(alloced_param)
-          Curl_safefree(param);
-        param = NULL;
-      }
-
-#ifdef DEBUG_CONFIG
-      fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
-#endif
-      res = getparameter(option, param, &usedarg, config);
-
-      if(param && *param && !usedarg)
-        /* we passed in a parameter that wasn't used! */
-        res = PARAM_GOT_EXTRA_PARAMETER;
-
-      if(res != PARAM_OK) {
-        /* the help request isn't really an error */
-        if(!strcmp(filename, "-")) {
-          filename=(char *)"<stdin>";
-        }
-        if(PARAM_HELP_REQUESTED != res) {
-          const char *reason = param2text(res);
-          warnf(config, "%s:%d: warning: '%s' %s\n",
-                filename, lineno, option, reason);
-        }
-      }
-
-      if(alloced_param)
-        Curl_safefree(param);
-
-      Curl_safefree(aline);
-    }
-    if(file != stdin)
-      fclose(file);
-  }
-  else
-    rc = 1; /* couldn't open the file */
-  return rc;
-}
-
-static void go_sleep(long ms)
-{
-#ifdef HAVE_POLL_FINE
-  /* portable subsecond "sleep" */
-  poll((void *)0, 0, (int)ms);
-#else
-  /* systems without poll() need other solutions */
-
-#ifdef WIN32
-  /* Windows offers a millisecond sleep */
-  Sleep(ms);
-#elif defined(MSDOS)
-  delay(ms);
-#else
-  /* Other systems must use select() for this */
-  struct timeval timeout;
-
-  timeout.tv_sec = ms/1000;
-  ms = ms%1000;
-  timeout.tv_usec = ms * 1000;
-
-  select(0, NULL,  NULL, NULL, &timeout);
-#endif
-
-#endif
-}
-
-#define RETRY_SLEEP_DEFAULT 1000L   /* ms */
-#define RETRY_SLEEP_MAX     600000L /* ms == 10 minutes */
-
-static bool
-output_expected(const char* url, const char* uploadfile)
-{
-  if(!uploadfile)
-    return TRUE;  /* download */
-  if(checkprefix("http://", url) || checkprefix("https://", url))
-    return TRUE;   /* HTTP(S) upload */
-
-  return FALSE; /* non-HTTP upload, probably no output should be expected */
-}
-
-static bool stdin_upload(const char *uploadfile)
-{
-  return (curlx_strequal(uploadfile, "-") ||
-          curlx_strequal(uploadfile, ".")) ? TRUE : FALSE;
-}
-
-/* Adds the file name to the URL if it doesn't already have one.
- * url will be freed before return if the returned pointer is different
- */
-static char *add_file_name_to_url(CURL *curl, char *url, const char *filename)
-{
-  /* If no file name part is given in the URL, we add this file name */
-  char *ptr=strstr(url, "://");
-  if(ptr)
-    ptr+=3;
-  else
-    ptr=url;
-  ptr = strrchr(ptr, '/');
-  if(!ptr || !strlen(++ptr)) {
-    /* The URL has no file name part, add the local file name. In order
-       to be able to do so, we have to create a new URL in another
-       buffer.*/
-
-    /* We only want the part of the local path that is on the right
-       side of the rightmost slash and backslash. */
-    const char *filep = strrchr(filename, '/');
-    char *file2 = strrchr(filep?filep:filename, '\\');
-    char *encfile;
-
-    if(file2)
-      filep = file2+1;
-    else if(filep)
-      filep++;
-    else
-      filep = filename;
-
-    /* URL encode the file name */
-    encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
-    if(encfile) {
-      char *urlbuffer = malloc(strlen(url) + strlen(encfile) + 3);
-      if(!urlbuffer) {
-        Curl_safefree(url);
-        return NULL;
-      }
-      if(ptr)
-        /* there is a trailing slash on the URL */
-        sprintf(urlbuffer, "%s%s", url, encfile);
-      else
-        /* there is no trailing slash on the URL */
-        sprintf(urlbuffer, "%s/%s", url, encfile);
-
-      curl_free(encfile);
-
-      Curl_safefree(url);
-      url = urlbuffer; /* use our new URL instead! */
-    }
-  }
-  return url;
-}
-
-/* Extracts the name portion of the URL.
- * Returns a heap-allocated string, or NULL if no name part
- */
-static char *get_url_file_name(const char *url)
-{
-  char *fn = NULL;
-
-  /* Find and get the remote file name */
-  const char * pc =strstr(url, "://");
-  if(pc)
-    pc+=3;
-  else
-    pc=url;
-  pc = strrchr(pc, '/');
-
-  if(pc) {
-    /* duplicate the string beyond the slash */
-    pc++;
-    fn = *pc ? strdup(pc): NULL;
-  }
-  return fn;
-}
-
-#ifdef CURLDEBUG
-static void memory_tracking_init(void)
-{
-  char *env;
-  /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
-  env = curlx_getenv("CURL_MEMDEBUG");
-  if(env) {
-    /* use the value as file name */
-    char fname[CURL_MT_LOGFNAME_BUFSIZE];
-    if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
-      env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
-    strcpy(fname, env);
-    curl_free(env);
-    curl_memdebug(fname);
-    /* this weird stuff here is to make curl_free() get called
-       before curl_memdebug() as otherwise memory tracking will
-       log a free() without an alloc! */
-  }
-  /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
-  env = curlx_getenv("CURL_MEMLIMIT");
-  if(env) {
-    char *endptr;
-    long num = strtol(env, &endptr, 10);
-    if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
-      curl_memlimit(num);
-    curl_free(env);
-  }
-}
-#else
-#  define memory_tracking_init() Curl_nop_stmt
-#endif
-
-static int
-operate(struct Configurable *config, int argc, argv_item_t argv[])
-{
-  char errorbuffer[CURL_ERROR_SIZE];
-  struct ProgressData progressbar;
-  struct getout *urlnode;
-
-  struct OutStruct heads;
-
-  CURL *curl = NULL;
-  char *httpgetfields = NULL;
-
-  bool stillflags;
-  int res = 0;
-  int i;
-
-  errorbuffer[0] = '\0';
-  /* default headers output stream is stdout */
-  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 = TRUE;
-  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);
-    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 *origopt = 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", origopt, 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
-   * 2: if #1 isn't found, use the windows API function SearchPath()
-   *    to find it along the app's path (includes app's dir and CWD)
-   *
-   * We support the environment variable thing for non-Windows platforms
-   * too. Just for the sake of it.
-   */
-  if(!config->cacert &&
-     !config->capath &&
-     !config->insecure_ok) {
-    char *env;
-    env = curlx_getenv("CURL_CA_BUNDLE");
-    if(env) {
-      config->cacert = strdup(env);
-      if(!config->cacert) {
-        curl_free(env);
-        helpf(config->errors, "out of memory\n");
-        res = CURLE_OUT_OF_MEMORY;
-        goto quit_curl;
-      }
-    }
-    else {
-      env = curlx_getenv("SSL_CERT_DIR");
-      if(env) {
-        config->capath = strdup(env);
-        if(!config->capath) {
-          curl_free(env);
-          helpf(config->errors, "out of memory\n");
-          res = CURLE_OUT_OF_MEMORY;
-          goto quit_curl;
-        }
-      }
-      else {
-        env = curlx_getenv("SSL_CERT_FILE");
-        if(env) {
-          config->cacert = strdup(env);
-          if(!config->cacert) {
-            curl_free(env);
-            helpf(config->errors, "out of memory\n");
-            res = CURLE_OUT_OF_MEMORY;
-            goto quit_curl;
-          }
-        }
-      }
-    }
-
-    if(env)
-      curl_free(env);
-#ifdef WIN32
-    else {
-      res = FindWin32CACert(config, "curl-ca-bundle.crt");
-      if(res)
-        goto quit_curl;
-    }
-#endif
-  }
-
-  if(config->postfields) {
-    if(config->use_httpget) {
-      /* Use the postfields data for a http get */
-      httpgetfields = strdup(config->postfields);
-      Curl_safefree(config->postfields);
-      if(SetHTTPrequest(config,
-                        (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
-                        &config->httpreq)) {
-        res = PARAM_BAD_USE;
-        goto quit_curl;
-      }
-    }
-    else {
-      if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) {
-        res = PARAM_BAD_USE;
-        goto quit_curl;
-      }
-    }
-  }
-
-  /* This is the first entry added to easysrc and it initializes the slist */
-  easysrc = curl_slist_append(easysrc, "CURL *hnd = curl_easy_init();");
-  if(!easysrc) {
-    helpf(config->errors, "out of memory\n");
-    res = CURLE_OUT_OF_MEMORY;
-    goto quit_curl;
-  }
-
-  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: */
-    if(!curlx_strequal(config->headerfile, "-")) {
-      FILE *newfile = fopen(config->headerfile, "wb");
-      if(!newfile) {
-        warnf(config, "Failed to open %s\n", config->headerfile);
-        res = CURLE_WRITE_ERROR;
-        goto quit_curl;
-      }
-      else {
-        heads.filename = config->headerfile;
-        heads.s_isreg = TRUE;
-        heads.fopened = TRUE;
-        heads.stream = newfile;
-      }
-    }
-  }
-
-  /*
-  ** Nested loops start here.
-  */
-
-  /* loop through the list of given URLs */
-
-  for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
-
-    int up; /* upload file counter within a single upload glob */
-    char *infiles; /* might be a glob pattern */
-    char *outfiles;
-    int infilenum;
-    URLGlob *inglob;
-
-    outfiles = NULL;
-    infilenum = 0;
-    inglob = NULL;
-
-    /* urlnode->url is the full URL (it might be NULL) */
-
-    if(!urlnode->url) {
-      /* This node has no URL. Free node data without destroying the
-         node itself nor modifying next pointer and continue to next */
-      Curl_safefree(urlnode->outfile);
-      Curl_safefree(urlnode->infile);
-      urlnode->flags = 0;
-      continue; /* next URL please */
-    }
-
-    /* save outfile pattern before expansion */
-    if(urlnode->outfile) {
-      outfiles = strdup(urlnode->outfile);
-      if(!outfiles) {
-        helpf(config->errors, "out of memory\n");
-        res = CURLE_OUT_OF_MEMORY;
-        break;
-      }
-    }
-
-    infiles = urlnode->infile;
-
-    if(!config->globoff && infiles) {
-      /* Unless explicitly shut off */
-      res = glob_url(&inglob, infiles, &infilenum,
-                     config->showerror?config->errors:NULL);
-      if(res) {
-        Curl_safefree(outfiles);
-        break;
-      }
-    }
-
-    /* Here's the loop for uploading multiple files within the same
-       single globbed string. If no upload, we enter the loop once anyway. */
-    for(up = 0 ;; up++) {
-
-      char *uploadfile; /* a single file, never a glob */
-      int separator;
-      URLGlob *urls;
-      int urlnum;
-
-      uploadfile = NULL;
-      separator = 0;
-      urls = NULL;
-      urlnum = 0;
-
-      if(!up && !infiles)
-        Curl_nop_stmt;
-      else {
-        if(inglob)
-          uploadfile = glob_next_url(inglob);
-        else if(!up)
-          uploadfile = strdup(infiles);
-        else
-          uploadfile = NULL;
-        if(!uploadfile)
-          break;
-      }
-
-      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);
-        if(res) {
-          Curl_safefree(uploadfile);
-          break;
-        }
-      }
-      else
-        urlnum = 1; /* without globbing, this is a single URL */
-
-      /* if multiple files extracted to stdout, insert separators! */
-      separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
-
-      /* Here's looping around each globbed URL */
-      for(i = 0 ;; i++) {
-
-        int infd;
-        bool infdopen;
-        char *outfile;
-        struct OutStruct outs;
-        struct InStruct input;
-        struct timeval retrystart;
-        curl_off_t uploadfilesize;
-        long retry_numretries;
-        long retry_sleep_default;
-        long retry_sleep;
-        char *this_url;
-
-        outfile = NULL;
-        infdopen = FALSE;
-        infd = STDIN_FILENO;
-        uploadfilesize = -1; /* -1 means unknown */
-
-        /* default output stream is stdout */
-        memset(&outs, 0, sizeof(struct OutStruct));
-        outs.stream = stdout;
-        outs.config = config;
-
-        if(urls)
-          this_url = glob_next_url(urls);
-        else if(!i) {
-          this_url = strdup(urlnode->url);
-        }
-        else
-          this_url = NULL;
-        if(!this_url)
-          break;
-
-        if(outfiles) {
-          outfile = strdup(outfiles);
-          if(!outfile) {
-            res = CURLE_OUT_OF_MEMORY;
-            goto show_error;
-          }
-        }
-
-        if((urlnode->flags&GETOUT_USEREMOTE) ||
-           (outfile && !curlx_strequal("-", outfile)) ) {
-
-          /*
-           * We have specified a file name to store the result in, or we have
-           * decided we want to use the remote file name.
-           */
-
-          if(!outfile) {
-            /* extract the file name from the URL */
-            outfile = get_url_file_name(this_url);
-            if((!outfile || !*outfile) && !config->content_disposition) {
-              helpf(config->errors, "Remote file name has no length!\n");
-              res = CURLE_WRITE_ERROR;
-              goto quit_urls;
-            }
-#if defined(MSDOS) || defined(WIN32)
-            /* For DOS and WIN32, we do some major replacing of
-               bad characters in the file name before using it */
-            outfile = sanitize_dos_name(outfile);
-            if(!outfile) {
-              res = CURLE_OUT_OF_MEMORY;
-              goto show_error;
-            }
-#endif /* MSDOS || WIN32 */
-          }
-          else if(urls) {
-            /* fill '#1' ... '#9' terms from URL pattern */
-            char *storefile = outfile;
-            outfile = glob_match_url(storefile, urls);
-            Curl_safefree(storefile);
-            if(!outfile) {
-              /* bad globbing */
-              warnf(config, "bad output glob!\n");
-              res = CURLE_FAILED_INIT;
-              goto quit_urls;
-            }
-          }
-
-          /* Create the directory hierarchy, if not pre-existent to a multiple
-             file output call */
-
-          if(config->create_dirs) {
-            res = create_dir_hierarchy(outfile, config->errors);
-            /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
-            if(res == CURLE_WRITE_ERROR)
-              goto quit_urls;
-            if(res) {
-              goto show_error;
-            }
-          }
-
-          if((urlnode->flags & GETOUT_USEREMOTE)
-             && config->content_disposition) {
-            /* Our header callback sets the filename */
-            DEBUGASSERT(!outs.filename);
-          }
-          else {
-            if(config->resume_from_current) {
-              /* We're told to continue from where we are now. Get the size
-                 of the file as it is now and open it for append instead */
-              struct_stat fileinfo;
-              /* VMS -- Danger, the filesize is only valid for stream files */
-              if(0 == stat(outfile, &fileinfo))
-                /* set offset to current file size: */
-                config->resume_from = fileinfo.st_size;
-              else
-                /* let offset be 0 */
-                config->resume_from = 0;
-            }
-
-            if(config->resume_from) {
-              /* open file for output: */
-              FILE *file = fopen(outfile, config->resume_from?"ab":"wb");
-              if(!file) {
-                helpf(config->errors, "Can't open '%s'!\n", outfile);
-                res = CURLE_WRITE_ERROR;
-                goto quit_urls;
-              }
-              outs.fopened = TRUE;
-              outs.stream = file;
-              outs.init = config->resume_from;
-            }
-            else {
-              outs.stream = NULL; /* open when needed */
-            }
-            outs.filename = outfile;
-            outs.s_isreg = TRUE;
-          }
-        }
-
-        if(uploadfile && !stdin_upload(uploadfile)) {
-          /*
-           * We have specified a file to upload and it isn't "-".
-           */
-          struct_stat fileinfo;
-
-          this_url = add_file_name_to_url(curl, this_url, uploadfile);
-          if(!this_url) {
-            res = CURLE_OUT_OF_MEMORY;
-            goto show_error;
-          }
-          /* VMS Note:
-           *
-           * Reading binary from files can be a problem...  Only FIXED, VAR
-           * etc WITHOUT implied CC will work Others need a \n appended to a
-           * line
-           *
-           * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a
-           * fixed file with implied CC needs to have a byte added for every
-           * record processed, this can by derived from Filesize & recordsize
-           * for VARiable record files the records need to be counted!  for
-           * every record add 1 for linefeed and subtract 2 for the record
-           * header for VARIABLE header files only the bare record data needs
-           * to be considered with one appended if implied CC
-           */
-
-          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) {
-              close(infd);
-              infd = STDIN_FILENO;
-            }
-            res = CURLE_READ_ERROR;
-            goto quit_urls;
-          }
-          infdopen = TRUE;
-
-          /* we ignore file size for char/block devices, sockets, etc. */
-          if(S_ISREG(fileinfo.st_mode))
-            uploadfilesize = fileinfo.st_size;
-
-        }
-        else if(uploadfile && stdin_upload(uploadfile)) {
-          /* count to see if there are more than one auth bit set
-             in the authtype field */
-          int authbits = 0;
-          int bitcheck = 0;
-          while(bitcheck < 32) {
-            if(config->authtype & (1 << bitcheck++)) {
-              authbits++;
-              if(authbits > 1) {
-                /* more than one, we're done! */
-                break;
-              }
-            }
-          }
-
-          /*
-           * If the user has also selected --anyauth or --proxy-anyauth
-           * we should warn him/her.
-           */
-          if(config->proxyanyauth || (authbits>1)) {
-            warnf(config,
-                  "Using --anyauth or --proxy-anyauth with upload from stdin"
-                  " involves a big risk of it not working. Use a temporary"
-                  " file or a fixed auth type instead!\n");
-          }
-
-          DEBUGASSERT(infdopen == FALSE);
-          DEBUGASSERT(infd == STDIN_FILENO);
-
-          set_binmode(stdin);
-          if(curlx_strequal(uploadfile, ".")) {
-            if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0)
-              warnf(config,
-                    "fcntl failed on fd=%d: %s\n", infd, strerror(errno));
-          }
-        }
-
-        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)))
-          /* we send the output to a tty, therefore we switch off the progress
-             meter */
-          config->noprogress = config->isatty = TRUE;
-
-        if(urlnum > 1 && !(config->mute)) {
-          fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
-                  i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
-          if(separator)
-            printf("%s%s\n", CURLseparator, this_url);
-        }
-        if(httpgetfields) {
-          char *urlbuffer;
-          /* Find out whether the url contains a file name */
-          const char *pc = strstr(this_url, "://");
-          char sep = '?';
-          if(pc)
-            pc += 3;
-          else
-            pc = this_url;
-
-          pc = strrchr(pc, '/'); /* check for a slash */
-
-          if(pc) {
-            /* there is a slash present in the URL */
-
-            if(strchr(pc, '?'))
-              /* Ouch, there's already a question mark in the URL string, we
-                 then append the data with an ampersand separator instead! */
-              sep='&';
-          }
-          /*
-           * 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);
-          else
-            /* Append  / before the ? to create a well-formed url
-               if the url contains a hostname only
-            */
-            sprintf(urlbuffer, "%s/?%s", this_url, httpgetfields);
-
-          Curl_safefree(this_url); /* free previous URL */
-          this_url = urlbuffer; /* use our new URL instead! */
-        }
-
-        if(!config->errors)
-          config->errors = stderr;
-
-        if((!outfile || !strcmp(outfile, "-")) && !config->use_ascii) {
-          /* We get the output to stdout and we have not got the ASCII/text
-             flag, then set stdout to be binary */
-          set_binmode(stdout);
-        }
-
-        if(config->tcp_nodelay)
-          my_setopt(curl, CURLOPT_TCP_NODELAY, 1);
-
-        /* where to store */
-        my_setopt(curl, CURLOPT_WRITEDATA, &outs);
-        /* what call to write */
-        my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
-
-        /* for uploads */
-        input.fd = infd;
-        input.config = config;
-        my_setopt(curl, CURLOPT_READDATA, &input);
-        /* what call to read */
-        if((outfile && !curlx_strequal("-", outfile)) ||
-           !checkprefix("telnet:", this_url))
-          my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
-
-        /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
-           CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
-        my_setopt(curl, CURLOPT_SEEKDATA, &input);
-        my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
-
-        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);
-
-        /* 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);
-        if(config->no_body) {
-          my_setopt(curl, CURLOPT_NOBODY, 1);
-          my_setopt(curl, CURLOPT_HEADER, 1);
-        }
-        else
-          my_setopt(curl, CURLOPT_HEADER, config->include_headers);
-
-#if !defined(CURL_DISABLE_PROXY)
-        {
-          /* TODO: Make this a run-time check instead of compile-time one. */
-
-          my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
-          my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
-
-          /* new in libcurl 7.3 */
-          my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
-
-          /* new in libcurl 7.5 */
-          if(config->proxy)
-            my_setopt(curl, CURLOPT_PROXYTYPE, config->proxyver);
-
-          /* new in libcurl 7.10 */
-          if(config->socksproxy) {
-            my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
-            my_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
-          }
-
-          /* new in libcurl 7.10.6 */
-          if(config->proxyanyauth)
-            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
-          else if(config->proxynegotiate)
-            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
-          else if(config->proxyntlm)
-            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
-          else if(config->proxydigest)
-            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
-          else if(config->proxybasic)
-            my_setopt(curl, CURLOPT_PROXYAUTH, 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);
-
-        if(config->netrc_opt)
-          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
-        else if(config->netrc || config->netrc_file)
-          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
-        else
-          my_setopt(curl, CURLOPT_NETRC, 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_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);
-
-        if(built_in_protos & CURLPROTO_HTTP) {
-
-          my_setopt(curl, CURLOPT_FOLLOWLOCATION,
-                    config->followlocation);
-          my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
-                    config->unrestricted_auth);
-
-          switch(config->httpreq) {
-          case HTTPREQ_SIMPLEPOST:
-            my_setopt_str(curl, CURLOPT_POSTFIELDS,
-                          config->postfields);
-            my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
-                      config->postfieldsize);
-            break;
-          case HTTPREQ_POST:
-            my_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
-            break;
-          default:
-            break;
-          }
-
-          my_setopt_str(curl, CURLOPT_REFERER, config->referer);
-          my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer);
-          my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
-          my_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
-
-          /* new in libcurl 7.5 */
-          my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
-
-          /* new in libcurl 7.9.1 */
-          if(config->httpversion)
-            my_setopt(curl, CURLOPT_HTTP_VERSION, config->httpversion);
-
-          /* new in libcurl 7.10.6 (default is Basic) */
-          if(config->authtype)
-            my_setopt(curl, CURLOPT_HTTPAUTH, config->authtype);
-
-          /* curl 7.19.1 (the 301 version existed in 7.18.2) */
-          my_setopt(curl, CURLOPT_POSTREDIR, config->post301 |
-                    (config->post302 ? CURL_REDIR_POST_302 : FALSE));
-
-          /* new in libcurl 7.21.6 */
-          if(config->encoding)
-            my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
-
-          /* new in libcurl 7.21.6 */
-          if(config->tr_encoding)
-            my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1);
-
-        } /* (built_in_protos & CURLPROTO_HTTP) */
-
-        my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
-        my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
-                  config->low_speed_limit);
-        my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
-        my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
-                  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);
-        my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
-        my_setopt(curl, CURLOPT_SSLKEY, config->key);
-        my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
-        my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
-
-        if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
-
-          /* SSH and SSL private key uses same command-line option */
-          /* new in libcurl 7.16.1 */
-          my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
-          /* new in libcurl 7.16.1 */
-          my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
-
-          /* new in libcurl 7.17.1: SSH host key md5 checking allows us
-             to fail if we are not talking to who we think we should */
-          my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
-                        config->hostpubmd5);
-        }
-
-        if(config->cacert)
-          my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
-        if(config->capath)
-          my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
-        if(config->crlfile)
-          my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
-
-        if(curlinfo->features & CURL_VERSION_SSL) {
-          if(config->insecure_ok) {
-            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
-            my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L);
-          }
-          else {
-            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
-            /* libcurl default is strict verifyhost -> 2L   */
-            /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
-          }
-        }
-
-        if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
-          if(!config->insecure_ok) {
-            char *home;
-            char *file;
-            res = CURLE_OUT_OF_MEMORY;
-            home = homedir();
-            if(home) {
-              file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR);
-              if(file) {
-                /* new in curl 7.19.6 */
-                res = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file);
-                curl_free(file);
-                if(res == CURLE_UNKNOWN_OPTION)
-                  /* libssh2 version older than 1.1.1 */
-                  res = CURLE_OK;
-              }
-              free(home);
-            }
-            if(res)
-              goto show_error;
-          }
-        }
-
-        if(config->no_body || config->remote_time) {
-          /* no body or use remote time */
-          my_setopt(curl, CURLOPT_FILETIME, TRUE);
-        }
-
-        my_setopt(curl, CURLOPT_CRLF, config->crlf);
-        my_setopt(curl, CURLOPT_QUOTE, config->quote);
-        my_setopt(curl, CURLOPT_POSTQUOTE, config->postquote);
-        my_setopt(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->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.7 */
-          my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession);
-        }
-#endif
-
-        my_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
-        my_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
-        my_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
-        my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
-        my_setopt(curl, CURLOPT_STDERR, config->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) {
-          /* 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);
-        }
-
-        /* new in libcurl 7.6.2: */
-        my_setopt(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);
-
-        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);
-
-        /* new in libcurl 7.10.5 */
-        if(config->disable_eprt)
-          /* disable it */
-          my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
-
-        if(config->tracetype != TRACE_NONE) {
-          my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
-          my_setopt(curl, CURLOPT_DEBUGDATA, config);
-          my_setopt(curl, CURLOPT_VERBOSE, TRUE);
-        }
-
-        /* new in curl 7.9.3 */
-        if(config->engine) {
-          res = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
-          if(res)
-            goto show_error;
-          my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
-        }
-
-        /* 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);
-
-        /* new in curl 7.10.8 */
-        if(config->max_filesize)
-          my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
-                    config->max_filesize);
-
-        if(4 == config->ip_version)
-          my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
-        else if(6 == config->ip_version)
-          my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
-        else
-          my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
-
-        /* new in curl 7.15.5 */
-        if(config->ftp_ssl_reqd)
-          my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
-
-        /* new in curl 7.11.0 */
-        else if(config->ftp_ssl)
-          my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
-
-        /* new in curl 7.16.0 */
-        else if(config->ftp_ssl_control)
-          my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
-
-        /* new in curl 7.16.1 */
-        if(config->ftp_ssl_ccc)
-          my_setopt(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
-
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-        {
-          /* TODO: Make this a run-time check instead of compile-time one. */
-
-          /* new in curl 7.19.4 */
-          if(config->socks5_gssapi_service)
-            my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
-                          config->socks5_gssapi_service);
-
-          /* new in curl 7.19.4 */
-          if(config->socks5_gssapi_nec)
-            my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
-                          config->socks5_gssapi_nec);
-        }
-#endif
-        /* curl 7.13.0 */
-        my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
-
-        my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
-
-        /* curl 7.14.2 */
-        my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
-
-        /* curl 7.15.1 */
-        my_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
-
-        /* curl 7.15.2 */
-        if(config->localport) {
-          my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
-          my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
-                        config->localportrange);
-        }
-
-        /* curl 7.15.5 */
-        my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
-                      config->ftp_alternative_to_user);
-
-        /* curl 7.16.0 */
-        if(config->disable_sessionid)
-          my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE,
-                    !config->disable_sessionid);
-
-        /* curl 7.16.2 */
-        if(config->raw) {
-          my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, FALSE);
-          my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, FALSE);
-        }
-
-        /* curl 7.17.1 */
-        if(!config->nokeepalive) {
-          my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, tool_sockopt_cb);
-          my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
-        }
-
-        /* curl 7.20.0 */
-        if(config->tftp_blksize)
-          my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
-
-        if(config->mail_from)
-          my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
-
-        if(config->mail_rcpt)
-          my_setopt(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
-
-        /* curl 7.20.x */
-        if(config->ftp_pret)
-          my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
-
-        if(config->proto_present)
-          my_setopt(curl, CURLOPT_PROTOCOLS, config->proto);
-        if(config->proto_redir_present)
-          my_setopt(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
-
-        if((urlnode->flags & GETOUT_USEREMOTE)
-           && config->content_disposition) {
-          my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
-          my_setopt(curl, CURLOPT_HEADERDATA, &outs);
-        }
-        else {
-          /* if HEADERFUNCTION was set to something in the previous loop, it
-             is important that we set it (back) to NULL now */
-          my_setopt(curl, CURLOPT_HEADERFUNCTION, NULL);
-          my_setopt(curl, CURLOPT_HEADERDATA, config->headerfile?&heads:NULL);
-        }
-
-        if(config->resolve)
-          /* new in 7.21.3 */
-          my_setopt(curl, CURLOPT_RESOLVE, config->resolve);
-
-        /* new in 7.21.4 */
-        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
-          if(config->tls_username)
-            my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
-                          config->tls_username);
-          if(config->tls_password)
-            my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
-                          config->tls_password);
-          if(config->tls_authtype)
-            my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
-                          config->tls_authtype);
-        }
-
-        /* new in 7.22.0 */
-        if(config->gssapi_delegation)
-          my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
-                        config->gssapi_delegation);
-
-        /* initialize retry vars for loop below */
-        retry_sleep_default = (config->retry_delay) ?
-          config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
-
-        retry_numretries = config->req_retry;
-        retry_sleep = retry_sleep_default; /* ms */
-        retrystart = cutil_tvnow();
-
-        for(;;) {
-          res = curl_easy_perform(curl);
-          if(!curl_slist_append(easysrc, "ret = curl_easy_perform(hnd);")) {
-            res = CURLE_OUT_OF_MEMORY;
-            goto show_error;
-          }
-
-          if(config->content_disposition && outs.stream && !config->mute &&
-             outs.filename)
-            printf("curl: Saved to filename '%s'\n", outs.filename);
-
-          /* if retry-max-time is non-zero, make sure we haven't exceeded the
-             time */
-          if(retry_numretries &&
-             (!config->retry_maxtime ||
-              (cutil_tvdiff(cutil_tvnow(), retrystart)<
-               config->retry_maxtime*1000L)) ) {
-            enum {
-              RETRY_NO,
-              RETRY_TIMEOUT,
-              RETRY_HTTP,
-              RETRY_FTP,
-              RETRY_LAST /* not used */
-            } retry = RETRY_NO;
-            long response;
-            if(CURLE_OPERATION_TIMEDOUT == res)
-              /* retry timeout always */
-              retry = RETRY_TIMEOUT;
-            else if((CURLE_OK == res) ||
-                    (config->failonerror &&
-                     (CURLE_HTTP_RETURNED_ERROR == res))) {
-              /* If it returned OK. _or_ failonerror was enabled and it
-                 returned due to such an error, check for HTTP transient
-                 errors to retry on. */
-              char *effective_url = NULL;
-              curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
-              if(effective_url &&
-                 checkprefix("http", effective_url)) {
-                /* This was HTTP(S) */
-                curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
-
-                switch(response) {
-                case 500: /* Internal Server Error */
-                case 502: /* Bad Gateway */
-                case 503: /* Service Unavailable */
-                case 504: /* Gateway Timeout */
-                  retry = RETRY_HTTP;
-                  /*
-                   * At this point, we have already written data to the output
-                   * file (or terminal). If we write to a file, we must rewind
-                   * or close/re-open the file so that the next attempt starts
-                   * over from the beginning.
-                   *
-                   * TODO: similar action for the upload case. We might need
-                   * to start over reading from a previous point if we have
-                   * uploaded something when this was returned.
-                   */
-                  break;
-                }
-              }
-            } /* if CURLE_OK */
-            else if(res) {
-              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
-
-              if(response/100 == 4)
-                /*
-                 * This is typically when the FTP server only allows a certain
-                 * amount of users and we are not one of them.  All 4xx codes
-                 * are transient.
-                 */
-                retry = RETRY_FTP;
-            }
-
-            if(retry) {
-              static const char * const m[]={
-                NULL, "timeout", "HTTP error", "FTP error"
-              };
-              warnf(config, "Transient problem: %s "
-                    "Will retry in %ld seconds. "
-                    "%ld retries left.\n",
-                    m[retry], retry_sleep/1000L, retry_numretries);
-
-              go_sleep(retry_sleep);
-              retry_numretries--;
-              if(!config->retry_delay) {
-                retry_sleep *= 2;
-                if(retry_sleep > RETRY_SLEEP_MAX)
-                  retry_sleep = RETRY_SLEEP_MAX;
-              }
-              if(outs.bytes && outs.filename) {
-                /* We have written data to a output file, we truncate file
-                 */
-                if(!config->mute)
-                  fprintf(config->errors, "Throwing away %"
-                          CURL_FORMAT_CURL_OFF_T " bytes\n",
-                          outs.bytes);
-                fflush(outs.stream);
-                /* truncate file at the position where we started appending */
-#ifdef HAVE_FTRUNCATE
-                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,
-                            "failed to truncate, exiting\n");
-                  res = CURLE_WRITE_ERROR;
-                  goto quit_urls;
-                }
-                /* now seek to the end of the file, the position where we
-                   just truncated the file in a large file-safe way */
-                fseek(outs.stream, 0, SEEK_END);
-#else
-                /* ftruncate is not available, so just reposition the file
-                   to the location we would have truncated it. This won't
-                   work properly with large files on 32-bit systems, but
-                   most of those will have ftruncate. */
-                fseek(outs.stream, (long)outs.init, SEEK_SET);
-#endif
-                outs.bytes = 0; /* clear for next round */
-              }
-              continue; /* curl_easy_perform loop */
-            }
-          } /* if retry_numretries */
-
-          /* In all ordinary cases, just break out of loop here */
-          break; /* curl_easy_perform loop */
-
-        }
-
-        if((config->progressmode == CURL_PROGRESS_BAR) &&
-           progressbar.calls)
-          /* if the custom progress bar has been displayed, we output a
-             newline here */
-          fputs("\n", progressbar.out);
-
-        if(config->writeout)
-          ourWriteOut(curl, config->writeout);
-#ifdef USE_ENVIRONMENT
-        if(config->writeenv)
-          ourWriteEnv(curl);
-#endif
-
-        /*
-        ** Code within this loop may jump directly here to label 'show_error'
-        ** in order to display an error message for CURLcode stored in 'res'
-        ** variable and exit loop once that necessary writing and cleanup
-        ** in label 'quit_urls' has been done.
-        */
-
-        show_error:
-
-#ifdef __VMS
-        if(is_vms_shell()) {
-          /* VMS DCL shell behavior */
-          if(!config->showerror)
-            vms_show = VMSSTS_HIDE;
-        }
-        else
-#endif
-        if(res && config->showerror) {
-          fprintf(config->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
-                  errorbuffer : curl_easy_strerror((CURLcode)res));
-          if(res == CURLE_SSL_CACERT)
-            fprintf(config->errors, "%s%s",
-                    CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
-        }
-
-        /* Fall through comment to 'quit_urls' label */
-
-        /*
-        ** Upon error condition and always that a message has already been
-        ** displayed, code within this loop may jump directly here to label
-        ** 'quit_urls' otherwise it should jump to 'show_error' label above.
-        **
-        ** When 'res' variable is _not_ CURLE_OK loop will exit once that
-        ** all code following 'quit_urls' has been executed. Otherwise it
-        ** will loop to the beginning from where it may exit if there are
-        ** no more urls left.
-        */
-
-        quit_urls:
-
-        /* Set file extended attributes */
-        if(!res && config->xattr && outs.fopened && outs.stream) {
-          int rc = fwrite_xattr(curl, fileno(outs.stream));
-          if(rc)
-            warnf(config, "Error setting extended attributes: %s\n",
-                  strerror(errno));
-        }
-
-        /* Close the file */
-        if(outs.fopened && outs.stream) {
-          int rc = fclose(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);
-          }
-        }
-        else if(!outs.s_isreg && outs.stream) {
-          /* Dump standard stream buffered data */
-          int rc = fflush(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);
-          }
-        }
-
-#ifdef __AMIGA__
-        if(!res && outs.s_isreg && outs.filename) {
-          /* Set the url (up to 80 chars) as comment for the file */
-          if(strlen(url) > 78)
-            url[79] = '\0';
-          SetComment(outs.filename, url);
-        }
-#endif
-
-#ifdef HAVE_UTIME
-        /* File time can only be set _after_ the file has been closed */
-        if(!res && config->remote_time && outs.s_isreg && outs.filename) {
-          /* Ask libcurl if we got a remote file time */
-          long filetime = -1;
-          curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
-          if(filetime >= 0) {
-            struct utimbuf times;
-            times.actime = (time_t)filetime;
-            times.modtime = (time_t)filetime;
-            utime(outs.filename, &times); /* set the time we got */
-          }
-        }
-#endif
-        /* No more business with this output struct */
-        if(outs.alloc_filename)
-          Curl_safefree(outs.filename);
-        memset(&outs, 0, sizeof(struct OutStruct));
-
-        /* Free loop-local allocated memory and close loop-local opened fd */
-
-        Curl_safefree(outfile);
-        Curl_safefree(this_url);
-
-        if(infdopen) {
-          close(infd);
-          infdopen = FALSE;
-          infd = STDIN_FILENO;
-        }
-
-        /* upon error exit loop */
-        if(res)
-          break;
-
-      } /* loop to the next URL */
-
-      /* Free loop-local allocated memory */
-
-      Curl_safefree(uploadfile);
-
-      if(urls) {
-        /* Free list of remaining URLs */
-        glob_cleanup(urls);
-        urls = NULL;
-      }
-
-      /* upon error exit loop */
-      if(res)
-        break;
-
-    } /* loop to the next globbed upload file */
-
-    /* Free loop-local allocated memory */
-
-    Curl_safefree(outfiles);
-
-    if(inglob) {
-      /* Free list of globbed upload files */
-      glob_cleanup(inglob);
-      inglob = NULL;
-    }
-
-    /* Free this URL node data without destroying the
-       the node itself nor modifying next pointer. */
-    Curl_safefree(urlnode->url);
-    Curl_safefree(urlnode->outfile);
-    Curl_safefree(urlnode->infile);
-    urlnode->flags = 0;
-
-    /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
-
-    /*
-    ** Bail out upon critical errors
-    */
-    switch(res) {
-    case CURLE_FAILED_INIT:
-    case CURLE_OUT_OF_MEMORY:
-    case CURLE_FUNCTION_NOT_FOUND:
-    case CURLE_BAD_FUNCTION_ARGUMENT:
-      goto quit_curl;
-    default:
-      /* Merrily loop to next URL */
-      break;
-    }
-
-  } /* for-loop through all URLs */
-
-  /*
-  ** Nested loops end here.
-  */
-
-  quit_curl:
-
-  /* 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;
-  }
-  if(easysrc)
-    curl_slist_append(easysrc, "curl_easy_cleanup(hnd);");
-
-  /* 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);
-
-  /* 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);
-
-  if(config->errors_fopened && config->errors)
-    fclose(config->errors);
-
-  main_free(); /* cleanup */
-
-  return res;
-}
-
-/* Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
-   open before starting to run.  Otherwise, the first three network
-   sockets opened by curl could be used for input sources, downloaded data
-   or error logs as they will effectively be stdin, stdout and/or stderr.
-*/
-static void checkfds(void)
-{
-#ifdef HAVE_PIPE
-  int fd[2] = { STDIN_FILENO, STDIN_FILENO };
-  while(fd[0] == STDIN_FILENO ||
-        fd[0] == STDOUT_FILENO ||
-        fd[0] == STDERR_FILENO ||
-        fd[1] == STDIN_FILENO ||
-        fd[1] == STDOUT_FILENO ||
-        fd[1] == STDERR_FILENO)
-    if(pipe(fd) < 0)
-      return;   /* Out of handles. This isn't really a big problem now, but
-                   will be when we try to create a socket later. */
-  close(fd[0]);
-  close(fd[1]);
-#endif
-}
-
-
-
-int main(int argc, char *argv[])
-{
-  int res;
-  struct Configurable config;
-
-  memset(&config, 0, sizeof(struct Configurable));
-
-  config.errors = stderr; /* default errors to stderr */
-
-  checkfds();
-
-  res = operate(&config, argc, argv);
-#ifdef __SYMBIAN32__
-  if(config.showerror)
-    pressanykey();
-#endif
-  free_config_fields(&config);
-
-#ifdef __NOVELL_LIBC__
-  if(getenv("_IN_NETWARE_BASH_") == NULL)
-    pressanykey();
-#endif
-#ifdef __VMS
-  vms_special_exit(res, vms_show);
-#else
-  return res;
-#endif
-}
-
-/*
- * Reads a line from the given file, ensuring is NUL terminated.
- * The pointer must be freed by the caller.
- * NULL is returned on an out of memory condition.
- */
-static char *my_get_line(FILE *fp)
-{
-  char buf[4096];
-  char *nl = NULL;
-  char *retval = NULL;
-
-  do {
-    if(NULL == fgets(buf, sizeof(buf), fp))
-      break;
-    if(NULL == retval) {
-      retval = strdup(buf);
-      if(!retval)
-        return NULL;
-    }
-    else {
-      char *ptr;
-      ptr = realloc(retval, strlen(retval) + strlen(buf) + 1);
-      if(NULL == ptr) {
-        Curl_safefree(retval);
-        return NULL;
-      }
-      retval = ptr;
-      strcat(retval, buf);
-    }
-  }
-  while(NULL == (nl = strchr(retval, '\n')));
-
-  if(NULL != nl)
-    *nl = '\0';
-
-  return retval;
-}
-
index 5250b2c..b45522b 100644 (file)
@@ -231,6 +231,19 @@ static char *rename_if_dos_device_name (char *file_name)
   return file_name;
 }
 
+#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
+
+/*
+ * Disable program default argument globbing. We do it on our own.
+ */
+char **__crt0_glob_function(char *arg)
+{
+  (void)arg;
+  return (char**)0;
+}
+
+#endif /* MSDOS && (__DJGPP__ || __GO32__) */
+
 #ifdef WIN32
 
 /*
index 658660f..ce475ac 100644 (file)
 
 char *sanitize_dos_name(char *file_name);
 
+#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
+
+char **__crt0_glob_function(char *arg);
+
+#endif /* MSDOS && (__DJGPP__ || __GO32__) */
+
 #ifdef WIN32
 
 CURLcode FindWin32CACert(struct Configurable *config, const char *bundle_file);
index aa0c060..21b5674 100644 (file)
@@ -31,3 +31,4 @@ extern struct curl_slist *easysrc_remarks;
 void dumpeasysrc(struct Configurable *config);
 
 #endif /* HEADER_CURL_TOOL_EASYSRC_H */
+
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
new file mode 100644 (file)
index 0000000..7ddd736
--- /dev/null
@@ -0,0 +1,1604 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#ifdef USE_MANUAL
+#  include "hugehelp.h"
+#endif
+
+#include "version.h"
+
+#include "tool_binmode.h"
+#include "tool_cfgable.h"
+#include "tool_cb_prg.h"
+#include "tool_formparse.h"
+#include "tool_getparam.h"
+#include "tool_help.h"
+#include "tool_helpers.h"
+#include "tool_libinfo.h"
+#include "tool_msgs.h"
+#include "tool_paramhlp.h"
+#include "tool_parsecfg.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef MSDOS
+#  define USE_WATT32
+#endif
+
+#define GetStr(str,val) do { \
+  if(*(str)) { \
+    free(*(str)); \
+    *(str) = NULL; \
+  } \
+  if((val)) \
+    *(str) = strdup((val)); \
+  if(!(val)) \
+    return PARAM_NO_MEM; \
+} WHILE_FALSE
+
+struct LongShort {
+  const char *letter; /* short name option */
+  const char *lname;  /* long name option */
+  bool extraparam;    /* whether it takes an additional argument */
+};
+
+static const struct LongShort aliases[]= {
+  /* all these ones, starting with "*" or "$" as a short-option have *no*
+     short option to mention. */
+  {"*",  "url",                      TRUE},
+  {"*a", "random-file",              TRUE},
+  {"*b", "egd-file",                 TRUE},
+  {"*c", "connect-timeout",          TRUE},
+  {"*d", "ciphers",                  TRUE},
+  {"*e", "disable-epsv",             FALSE},
+  {"*E", "epsv",                     FALSE},
+         /* 'epsv' made like this to make --no-epsv and --epsv to work
+             although --disable-epsv is the documented option */
+#ifdef USE_ENVIRONMENT
+  {"*f", "environment",              FALSE},
+#endif
+  {"*g", "trace",                    TRUE},
+  {"*h", "trace-ascii",              TRUE},
+  {"*i", "limit-rate",               TRUE},
+  {"*j", "compressed",               FALSE},
+  {"*J", "tr-encoding",              FALSE},
+  {"*k", "digest",                   FALSE},
+  {"*l", "negotiate",                FALSE},
+  {"*m", "ntlm",                     FALSE},
+  {"*M", "ntlm-wb",                  FALSE},
+  {"*n", "basic",                    FALSE},
+  {"*o", "anyauth",                  FALSE},
+#ifdef USE_WATT32
+  {"*p", "wdebug",                   FALSE},
+#endif
+  {"*q", "ftp-create-dirs",          FALSE},
+  {"*r", "create-dirs",              FALSE},
+  {"*s", "max-redirs",               TRUE},
+  {"*t", "proxy-ntlm",               FALSE},
+  {"*u", "crlf",                     FALSE},
+  {"*v", "stderr",                   TRUE},
+  {"*w", "interface",                TRUE},
+  {"*x", "krb" ,                     TRUE},
+  {"*x", "krb4" ,                    TRUE},
+         /* 'krb4' is the previous name */
+  {"*y", "max-filesize",             TRUE},
+  {"*z", "disable-eprt",             FALSE},
+  {"*Z", "eprt",                     FALSE},
+         /* 'eprt' made like this to make --no-eprt and --eprt to work
+             although --disable-eprt is the documented option */
+  {"$a", "ftp-ssl",                  FALSE},
+         /* 'ftp-ssl' deprecated name since 7.20.0 */
+  {"$a", "ssl",                      FALSE},
+         /* 'ssl' new option name in 7.20.0, previously this was ftp-ssl */
+  {"$b", "ftp-pasv",                 FALSE},
+  {"$c", "socks5",                   TRUE},
+  {"$c", "socks",                    TRUE},
+         /* 'socks' is how the option once was documented but we prefer
+            the --socks5 version for explicit version */
+  {"$d", "tcp-nodelay",              FALSE},
+  {"$e", "proxy-digest",             FALSE},
+  {"$f", "proxy-basic",              FALSE},
+  {"$g", "retry",                    TRUE},
+  {"$h", "retry-delay",              TRUE},
+  {"$i", "retry-max-time",           TRUE},
+  {"$k", "proxy-negotiate",          FALSE},
+  {"$m", "ftp-account",              TRUE},
+  {"$n", "proxy-anyauth",            FALSE},
+  {"$o", "trace-time",               FALSE},
+  {"$p", "ignore-content-length",    FALSE},
+  {"$q", "ftp-skip-pasv-ip",         FALSE},
+  {"$r", "ftp-method",               TRUE},
+  {"$s", "local-port",               TRUE},
+  {"$t", "socks4",                   TRUE},
+  {"$T", "socks4a",                  TRUE},
+  {"$u", "ftp-alternative-to-user",  TRUE},
+  {"$v", "ftp-ssl-reqd",             FALSE},
+         /* 'ftp-ssl-reqd' deprecated name since 7.20.0 */
+  {"$v", "ssl-reqd",                 FALSE},
+         /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
+  {"$w", "sessionid",                FALSE},
+         /* Â¡sessionid' listed as --no-sessionid in the help */
+  {"$x", "ftp-ssl-control",          FALSE},
+  {"$y", "ftp-ssl-ccc",              FALSE},
+  {"$j", "ftp-ssl-ccc-mode",         TRUE},
+  {"$z", "libcurl",                  TRUE},
+  {"$#", "raw",                      FALSE},
+  {"$0", "post301",                  FALSE},
+  {"$1", "keepalive",                FALSE},
+         /* 'keepalive' listed as --no-keepalive in the help */
+  {"$2", "socks5-hostname",          TRUE},
+  {"$3", "keepalive-time",           TRUE},
+  {"$4", "post302",                  FALSE},
+  {"$5", "noproxy",                  TRUE},
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+  {"$6", "socks5-gssapi-service",    TRUE},
+  {"$7", "socks5-gssapi-nec",        FALSE},
+#endif
+  {"$8", "proxy1.0",                 TRUE},
+  {"$9", "tftp-blksize",             TRUE},
+  {"$A", "mail-from",                TRUE},
+  {"$B", "mail-rcpt",                TRUE},
+  {"$C", "ftp-pret",                 FALSE},
+  {"$D", "proto",                    TRUE},
+  {"$E", "proto-redir",              TRUE},
+  {"$F", "resolve",                  TRUE},
+  {"$G", "delegation",               TRUE},
+  {"0",  "http1.0",                  FALSE},
+  {"1",  "tlsv1",                    FALSE},
+  {"2",  "sslv2",                    FALSE},
+  {"3",  "sslv3",                    FALSE},
+  {"4",  "ipv4",                     FALSE},
+  {"6",  "ipv6",                     FALSE},
+  {"a",  "append",                   FALSE},
+  {"A",  "user-agent",               TRUE},
+  {"b",  "cookie",                   TRUE},
+  {"B",  "use-ascii",                FALSE},
+  {"c",  "cookie-jar",               TRUE},
+  {"C",  "continue-at",              TRUE},
+  {"d",  "data",                     TRUE},
+  {"da", "data-ascii",               TRUE},
+  {"db", "data-binary",              TRUE},
+  {"de", "data-urlencode",           TRUE},
+  {"D",  "dump-header",              TRUE},
+  {"e",  "referer",                  TRUE},
+  {"E",  "cert",                     TRUE},
+  {"Ea", "cacert",                   TRUE},
+  {"Eb", "cert-type",                TRUE},
+  {"Ec", "key",                      TRUE},
+  {"Ed", "key-type",                 TRUE},
+  {"Ee", "pass",                     TRUE},
+  {"Ef", "engine",                   TRUE},
+  {"Eg", "capath ",                  TRUE},
+  {"Eh", "pubkey",                   TRUE},
+  {"Ei", "hostpubmd5",               TRUE},
+  {"Ej", "crlfile",                  TRUE},
+  {"Ek", "tlsuser",                  TRUE},
+  {"El", "tlspassword",              TRUE},
+  {"Em", "tlsauthtype",              TRUE},
+  {"f",  "fail",                     FALSE},
+  {"F",  "form",                     TRUE},
+  {"Fs", "form-string",              TRUE},
+  {"g",  "globoff",                  FALSE},
+  {"G",  "get",                      FALSE},
+  {"h",  "help",                     FALSE},
+  {"H",  "header",                   TRUE},
+  {"i",  "include",                  FALSE},
+  {"I",  "head",                     FALSE},
+  {"j",  "junk-session-cookies",     FALSE},
+  {"J",  "remote-header-name",       FALSE},
+  {"k",  "insecure",                 FALSE},
+  {"K",  "config",                   TRUE},
+  {"l",  "list-only",                FALSE},
+  {"L",  "location",                 FALSE},
+  {"Lt", "location-trusted",         FALSE},
+  {"m",  "max-time",                 TRUE},
+  {"M",  "manual",                   FALSE},
+  {"n",  "netrc",                    FALSE},
+  {"no", "netrc-optional",           FALSE},
+  {"ne", "netrc-file",               TRUE},
+  {"N",  "buffer",                   FALSE},
+         /* 'buffer' listed as --no-buffer in the help */
+  {"o",  "output",                   TRUE},
+  {"O",  "remote-name",              FALSE},
+  {"Oa", "remote-name-all",          FALSE},
+  {"p",  "proxytunnel",              FALSE},
+  {"P",  "ftpport",                  TRUE},
+         /* 'ftpport' old version */
+  {"P",  "ftp-port",                 TRUE},
+  {"q",  "disable",                  FALSE},
+  {"Q",  "quote",                    TRUE},
+  {"r",  "range",                    TRUE},
+  {"R",  "remote-time",              FALSE},
+  {"s",  "silent",                   FALSE},
+  {"S",  "show-error",               FALSE},
+  {"t",  "telnet-options",           TRUE},
+         /* 'telnet-options' documented as telnet-option */
+  {"T",  "upload-file",              TRUE},
+  {"u",  "user",                     TRUE},
+  {"U",  "proxy-user",               TRUE},
+  {"v",  "verbose",                  FALSE},
+  {"V",  "version",                  FALSE},
+  {"w",  "write-out",                TRUE},
+  {"x",  "proxy",                    TRUE},
+  {"X",  "request",                  TRUE},
+  {"X",  "http-request",             TRUE},
+         /* 'http-request' OBSOLETE VERSION */
+  {"Y",  "speed-limit",              TRUE},
+  {"y",  "speed-time",               TRUE},
+  {"z",  "time-cond",                TRUE},
+  {"#",  "progress-bar",             FALSE},
+  {"~",  "xattr",                    FALSE},
+};
+
+struct feat {
+  const char *name;
+  int bitmask;
+};
+
+static const struct feat feats[] = {
+  {"AsynchDNS",      CURL_VERSION_ASYNCHDNS},
+  {"Debug",          CURL_VERSION_DEBUG},
+  {"TrackMemory",    CURL_VERSION_CURLDEBUG},
+  {"GSS-Negotiate",  CURL_VERSION_GSSNEGOTIATE},
+  {"IDN",            CURL_VERSION_IDN},
+  {"IPv6",           CURL_VERSION_IPV6},
+  {"Largefile",      CURL_VERSION_LARGEFILE},
+  {"NTLM",           CURL_VERSION_NTLM},
+  {"NTLM_WB",        CURL_VERSION_NTLM_WB},
+  {"SPNEGO",         CURL_VERSION_SPNEGO},
+  {"SSL",            CURL_VERSION_SSL},
+  {"SSPI",           CURL_VERSION_SSPI},
+  {"krb4",           CURL_VERSION_KERBEROS4},
+  {"libz",           CURL_VERSION_LIBZ},
+  {"CharConv",       CURL_VERSION_CONV},
+  {"TLS-SRP",        CURL_VERSION_TLSAUTH_SRP}
+};
+
+ParameterError getparameter(char *flag,    /* f or -long-flag */
+                            char *nextarg, /* NULL if unset */
+                            bool *usedarg, /* set to TRUE if the arg
+                                              has been used */
+                            struct Configurable *config)
+{
+  char letter;
+  char subletter = '\0'; /* subletters can only occur on long options */
+  int rc;
+  const char *parse = NULL;
+  unsigned int j;
+  time_t now;
+  int hit = -1;
+  bool longopt = FALSE;
+  bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
+  ParameterError err;
+  bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
+                         by using --OPTION or --no-OPTION */
+
+
+  if(('-' != flag[0]) ||
+     (('-' == flag[0]) && ('-' == flag[1]))) {
+    /* this should be a long name */
+    char *word = ('-' == flag[0]) ? flag+2 : flag;
+    size_t fnam = strlen(word);
+    int numhits = 0;
+
+    if(!strncmp(word, "no-", 3)) {
+      /* disable this option but ignore the "no-" part when looking for it */
+      word += 3;
+      toggle = FALSE;
+    }
+
+    for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+      if(curlx_strnequal(aliases[j].lname, word, fnam)) {
+        longopt = TRUE;
+        numhits++;
+        if(curlx_raw_equal(aliases[j].lname, word)) {
+          parse = aliases[j].letter;
+          hit = j;
+          numhits = 1; /* a single unique hit */
+          break;
+        }
+        parse = aliases[j].letter;
+        hit = j;
+      }
+    }
+    if(numhits > 1) {
+      /* this is at least the second match! */
+      return PARAM_OPTION_AMBIGUOUS;
+    }
+    if(hit < 0) {
+      return PARAM_OPTION_UNKNOWN;
+    }
+  }
+  else {
+    flag++; /* prefixed with one dash, pass it */
+    hit = -1;
+    parse = flag;
+  }
+
+  do {
+    /* we can loop here if we have multiple single-letters */
+
+    if(!longopt) {
+      if(NULL != parse) {
+        letter = (char)*parse;
+      }
+      else {
+        letter = '\0';
+      }
+      subletter='\0';
+    }
+    else {
+      letter = parse[0];
+      subletter = parse[1];
+    }
+    *usedarg = FALSE; /* default is that we don't use the arg */
+
+    if(hit < 0) {
+      for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+        if(letter == aliases[j].letter[0]) {
+          hit = j;
+          break;
+        }
+      }
+      if(hit < 0) {
+        return PARAM_OPTION_UNKNOWN;
+      }
+    }
+
+    if(aliases[hit].extraparam) {
+      /* this option requires an extra parameter */
+      if(!longopt && parse[1]) {
+        nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
+        singleopt = TRUE;   /* don't loop anymore after this */
+      }
+      else if(!nextarg)
+        return PARAM_REQUIRES_PARAMETER;
+      else
+        *usedarg = TRUE; /* mark it as used */
+    }
+
+    switch(letter) {
+    case '*': /* options without a short option */
+      switch(subletter) {
+      case 'a': /* random-file */
+        GetStr(&config->random_file, nextarg);
+        break;
+      case 'b': /* egd-file */
+        GetStr(&config->egd_file, nextarg);
+        break;
+      case 'c': /* connect-timeout */
+        if(str2num(&config->connecttimeout, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+      case 'd': /* ciphers */
+        GetStr(&config->cipher_list, nextarg);
+        break;
+      case 'e': /* --disable-epsv */
+        config->disable_epsv = toggle;
+        break;
+      case 'E': /* --epsv */
+        config->disable_epsv = (!toggle)?TRUE:FALSE;
+        break;
+#ifdef USE_ENVIRONMENT
+      case 'f':
+        config->writeenv = toggle;
+        break;
+#endif
+      case 'g': /* --trace */
+        GetStr(&config->trace_dump, nextarg);
+        if(config->tracetype && (config->tracetype != TRACE_BIN))
+          warnf(config, "--trace overrides an earlier trace/verbose option\n");
+        config->tracetype = TRACE_BIN;
+        break;
+      case 'h': /* --trace-ascii */
+        GetStr(&config->trace_dump, nextarg);
+        if(config->tracetype && (config->tracetype != TRACE_ASCII))
+          warnf(config,
+                "--trace-ascii overrides an earlier trace/verbose option\n");
+        config->tracetype = TRACE_ASCII;
+        break;
+      case 'i': /* --limit-rate */
+      {
+        /* We support G, M, K too */
+        char *unit;
+        curl_off_t value = curlx_strtoofft(nextarg, &unit, 0);
+
+        if(!*unit)
+          unit = (char *)"b";
+        else if(strlen(unit) > 1)
+          unit = (char *)"w"; /* unsupported */
+
+        switch(*unit) {
+        case 'G':
+        case 'g':
+          value *= 1024*1024*1024;
+          break;
+        case 'M':
+        case 'm':
+          value *= 1024*1024;
+          break;
+        case 'K':
+        case 'k':
+          value *= 1024;
+          break;
+        case 'b':
+        case 'B':
+          /* for plain bytes, leave as-is */
+          break;
+        default:
+          warnf(config, "unsupported rate unit. Use G, M, K or B!\n");
+          return PARAM_BAD_USE;
+        }
+        config->recvpersecond = value;
+        config->sendpersecond = value;
+      }
+      break;
+
+      case 'j': /* --compressed */
+        if(toggle && !(curlinfo->features & CURL_VERSION_LIBZ))
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        config->encoding = toggle;
+        break;
+
+      case 'J': /* --tr-encoding */
+        config->tr_encoding = toggle;
+        break;
+
+      case 'k': /* --digest */
+        if(toggle)
+          config->authtype |= CURLAUTH_DIGEST;
+        else
+          config->authtype &= ~CURLAUTH_DIGEST;
+        break;
+
+      case 'l': /* --negotiate */
+        if(toggle) {
+          if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
+            config->authtype |= CURLAUTH_GSSNEGOTIATE;
+          else
+            return PARAM_LIBCURL_DOESNT_SUPPORT;
+        }
+        else
+          config->authtype &= ~CURLAUTH_GSSNEGOTIATE;
+        break;
+
+      case 'm': /* --ntlm */
+        if(toggle) {
+          if(curlinfo->features & CURL_VERSION_NTLM)
+            config->authtype |= CURLAUTH_NTLM;
+          else
+            return PARAM_LIBCURL_DOESNT_SUPPORT;
+        }
+        else
+          config->authtype &= ~CURLAUTH_NTLM;
+        break;
+
+      case 'M': /* --ntlm-wb */
+        if(toggle) {
+          if(curlinfo->features & CURL_VERSION_NTLM_WB)
+            config->authtype |= CURLAUTH_NTLM_WB;
+          else
+            return PARAM_LIBCURL_DOESNT_SUPPORT;
+        }
+        else
+          config->authtype &= ~CURLAUTH_NTLM_WB;
+        break;
+
+      case 'n': /* --basic for completeness */
+        if(toggle)
+          config->authtype |= CURLAUTH_BASIC;
+        else
+          config->authtype &= ~CURLAUTH_BASIC;
+        break;
+
+      case 'o': /* --anyauth, let libcurl pick it */
+        if(toggle)
+          config->authtype = CURLAUTH_ANY;
+        /* --no-anyauth simply doesn't touch it */
+        break;
+
+#ifdef USE_WATT32
+      case 'p': /* --wdebug */
+        dbug_init();
+        break;
+#endif
+      case 'q': /* --ftp-create-dirs */
+        config->ftp_create_dirs = toggle;
+        break;
+
+      case 'r': /* --create-dirs */
+        config->create_dirs = TRUE;
+        break;
+
+      case 's': /* --max-redirs */
+        /* specified max no of redirects (http(s)) */
+        if(str2num(&config->maxredirs, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+
+      case 't': /* --proxy-ntlm */
+        if(curlinfo->features & CURL_VERSION_NTLM)
+          config->proxyntlm = toggle;
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+
+      case 'u': /* --crlf */
+        /* LF -> CRLF conversion? */
+        config->crlf = TRUE;
+        break;
+
+      case 'v': /* --stderr */
+        if(strcmp(nextarg, "-")) {
+          FILE *newfile = fopen(nextarg, "wt");
+          if(!newfile)
+            warnf(config, "Failed to open %s!\n", nextarg);
+          else {
+            if(config->errors_fopened)
+              fclose(config->errors);
+            config->errors = newfile;
+            config->errors_fopened = TRUE;
+          }
+        }
+        else
+          config->errors = stdout;
+        break;
+      case 'w': /* --interface */
+        /* interface */
+        GetStr(&config->iface, nextarg);
+        break;
+      case 'x': /* --krb */
+        /* kerberos level string */
+        if(curlinfo->features & (CURL_VERSION_KERBEROS4 |
+                                 CURL_VERSION_GSSNEGOTIATE))
+          GetStr(&config->krblevel, nextarg);
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+      case 'y': /* --max-filesize */
+        if(str2offset(&config->max_filesize, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+      case 'z': /* --disable-eprt */
+        config->disable_eprt = toggle;
+        break;
+      case 'Z': /* --eprt */
+        config->disable_eprt = (!toggle)?TRUE:FALSE;
+        break;
+
+      default: /* the URL! */
+      {
+        struct getout *url;
+        if(config->url_get || ((config->url_get = config->url_list) != NULL)) {
+          /* there's a node here, if it already is filled-in continue to find
+             an "empty" node */
+          while(config->url_get && (config->url_get->flags&GETOUT_URL))
+            config->url_get = config->url_get->next;
+        }
+
+        /* now there might or might not be an available node to fill in! */
+
+        if(config->url_get)
+          /* existing node */
+          url = config->url_get;
+        else
+          /* there was no free node, create one! */
+          url = new_getout(config);
+
+        if(url) {
+          /* fill in the URL */
+          GetStr(&url->url, nextarg);
+          url->flags |= GETOUT_URL;
+        }
+      }
+      }
+      break;
+    case '$': /* more options without a short option */
+      switch(subletter) {
+      case 'a': /* --ftp-ssl */
+        if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        config->ftp_ssl = toggle;
+        break;
+      case 'b': /* --ftp-pasv */
+        Curl_safefree(config->ftpport);
+        break;
+      case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
+                   the name locally and passes on the resolved address */
+        GetStr(&config->socksproxy, nextarg);
+        config->socksver = CURLPROXY_SOCKS5;
+        break;
+      case 't': /* --socks4 specifies a socks4 proxy to use */
+        GetStr(&config->socksproxy, nextarg);
+        config->socksver = CURLPROXY_SOCKS4;
+        break;
+      case 'T': /* --socks4a specifies a socks4a proxy to use */
+        GetStr(&config->socksproxy, nextarg);
+        config->socksver = CURLPROXY_SOCKS4A;
+        break;
+      case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
+                   resolving with the proxy */
+        GetStr(&config->socksproxy, nextarg);
+        config->socksver = CURLPROXY_SOCKS5_HOSTNAME;
+        break;
+      case 'd': /* --tcp-nodelay option */
+        config->tcp_nodelay = toggle;
+        break;
+      case 'e': /* --proxy-digest */
+        config->proxydigest = toggle;
+        break;
+      case 'f': /* --proxy-basic */
+        config->proxybasic = toggle;
+        break;
+      case 'g': /* --retry */
+        if(str2num(&config->req_retry, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+      case 'h': /* --retry-delay */
+        if(str2num(&config->retry_delay, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+      case 'i': /* --retry-max-time */
+        if(str2num(&config->retry_maxtime, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+
+      case 'k': /* --proxy-negotiate */
+        if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
+          config->proxynegotiate = toggle;
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+      case 'm': /* --ftp-account */
+        GetStr(&config->ftp_account, nextarg);
+        break;
+      case 'n': /* --proxy-anyauth */
+        config->proxyanyauth = toggle;
+        break;
+      case 'o': /* --trace-time */
+        config->tracetime = toggle;
+        break;
+      case 'p': /* --ignore-content-length */
+        config->ignorecl = toggle;
+        break;
+      case 'q': /* --ftp-skip-pasv-ip */
+        config->ftp_skip_ip = toggle;
+        break;
+      case 'r': /* --ftp-method (undocumented at this point) */
+        config->ftp_filemethod = ftpfilemethod(config, nextarg);
+        break;
+      case 's': /* --local-port */
+        rc = sscanf(nextarg, "%d - %d",
+                    &config->localport,
+                    &config->localportrange);
+        if(!rc)
+          return PARAM_BAD_USE;
+        else if(rc == 1)
+          config->localportrange = 1; /* default number of ports to try */
+        else {
+          config->localportrange -= config->localport;
+          if(config->localportrange < 1) {
+            warnf(config, "bad range input\n");
+            return PARAM_BAD_USE;
+          }
+        }
+        break;
+      case 'u': /* --ftp-alternative-to-user */
+        GetStr(&config->ftp_alternative_to_user, nextarg);
+        break;
+      case 'v': /* --ftp-ssl-reqd */
+        if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        config->ftp_ssl_reqd = toggle;
+        break;
+      case 'w': /* --no-sessionid */
+        config->disable_sessionid = (!toggle)?TRUE:FALSE;
+        break;
+      case 'x': /* --ftp-ssl-control */
+        if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        config->ftp_ssl_control = toggle;
+        break;
+      case 'y': /* --ftp-ssl-ccc */
+        config->ftp_ssl_ccc = toggle;
+        if(!config->ftp_ssl_ccc_mode)
+          config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
+        break;
+      case 'j': /* --ftp-ssl-ccc-mode */
+        config->ftp_ssl_ccc = TRUE;
+        config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
+        break;
+      case 'z': /* --libcurl */
+        GetStr(&config->libcurl, nextarg);
+        break;
+      case '#': /* --raw */
+        config->raw = toggle;
+        break;
+      case '0': /* --post301 */
+        config->post301 = toggle;
+        break;
+      case '1': /* --no-keepalive */
+        config->nokeepalive = (!toggle)?TRUE:FALSE;
+        break;
+      case '3': /* --keepalive-time */
+        if(str2num(&config->alivetime, nextarg))
+          return PARAM_BAD_NUMERIC;
+        break;
+      case '4': /* --post302 */
+        config->post302 = toggle;
+        break;
+      case '5': /* --noproxy */
+        /* This specifies the noproxy list */
+        GetStr(&config->noproxy, nextarg);
+        break;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+      case '6': /* --socks5-gssapi-service */
+        GetStr(&config->socks5_gssapi_service, nextarg);
+        break;
+      case '7': /* --socks5-gssapi-nec*/
+        config->socks5_gssapi_nec = TRUE;
+        break;
+#endif
+      case '8': /* --proxy1.0 */
+        /* http 1.0 proxy */
+        GetStr(&config->proxy, nextarg);
+        config->proxyver = CURLPROXY_HTTP_1_0;
+        break;
+      case '9': /* --tftp-blksize */
+        str2num(&config->tftp_blksize, nextarg);
+        break;
+      case 'A': /* --mail-from */
+        GetStr(&config->mail_from, nextarg);
+        break;
+      case 'B': /* --mail-rcpt */
+        /* append receiver to a list */
+        err = add2list(&config->mail_rcpt, nextarg);
+        if(err)
+          return err;
+        break;
+      case 'C': /* --ftp-pret */
+        config->ftp_pret = toggle;
+        break;
+      case 'D': /* --proto */
+        config->proto_present = TRUE;
+        if(proto2num(config, &config->proto, nextarg))
+          return PARAM_BAD_USE;
+        break;
+      case 'E': /* --proto-redir */
+        config->proto_redir_present = TRUE;
+        if(proto2num(config, &config->proto_redir, nextarg))
+          return PARAM_BAD_USE;
+        break;
+      case 'F': /* --resolve */
+        err = add2list(&config->resolve, nextarg);
+        if(err)
+          return err;
+        break;
+      case 'G': /* --delegation LEVEL */
+        config->gssapi_delegation = delegation(config, nextarg);
+        break;
+      }
+      break;
+    case '#': /* --progress-bar */
+      if(toggle)
+        config->progressmode = CURL_PROGRESS_BAR;
+      else
+        config->progressmode = CURL_PROGRESS_STATS;
+      break;
+    case '~': /* --xattr */
+      config->xattr = toggle;
+      break;
+    case '0':
+      /* HTTP version 1.0 */
+      config->httpversion = CURL_HTTP_VERSION_1_0;
+      break;
+    case '1':
+      /* TLS version 1 */
+      config->ssl_version = CURL_SSLVERSION_TLSv1;
+      break;
+    case '2':
+      /* SSL version 2 */
+      config->ssl_version = CURL_SSLVERSION_SSLv2;
+      break;
+    case '3':
+      /* SSL version 3 */
+      config->ssl_version = CURL_SSLVERSION_SSLv3;
+      break;
+    case '4':
+      /* IPv4 */
+      config->ip_version = 4;
+      break;
+    case '6':
+      /* IPv6 */
+      config->ip_version = 6;
+      break;
+    case 'a':
+      /* This makes the FTP sessions use APPE instead of STOR */
+      config->ftp_append = toggle;
+      break;
+    case 'A':
+      /* This specifies the User-Agent name */
+      GetStr(&config->useragent, nextarg);
+      break;
+    case 'b': /* cookie string coming up: */
+      if(nextarg[0] == '@') {
+        nextarg++;
+      }
+      else if(strchr(nextarg, '=')) {
+        /* A cookie string must have a =-letter */
+        GetStr(&config->cookie, nextarg);
+        break;
+      }
+      /* We have a cookie file to read from! */
+      GetStr(&config->cookiefile, nextarg);
+      break;
+    case 'B':
+      /* use ASCII/text when transferring */
+      config->use_ascii = toggle;
+      break;
+    case 'c':
+      /* get the file name to dump all cookies in */
+      GetStr(&config->cookiejar, nextarg);
+      break;
+    case 'C':
+      /* This makes us continue an ftp transfer at given position */
+      if(!curlx_strequal(nextarg, "-")) {
+        if(str2offset(&config->resume_from, nextarg))
+          return PARAM_BAD_NUMERIC;
+        config->resume_from_current = FALSE;
+      }
+      else {
+        config->resume_from_current = TRUE;
+        config->resume_from = 0;
+      }
+      config->use_resume=TRUE;
+      break;
+    case 'd':
+      /* postfield data */
+    {
+      char *postdata = NULL;
+      FILE *file;
+      size_t size = 0;
+
+      if(subletter == 'e') { /* --data-urlencode*/
+        /* [name]=[content], we encode the content part only
+         * [name]@[file name]
+         *
+         * Case 2: we first load the file using that name and then encode
+         * the content.
+         */
+        const char *p = strchr(nextarg, '=');
+        size_t nlen;
+        char is_file;
+        if(!p)
+          /* there was no '=' letter, check for a '@' instead */
+          p = strchr(nextarg, '@');
+        if(p) {
+          nlen = p - nextarg; /* length of the name part */
+          is_file = *p++; /* pass the separator */
+        }
+        else {
+          /* neither @ nor =, so no name and it isn't a file */
+          nlen = is_file = 0;
+          p = nextarg;
+        }
+        if('@' == is_file) {
+          /* a '@' letter, it means that a file name or - (stdin) follows */
+
+          if(curlx_strequal("-", p)) {
+            file = stdin;
+            set_binmode(stdin);
+          }
+          else {
+            file = fopen(p, "rb");
+            if(!file)
+              warnf(config,
+                    "Couldn't read data from file \"%s\", this makes "
+                    "an empty POST.\n", nextarg);
+          }
+
+          err = file2memory(&postdata, &size, file);
+
+          if(file && (file != stdin))
+            fclose(file);
+          if(err)
+            return err;
+        }
+        else {
+          GetStr(&postdata, p);
+          size = strlen(postdata);
+        }
+
+        if(!postdata) {
+          /* no data from the file, point to a zero byte string to make this
+             get sent as a POST anyway */
+          postdata = strdup("");
+          size = 0;
+        }
+        else {
+          char *enc = curl_easy_escape(config->easy, postdata, (int)size);
+          Curl_safefree(postdata); /* no matter if it worked or not */
+          if(enc) {
+            /* now make a string with the name from above and append the
+               encoded string */
+            size_t outlen = nlen + strlen(enc) + 2;
+            char *n = malloc(outlen);
+            if(!n) {
+              curl_free(enc);
+              return PARAM_NO_MEM;
+            }
+            if(nlen > 0) { /* only append '=' if we have a name */
+              snprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
+              size = outlen-1;
+            }
+            else {
+              strcpy(n, enc);
+              size = outlen-2; /* since no '=' was inserted */
+            }
+            curl_free(enc);
+            postdata = n;
+          }
+          else
+            return PARAM_NO_MEM;
+        }
+      }
+      else if('@' == *nextarg) {
+        /* the data begins with a '@' letter, it means that a file name
+           or - (stdin) follows */
+        nextarg++; /* pass the @ */
+
+        if(curlx_strequal("-", nextarg)) {
+          file = stdin;
+          if(subletter == 'b') /* forced data-binary */
+            set_binmode(stdin);
+        }
+        else {
+          file = fopen(nextarg, "rb");
+          if(!file)
+            warnf(config, "Couldn't read data from file \"%s\", this makes "
+                  "an empty POST.\n", nextarg);
+        }
+
+        if(subletter == 'b')
+          /* forced binary */
+          err = file2memory(&postdata, &size, file);
+        else {
+          err = file2string(&postdata, file);
+          if(postdata)
+            size = strlen(postdata);
+        }
+
+        if(file && (file != stdin))
+          fclose(file);
+        if(err)
+          return err;
+
+        if(!postdata) {
+          /* no data from the file, point to a zero byte string to make this
+             get sent as a POST anyway */
+          postdata=strdup("");
+        }
+      }
+      else {
+        GetStr(&postdata, nextarg);
+        size = strlen(postdata);
+      }
+
+#ifdef CURL_DOES_CONVERSIONS
+      if(subletter != 'b') { /* NOT forced binary, convert to ASCII */
+        convert_to_network(postdata, strlen(postdata));
+      }
+#endif
+
+      if(config->postfields) {
+        /* we already have a string, we append this one with a separating
+           &-letter */
+        char *oldpost = config->postfields;
+        curl_off_t oldlen = config->postfieldsize;
+        curl_off_t newlen = oldlen + size + 2;
+        config->postfields = malloc((size_t)newlen);
+        if(!config->postfields) {
+          Curl_safefree(postdata);
+          return PARAM_NO_MEM;
+        }
+        memcpy(config->postfields, oldpost, (size_t)oldlen);
+        /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
+        config->postfields[oldlen] = '\x26';
+        memcpy(&config->postfields[oldlen+1], postdata, size);
+        config->postfields[oldlen+1+size] = '\0';
+        Curl_safefree(oldpost);
+        Curl_safefree(postdata);
+        config->postfieldsize += size+1;
+      }
+      else {
+        config->postfields = postdata;
+        config->postfieldsize = size;
+      }
+    }
+    /*
+      We can't set the request type here, as this data might be used in
+      a simple GET if -G is used. Already or soon.
+
+      if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
+      return PARAM_BAD_USE;
+    */
+    break;
+    case 'D':
+      /* dump-header to given file name */
+      GetStr(&config->headerfile, nextarg);
+      break;
+    case 'e':
+    {
+      char *ptr = strstr(nextarg, ";auto");
+      if(ptr) {
+        /* Automatic referer requested, this may be combined with a
+           set initial one */
+        config->autoreferer = TRUE;
+        *ptr = 0; /* zero terminate here */
+      }
+      else
+        config->autoreferer = FALSE;
+      GetStr(&config->referer, nextarg);
+    }
+    break;
+    case 'E':
+      switch(subletter) {
+      case 'a': /* CA info PEM file */
+        /* CA info PEM file */
+        GetStr(&config->cacert, nextarg);
+        break;
+      case 'b': /* cert file type */
+        GetStr(&config->cert_type, nextarg);
+        break;
+      case 'c': /* private key file */
+        GetStr(&config->key, nextarg);
+        break;
+      case 'd': /* private key file type */
+        GetStr(&config->key_type, nextarg);
+        break;
+      case 'e': /* private key passphrase */
+        GetStr(&config->key_passwd, nextarg);
+        cleanarg(nextarg);
+        break;
+      case 'f': /* crypto engine */
+        GetStr(&config->engine, nextarg);
+        if(config->engine && curlx_raw_equal(config->engine,"list"))
+          config->list_engines = TRUE;
+        break;
+      case 'g': /* CA info PEM file */
+        /* CA cert directory */
+        GetStr(&config->capath, nextarg);
+        break;
+      case 'h': /* --pubkey public key file */
+        GetStr(&config->pubkey, nextarg);
+        break;
+      case 'i': /* --hostpubmd5 md5 of the host public key */
+        GetStr(&config->hostpubmd5, nextarg);
+        if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
+          return PARAM_BAD_USE;
+        break;
+      case 'j': /* CRL info PEM file */
+        /* CRL file */
+        GetStr(&config->crlfile, nextarg);
+        break;
+      case 'k': /* TLS username */
+        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
+          GetStr(&config->tls_username, nextarg);
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+      case 'l': /* TLS password */
+        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
+          GetStr(&config->tls_password, nextarg);
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+      case 'm': /* TLS authentication type */
+        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+          GetStr(&config->tls_authtype, nextarg);
+          if(!strequal(config->tls_authtype, "SRP"))
+            return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
+        }
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+      default: /* certificate file */
+      {
+        char *ptr = strchr(nextarg, ':');
+        /* Since we live in a world of weirdness and confusion, the win32
+           dudes can use : when using drive letters and thus
+           c:\file:password needs to work. In order not to break
+           compatibility, we still use : as separator, but we try to detect
+           when it is used for a file name! On windows. */
+#ifdef WIN32
+        if(ptr &&
+           (ptr == &nextarg[1]) &&
+           (nextarg[2] == '\\' || nextarg[2] == '/') &&
+           (ISALPHA(nextarg[0])) )
+          /* colon in the second column, followed by a backslash, and the
+             first character is an alphabetic letter:
+
+             this is a drive letter colon */
+          ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
+#endif
+        if(ptr) {
+          /* we have a password too */
+          *ptr = '\0';
+          ptr++;
+          GetStr(&config->key_passwd, ptr);
+        }
+        GetStr(&config->cert, nextarg);
+        cleanarg(nextarg);
+      }
+      }
+      break;
+    case 'f':
+      /* fail hard on errors  */
+      config->failonerror = toggle;
+      break;
+    case 'F':
+      /* "form data" simulation, this is a little advanced so lets do our best
+         to sort this out slowly and carefully */
+      if(formparse(config,
+                   nextarg,
+                   &config->httppost,
+                   &config->last_post,
+                   (subletter=='s')?TRUE:FALSE)) /* 's' means literal string */
+        return PARAM_BAD_USE;
+      if(SetHTTPrequest(config, HTTPREQ_POST, &config->httpreq))
+        return PARAM_BAD_USE;
+      break;
+
+    case 'g': /* g disables URLglobbing */
+      config->globoff = toggle;
+      break;
+
+    case 'G': /* HTTP GET */
+      config->use_httpget = TRUE;
+      break;
+
+    case 'h': /* h for help */
+      if(toggle) {
+        tool_help();
+        return PARAM_HELP_REQUESTED;
+      }
+      /* we now actually support --no-help too! */
+      break;
+    case 'H':
+      /* A custom header to append to a list */
+      err = add2list(&config->headers, nextarg);
+      if(err)
+        return err;
+      break;
+    case 'i':
+      config->include_headers = toggle; /* include the headers as well in the
+                                           general output stream */
+      break;
+    case 'j':
+      config->cookiesession = toggle;
+      break;
+    case 'I':
+      /*
+       * no_body will imply include_headers later on
+       */
+      config->no_body = toggle;
+      if(SetHTTPrequest(config,
+                        (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
+                        &config->httpreq))
+        return PARAM_BAD_USE;
+      break;
+    case 'J': /* --remote-header-name */
+      if(config->include_headers) {
+        warnf(config,
+              "--include and --remote-header-name cannot be combined.\n");
+        return PARAM_BAD_USE;
+      }
+      config->content_disposition = toggle;
+      break;
+    case 'k': /* allow insecure SSL connects */
+      config->insecure_ok = toggle;
+      break;
+    case 'K': /* parse config file */
+      if(parseconfig(nextarg, config))
+        warnf(config, "error trying read config from the '%s' file\n",
+              nextarg);
+      break;
+    case 'l':
+      config->dirlistonly = toggle; /* only list the names of the FTP dir */
+      break;
+    case 'L':
+      config->followlocation = toggle; /* Follow Location: HTTP headers */
+      switch (subletter) {
+      case 't':
+        /* Continue to send authentication (user+password) when following
+         * locations, even when hostname changed */
+        config->unrestricted_auth = toggle;
+        break;
+      }
+      break;
+    case 'm':
+      /* specified max time */
+      if(str2num(&config->timeout, nextarg))
+        return PARAM_BAD_NUMERIC;
+      break;
+    case 'M': /* M for manual, huge help */
+      if(toggle) { /* --no-manual shows no manual... */
+#ifdef USE_MANUAL
+        hugehelp();
+        return PARAM_HELP_REQUESTED;
+#else
+        warnf(config,
+              "built-in manual was disabled at build-time!\n");
+        return PARAM_OPTION_UNKNOWN;
+#endif
+      }
+      break;
+    case 'n':
+      switch(subletter) {
+      case 'o': /* CA info PEM file */
+        /* use .netrc or URL */
+        config->netrc_opt = toggle;
+        break;
+      case 'e': /* netrc-file */
+        GetStr(&config->netrc_file, nextarg);
+        break;
+      default:
+        /* pick info from .netrc, if this is used for http, curl will
+           automatically enfore user+password with the request */
+        config->netrc = toggle;
+        break;
+      }
+      break;
+    case 'N':
+      /* disable the output I/O buffering. note that the option is called
+         --buffer but is mostly used in the negative form: --no-buffer */
+      if(longopt)
+        config->nobuffer = (!toggle)?TRUE:FALSE;
+      else
+        config->nobuffer = toggle;
+      break;
+    case 'O': /* --remote-name */
+      if(subletter == 'a') { /* --remote-name-all */
+        config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
+        break;
+      }
+      /* fall-through! */
+    case 'o': /* --output */
+      /* output file */
+    {
+      struct getout *url;
+      if(config->url_out || ((config->url_out = config->url_list) != NULL)) {
+        /* there's a node here, if it already is filled-in continue to find
+           an "empty" node */
+        while(config->url_out && (config->url_out->flags&GETOUT_OUTFILE))
+          config->url_out = config->url_out->next;
+      }
+
+      /* now there might or might not be an available node to fill in! */
+
+      if(config->url_out)
+        /* existing node */
+        url = config->url_out;
+      else
+        /* there was no free node, create one! */
+        url = new_getout(config);
+
+      if(url) {
+        /* fill in the outfile */
+        if('o' == letter) {
+          GetStr(&url->outfile, nextarg);
+          url->flags &= ~GETOUT_USEREMOTE; /* switch off */
+        }
+        else {
+          url->outfile = NULL; /* leave it */
+          if(toggle)
+            url->flags |= GETOUT_USEREMOTE;  /* switch on */
+          else
+            url->flags &= ~GETOUT_USEREMOTE; /* switch off */
+        }
+        url->flags |= GETOUT_OUTFILE;
+      }
+    }
+    break;
+    case 'P':
+      /* This makes the FTP sessions use PORT instead of PASV */
+      /* use <eth0> or <192.168.10.10> style addresses. Anything except
+         this will make us try to get the "default" address.
+         NOTE: this is a changed behaviour since the released 4.1!
+      */
+      GetStr(&config->ftpport, nextarg);
+      break;
+    case 'p':
+      /* proxy tunnel for non-http protocols */
+      config->proxytunnel = toggle;
+      break;
+
+    case 'q': /* if used first, already taken care of, we do it like
+                 this so we don't cause an error! */
+      break;
+    case 'Q':
+      /* QUOTE command to send to FTP server */
+      switch(nextarg[0]) {
+      case '-':
+        /* prefixed with a dash makes it a POST TRANSFER one */
+        nextarg++;
+        err = add2list(&config->postquote, nextarg);
+        break;
+      case '+':
+        /* prefixed with a plus makes it a just-before-transfer one */
+        nextarg++;
+        err = add2list(&config->prequote, nextarg);
+        break;
+      default:
+        err = add2list(&config->quote, nextarg);
+        break;
+      }
+      if(err)
+        return err;
+      break;
+    case 'r':
+      /* Specifying a range WITHOUT A DASH will create an illegal HTTP range
+         (and won't actually be range by definition). The man page previously
+         claimed that to be a good way, why this code is added to work-around
+         it. */
+      if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
+        char buffer[32];
+        curl_off_t off;
+        warnf(config,
+              "A specified range MUST include at least one dash (-). "
+              "Appending one for you!\n");
+        off = curlx_strtoofft(nextarg, NULL, 10);
+        snprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
+        Curl_safefree(config->range);
+        config->range = strdup(buffer);
+      }
+      {
+        /* byte range requested */
+        char *tmp_range;
+        tmp_range = nextarg;
+        while(*tmp_range != '\0') {
+          if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
+            warnf(config,"Invalid character is found in given range. "
+                  "A specified range MUST have only digits in "
+                  "\'start\'-\'stop\'. The server's response to this "
+                  "request is uncertain.\n");
+            break;
+          }
+          tmp_range++;
+        }
+        /* byte range requested */
+        GetStr(&config->range, nextarg);
+      }
+      break;
+    case 'R':
+      /* use remote file's time */
+      config->remote_time = toggle;
+      break;
+    case 's':
+      /* don't show progress meter, don't show errors : */
+      if(toggle)
+        config->mute = config->noprogress = TRUE;
+      else
+        config->mute = config->noprogress = FALSE;
+      config->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
+      break;
+    case 'S':
+      /* show errors */
+      config->showerror = toggle; /* toggle on if used with -s */
+      break;
+    case 't':
+      /* Telnet options */
+      err = add2list(&config->telnet_options, nextarg);
+      if(err)
+        return err;
+      break;
+    case 'T':
+      /* we are uploading */
+    {
+      struct getout *url;
+      if(config->url_out || ((config->url_out = config->url_list) != NULL)) {
+        /* there's a node here, if it already is filled-in continue to find
+           an "empty" node */
+        while(config->url_out && (config->url_out->flags&GETOUT_UPLOAD))
+          config->url_out = config->url_out->next;
+      }
+
+      /* now there might or might not be an available node to fill in! */
+
+      if(config->url_out)
+        /* existing node */
+        url = config->url_out;
+      else
+        /* there was no free node, create one! */
+        url = new_getout(config);
+
+      if(url) {
+        url->flags |= GETOUT_UPLOAD; /* mark -T used */
+        if(!*nextarg)
+          url->flags |= GETOUT_NOUPLOAD;
+        else {
+          /* "-" equals stdin, but keep the string around for now */
+          GetStr(&url->infile, nextarg);
+        }
+      }
+    }
+    break;
+    case 'u':
+      /* user:password  */
+      GetStr(&config->userpwd, nextarg);
+      cleanarg(nextarg);
+      checkpasswd("host", &config->userpwd);
+      break;
+    case 'U':
+      /* Proxy user:password  */
+      GetStr(&config->proxyuserpwd, nextarg);
+      cleanarg(nextarg);
+      checkpasswd("proxy", &config->proxyuserpwd);
+      break;
+    case 'v':
+      if(toggle) {
+        /* the '%' thing here will cause the trace get sent to stderr */
+        Curl_safefree(config->trace_dump);
+        config->trace_dump = strdup("%");
+        if(config->tracetype && (config->tracetype != TRACE_PLAIN))
+          warnf(config,
+                "-v, --verbose overrides an earlier trace/verbose option\n");
+        config->tracetype = TRACE_PLAIN;
+      }
+      else
+        /* verbose is disabled here */
+        config->tracetype = TRACE_NONE;
+      break;
+    case 'V':
+    {
+      const char *const *proto;
+
+      if(!toggle)
+        /* --no-version yields no output! */
+        break;
+
+      printf(CURL_ID "%s\n", curl_version());
+      if(curlinfo->protocols) {
+        printf("Protocols: ");
+        for(proto = curlinfo->protocols; *proto; ++proto) {
+          printf("%s ", *proto);
+        }
+        puts(""); /* newline */
+      }
+      if(curlinfo->features) {
+        unsigned int i;
+        printf("Features: ");
+        for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
+          if(curlinfo->features & feats[i].bitmask)
+            printf("%s ", feats[i].name);
+        }
+        puts(""); /* newline */
+      }
+    }
+    return PARAM_HELP_REQUESTED;
+    case 'w':
+      /* get the output string */
+      if('@' == *nextarg) {
+        /* the data begins with a '@' letter, it means that a file name
+           or - (stdin) follows */
+        FILE *file;
+        const char *fname;
+        nextarg++; /* pass the @ */
+        if(curlx_strequal("-", nextarg)) {
+          fname = "<stdin>";
+          file = stdin;
+        }
+        else {
+          fname = nextarg;
+          file = fopen(nextarg, "r");
+        }
+        err = file2string(&config->writeout, file);
+        if(file && (file != stdin))
+          fclose(file);
+        if(err)
+          return err;
+        if(!config->writeout)
+          warnf(config, "Failed to read %s", fname);
+      }
+      else
+        GetStr(&config->writeout, nextarg);
+      break;
+    case 'x':
+      /* proxy */
+      GetStr(&config->proxy, nextarg);
+      config->proxyver = CURLPROXY_HTTP;
+      break;
+    case 'X':
+      /* set custom request */
+      GetStr(&config->customrequest, nextarg);
+      break;
+    case 'y':
+      /* low speed time */
+      if(str2num(&config->low_speed_time, nextarg))
+        return PARAM_BAD_NUMERIC;
+      if(!config->low_speed_limit)
+        config->low_speed_limit = 1;
+      break;
+    case 'Y':
+      /* low speed limit */
+      if(str2num(&config->low_speed_limit, nextarg))
+        return PARAM_BAD_NUMERIC;
+      if(!config->low_speed_time)
+        config->low_speed_time = 30;
+      break;
+    case 'z': /* time condition coming up */
+      switch(*nextarg) {
+      case '+':
+        nextarg++;
+      default:
+        /* If-Modified-Since: (section 14.28 in RFC2068) */
+        config->timecond = CURL_TIMECOND_IFMODSINCE;
+        break;
+      case '-':
+        /* If-Unmodified-Since:  (section 14.24 in RFC2068) */
+        config->timecond = CURL_TIMECOND_IFUNMODSINCE;
+        nextarg++;
+        break;
+      case '=':
+        /* Last-Modified:  (section 14.29 in RFC2068) */
+        config->timecond = CURL_TIMECOND_LASTMOD;
+        nextarg++;
+        break;
+      }
+      now = time(NULL);
+      config->condtime=curl_getdate(nextarg, &now);
+      if(-1 == (int)config->condtime) {
+        /* now let's see if it is a file name to get the time from instead! */
+        struct_stat statbuf;
+        if(-1 == stat(nextarg, &statbuf)) {
+          /* failed, remove time condition */
+          config->timecond = CURL_TIMECOND_NONE;
+          warnf(config,
+                "Illegal date format for -z, --timecond (and not "
+                "a file name). Disabling time condition. "
+                "See curl_getdate(3) for valid date syntax.\n");
+        }
+        else {
+          /* pull the time out from the file */
+          config->condtime = statbuf.st_mtime;
+        }
+      }
+      break;
+    default: /* unknown flag */
+      return PARAM_OPTION_UNKNOWN;
+    }
+    hit = -1;
+
+  } while(!longopt && !singleopt && *++parse && !*usedarg);
+
+  return PARAM_OK;
+}
+
diff --git a/src/tool_getparam.h b/src/tool_getparam.h
new file mode 100644 (file)
index 0000000..c402fd7
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_TOOL_GETPARAM_H
+#define HEADER_CURL_TOOL_GETPARAM_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+typedef enum {
+  PARAM_OK,
+  PARAM_OPTION_AMBIGUOUS,
+  PARAM_OPTION_UNKNOWN,
+  PARAM_REQUIRES_PARAMETER,
+  PARAM_BAD_USE,
+  PARAM_HELP_REQUESTED,
+  PARAM_GOT_EXTRA_PARAMETER,
+  PARAM_BAD_NUMERIC,
+  PARAM_LIBCURL_DOESNT_SUPPORT,
+  PARAM_NO_MEM,
+  PARAM_LAST
+} ParameterError;
+
+ParameterError getparameter(char *flag,
+                            char *nextarg,
+                            bool *usedarg,
+                            struct Configurable *config);
+
+#endif /* HEADER_CURL_TOOL_GETPARAM_H */
+
diff --git a/src/tool_help.c b/src/tool_help.c
new file mode 100644 (file)
index 0000000..7c7d8d3
--- /dev/null
@@ -0,0 +1,238 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include "tool_panykey.h"
+#include "tool_help.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef MSDOS
+#  define USE_WATT32
+#endif
+
+/*
+ * A few of these source lines are >80 columns wide, but that's only because
+ * breaking the strings narrower makes this chunk look even worse!
+ *
+ *  Starting with 7.18.0, this list of command line options is sorted based
+ *  on the long option name. It is not done automatically, although a command
+ *  line like the following can help out:
+ *
+ *  curl --help | cut -c5- | grep "^-" | sort
+ */
+
+static const char *const helptext[] = {
+  "Usage: curl [options...] <url>",
+  "Options: (H) means HTTP/HTTPS only, (F) means FTP only",
+  "     --anyauth       Pick \"any\" authentication method (H)",
+  " -a, --append        Append to target file when uploading (F/SFTP)",
+  "     --basic         Use HTTP Basic Authentication (H)",
+  "     --cacert FILE   CA certificate to verify peer against (SSL)",
+  "     --capath DIR    CA directory to verify peer against (SSL)",
+  " -E, --cert CERT[:PASSWD] Client certificate file and password (SSL)",
+  "     --cert-type TYPE Certificate file type (DER/PEM/ENG) (SSL)",
+  "     --ciphers LIST  SSL ciphers to use (SSL)",
+  "     --compressed    Request compressed response (using deflate or gzip)",
+  " -K, --config FILE   Specify which config file to read",
+  "     --connect-timeout SECONDS  Maximum time allowed for connection",
+  " -C, --continue-at OFFSET  Resumed transfer offset",
+  " -b, --cookie STRING/FILE  String or file to read cookies from (H)",
+  " -c, --cookie-jar FILE  Write cookies to this file after operation (H)",
+  "     --create-dirs   Create necessary local directory hierarchy",
+  "     --crlf          Convert LF to CRLF in upload",
+  "     --crlfile FILE  Get a CRL list in PEM format from the given file",
+  " -d, --data DATA     HTTP POST data (H)",
+  "     --data-ascii DATA  HTTP POST ASCII data (H)",
+  "     --data-binary DATA  HTTP POST binary data (H)",
+  "     --data-urlencode DATA  HTTP POST data url encoded (H)",
+  "     --delegation STRING GSS-API delegation permission",
+  "     --digest        Use HTTP Digest Authentication (H)",
+  "     --disable-eprt  Inhibit using EPRT or LPRT (F)",
+  "     --disable-epsv  Inhibit using EPSV (F)",
+  " -D, --dump-header FILE  Write the headers to this file",
+  "     --egd-file FILE  EGD socket path for random data (SSL)",
+  "     --engine ENGINGE  Crypto engine (SSL). \"--engine list\" for list",
+#ifdef USE_ENVIRONMENT
+  "     --environment   Write results to environment variables (RISC OS)",
+#endif
+  " -f, --fail          Fail silently (no output at all) on HTTP errors (H)",
+  " -F, --form CONTENT  Specify HTTP multipart POST data (H)",
+  "     --form-string STRING  Specify HTTP multipart POST data (H)",
+  "     --ftp-account DATA  Account data string (F)",
+  "     --ftp-alternative-to-user COMMAND  "
+  "String to replace \"USER [name]\" (F)",
+  "     --ftp-create-dirs  Create the remote dirs if not present (F)",
+  "     --ftp-method [MULTICWD/NOCWD/SINGLECWD] Control CWD usage (F)",
+  "     --ftp-pasv      Use PASV/EPSV instead of PORT (F)",
+  " -P, --ftp-port ADR  Use PORT with given address instead of PASV (F)",
+  "     --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
+  "     --ftp-pret      Send PRET before PASV (for drftpd) (F)",
+  "     --ftp-ssl-ccc   Send CCC after authenticating (F)",
+  "     --ftp-ssl-ccc-mode ACTIVE/PASSIVE  Set CCC mode (F)",
+  "     --ftp-ssl-control Require SSL/TLS for ftp login, "
+  "clear for transfer (F)",
+  " -G, --get           Send the -d data with a HTTP GET (H)",
+  " -g, --globoff       Disable URL sequences and ranges using {} and []",
+  " -H, --header LINE   Custom header to pass to server (H)",
+  " -I, --head          Show document info only",
+  " -h, --help          This help text",
+  "     --hostpubmd5 MD5  "
+  "Hex encoded MD5 string of the host public key. (SSH)",
+  " -0, --http1.0       Use HTTP 1.0 (H)",
+  "     --ignore-content-length  Ignore the HTTP Content-Length header",
+  " -i, --include       Include protocol headers in the output (H/F)",
+  " -k, --insecure      Allow connections to SSL sites without certs (H)",
+  "     --interface INTERFACE  Specify network interface/address to use",
+  " -4, --ipv4          Resolve name to IPv4 address",
+  " -6, --ipv6          Resolve name to IPv6 address",
+  " -j, --junk-session-cookies Ignore session cookies read from file (H)",
+  "     --keepalive-time SECONDS  Interval between keepalive probes",
+  "     --key KEY       Private key file name (SSL/SSH)",
+  "     --key-type TYPE Private key file type (DER/PEM/ENG) (SSL)",
+  "     --krb LEVEL     Enable Kerberos with specified security level (F)",
+  "     --libcurl FILE  Dump libcurl equivalent code of this command line",
+  "     --limit-rate RATE  Limit transfer speed to this rate",
+  " -l, --list-only     List only names of an FTP directory (F)",
+  "     --local-port RANGE  Force use of these local port numbers",
+  " -L, --location      Follow redirects (H)",
+  "     --location-trusted like --location and send auth to other hosts (H)",
+  " -M, --manual        Display the full manual",
+  "     --mail-from FROM  Mail from this address",
+  "     --mail-rcpt TO  Mail to this receiver(s)",
+  "     --max-filesize BYTES  Maximum file size to download (H/F)",
+  "     --max-redirs NUM  Maximum number of redirects allowed (H)",
+  " -m, --max-time SECONDS  Maximum time allowed for the transfer",
+  "     --negotiate     Use HTTP Negotiate Authentication (H)",
+  " -n, --netrc         Must read .netrc for user name and password",
+  "     --netrc-optional Use either .netrc or URL; overrides -n",
+  "     --netrc-file FILE  Set up the netrc filename to use",
+  " -N, --no-buffer     Disable buffering of the output stream",
+  "     --no-keepalive  Disable keepalive use on the connection",
+  "     --no-sessionid  Disable SSL session-ID reusing (SSL)",
+  "     --noproxy       List of hosts which do not use proxy",
+  "     --ntlm          Use HTTP NTLM authentication (H)",
+  " -o, --output FILE   Write output to <file> instead of stdout",
+  "     --pass PASS     Pass phrase for the private key (SSL/SSH)",
+  "     --post301       "
+  "Do not switch to GET after following a 301 redirect (H)",
+  "     --post302       "
+  "Do not switch to GET after following a 302 redirect (H)",
+  " -#, --progress-bar  Display transfer progress as a progress bar",
+  "     --proto PROTOCOLS  Enable/disable specified protocols",
+  "     --proto-redir PROTOCOLS  "
+  "Enable/disable specified protocols on redirect",
+  " -x, --proxy [PROTOCOL://]HOST[:PORT] Use proxy on given port",
+  "     --proxy-anyauth Pick \"any\" proxy authentication method (H)",
+  "     --proxy-basic   Use Basic authentication on the proxy (H)",
+  "     --proxy-digest  Use Digest authentication on the proxy (H)",
+  "     --proxy-negotiate Use Negotiate authentication on the proxy (H)",
+  "     --proxy-ntlm    Use NTLM authentication on the proxy (H)",
+  " -U, --proxy-user USER[:PASSWORD]  Proxy user and password",
+  "     --proxy1.0 HOST[:PORT]  Use HTTP/1.0 proxy on given port",
+  " -p, --proxytunnel   Operate through a HTTP proxy tunnel (using CONNECT)",
+  "     --pubkey KEY    Public key file name (SSH)",
+  " -Q, --quote CMD     Send command(s) to server before transfer (F/SFTP)",
+  "     --random-file FILE  File for reading random data from (SSL)",
+  " -r, --range RANGE   Retrieve only the bytes within a range",
+  "     --raw           Do HTTP \"raw\", without any transfer decoding (H)",
+  " -e, --referer       Referer URL (H)",
+  " -J, --remote-header-name Use the header-provided filename (H)",
+  " -O, --remote-name   Write output to a file named as the remote file",
+  "     --remote-name-all Use the remote file name for all URLs",
+  " -R, --remote-time   Set the remote file's time on the local output",
+  " -X, --request COMMAND  Specify request command to use",
+  "     --resolve HOST:PORT:ADDRESS  Force resolve of HOST:PORT to ADDRESS",
+  "     --retry NUM   "
+  "Retry request NUM times if transient problems occur",
+  "     --retry-delay SECONDS "
+  "When retrying, wait this many seconds between each",
+  "     --retry-max-time SECONDS  Retry only within this period",
+  " -S, --show-error    "
+  "Show error. With -s, make curl show errors when they occur",
+  " -s, --silent        Silent mode. Don't output anything",
+  "     --socks4 HOST[:PORT]  SOCKS4 proxy on given host + port",
+  "     --socks4a HOST[:PORT]  SOCKS4a proxy on given host + port",
+  "     --socks5 HOST[:PORT]  SOCKS5 proxy on given host + port",
+  "     --socks5-hostname HOST[:PORT] "
+  "SOCKS5 proxy, pass host name to proxy",
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+  "     --socks5-gssapi-service NAME  SOCKS5 proxy service name for gssapi",
+  "     --socks5-gssapi-nec  Compatibility with NEC SOCKS5 server",
+#endif
+  " -Y, --speed-limit RATE  "
+  "Stop transfers below speed-limit for 'speed-time' secs",
+  " -y, --speed-time SECONDS  "
+  "Time for trig speed-limit abort. Defaults to 30",
+  "     --ssl           Try SSL/TLS (FTP, IMAP, POP3, SMTP)",
+  "     --ssl-reqd      Require SSL/TLS (FTP, IMAP, POP3, SMTP)",
+  " -2, --sslv2         Use SSLv2 (SSL)",
+  " -3, --sslv3         Use SSLv3 (SSL)",
+  "     --stderr FILE   Where to redirect stderr. - means stdout",
+  "     --tcp-nodelay   Use the TCP_NODELAY option",
+  " -t, --telnet-option OPT=VAL  Set telnet option",
+  "     --tftp-blksize VALUE  Set TFTP BLKSIZE option (must be >512)",
+  " -z, --time-cond TIME  Transfer based on a time condition",
+  " -1, --tlsv1         Use TLSv1 (SSL)",
+  "     --trace FILE    Write a debug trace to the given file",
+  "     --trace-ascii FILE  Like --trace but without the hex output",
+  "     --trace-time    Add time stamps to trace/verbose output",
+  "     --tr-encoding   Request compressed transfer encoding (H)",
+  " -T, --upload-file FILE  Transfer FILE to destination",
+  "     --url URL       URL to work with",
+  " -B, --use-ascii     Use ASCII/text transfer",
+  " -u, --user USER[:PASSWORD]  Server user and password",
+  "     --tlsuser USER  TLS username",
+  "     --tlspassword STRING TLS password",
+  "     --tlsauthtype STRING  TLS authentication type (default SRP)",
+  " -A, --user-agent STRING  User-Agent to send to server (H)",
+  " -v, --verbose       Make the operation more talkative",
+  " -V, --version       Show version number and quit",
+#ifdef USE_WATT32
+  "     --wdebug        Turn on Watt-32 debugging",
+#endif
+  " -w, --write-out FORMAT  What to output after completion",
+  "     --xattr        Store metadata in extended file attributes",
+  " -q                 If used as the first parameter disables .curlrc",
+  NULL
+};
+
+#ifdef NETWARE
+#  define PRINT_LINES_PAUSE 23
+#endif
+
+#ifdef __SYMBIAN32__
+#  define PRINT_LINES_PAUSE 16
+#endif
+
+void tool_help(void)
+{
+  int i;
+  for(i = 0; helptext[i]; i++) {
+    puts(helptext[i]);
+#ifdef PRINT_LINES_PAUSE
+    if(i && ((i % PRINT_LINES_PAUSE) == 0))
+      tool_pressanykey();
+#endif
+  }
+}
+
similarity index 88%
rename from src/tool_myfunc.h
rename to src/tool_help.h
index b1d9c66..f966411 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_TOOL_MYFUNC_H
-#define HEADER_CURL_TOOL_MYFUNC_H
+#ifndef HEADER_CURL_TOOL_HELP_H
+#define HEADER_CURL_TOOL_HELP_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -23,7 +23,7 @@
  ***************************************************************************/
 #include "setup.h"
 
-char *my_useragent(void);
+void tool_help(void);
 
-#endif /* HEADER_CURL_TOOL_MYFUNC_H */
+#endif /* HEADER_CURL_TOOL_HELP_H */
 
diff --git a/src/tool_helpers.c b/src/tool_helpers.c
new file mode 100644 (file)
index 0000000..b637178
--- /dev/null
@@ -0,0 +1,78 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** Helper functions that are used from more tha one source file.
+*/
+
+const char *param2text(int res)
+{
+  ParameterError error = (ParameterError)res;
+  switch(error) {
+  case PARAM_GOT_EXTRA_PARAMETER:
+    return "had unsupported trailing garbage";
+  case PARAM_OPTION_UNKNOWN:
+    return "is unknown";
+  case PARAM_OPTION_AMBIGUOUS:
+    return "is ambiguous";
+  case PARAM_REQUIRES_PARAMETER:
+    return "requires parameter";
+  case PARAM_BAD_USE:
+    return "is badly used here";
+  case PARAM_BAD_NUMERIC:
+    return "expected a proper numerical parameter";
+  case PARAM_LIBCURL_DOESNT_SUPPORT:
+    return "the installed libcurl version doesn't support this";
+  case PARAM_NO_MEM:
+    return "out of memory";
+  default:
+    return "unknown error";
+  }
+}
+
+int SetHTTPrequest(struct Configurable *config, HttpReq req, HttpReq *store)
+{
+  if((*store == HTTPREQ_UNSPEC) ||
+     (*store == req)) {
+    *store = req;
+    return 0;
+  }
+  warnf(config, "You can only select one HTTP request!\n");
+  return 1;
+}
+
diff --git a/src/tool_helpers.h b/src/tool_helpers.h
new file mode 100644 (file)
index 0000000..4385bfc
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_TOOL_HELPERS_H
+#define HEADER_CURL_TOOL_HELPERS_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+const char *param2text(int res);
+
+int SetHTTPrequest(struct Configurable *config, HttpReq req, HttpReq *store);
+
+#endif /* HEADER_CURL_TOOL_HELPERS_H */
+
diff --git a/src/tool_main.c b/src/tool_main.c
new file mode 100644 (file)
index 0000000..86780c7
--- /dev/null
@@ -0,0 +1,112 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#include <sys/stat.h>
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_convert.h"
+#include "tool_operate.h"
+#include "tool_panykey.h"
+#include "tool_vms.h"
+#include "tool_main.h"
+
+/*
+ * This is low-level hard-hacking memory leak tracking and similar. Using
+ * the library level code from this client-side is ugly, but we do this
+ * anyway for convenience.
+ */
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef __VMS
+static int vms_show = 0;
+#endif
+
+/*
+ * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
+ * open before starting to run.  Otherwise, the first three network
+ * sockets opened by curl could be used for input sources, downloaded data
+ * or error logs as they will effectively be stdin, stdout and/or stderr.
+ */
+static void main_checkfds(void)
+{
+#ifdef HAVE_PIPE
+  int fd[2] = { STDIN_FILENO, STDIN_FILENO };
+  while(fd[0] == STDIN_FILENO ||
+        fd[0] == STDOUT_FILENO ||
+        fd[0] == STDERR_FILENO ||
+        fd[1] == STDIN_FILENO ||
+        fd[1] == STDOUT_FILENO ||
+        fd[1] == STDERR_FILENO)
+    if(pipe(fd) < 0)
+      return;   /* Out of handles. This isn't really a big problem now, but
+                   will be when we try to create a socket later. */
+  close(fd[0]);
+  close(fd[1]);
+#endif
+}
+
+/*
+** curl tool main function.
+*/
+int main(int argc, char *argv[])
+{
+  int res;
+  struct Configurable config;
+
+  memset(&config, 0, sizeof(struct Configurable));
+
+  config.errors = stderr; /* default errors to stderr */
+
+  main_checkfds();
+
+  res = operate(&config, argc, argv);
+
+#ifdef __SYMBIAN32__
+  if(config.showerror)
+    tool_pressanykey();
+#endif
+
+  free_config_fields(&config);
+
+#ifdef __NOVELL_LIBC__
+  if(getenv("_IN_NETWARE_BASH_") == NULL)
+    tool_pressanykey();
+#endif
+
+#ifdef __VMS
+  vms_special_exit(res, vms_show);
+#else
+  return res;
+#endif
+}
+
diff --git a/src/tool_main.h b/src/tool_main.h
new file mode 100644 (file)
index 0000000..2193cb9
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_TOOL_MAIN_H
+#define HEADER_CURL_TOOL_MAIN_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#define DEFAULT_MAXREDIRS  50L
+
+#define RETRY_SLEEP_DEFAULT 1000L   /* ms */
+#define RETRY_SLEEP_MAX     600000L /* ms == 10 minutes */
+
+#ifndef STDIN_FILENO
+#  define STDIN_FILENO  fileno(stdin)
+#endif
+
+#ifndef STDOUT_FILENO
+#  define STDOUT_FILENO  fileno(stdout)
+#endif
+
+#ifndef STDERR_FILENO
+#  define STDERR_FILENO  fileno(stderr)
+#endif
+
+#endif /* HEADER_CURL_TOOL_MAIN_H */
+
diff --git a/src/tool_operate.c b/src/tool_operate.c
new file mode 100644 (file)
index 0000000..6fe908a
--- /dev/null
@@ -0,0 +1,1541 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#ifdef HAVE_UTIME_H
+#  include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+#  include <sys/utime.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+#  include <locale.h>
+#endif
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "curlutil.h"
+#include "homedir.h"
+#include "urlglob.h"
+#include "writeout.h"
+#include "xattr.h"
+
+#ifdef USE_ENVIRONMENT
+#  include "writeenv.h"
+#endif
+
+#include "tool_binmode.h"
+#include "tool_cfgable.h"
+#include "tool_cb_dbg.h"
+#include "tool_cb_hdr.h"
+#include "tool_cb_prg.h"
+#include "tool_cb_rea.h"
+#include "tool_cb_see.h"
+#include "tool_cb_skt.h"
+#include "tool_cb_wrt.h"
+#include "tool_dirhie.h"
+#include "tool_easysrc.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_libinfo.h"
+#include "tool_main.h"
+#include "tool_msgs.h"
+#include "tool_operate.h"
+#include "tool_operhlp.h"
+#include "tool_parsecfg.h"
+#include "tool_setopt.h"
+#include "tool_sleep.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define CURLseparator  "--_curl_--"
+
+#ifndef O_BINARY
+/* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
+   source code but yet it doesn't ruin anything */
+#  define O_BINARY 0
+#endif
+
+#define CURL_CA_CERT_ERRORMSG1                                              \
+  "More details here: http://curl.haxx.se/docs/sslcerts.html\n\n"           \
+  "curl performs SSL certificate verification by default, "                 \
+  "using a \"bundle\"\n"                                                    \
+  " of Certificate Authority (CA) public keys (CA certs). If the default\n" \
+  " bundle file isn't adequate, you can specify an alternate file\n"        \
+  " using the --cacert option.\n"
+
+#define CURL_CA_CERT_ERRORMSG2                                              \
+  "If this HTTPS server uses a certificate signed by a CA represented in\n" \
+  " the bundle, the certificate verification probably failed due to a\n"    \
+  " problem with the certificate (it might be expired, or the name might\n" \
+  " not match the domain name in the URL).\n"                               \
+  "If you'd like to turn off curl's verification of the certificate, use\n" \
+  " the -k (or --insecure) option.\n"
+
+int operate(struct Configurable *config, int argc, argv_item_t argv[])
+{
+  char errorbuffer[CURL_ERROR_SIZE];
+  struct ProgressData progressbar;
+  struct getout *urlnode;
+
+  struct OutStruct heads;
+
+  CURL *curl = NULL;
+  char *httpgetfields = NULL;
+
+  bool stillflags;
+  int res = 0;
+  int i;
+
+  errorbuffer[0] = '\0';
+  /* default headers output stream is stdout */
+  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 = TRUE;
+  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);
+    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 *origopt = 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", origopt, 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
+   * 2: if #1 isn't found, use the windows API function SearchPath()
+   *    to find it along the app's path (includes app's dir and CWD)
+   *
+   * We support the environment variable thing for non-Windows platforms
+   * too. Just for the sake of it.
+   */
+  if(!config->cacert &&
+     !config->capath &&
+     !config->insecure_ok) {
+    char *env;
+    env = curlx_getenv("CURL_CA_BUNDLE");
+    if(env) {
+      config->cacert = strdup(env);
+      if(!config->cacert) {
+        curl_free(env);
+        helpf(config->errors, "out of memory\n");
+        res = CURLE_OUT_OF_MEMORY;
+        goto quit_curl;
+      }
+    }
+    else {
+      env = curlx_getenv("SSL_CERT_DIR");
+      if(env) {
+        config->capath = strdup(env);
+        if(!config->capath) {
+          curl_free(env);
+          helpf(config->errors, "out of memory\n");
+          res = CURLE_OUT_OF_MEMORY;
+          goto quit_curl;
+        }
+      }
+      else {
+        env = curlx_getenv("SSL_CERT_FILE");
+        if(env) {
+          config->cacert = strdup(env);
+          if(!config->cacert) {
+            curl_free(env);
+            helpf(config->errors, "out of memory\n");
+            res = CURLE_OUT_OF_MEMORY;
+            goto quit_curl;
+          }
+        }
+      }
+    }
+
+    if(env)
+      curl_free(env);
+#ifdef WIN32
+    else {
+      res = FindWin32CACert(config, "curl-ca-bundle.crt");
+      if(res)
+        goto quit_curl;
+    }
+#endif
+  }
+
+  if(config->postfields) {
+    if(config->use_httpget) {
+      /* Use the postfields data for a http get */
+      httpgetfields = strdup(config->postfields);
+      Curl_safefree(config->postfields);
+      if(SetHTTPrequest(config,
+                        (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
+                        &config->httpreq)) {
+        res = PARAM_BAD_USE;
+        goto quit_curl;
+      }
+    }
+    else {
+      if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) {
+        res = PARAM_BAD_USE;
+        goto quit_curl;
+      }
+    }
+  }
+
+  /* This is the first entry added to easysrc and it initializes the slist */
+  easysrc = curl_slist_append(easysrc, "CURL *hnd = curl_easy_init();");
+  if(!easysrc) {
+    helpf(config->errors, "out of memory\n");
+    res = CURLE_OUT_OF_MEMORY;
+    goto quit_curl;
+  }
+
+  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: */
+    if(!curlx_strequal(config->headerfile, "-")) {
+      FILE *newfile = fopen(config->headerfile, "wb");
+      if(!newfile) {
+        warnf(config, "Failed to open %s\n", config->headerfile);
+        res = CURLE_WRITE_ERROR;
+        goto quit_curl;
+      }
+      else {
+        heads.filename = config->headerfile;
+        heads.s_isreg = TRUE;
+        heads.fopened = TRUE;
+        heads.stream = newfile;
+      }
+    }
+  }
+
+  /*
+  ** Nested loops start here.
+  */
+
+  /* loop through the list of given URLs */
+
+  for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
+
+    int up; /* upload file counter within a single upload glob */
+    char *infiles; /* might be a glob pattern */
+    char *outfiles;
+    int infilenum;
+    URLGlob *inglob;
+
+    outfiles = NULL;
+    infilenum = 0;
+    inglob = NULL;
+
+    /* urlnode->url is the full URL (it might be NULL) */
+
+    if(!urlnode->url) {
+      /* This node has no URL. Free node data without destroying the
+         node itself nor modifying next pointer and continue to next */
+      Curl_safefree(urlnode->outfile);
+      Curl_safefree(urlnode->infile);
+      urlnode->flags = 0;
+      continue; /* next URL please */
+    }
+
+    /* save outfile pattern before expansion */
+    if(urlnode->outfile) {
+      outfiles = strdup(urlnode->outfile);
+      if(!outfiles) {
+        helpf(config->errors, "out of memory\n");
+        res = CURLE_OUT_OF_MEMORY;
+        break;
+      }
+    }
+
+    infiles = urlnode->infile;
+
+    if(!config->globoff && infiles) {
+      /* Unless explicitly shut off */
+      res = glob_url(&inglob, infiles, &infilenum,
+                     config->showerror?config->errors:NULL);
+      if(res) {
+        Curl_safefree(outfiles);
+        break;
+      }
+    }
+
+    /* Here's the loop for uploading multiple files within the same
+       single globbed string. If no upload, we enter the loop once anyway. */
+    for(up = 0 ;; up++) {
+
+      char *uploadfile; /* a single file, never a glob */
+      int separator;
+      URLGlob *urls;
+      int urlnum;
+
+      uploadfile = NULL;
+      separator = 0;
+      urls = NULL;
+      urlnum = 0;
+
+      if(!up && !infiles)
+        Curl_nop_stmt;
+      else {
+        if(inglob)
+          uploadfile = glob_next_url(inglob);
+        else if(!up)
+          uploadfile = strdup(infiles);
+        else
+          uploadfile = NULL;
+        if(!uploadfile)
+          break;
+      }
+
+      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);
+        if(res) {
+          Curl_safefree(uploadfile);
+          break;
+        }
+      }
+      else
+        urlnum = 1; /* without globbing, this is a single URL */
+
+      /* if multiple files extracted to stdout, insert separators! */
+      separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
+
+      /* Here's looping around each globbed URL */
+      for(i = 0 ;; i++) {
+
+        int infd;
+        bool infdopen;
+        char *outfile;
+        struct OutStruct outs;
+        struct InStruct input;
+        struct timeval retrystart;
+        curl_off_t uploadfilesize;
+        long retry_numretries;
+        long retry_sleep_default;
+        long retry_sleep;
+        char *this_url;
+
+        outfile = NULL;
+        infdopen = FALSE;
+        infd = STDIN_FILENO;
+        uploadfilesize = -1; /* -1 means unknown */
+
+        /* default output stream is stdout */
+        memset(&outs, 0, sizeof(struct OutStruct));
+        outs.stream = stdout;
+        outs.config = config;
+
+        if(urls)
+          this_url = glob_next_url(urls);
+        else if(!i) {
+          this_url = strdup(urlnode->url);
+        }
+        else
+          this_url = NULL;
+        if(!this_url)
+          break;
+
+        if(outfiles) {
+          outfile = strdup(outfiles);
+          if(!outfile) {
+            res = CURLE_OUT_OF_MEMORY;
+            goto show_error;
+          }
+        }
+
+        if((urlnode->flags&GETOUT_USEREMOTE) ||
+           (outfile && !curlx_strequal("-", outfile)) ) {
+
+          /*
+           * We have specified a file name to store the result in, or we have
+           * decided we want to use the remote file name.
+           */
+
+          if(!outfile) {
+            /* extract the file name from the URL */
+            outfile = get_url_file_name(this_url);
+            if((!outfile || !*outfile) && !config->content_disposition) {
+              helpf(config->errors, "Remote file name has no length!\n");
+              res = CURLE_WRITE_ERROR;
+              goto quit_urls;
+            }
+#if defined(MSDOS) || defined(WIN32)
+            /* For DOS and WIN32, we do some major replacing of
+               bad characters in the file name before using it */
+            outfile = sanitize_dos_name(outfile);
+            if(!outfile) {
+              res = CURLE_OUT_OF_MEMORY;
+              goto show_error;
+            }
+#endif /* MSDOS || WIN32 */
+          }
+          else if(urls) {
+            /* fill '#1' ... '#9' terms from URL pattern */
+            char *storefile = outfile;
+            outfile = glob_match_url(storefile, urls);
+            Curl_safefree(storefile);
+            if(!outfile) {
+              /* bad globbing */
+              warnf(config, "bad output glob!\n");
+              res = CURLE_FAILED_INIT;
+              goto quit_urls;
+            }
+          }
+
+          /* Create the directory hierarchy, if not pre-existent to a multiple
+             file output call */
+
+          if(config->create_dirs) {
+            res = create_dir_hierarchy(outfile, config->errors);
+            /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
+            if(res == CURLE_WRITE_ERROR)
+              goto quit_urls;
+            if(res) {
+              goto show_error;
+            }
+          }
+
+          if((urlnode->flags & GETOUT_USEREMOTE)
+             && config->content_disposition) {
+            /* Our header callback sets the filename */
+            DEBUGASSERT(!outs.filename);
+          }
+          else {
+            if(config->resume_from_current) {
+              /* We're told to continue from where we are now. Get the size
+                 of the file as it is now and open it for append instead */
+              struct_stat fileinfo;
+              /* VMS -- Danger, the filesize is only valid for stream files */
+              if(0 == stat(outfile, &fileinfo))
+                /* set offset to current file size: */
+                config->resume_from = fileinfo.st_size;
+              else
+                /* let offset be 0 */
+                config->resume_from = 0;
+            }
+
+            if(config->resume_from) {
+              /* open file for output: */
+              FILE *file = fopen(outfile, config->resume_from?"ab":"wb");
+              if(!file) {
+                helpf(config->errors, "Can't open '%s'!\n", outfile);
+                res = CURLE_WRITE_ERROR;
+                goto quit_urls;
+              }
+              outs.fopened = TRUE;
+              outs.stream = file;
+              outs.init = config->resume_from;
+            }
+            else {
+              outs.stream = NULL; /* open when needed */
+            }
+            outs.filename = outfile;
+            outs.s_isreg = TRUE;
+          }
+        }
+
+        if(uploadfile && !stdin_upload(uploadfile)) {
+          /*
+           * We have specified a file to upload and it isn't "-".
+           */
+          struct_stat fileinfo;
+
+          this_url = add_file_name_to_url(curl, this_url, uploadfile);
+          if(!this_url) {
+            res = CURLE_OUT_OF_MEMORY;
+            goto show_error;
+          }
+          /* VMS Note:
+           *
+           * Reading binary from files can be a problem...  Only FIXED, VAR
+           * etc WITHOUT implied CC will work Others need a \n appended to a
+           * line
+           *
+           * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a
+           * fixed file with implied CC needs to have a byte added for every
+           * record processed, this can by derived from Filesize & recordsize
+           * for VARiable record files the records need to be counted!  for
+           * every record add 1 for linefeed and subtract 2 for the record
+           * header for VARIABLE header files only the bare record data needs
+           * to be considered with one appended if implied CC
+           */
+
+          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) {
+              close(infd);
+              infd = STDIN_FILENO;
+            }
+            res = CURLE_READ_ERROR;
+            goto quit_urls;
+          }
+          infdopen = TRUE;
+
+          /* we ignore file size for char/block devices, sockets, etc. */
+          if(S_ISREG(fileinfo.st_mode))
+            uploadfilesize = fileinfo.st_size;
+
+        }
+        else if(uploadfile && stdin_upload(uploadfile)) {
+          /* count to see if there are more than one auth bit set
+             in the authtype field */
+          int authbits = 0;
+          int bitcheck = 0;
+          while(bitcheck < 32) {
+            if(config->authtype & (1 << bitcheck++)) {
+              authbits++;
+              if(authbits > 1) {
+                /* more than one, we're done! */
+                break;
+              }
+            }
+          }
+
+          /*
+           * If the user has also selected --anyauth or --proxy-anyauth
+           * we should warn him/her.
+           */
+          if(config->proxyanyauth || (authbits>1)) {
+            warnf(config,
+                  "Using --anyauth or --proxy-anyauth with upload from stdin"
+                  " involves a big risk of it not working. Use a temporary"
+                  " file or a fixed auth type instead!\n");
+          }
+
+          DEBUGASSERT(infdopen == FALSE);
+          DEBUGASSERT(infd == STDIN_FILENO);
+
+          set_binmode(stdin);
+          if(curlx_strequal(uploadfile, ".")) {
+            if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0)
+              warnf(config,
+                    "fcntl failed on fd=%d: %s\n", infd, strerror(errno));
+          }
+        }
+
+        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)))
+          /* we send the output to a tty, therefore we switch off the progress
+             meter */
+          config->noprogress = config->isatty = TRUE;
+
+        if(urlnum > 1 && !(config->mute)) {
+          fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
+                  i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
+          if(separator)
+            printf("%s%s\n", CURLseparator, this_url);
+        }
+        if(httpgetfields) {
+          char *urlbuffer;
+          /* Find out whether the url contains a file name */
+          const char *pc = strstr(this_url, "://");
+          char sep = '?';
+          if(pc)
+            pc += 3;
+          else
+            pc = this_url;
+
+          pc = strrchr(pc, '/'); /* check for a slash */
+
+          if(pc) {
+            /* there is a slash present in the URL */
+
+            if(strchr(pc, '?'))
+              /* Ouch, there's already a question mark in the URL string, we
+                 then append the data with an ampersand separator instead! */
+              sep='&';
+          }
+          /*
+           * 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);
+          else
+            /* Append  / before the ? to create a well-formed url
+               if the url contains a hostname only
+            */
+            sprintf(urlbuffer, "%s/?%s", this_url, httpgetfields);
+
+          Curl_safefree(this_url); /* free previous URL */
+          this_url = urlbuffer; /* use our new URL instead! */
+        }
+
+        if(!config->errors)
+          config->errors = stderr;
+
+        if((!outfile || !strcmp(outfile, "-")) && !config->use_ascii) {
+          /* We get the output to stdout and we have not got the ASCII/text
+             flag, then set stdout to be binary */
+          set_binmode(stdout);
+        }
+
+        if(config->tcp_nodelay)
+          my_setopt(curl, CURLOPT_TCP_NODELAY, 1);
+
+        /* where to store */
+        my_setopt(curl, CURLOPT_WRITEDATA, &outs);
+        /* what call to write */
+        my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
+
+        /* for uploads */
+        input.fd = infd;
+        input.config = config;
+        my_setopt(curl, CURLOPT_READDATA, &input);
+        /* what call to read */
+        if((outfile && !curlx_strequal("-", outfile)) ||
+           !checkprefix("telnet:", this_url))
+          my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
+
+        /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
+           CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
+        my_setopt(curl, CURLOPT_SEEKDATA, &input);
+        my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
+
+        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);
+
+        /* 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);
+        if(config->no_body) {
+          my_setopt(curl, CURLOPT_NOBODY, 1);
+          my_setopt(curl, CURLOPT_HEADER, 1);
+        }
+        else
+          my_setopt(curl, CURLOPT_HEADER, config->include_headers);
+
+#if !defined(CURL_DISABLE_PROXY)
+        {
+          /* TODO: Make this a run-time check instead of compile-time one. */
+
+          my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
+          my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
+
+          /* new in libcurl 7.3 */
+          my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
+
+          /* new in libcurl 7.5 */
+          if(config->proxy)
+            my_setopt(curl, CURLOPT_PROXYTYPE, config->proxyver);
+
+          /* new in libcurl 7.10 */
+          if(config->socksproxy) {
+            my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
+            my_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
+          }
+
+          /* new in libcurl 7.10.6 */
+          if(config->proxyanyauth)
+            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+          else if(config->proxynegotiate)
+            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
+          else if(config->proxyntlm)
+            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
+          else if(config->proxydigest)
+            my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
+          else if(config->proxybasic)
+            my_setopt(curl, CURLOPT_PROXYAUTH, 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);
+
+        if(config->netrc_opt)
+          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+        else if(config->netrc || config->netrc_file)
+          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
+        else
+          my_setopt(curl, CURLOPT_NETRC, 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_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);
+
+        if(built_in_protos & CURLPROTO_HTTP) {
+
+          my_setopt(curl, CURLOPT_FOLLOWLOCATION,
+                    config->followlocation);
+          my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
+                    config->unrestricted_auth);
+
+          switch(config->httpreq) {
+          case HTTPREQ_SIMPLEPOST:
+            my_setopt_str(curl, CURLOPT_POSTFIELDS,
+                          config->postfields);
+            my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+                      config->postfieldsize);
+            break;
+          case HTTPREQ_POST:
+            my_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
+            break;
+          default:
+            break;
+          }
+
+          my_setopt_str(curl, CURLOPT_REFERER, config->referer);
+          my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer);
+          my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
+          my_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
+
+          /* new in libcurl 7.5 */
+          my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
+
+          /* new in libcurl 7.9.1 */
+          if(config->httpversion)
+            my_setopt(curl, CURLOPT_HTTP_VERSION, config->httpversion);
+
+          /* new in libcurl 7.10.6 (default is Basic) */
+          if(config->authtype)
+            my_setopt(curl, CURLOPT_HTTPAUTH, config->authtype);
+
+          /* curl 7.19.1 (the 301 version existed in 7.18.2) */
+          my_setopt(curl, CURLOPT_POSTREDIR, config->post301 |
+                    (config->post302 ? CURL_REDIR_POST_302 : FALSE));
+
+          /* new in libcurl 7.21.6 */
+          if(config->encoding)
+            my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
+
+          /* new in libcurl 7.21.6 */
+          if(config->tr_encoding)
+            my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1);
+
+        } /* (built_in_protos & CURLPROTO_HTTP) */
+
+        my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
+        my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
+                  config->low_speed_limit);
+        my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
+        my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
+                  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);
+        my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
+        my_setopt(curl, CURLOPT_SSLKEY, config->key);
+        my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
+        my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
+
+        if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
+
+          /* SSH and SSL private key uses same command-line option */
+          /* new in libcurl 7.16.1 */
+          my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
+          /* new in libcurl 7.16.1 */
+          my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
+
+          /* new in libcurl 7.17.1: SSH host key md5 checking allows us
+             to fail if we are not talking to who we think we should */
+          my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+                        config->hostpubmd5);
+        }
+
+        if(config->cacert)
+          my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
+        if(config->capath)
+          my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
+        if(config->crlfile)
+          my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
+
+        if(curlinfo->features & CURL_VERSION_SSL) {
+          if(config->insecure_ok) {
+            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+            my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L);
+          }
+          else {
+            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
+            /* libcurl default is strict verifyhost -> 2L   */
+            /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
+          }
+        }
+
+        if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
+          if(!config->insecure_ok) {
+            char *home;
+            char *file;
+            res = CURLE_OUT_OF_MEMORY;
+            home = homedir();
+            if(home) {
+              file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR);
+              if(file) {
+                /* new in curl 7.19.6 */
+                res = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file);
+                curl_free(file);
+                if(res == CURLE_UNKNOWN_OPTION)
+                  /* libssh2 version older than 1.1.1 */
+                  res = CURLE_OK;
+              }
+              free(home);
+            }
+            if(res)
+              goto show_error;
+          }
+        }
+
+        if(config->no_body || config->remote_time) {
+          /* no body or use remote time */
+          my_setopt(curl, CURLOPT_FILETIME, TRUE);
+        }
+
+        my_setopt(curl, CURLOPT_CRLF, config->crlf);
+        my_setopt(curl, CURLOPT_QUOTE, config->quote);
+        my_setopt(curl, CURLOPT_POSTQUOTE, config->postquote);
+        my_setopt(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->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.7 */
+          my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession);
+        }
+#endif
+
+        my_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
+        my_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
+        my_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
+        my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
+        my_setopt(curl, CURLOPT_STDERR, config->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) {
+          /* 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);
+        }
+
+        /* new in libcurl 7.6.2: */
+        my_setopt(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);
+
+        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);
+
+        /* new in libcurl 7.10.5 */
+        if(config->disable_eprt)
+          /* disable it */
+          my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
+
+        if(config->tracetype != TRACE_NONE) {
+          my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
+          my_setopt(curl, CURLOPT_DEBUGDATA, config);
+          my_setopt(curl, CURLOPT_VERBOSE, TRUE);
+        }
+
+        /* new in curl 7.9.3 */
+        if(config->engine) {
+          res = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
+          if(res)
+            goto show_error;
+          my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
+        }
+
+        /* 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);
+
+        /* new in curl 7.10.8 */
+        if(config->max_filesize)
+          my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
+                    config->max_filesize);
+
+        if(4 == config->ip_version)
+          my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+        else if(6 == config->ip_version)
+          my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
+        else
+          my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
+
+        /* new in curl 7.15.5 */
+        if(config->ftp_ssl_reqd)
+          my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
+
+        /* new in curl 7.11.0 */
+        else if(config->ftp_ssl)
+          my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
+
+        /* new in curl 7.16.0 */
+        else if(config->ftp_ssl_control)
+          my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
+
+        /* new in curl 7.16.1 */
+        if(config->ftp_ssl_ccc)
+          my_setopt(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+        {
+          /* TODO: Make this a run-time check instead of compile-time one. */
+
+          /* new in curl 7.19.4 */
+          if(config->socks5_gssapi_service)
+            my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
+                          config->socks5_gssapi_service);
+
+          /* new in curl 7.19.4 */
+          if(config->socks5_gssapi_nec)
+            my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
+                          config->socks5_gssapi_nec);
+        }
+#endif
+        /* curl 7.13.0 */
+        my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
+
+        my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
+
+        /* curl 7.14.2 */
+        my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
+
+        /* curl 7.15.1 */
+        my_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
+
+        /* curl 7.15.2 */
+        if(config->localport) {
+          my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
+          my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
+                        config->localportrange);
+        }
+
+        /* curl 7.15.5 */
+        my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
+                      config->ftp_alternative_to_user);
+
+        /* curl 7.16.0 */
+        if(config->disable_sessionid)
+          my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE,
+                    !config->disable_sessionid);
+
+        /* curl 7.16.2 */
+        if(config->raw) {
+          my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, FALSE);
+          my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, FALSE);
+        }
+
+        /* curl 7.17.1 */
+        if(!config->nokeepalive) {
+          my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, tool_sockopt_cb);
+          my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
+        }
+
+        /* curl 7.20.0 */
+        if(config->tftp_blksize)
+          my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
+
+        if(config->mail_from)
+          my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
+
+        if(config->mail_rcpt)
+          my_setopt(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
+
+        /* curl 7.20.x */
+        if(config->ftp_pret)
+          my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
+
+        if(config->proto_present)
+          my_setopt(curl, CURLOPT_PROTOCOLS, config->proto);
+        if(config->proto_redir_present)
+          my_setopt(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
+
+        if((urlnode->flags & GETOUT_USEREMOTE)
+           && config->content_disposition) {
+          my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
+          my_setopt(curl, CURLOPT_HEADERDATA, &outs);
+        }
+        else {
+          /* if HEADERFUNCTION was set to something in the previous loop, it
+             is important that we set it (back) to NULL now */
+          my_setopt(curl, CURLOPT_HEADERFUNCTION, NULL);
+          my_setopt(curl, CURLOPT_HEADERDATA, config->headerfile?&heads:NULL);
+        }
+
+        if(config->resolve)
+          /* new in 7.21.3 */
+          my_setopt(curl, CURLOPT_RESOLVE, config->resolve);
+
+        /* new in 7.21.4 */
+        if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+          if(config->tls_username)
+            my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
+                          config->tls_username);
+          if(config->tls_password)
+            my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
+                          config->tls_password);
+          if(config->tls_authtype)
+            my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
+                          config->tls_authtype);
+        }
+
+        /* new in 7.22.0 */
+        if(config->gssapi_delegation)
+          my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
+                        config->gssapi_delegation);
+
+        /* initialize retry vars for loop below */
+        retry_sleep_default = (config->retry_delay) ?
+          config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
+
+        retry_numretries = config->req_retry;
+        retry_sleep = retry_sleep_default; /* ms */
+        retrystart = cutil_tvnow();
+
+        for(;;) {
+          res = curl_easy_perform(curl);
+          if(!curl_slist_append(easysrc, "ret = curl_easy_perform(hnd);")) {
+            res = CURLE_OUT_OF_MEMORY;
+            goto show_error;
+          }
+
+          if(config->content_disposition && outs.stream && !config->mute &&
+             outs.filename)
+            printf("curl: Saved to filename '%s'\n", outs.filename);
+
+          /* if retry-max-time is non-zero, make sure we haven't exceeded the
+             time */
+          if(retry_numretries &&
+             (!config->retry_maxtime ||
+              (cutil_tvdiff(cutil_tvnow(), retrystart)<
+               config->retry_maxtime*1000L)) ) {
+            enum {
+              RETRY_NO,
+              RETRY_TIMEOUT,
+              RETRY_HTTP,
+              RETRY_FTP,
+              RETRY_LAST /* not used */
+            } retry = RETRY_NO;
+            long response;
+            if(CURLE_OPERATION_TIMEDOUT == res)
+              /* retry timeout always */
+              retry = RETRY_TIMEOUT;
+            else if((CURLE_OK == res) ||
+                    (config->failonerror &&
+                     (CURLE_HTTP_RETURNED_ERROR == res))) {
+              /* If it returned OK. _or_ failonerror was enabled and it
+                 returned due to such an error, check for HTTP transient
+                 errors to retry on. */
+              char *effective_url = NULL;
+              curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
+              if(effective_url &&
+                 checkprefix("http", effective_url)) {
+                /* This was HTTP(S) */
+                curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+
+                switch(response) {
+                case 500: /* Internal Server Error */
+                case 502: /* Bad Gateway */
+                case 503: /* Service Unavailable */
+                case 504: /* Gateway Timeout */
+                  retry = RETRY_HTTP;
+                  /*
+                   * At this point, we have already written data to the output
+                   * file (or terminal). If we write to a file, we must rewind
+                   * or close/re-open the file so that the next attempt starts
+                   * over from the beginning.
+                   *
+                   * TODO: similar action for the upload case. We might need
+                   * to start over reading from a previous point if we have
+                   * uploaded something when this was returned.
+                   */
+                  break;
+                }
+              }
+            } /* if CURLE_OK */
+            else if(res) {
+              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+
+              if(response/100 == 4)
+                /*
+                 * This is typically when the FTP server only allows a certain
+                 * amount of users and we are not one of them.  All 4xx codes
+                 * are transient.
+                 */
+                retry = RETRY_FTP;
+            }
+
+            if(retry) {
+              static const char * const m[]={
+                NULL, "timeout", "HTTP error", "FTP error"
+              };
+              warnf(config, "Transient problem: %s "
+                    "Will retry in %ld seconds. "
+                    "%ld retries left.\n",
+                    m[retry], retry_sleep/1000L, retry_numretries);
+
+              tool_go_sleep(retry_sleep);
+              retry_numretries--;
+              if(!config->retry_delay) {
+                retry_sleep *= 2;
+                if(retry_sleep > RETRY_SLEEP_MAX)
+                  retry_sleep = RETRY_SLEEP_MAX;
+              }
+              if(outs.bytes && outs.filename) {
+                /* We have written data to a output file, we truncate file
+                 */
+                if(!config->mute)
+                  fprintf(config->errors, "Throwing away %"
+                          CURL_FORMAT_CURL_OFF_T " bytes\n",
+                          outs.bytes);
+                fflush(outs.stream);
+                /* truncate file at the position where we started appending */
+#ifdef HAVE_FTRUNCATE
+                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,
+                            "failed to truncate, exiting\n");
+                  res = CURLE_WRITE_ERROR;
+                  goto quit_urls;
+                }
+                /* now seek to the end of the file, the position where we
+                   just truncated the file in a large file-safe way */
+                fseek(outs.stream, 0, SEEK_END);
+#else
+                /* ftruncate is not available, so just reposition the file
+                   to the location we would have truncated it. This won't
+                   work properly with large files on 32-bit systems, but
+                   most of those will have ftruncate. */
+                fseek(outs.stream, (long)outs.init, SEEK_SET);
+#endif
+                outs.bytes = 0; /* clear for next round */
+              }
+              continue; /* curl_easy_perform loop */
+            }
+          } /* if retry_numretries */
+
+          /* In all ordinary cases, just break out of loop here */
+          break; /* curl_easy_perform loop */
+
+        }
+
+        if((config->progressmode == CURL_PROGRESS_BAR) &&
+           progressbar.calls)
+          /* if the custom progress bar has been displayed, we output a
+             newline here */
+          fputs("\n", progressbar.out);
+
+        if(config->writeout)
+          ourWriteOut(curl, config->writeout);
+#ifdef USE_ENVIRONMENT
+        if(config->writeenv)
+          ourWriteEnv(curl);
+#endif
+
+        /*
+        ** Code within this loop may jump directly here to label 'show_error'
+        ** in order to display an error message for CURLcode stored in 'res'
+        ** variable and exit loop once that necessary writing and cleanup
+        ** in label 'quit_urls' has been done.
+        */
+
+        show_error:
+
+#ifdef __VMS
+        if(is_vms_shell()) {
+          /* VMS DCL shell behavior */
+          if(!config->showerror)
+            vms_show = VMSSTS_HIDE;
+        }
+        else
+#endif
+        if(res && config->showerror) {
+          fprintf(config->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
+                  errorbuffer : curl_easy_strerror((CURLcode)res));
+          if(res == CURLE_SSL_CACERT)
+            fprintf(config->errors, "%s%s",
+                    CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
+        }
+
+        /* Fall through comment to 'quit_urls' label */
+
+        /*
+        ** Upon error condition and always that a message has already been
+        ** displayed, code within this loop may jump directly here to label
+        ** 'quit_urls' otherwise it should jump to 'show_error' label above.
+        **
+        ** When 'res' variable is _not_ CURLE_OK loop will exit once that
+        ** all code following 'quit_urls' has been executed. Otherwise it
+        ** will loop to the beginning from where it may exit if there are
+        ** no more urls left.
+        */
+
+        quit_urls:
+
+        /* Set file extended attributes */
+        if(!res && config->xattr && outs.fopened && outs.stream) {
+          int rc = fwrite_xattr(curl, fileno(outs.stream));
+          if(rc)
+            warnf(config, "Error setting extended attributes: %s\n",
+                  strerror(errno));
+        }
+
+        /* Close the file */
+        if(outs.fopened && outs.stream) {
+          int rc = fclose(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);
+          }
+        }
+        else if(!outs.s_isreg && outs.stream) {
+          /* Dump standard stream buffered data */
+          int rc = fflush(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);
+          }
+        }
+
+#ifdef __AMIGA__
+        if(!res && outs.s_isreg && outs.filename) {
+          /* Set the url (up to 80 chars) as comment for the file */
+          if(strlen(url) > 78)
+            url[79] = '\0';
+          SetComment(outs.filename, url);
+        }
+#endif
+
+#ifdef HAVE_UTIME
+        /* File time can only be set _after_ the file has been closed */
+        if(!res && config->remote_time && outs.s_isreg && outs.filename) {
+          /* Ask libcurl if we got a remote file time */
+          long filetime = -1;
+          curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+          if(filetime >= 0) {
+            struct utimbuf times;
+            times.actime = (time_t)filetime;
+            times.modtime = (time_t)filetime;
+            utime(outs.filename, &times); /* set the time we got */
+          }
+        }
+#endif
+        /* No more business with this output struct */
+        if(outs.alloc_filename)
+          Curl_safefree(outs.filename);
+        memset(&outs, 0, sizeof(struct OutStruct));
+
+        /* Free loop-local allocated memory and close loop-local opened fd */
+
+        Curl_safefree(outfile);
+        Curl_safefree(this_url);
+
+        if(infdopen) {
+          close(infd);
+          infdopen = FALSE;
+          infd = STDIN_FILENO;
+        }
+
+        /* upon error exit loop */
+        if(res)
+          break;
+
+      } /* loop to the next URL */
+
+      /* Free loop-local allocated memory */
+
+      Curl_safefree(uploadfile);
+
+      if(urls) {
+        /* Free list of remaining URLs */
+        glob_cleanup(urls);
+        urls = NULL;
+      }
+
+      /* upon error exit loop */
+      if(res)
+        break;
+
+    } /* loop to the next globbed upload file */
+
+    /* Free loop-local allocated memory */
+
+    Curl_safefree(outfiles);
+
+    if(inglob) {
+      /* Free list of globbed upload files */
+      glob_cleanup(inglob);
+      inglob = NULL;
+    }
+
+    /* Free this URL node data without destroying the
+       the node itself nor modifying next pointer. */
+    Curl_safefree(urlnode->url);
+    Curl_safefree(urlnode->outfile);
+    Curl_safefree(urlnode->infile);
+    urlnode->flags = 0;
+
+    /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
+
+    /*
+    ** Bail out upon critical errors
+    */
+    switch(res) {
+    case CURLE_FAILED_INIT:
+    case CURLE_OUT_OF_MEMORY:
+    case CURLE_FUNCTION_NOT_FOUND:
+    case CURLE_BAD_FUNCTION_ARGUMENT:
+      goto quit_curl;
+    default:
+      /* Merrily loop to next URL */
+      break;
+    }
+
+  } /* for-loop through all URLs */
+
+  /*
+  ** Nested loops end here.
+  */
+
+  quit_curl:
+
+  /* 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;
+  }
+  if(easysrc)
+    curl_slist_append(easysrc, "curl_easy_cleanup(hnd);");
+
+  /* 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);
+
+  /* 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);
+
+  if(config->errors_fopened && config->errors)
+    fclose(config->errors);
+
+  main_free(); /* cleanup */
+
+  return res;
+}
+
diff --git a/src/tool_operate.h b/src/tool_operate.h
new file mode 100644 (file)
index 0000000..4986cc4
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TOOL_OPERATE_H
+#define HEADER_CURL_TOOL_OPERATE_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+int operate(struct Configurable *config, int argc, argv_item_t argv[]);
+
+#endif /* HEADER_CURL_TOOL_OPERATE_H */
+
diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c
new file mode 100644 (file)
index 0000000..1a72035
--- /dev/null
@@ -0,0 +1,231 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "version.h"
+
+#include "tool_cfgable.h"
+#include "tool_convert.h"
+#include "tool_operhlp.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+ * my_useragent: returns allocated string with default user agent
+ */
+char *my_useragent(void)
+{
+  char useragent[256]; /* we don't want a larger default user agent */
+
+  snprintf(useragent, sizeof(useragent),
+           CURL_NAME "/" CURL_VERSION " (" OS ") " "%s", curl_version());
+
+  return strdup(useragent);
+}
+
+/*
+ * Print list of OpenSSL supported engines
+ */
+void list_engines(const struct curl_slist *engines)
+{
+  puts("Build-time engines:");
+  if(!engines) {
+    puts("  <none>");
+    return;
+  }
+  for(; engines; engines = engines->next)
+    printf("  %s\n", engines->data);
+}
+
+void clean_getout(struct Configurable *config)
+{
+  struct getout *next;
+  struct getout *node = config->url_list;
+
+  while(node) {
+    next = node->next;
+    Curl_safefree(node->url);
+    Curl_safefree(node->outfile);
+    Curl_safefree(node->infile);
+    Curl_safefree(node);
+    node = next;
+  }
+  config->url_list = NULL;
+}
+
+bool output_expected(const char *url, const char *uploadfile)
+{
+  if(!uploadfile)
+    return TRUE;  /* download */
+  if(checkprefix("http://", url) || checkprefix("https://", url))
+    return TRUE;   /* HTTP(S) upload */
+
+  return FALSE; /* non-HTTP upload, probably no output should be expected */
+}
+
+bool stdin_upload(const char *uploadfile)
+{
+  return (curlx_strequal(uploadfile, "-") ||
+          curlx_strequal(uploadfile, ".")) ? TRUE : FALSE;
+}
+
+/*
+ * Adds the file name to the URL if it doesn't already have one.
+ * url will be freed before return if the returned pointer is different
+ */
+char *add_file_name_to_url(CURL *curl, char *url, const char *filename)
+{
+  /* If no file name part is given in the URL, we add this file name */
+  char *ptr = strstr(url, "://");
+  if(ptr)
+    ptr += 3;
+  else
+    ptr = url;
+  ptr = strrchr(ptr, '/');
+  if(!ptr || !strlen(++ptr)) {
+    /* The URL has no file name part, add the local file name. In order
+       to be able to do so, we have to create a new URL in another
+       buffer.*/
+
+    /* We only want the part of the local path that is on the right
+       side of the rightmost slash and backslash. */
+    const char *filep = strrchr(filename, '/');
+    char *file2 = strrchr(filep?filep:filename, '\\');
+    char *encfile;
+
+    if(file2)
+      filep = file2 + 1;
+    else if(filep)
+      filep++;
+    else
+      filep = filename;
+
+    /* URL encode the file name */
+    encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
+    if(encfile) {
+      char *urlbuffer = malloc(strlen(url) + strlen(encfile) + 3);
+      if(!urlbuffer) {
+        Curl_safefree(url);
+        return NULL;
+      }
+      if(ptr)
+        /* there is a trailing slash on the URL */
+        sprintf(urlbuffer, "%s%s", url, encfile);
+      else
+        /* there is no trailing slash on the URL */
+        sprintf(urlbuffer, "%s/%s", url, encfile);
+
+      curl_free(encfile);
+
+      Curl_safefree(url);
+      url = urlbuffer; /* use our new URL instead! */
+    }
+  }
+  return url;
+}
+
+/* Extracts the name portion of the URL.
+ * Returns a heap-allocated string, or NULL if no name part
+ */
+char *get_url_file_name(const char *url)
+{
+  char *fn = NULL;
+
+  /* Find and get the remote file name */
+  const char *pc = strstr(url, "://");
+  if(pc)
+    pc += 3;
+  else
+    pc = url;
+  pc = strrchr(pc, '/');
+
+  if(pc) {
+    /* duplicate the string beyond the slash */
+    pc++;
+    fn = *pc ? strdup(pc): NULL;
+  }
+  return fn;
+}
+
+/*
+ * This is the main global constructor for the app. Call this before
+ * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
+ * used, or havoc may be the result.
+ */
+CURLcode main_init(void)
+{
+#if defined(__DJGPP__) || defined(__GO32__)
+  /* stop stat() wasting time */
+  _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
+#endif
+
+  return curl_global_init(CURL_GLOBAL_DEFAULT);
+}
+
+/*
+ * This is the main global destructor for the app. Call this after
+ * _all_ libcurl usage is done.
+ */
+void main_free(void)
+{
+  curl_global_cleanup();
+  convert_cleanup();
+}
+
+#ifdef CURLDEBUG
+void memory_tracking_init(void)
+{
+  char *env;
+  /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
+  env = curlx_getenv("CURL_MEMDEBUG");
+  if(env) {
+    /* use the value as file name */
+    char fname[CURL_MT_LOGFNAME_BUFSIZE];
+    if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
+      env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
+    strcpy(fname, env);
+    curl_free(env);
+    curl_memdebug(fname);
+    /* this weird stuff here is to make curl_free() get called
+       before curl_memdebug() as otherwise memory tracking will
+       log a free() without an alloc! */
+  }
+  /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
+  env = curlx_getenv("CURL_MEMLIMIT");
+  if(env) {
+    char *endptr;
+    long num = strtol(env, &endptr, 10);
+    if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
+      curl_memlimit(num);
+    curl_free(env);
+  }
+}
+#endif
+
diff --git a/src/tool_operhlp.h b/src/tool_operhlp.h
new file mode 100644 (file)
index 0000000..911f2f8
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_TOOL_OPERHLP_H
+#define HEADER_CURL_TOOL_OPERHLP_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+char *my_useragent(void);
+
+void list_engines(const struct curl_slist *engines);
+
+void clean_getout(struct Configurable *config);
+
+bool output_expected(const char *url, const char *uploadfile);
+
+bool stdin_upload(const char *uploadfile);
+
+char *add_file_name_to_url(CURL *curl, char *url, const char *filename);
+
+char *get_url_file_name(const char *url);
+
+CURLcode main_init(void);
+
+void main_free(void);
+
+#ifdef CURLDEBUG
+void memory_tracking_init(void);
+#else
+#  define memory_tracking_init() Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_TOOL_OPERHLP_H */
+
similarity index 70%
rename from src/tool_myfunc.c
rename to src/tool_panykey.c
index 08afc99..8e1fd8d 100644 (file)
  ***************************************************************************/
 #include "setup.h"
 
-#include <curl/curl.h>
+#if defined(__SYMBIAN32__) || defined(NETWARE)
 
-#define ENABLE_CURLX_PRINTF
-/* use our own printf() functions */
-#include "curlx.h"
-
-#include "version.h"
-#include "tool_myfunc.h"
+#include "tool_panykey.h"
 
 #include "memdebug.h" /* keep this as LAST include */
 
-/*
- * my_useragent: returns allocated string with default user agent
- */
-
-char *my_useragent(void)
+void tool_pressanykey(void)
 {
-  char useragent[256]; /* we don't want a larger default user agent */
-
-  snprintf(useragent, sizeof(useragent),
-           CURL_NAME "/" CURL_VERSION " (" OS ") " "%s", curl_version());
-
-  return strdup(useragent);
+#if defined(__SYMBIAN32__)
+  getchar();
+#elif defined(NETWARE)
+  pressanykey();
+#endif
 }
 
+#endif /* __SYMBIAN32__ || NETWARE */
+
diff --git a/src/tool_panykey.h b/src/tool_panykey.h
new file mode 100644 (file)
index 0000000..30fd658
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_TOOL_PANYKEY_H
+#define HEADER_CURL_TOOL_PANYKEY_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#if defined(__SYMBIAN32__) || defined(NETWARE)
+
+void tool_pressanykey(void);
+
+#else
+
+#define tool_pressanykey() Curl_nop_stmt
+
+#endif
+
+#endif /* HEADER_CURL_TOOL_PANYKEY_H */
+
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
new file mode 100644 (file)
index 0000000..4f36719
--- /dev/null
@@ -0,0 +1,384 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "homedir.h"
+#include "getpass.h"
+
+#include "tool_cfgable.h"
+#include "tool_getparam.h"
+#include "tool_msgs.h"
+#include "tool_paramhlp.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+struct getout *new_getout(struct Configurable *config)
+{
+  struct getout *node =malloc(sizeof(struct getout));
+  struct getout *last= config->url_last;
+  if(node) {
+    /* clear the struct */
+    memset(node, 0, sizeof(struct getout));
+
+    /* append this new node last in the list */
+    if(last)
+      last->next = node;
+    else
+      config->url_list = node; /* first node */
+
+    /* move the last pointer */
+    config->url_last = node;
+
+    node->flags = config->default_node_flags;
+  }
+  return node;
+}
+
+ParameterError file2string(char **bufp, FILE *file)
+{
+  char buffer[256];
+  char *ptr;
+  char *string = NULL;
+  size_t stringlen = 0;
+  size_t buflen;
+
+  if(file) {
+    while(fgets(buffer, sizeof(buffer), file)) {
+      if((ptr = strchr(buffer, '\r')) != NULL)
+        *ptr = '\0';
+      if((ptr = strchr(buffer, '\n')) != NULL)
+        *ptr = '\0';
+      buflen = strlen(buffer);
+      if((ptr = realloc(string, stringlen+buflen+1)) == NULL) {
+        Curl_safefree(string);
+        return PARAM_NO_MEM;
+      }
+      string = ptr;
+      strcpy(string+stringlen, buffer);
+      stringlen += buflen;
+    }
+  }
+  *bufp = string;
+  return PARAM_OK;
+}
+
+ParameterError file2memory(char **bufp, size_t *size, FILE *file)
+{
+  char *newbuf;
+  char *buffer = NULL;
+  size_t alloc = 512;
+  size_t nused = 0;
+  size_t nread;
+
+  if(file) {
+    do {
+      if(!buffer || (alloc == nused)) {
+        /* size_t overflow detection for huge files */
+        if(alloc+1 > ((size_t)-1)/2) {
+          Curl_safefree(buffer);
+          return PARAM_NO_MEM;
+        }
+        alloc *= 2;
+        /* allocate an extra char, reserved space, for null termination */
+        if((newbuf = realloc(buffer, alloc+1)) == NULL) {
+          Curl_safefree(buffer);
+          return PARAM_NO_MEM;
+        }
+        buffer = newbuf;
+      }
+      nread = fread(buffer+nused, 1, alloc-nused, file);
+      nused += nread;
+    } while(nread);
+    /* null terminate the buffer in case it's used as a string later */
+    buffer[nused] = '\0';
+    /* free trailing slack space, if possible */
+    if(alloc != nused) {
+      if((newbuf = realloc(buffer, nused+1)) != NULL)
+        buffer = newbuf;
+    }
+    /* discard buffer if nothing was read */
+    if(!nused) {
+      Curl_safefree(buffer); /* no string */
+    }
+  }
+  *size = nused;
+  *bufp = buffer;
+  return PARAM_OK;
+}
+
+void cleanarg(char *str)
+{
+#ifdef HAVE_WRITABLE_ARGV
+  /* now that GetStr has copied the contents of nextarg, wipe the next
+   * argument out so that the username:password isn't displayed in the
+   * system process list */
+  if(str) {
+    size_t len = strlen(str);
+    memset(str, ' ', len);
+  }
+#else
+  (void)str;
+#endif
+}
+
+/*
+ * Parse the string and write the integer in the given address. Return
+ * non-zero on failure, zero on success.
+ *
+ * The string must start with a digit to be valid.
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+int str2num(long *val, const char *str)
+{
+  if(str && ISDIGIT(*str)) {
+    char *endptr;
+    long num = strtol(str, &endptr, 10);
+    if((endptr != str) && (endptr == str + strlen(str))) {
+      *val = num;
+      return 0;  /* Ok */
+    }
+  }
+  return 1; /* badness */
+}
+
+/*
+ * Parse the string and modify the long in the given address. Return
+ * non-zero on failure, zero on success.
+ *
+ * The string is a list of protocols
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+long proto2num(struct Configurable *config, long *val, const char *str)
+{
+  char *buffer;
+  const char *sep = ",";
+  char *token;
+
+  static struct sprotos {
+    const char *name;
+    long bit;
+  } const protos[] = {
+    { "all", CURLPROTO_ALL },
+    { "http", CURLPROTO_HTTP },
+    { "https", CURLPROTO_HTTPS },
+    { "ftp", CURLPROTO_FTP },
+    { "ftps", CURLPROTO_FTPS },
+    { "scp", CURLPROTO_SCP },
+    { "sftp", CURLPROTO_SFTP },
+    { "telnet", CURLPROTO_TELNET },
+    { "ldap", CURLPROTO_LDAP },
+    { "ldaps", CURLPROTO_LDAPS },
+    { "dict", CURLPROTO_DICT },
+    { "file", CURLPROTO_FILE },
+    { "tftp", CURLPROTO_TFTP },
+    { "imap", CURLPROTO_IMAP },
+    { "imaps", CURLPROTO_IMAPS },
+    { "pop3", CURLPROTO_POP3 },
+    { "pop3s", CURLPROTO_POP3S },
+    { "smtp", CURLPROTO_SMTP },
+    { "smtps", CURLPROTO_SMTPS },
+    { "rtsp", CURLPROTO_RTSP },
+    { "gopher", CURLPROTO_GOPHER },
+    { NULL, 0 }
+  };
+
+  if(!str)
+    return 1;
+
+  buffer = strdup(str); /* because strtok corrupts it */
+
+  for(token = strtok(buffer, sep);
+      token;
+      token = strtok(NULL, sep)) {
+    enum e_action { allow, deny, set } action = allow;
+
+    struct sprotos const *pp;
+
+    /* Process token modifiers */
+    while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
+      switch (*token++) {
+      case '=':
+        action = set;
+        break;
+      case '-':
+        action = deny;
+        break;
+      case '+':
+        action = allow;
+        break;
+      default: /* Includes case of terminating NULL */
+        Curl_safefree(buffer);
+        return 1;
+      }
+    }
+
+    for(pp=protos; pp->name; pp++) {
+      if(curlx_raw_equal(token, pp->name)) {
+        switch (action) {
+        case deny:
+          *val &= ~(pp->bit);
+          break;
+        case allow:
+          *val |= pp->bit;
+          break;
+        case set:
+          *val = pp->bit;
+          break;
+        }
+        break;
+      }
+    }
+
+    if(!(pp->name)) { /* unknown protocol */
+      /* If they have specified only this protocol, we say treat it as
+         if no protocols are allowed */
+      if(action == set)
+        *val = 0;
+      warnf(config, "unrecognized protocol '%s'\n", token);
+    }
+  }
+  Curl_safefree(buffer);
+  return 0;
+}
+
+/**
+ * Parses the given string looking for an offset (which may be
+ * a larger-than-integer value).
+ *
+ * @param val  the offset to populate
+ * @param str  the buffer containing the offset
+ * @return zero if successful, non-zero if failure.
+ */
+int str2offset(curl_off_t *val, const char *str)
+{
+#if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+  *val = curlx_strtoofft(str, NULL, 0);
+  if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE))
+    return 1;
+#else
+  *val = strtol(str, NULL, 0);
+  if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE)
+    return 1;
+#endif
+  return 0;
+}
+
+void checkpasswd(const char *kind, /* for what purpose */
+                 char **userpwd)   /* pointer to allocated string */
+{
+  char *ptr;
+  if(!*userpwd)
+    return;
+
+  ptr = strchr(*userpwd, ':');
+  if(!ptr) {
+    /* no password present, prompt for one */
+    char passwd[256]="";
+    char prompt[256];
+    size_t passwdlen;
+    size_t userlen = strlen(*userpwd);
+    char *passptr;
+
+    /* build a nice-looking prompt */
+    curlx_msnprintf(prompt, sizeof(prompt),
+                    "Enter %s password for user '%s':",
+                    kind, *userpwd);
+
+    /* get password */
+    getpass_r(prompt, passwd, sizeof(passwd));
+    passwdlen = strlen(passwd);
+
+    /* extend the allocated memory area to fit the password too */
+    passptr = realloc(*userpwd,
+                      passwdlen + 1 + /* an extra for the colon */
+                      userlen + 1);   /* an extra for the zero */
+
+    if(passptr) {
+      /* append the password separated with a colon */
+      passptr[userlen]=':';
+      memcpy(&passptr[userlen+1], passwd, passwdlen+1);
+      *userpwd = passptr;
+    }
+  }
+}
+
+ParameterError add2list(struct curl_slist **list, const char *ptr)
+{
+  struct curl_slist *newlist = curl_slist_append(*list, ptr);
+  if(newlist)
+    *list = newlist;
+  else
+    return PARAM_NO_MEM;
+
+  return PARAM_OK;
+}
+
+int ftpfilemethod(struct Configurable *config, const char *str)
+{
+  if(curlx_raw_equal("singlecwd", str))
+    return CURLFTPMETHOD_SINGLECWD;
+  if(curlx_raw_equal("nocwd", str))
+    return CURLFTPMETHOD_NOCWD;
+  if(curlx_raw_equal("multicwd", str))
+    return CURLFTPMETHOD_MULTICWD;
+  warnf(config, "unrecognized ftp file method '%s', using default\n", str);
+  return CURLFTPMETHOD_MULTICWD;
+}
+
+int ftpcccmethod(struct Configurable *config, const char *str)
+{
+  if(curlx_raw_equal("passive", str))
+    return CURLFTPSSL_CCC_PASSIVE;
+  if(curlx_raw_equal("active", str))
+    return CURLFTPSSL_CCC_ACTIVE;
+  warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
+  return CURLFTPSSL_CCC_PASSIVE;
+}
+
+long delegation(struct Configurable *config, char *str)
+{
+  if(curlx_raw_equal("none", str))
+    return CURLGSSAPI_DELEGATION_NONE;
+  if(curlx_raw_equal("policy", str))
+    return CURLGSSAPI_DELEGATION_POLICY_FLAG;
+  if(curlx_raw_equal("always", str))
+    return CURLGSSAPI_DELEGATION_FLAG;
+  warnf(config, "unrecognized delegation method '%s', using none\n", str);
+  return CURLGSSAPI_DELEGATION_NONE;
+}
+
diff --git a/src/tool_paramhlp.h b/src/tool_paramhlp.h
new file mode 100644 (file)
index 0000000..8b7ec94
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef HEADER_CURL_TOOL_PARAMHLP_H
+#define HEADER_CURL_TOOL_PARAMHLP_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+struct getout *new_getout(struct Configurable *config);
+
+ParameterError file2string(char **bufp, FILE *file);
+
+ParameterError file2memory(char **bufp, size_t *size, FILE *file);
+
+void cleanarg(char *str);
+
+int str2num(long *val, const char *str);
+
+long proto2num(struct Configurable *config, long *val, const char *str);
+
+int str2offset(curl_off_t *val, const char *str);
+
+void checkpasswd(const char *kind, char **userpwd);
+
+ParameterError add2list(struct curl_slist **list, const char *ptr);
+
+int ftpfilemethod(struct Configurable *config, const char *str);
+
+int ftpcccmethod(struct Configurable *config, const char *str);
+
+long delegation(struct Configurable *config, char *str);
+
+
+
+#endif /* HEADER_CURL_TOOL_PARAMHLP_H */
+
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
new file mode 100644 (file)
index 0000000..44d077e
--- /dev/null
@@ -0,0 +1,309 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#include <curl/curl.h>
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "homedir.h"
+
+#include "tool_cfgable.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_msgs.h"
+#include "tool_parsecfg.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define CURLRC DOT_CHAR "curlrc"
+#define ISSEP(x) (((x) == '=') || ((x) == ':'))
+
+static const char *unslashquote(const char *line, char *param);
+static char *my_get_line(FILE *fp);
+
+/* return 0 on everything-is-fine, and non-zero otherwise */
+int parseconfig(const char *filename,
+                struct Configurable *config)
+{
+  int res;
+  FILE *file;
+  char filebuffer[512];
+  bool usedarg;
+  char *home;
+  int rc = 0;
+
+  if(!filename || !*filename) {
+    /* NULL or no file name attempts to load .curlrc from the homedir! */
+
+#ifndef __AMIGA__
+    filename = CURLRC;   /* sensible default */
+    home = homedir();    /* portable homedir finder */
+    if(home) {
+      if(strlen(home) < (sizeof(filebuffer) - strlen(CURLRC))) {
+        snprintf(filebuffer, sizeof(filebuffer),
+                 "%s%s%s", home, DIR_CHAR, CURLRC);
+
+#ifdef WIN32
+        /* Check if the file exists - if not, try CURLRC in the same
+         * directory as our executable
+         */
+        file = fopen(filebuffer, "r");
+        if(file != NULL) {
+          fclose(file);
+          filename = filebuffer;
+        }
+        else {
+          /* Get the filename of our executable. GetModuleFileName is
+           * already declared via inclusions done in setup header file.
+           * We assume that we are using the ASCII version here.
+           */
+          int n = GetModuleFileName(0, filebuffer, sizeof(filebuffer));
+          if(n > 0 && n < (int)sizeof(filebuffer)) {
+            /* We got a valid filename - get the directory part */
+            char *lastdirchar = strrchr(filebuffer, '\\');
+            if(lastdirchar) {
+              size_t remaining;
+              *lastdirchar = 0;
+              /* If we have enough space, build the RC filename */
+              remaining = sizeof(filebuffer) - strlen(filebuffer);
+              if(strlen(CURLRC) < remaining - 1) {
+                snprintf(lastdirchar, remaining,
+                         "%s%s", DIR_CHAR, CURLRC);
+                /* Don't bother checking if it exists - we do
+                 * that later
+                 */
+                filename = filebuffer;
+              }
+            }
+          }
+        }
+#else /* WIN32 */
+        filename = filebuffer;
+#endif /* WIN32 */
+      }
+      Curl_safefree(home); /* we've used it, now free it */
+    }
+
+# else /* __AMIGA__ */
+    /* On AmigaOS all the config files are into env:
+     */
+    filename = "ENV:" CURLRC;
+
+#endif
+  }
+
+  if(strcmp(filename,"-"))
+    file = fopen(filename, "r");
+  else
+    file = stdin;
+
+  if(file) {
+    char *line;
+    char *aline;
+    char *option;
+    char *param;
+    int lineno = 0;
+    bool alloced_param;
+
+    while(NULL != (aline = my_get_line(file))) {
+      lineno++;
+      line = aline;
+      alloced_param=FALSE;
+
+      /* line with # in the first non-blank column is a comment! */
+      while(*line && ISSPACE(*line))
+        line++;
+
+      switch(*line) {
+      case '#':
+      case '/':
+      case '\r':
+      case '\n':
+      case '*':
+      case '\0':
+        Curl_safefree(aline);
+        continue;
+      }
+
+      /* the option keywords starts here */
+      option = line;
+      while(*line && !ISSPACE(*line) && !ISSEP(*line))
+        line++;
+      /* ... and has ended here */
+
+      if(*line)
+        *line++ = '\0'; /* zero terminate, we have a local copy of the data */
+
+#ifdef DEBUG_CONFIG
+      fprintf(stderr, "GOT: %s\n", option);
+#endif
+
+      /* pass spaces and separator(s) */
+      while(*line && (ISSPACE(*line) || ISSEP(*line)))
+        line++;
+
+      /* the parameter starts here (unless quoted) */
+      if(*line == '\"') {
+        /* quoted parameter, do the quote dance */
+        line++;
+        param = malloc(strlen(line) + 1); /* parameter */
+        if(!param) {
+          /* out of memory */
+          Curl_safefree(aline);
+          rc = 1;
+          break;
+        }
+        alloced_param = TRUE;
+        (void)unslashquote(line, param);
+      }
+      else {
+        param = line; /* parameter starts here */
+        while(*line && !ISSPACE(*line))
+          line++;
+        *line = '\0'; /* zero terminate */
+      }
+
+      if(param && !*param) {
+        /* do this so getparameter can check for required parameters.
+           Otherwise it always thinks there's a parameter. */
+        if(alloced_param)
+          Curl_safefree(param);
+        param = NULL;
+      }
+
+#ifdef DEBUG_CONFIG
+      fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
+#endif
+      res = getparameter(option, param, &usedarg, config);
+
+      if(param && *param && !usedarg)
+        /* we passed in a parameter that wasn't used! */
+        res = PARAM_GOT_EXTRA_PARAMETER;
+
+      if(res != PARAM_OK) {
+        /* the help request isn't really an error */
+        if(!strcmp(filename, "-")) {
+          filename = (char *)"<stdin>";
+        }
+        if(PARAM_HELP_REQUESTED != res) {
+          const char *reason = param2text(res);
+          warnf(config, "%s:%d: warning: '%s' %s\n",
+                filename, lineno, option, reason);
+        }
+      }
+
+      if(alloced_param)
+        Curl_safefree(param);
+
+      Curl_safefree(aline);
+    }
+    if(file != stdin)
+      fclose(file);
+  }
+  else
+    rc = 1; /* couldn't open the file */
+
+  return rc;
+}
+
+/*
+ * Copies the string from line to the buffer at param, unquoting
+ * backslash-quoted characters and NUL-terminating the output string.
+ * Stops at the first non-backslash-quoted double quote character or the
+ * end of the input string. param must be at least as long as the input
+ * string.  Returns the pointer after the last handled input character.
+ */
+static const char *unslashquote(const char *line, char *param)
+{
+  while(*line && (*line != '\"')) {
+    if(*line == '\\') {
+      char out;
+      line++;
+
+      /* default is to output the letter after the backslash */
+      switch(out = *line) {
+      case '\0':
+        continue; /* this'll break out of the loop */
+      case 't':
+        out = '\t';
+        break;
+      case 'n':
+        out = '\n';
+        break;
+      case 'r':
+        out = '\r';
+        break;
+      case 'v':
+        out = '\v';
+        break;
+      }
+      *param++ = out;
+      line++;
+    }
+    else
+      *param++ = *line++;
+  }
+  *param = '\0'; /* always zero terminate */
+  return line;
+}
+
+/*
+ * Reads a line from the given file, ensuring is NUL terminated.
+ * The pointer must be freed by the caller.
+ * NULL is returned on an out of memory condition.
+ */
+static char *my_get_line(FILE *fp)
+{
+  char buf[4096];
+  char *nl = NULL;
+  char *retval = NULL;
+
+  do {
+    if(NULL == fgets(buf, sizeof(buf), fp))
+      break;
+    if(!retval) {
+      retval = strdup(buf);
+      if(!retval)
+        return NULL;
+    }
+    else {
+      char *ptr;
+      ptr = realloc(retval, strlen(retval) + strlen(buf) + 1);
+      if(!ptr) {
+        Curl_safefree(retval);
+        return NULL;
+      }
+      retval = ptr;
+      strcat(retval, buf);
+    }
+    nl = strchr(retval, '\n');
+  } while(!nl);
+
+  if(nl)
+    *nl = '\0';
+
+  return retval;
+}
+
diff --git a/src/tool_parsecfg.h b/src/tool_parsecfg.h
new file mode 100644 (file)
index 0000000..faa1f19
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_TOOL_PARSECFG_H
+#define HEADER_CURL_TOOL_PARSECFG_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+int parseconfig(const char *filename,
+                struct Configurable *config);
+
+#endif /* HEADER_CURL_TOOL_PARSECFG_H */
+
diff --git a/src/tool_sleep.c b/src/tool_sleep.c
new file mode 100644 (file)
index 0000000..1548d58
--- /dev/null
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+#elif defined(HAVE_POLL_H)
+#  include <poll.h>
+#endif
+
+#ifdef MSDOS
+#  include <dos.h>
+#endif
+
+#include "tool_sleep.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void tool_go_sleep(long ms)
+{
+#if defined(MSDOS)
+  delay(ms);
+#elif defined(WIN32)
+  Sleep(ms);
+#elif defined(HAVE_POLL_FINE)
+  poll((void *)0, 0, (int)ms);
+#else
+  struct timeval timeout;
+  timeout.tv_sec = ms / 1000L;
+  ms = ms % 1000L;
+  timeout.tv_usec = ms * 1000L;
+  select(0, NULL,  NULL, NULL, &timeout);
+#endif
+}
+
diff --git a/src/tool_sleep.h b/src/tool_sleep.h
new file mode 100644 (file)
index 0000000..29655ce
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TOOL_SLEEP_H
+#define HEADER_CURL_TOOL_SLEEP_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "setup.h"
+
+void tool_go_sleep(long ms);
+
+#endif /* HEADER_CURL_TOOL_SLEEP_H */
+
index 38d8a1e..f550d64 100644 (file)
@@ -155,10 +155,6 @@ SOURCE=.\hugehelp.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\main.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\lib\nonblock.c\r
 # End Source File\r
 # Begin Source File\r
@@ -231,10 +227,26 @@ SOURCE=.\tool_formparse.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\tool_getparam.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_help.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_helpers.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\tool_libinfo.c\r
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\tool_main.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\tool_mfiles.c\r
 # End Source File\r
 # Begin Source File\r
@@ -243,7 +255,23 @@ SOURCE=.\tool_msgs.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\tool_myfunc.c\r
+SOURCE=.\tool_operate.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_operhlp.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_panykey.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_paramhlp.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_parsecfg.c\r
 # End Source File\r
 # Begin Source File\r
 \r
@@ -251,6 +279,10 @@ SOURCE=.\tool_setopt.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\tool_sleep.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\tool_vms.c\r
 # End Source File\r
 # Begin Source File\r
@@ -371,10 +403,26 @@ SOURCE=.\tool_formparse.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\tool_getparam.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_help.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_helpers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\tool_libinfo.h\r
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\tool_main.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\tool_mfiles.h\r
 # End Source File\r
 # Begin Source File\r
@@ -383,7 +431,23 @@ SOURCE=.\tool_msgs.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\tool_myfunc.h\r
+SOURCE=.\tool_operate.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_operhlp.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_panykey.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_paramhlp.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\tool_parsecfg.h\r
 # End Source File\r
 # Begin Source File\r
 \r
@@ -395,6 +459,10 @@ SOURCE=.\tool_setopt.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\tool_sleep.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\tool_vms.h\r
 # End Source File\r
 # Begin Source File\r