Skip to content
Snippets Groups Projects
main.c 60.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • Daniel Stenberg's avatar
    Daniel Stenberg committed
    /*****************************************************************************
     *                                  _   _ ____  _     
     *  Project                     ___| | | |  _ \| |    
     *                             / __| | | | |_) | |    
     *                            | (__| |_| |  _ <| |___ 
     *                             \___|\___/|_| \_\_____|
     *
    
     * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * In order to be useful for every potential user, curl and libcurl are
     * dual-licensed under the MPL and the MIT/X-derivate licenses.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * 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 MPL or the MIT/X-derivate
     * licenses. You may pick one of these licenses.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     * KIND, either express or implied.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * $Id$
     *****************************************************************************/
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
    /* This is now designed to have its own local setup.h */
    #include "setup.h"
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdarg.h>
    
    #include <sys/types.h>
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <sys/stat.h>
    #include <ctype.h>
    
    #include <curl/curl.h>
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    #define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <curl/mprintf.h>
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include "urlglob.h"
    
    #include "writeout.h"
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #define CURLseparator	"--_curl_--"
    
    #if defined(WIN32)&&!defined(__CYGWIN32__)
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <winsock.h>
    #endif
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include "version.h"
    
    #ifdef HAVE_IO_H /* typical win32 habit */
    #include <io.h>
    #endif
    
    #ifdef HAVE_UNISTD_H
    #include <unistd.h>
    #endif
    
    
    #ifdef HAVE_FCNTL_H
    #include <fcntl.h>
    #endif
    
    
    /* The last #include file should be: */
    #ifdef MALLOCDEBUG
    /* this is low-level hard-hacking memory leak tracking shit */
    #include "../lib/memdebug.h"
    #endif
    
    
    #define DEFAULT_MAXREDIRS  50L
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifndef __cplusplus        /* (rabe) */
    typedef char bool;
    #endif                     /* (rabe) */
    
    
    #define CURL_PROGRESS_STATS 0 /* default progress display */
    #define CURL_PROGRESS_BAR   1
    
    
    typedef enum {
      HTTPREQ_UNSPEC,
      HTTPREQ_GET,
      HTTPREQ_HEAD,
      HTTPREQ_POST,
      HTTPREQ_SIMPLEPOST,
      HTTPREQ_CUSTOM,
      HTTPREQ_LAST
    } HttpReq;
    
    
    /* Just a set of bits */
    #define CONF_DEFAULT  0
    
    #define CONF_USEREMOTETIME (1<<0) /* set the remote time on the local file */
    
    #define CONF_AUTO_REFERER (1<<4) /* the automatic referer-system please! */
    
    #define CONF_VERBOSE  (1<<5) /* talk a lot */
    #define CONF_HEADER   (1<<8) /* throw the header out too */
    #define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */
    #define CONF_NOBODY   (1<<11) /* use HEAD to get http document */
    #define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
    #define CONF_UPLOAD   (1<<14) /* this is an upload */
    #define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
    #define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
    #define CONF_NETRC    (1<<22)  /* read user+password from .netrc */
    #define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
    
    #define CONF_GETTEXT  (1<<24) /* use ASCII/text for transfer */
    
    #define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */
    
    #define CONF_MUTE     (1<<28) /* force NOPROGRESS */
    
    
    #ifndef HAVE_STRDUP
    /* Ultrix doesn't have strdup(), so make a quick clone: */
    char *strdup(char *str)
    {
      int len;
      char *newstr;
    
      len = strlen(str);
      newstr = (char *) malloc((len+1)*sizeof(char));
      if (!newstr)
        return (char *)NULL;
    
      strcpy(newstr,str);
    
      return newstr;
    
    }
    #endif 
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifdef	VMS
    int	vms_show = 0;
    #define	FAC_CURL	0xC01
    #define	FAC_SYSTEM	0
    #define	MSG_NORMAL	0
    #define	VMS_STS(c,f,e,s) (((c&0xF)<<28)|((f&0xFFF)<<16)|((e&0x1FFF)<3)|(s&7))
    #define	VMSSTS_HIDE	VMS_STS(1,0,0,0)
    #define	SEV_WARNING	0
    #define	SEV_SUCCESS	1
    #define	SEV_ERROR	2
    #define	SEV_INFO	3	/* success, with an extra hint */
    #define	SEV_FATAL	4
    globalvalue int  CURL_UNSUPPROTO;		/* these are from curlmsg.msg file..... */
    globalvalue int  CURL_FAILINIT;
    globalvalue int  CURL_BADURLSYN;
    globalvalue int  CURL_BADURLUSER;
    globalvalue int  CURL_BADPROXY;
    globalvalue int  CURL_BADHOST;
    globalvalue int  CURL_FAILHOST;
    globalvalue int  CURL_FTPUNKREPLY;
    globalvalue int  CURL_FTPNOACC;
    globalvalue int  CURL_FTPUSRPW;
    globalvalue int  CURL_FTPBADPASS;
    globalvalue int  CURL_FTPBADUSER;
    globalvalue int  CURL_FTPBADPASV;
    globalvalue int  CURL_FTPBAD227;
    globalvalue int  CURL_FTPBADHOST227;
    globalvalue int  CURL_FTPNORECONN;
    globalvalue int  CURL_FTPNOBIN;
    globalvalue int  CURL_PARTIALFILE;
    globalvalue int  CURL_FTPNORETR;
    globalvalue int  CURL_FTPWRITERR;
    globalvalue int  CURL_FTPNOQUOTE;
    globalvalue int  CURL_HTTPPNF;
    globalvalue int  CURL_WRITERR;
    globalvalue int  CURL_BADUSER;
    globalvalue int  CURL_FTPNOSTOR;
    globalvalue int  CURL_READERR;
    globalvalue int  CURL_OUTOFMEM;
    globalvalue int  CURL_TIMEOUT;
    globalvalue int  CURL_FTPNOASCII;
    globalvalue int  CURL_FTPNOPORT;
    globalvalue int  CURL_FTPNOREST;
    globalvalue int  CURL_FTPNOSIZE;
    globalvalue int  CURL_HTTPRNGERR;
    globalvalue int  CURL_HTTPPOSTERR;
    globalvalue int  CURL_SSLNOCONN;
    globalvalue int  CURL_FTPBADRESUME;
    globalvalue int  CURL_FILENOACC;
    globalvalue int  CURL_LDAPNOBIND;
    globalvalue int  CURL_LDAPNOSRCH;
    globalvalue int  CURL_LDAPNOLIB;
    globalvalue int  CURL_LDAPNOFUNC;
    globalvalue int  CURL_ABORTCB;
    globalvalue int  CURL_BADPARAM;
    globalvalue int  CURL_BADORDER;
    globalvalue int  CURL_BADPWD;
    globalvalue int  CURL_MNYREDIR;
    long	vms_cond[] = {
    	VMS_STS(1,FAC_SYSTEM,MSG_NORMAL,SEV_SUCCESS),
    	CURL_UNSUPPROTO,		/* these are from curlmsg.msg file..... */
    	CURL_FAILINIT,
    	CURL_BADURLSYN,
    	CURL_BADURLUSER,
    	CURL_BADPROXY,
    	CURL_BADHOST,
    	CURL_FAILHOST,
    	CURL_FTPUNKREPLY,
    	CURL_FTPNOACC,
    	CURL_FTPUSRPW,
    	CURL_FTPBADPASS,
    	CURL_FTPBADUSER,
    	CURL_FTPBADPASV,
    	CURL_FTPBAD227,
    	CURL_FTPBADHOST227,
    	CURL_FTPNORECONN,
    	CURL_FTPNOBIN,
    	CURL_PARTIALFILE,
    	CURL_FTPNORETR,
    	CURL_FTPWRITERR,
    	CURL_FTPNOQUOTE,
    	CURL_HTTPPNF,
    	CURL_WRITERR,
    	CURL_BADUSER,
    	CURL_FTPNOSTOR,
    	CURL_READERR,
    	CURL_OUTOFMEM,
    	CURL_TIMEOUT,
    	CURL_FTPNOASCII,
    	CURL_FTPNOPORT,
    	CURL_FTPNOREST,
    	CURL_FTPNOSIZE,
    	CURL_HTTPRNGERR,
    	CURL_HTTPPOSTERR,
    	CURL_SSLNOCONN,
    	CURL_FTPBADRESUME,
    	CURL_FILENOACC,
    	CURL_LDAPNOBIND,
    	CURL_LDAPNOSRCH,
    	CURL_LDAPNOLIB,
    	CURL_LDAPNOFUNC,
    	CURL_ABORTCB,
    	CURL_BADPARAM,
    	CURL_BADORDER,
    	CURL_BADPWD,
    	CURL_MNYREDIR
    };
    #endif
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    extern void hugehelp(void);
    
    
    /*
     * 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)
    
      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)
    {
    
    int SetHTTPrequest(HttpReq req, HttpReq *store)
    {
      if((*store == HTTPREQ_UNSPEC) ||
         (*store == req)) {
        *store = req;
    
      }
      fprintf(stderr, "You can only select one HTTP request!\n");
    
    static void helpf(const char *fmt, ...)
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    {
      va_list ap;
      if(fmt) {
        va_start(ap, fmt);
        fputs("curl: ", stderr); /* prefix it */
        vfprintf(stderr, fmt, ap);
        va_end(ap);
      }
      fprintf(stderr, "curl: try 'curl --help' for more information\n");
    }
    
    
    /*
     * A chain of these nodes contain URL to get and where to put the URL's
     * contents.
     */
    struct getout {
      struct getout *next;
      char *url;
      char *outfile;
      int flags;
    };
    #define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
    #define GETOUT_URL     (1<<1) /* set when URL is deemed done */
    #define GETOUT_USEREMOTE (1<<2) /* use remote file name locally */
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    static void help(void)
    {
      printf(CURL_ID "%s\n"
           "Usage: curl [options...] <url>\n"
           "Options: (H) means HTTP/HTTPS only, (F) means FTP only\n"
           " -a/--append        Append to target file when uploading (F)\n"
           " -A/--user-agent <string> User-Agent to send to server (H)\n"
           " -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)\n"
    
           " -B/--use-ascii     Use ASCII/text transfer\n",
             curl_version());
      puts(" -C/--continue-at <offset> Specify absolute resume offset\n"
    
           " -d/--data <data>   HTTP POST data (H)\n"
           "    --data-ascii <data>   HTTP POST ASCII data (H)\n"
           "    --data-binary <data>  HTTP POST binary data (H)\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -D/--dump-header <file> Write the headers to this file\n"
    
           "    --egd-file <file> EGD socket path for random data (SSL)\n"
    
           " -e/--referer       Referer page (H)");
      puts(" -E/--cert <cert[:passwd]> Specifies your certificate file and password (HTTPS)\n"
    
           "    --cacert <file> CA certifciate to verify peer against (HTTPS)\n"
    
           "    --connect-timeout <seconds> Maximum time allowed for connection\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -f/--fail          Fail silently (no output at all) on errors (H)\n"
           " -F/--form <name=content> Specify HTTP POST data (H)\n"
    
           " -g/--globoff       Disable URL sequences and ranges using {} and []\n"
    
           " -G/--get           Send the -d data with a HTTP GET (H)\n");
      puts(" -h/--help          This help text\n"
           " -H/--header <line> Custom header to pass to server. (H)"
           " -i/--include       Include the HTTP-header in the output (H)\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -I/--head          Fetch document info only (HTTP HEAD/FTP SIZE)\n"
    
           "    --interface <interface> Specify the interface to be used\n"
    
           "    --krb4 <level>  Enable krb4 with specified security level (F)\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -K/--config        Specify which config file to read\n"
    
           " -l/--list-only     List only names of an FTP directory (F)");
      puts(" -L/--location      Follow Location: hints (H)\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -m/--max-time <seconds> Maximum time allowed for the transfer\n"
           " -M/--manual        Display huge help text\n"
           " -n/--netrc         Read .netrc for user name and password\n"
    
           " -N/--no-buffer     Disables the buffering of the output stream");
      puts(" -o/--output <file> Write output to <file> instead of stdout\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -O/--remote-name   Write output to a file named as the remote file\n"
    
           " -p/--proxytunnel   Perform non-HTTP services through a HTTP proxy\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -P/--ftpport <address> Use PORT with address instead of PASV when ftping (F)\n"
           " -q                 When used as the first parameter disables .curlrc\n"
    
           " -Q/--quote <cmd>   Send QUOTE command to FTP before file transfer (F)");
      puts(" -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -s/--silent        Silent mode. Don't output anything\n"
           " -S/--show-error    Show error. With -s, make curl show errors when they occur\n"
    
           "    --stderr <file> Where to redirect stderr. - means stdout.\n"
    
           " -t/--telnet-option <OPT=val> Set telnet option\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -T/--upload-file <file> Transfer/upload <file> to remote site\n"
    
           "    --url <URL>     Another way to specify URL to work with");
      puts(" -u/--user <user[:password]> Specify user and password to use\n"
    
           " -U/--proxy-user <user[:password]> Specify Proxy authentication\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -v/--verbose       Makes the operation more talkative\n"
           " -V/--version       Outputs version number then quits\n"
    
           " -w/--write-out [format] What to output after completion\n"
    
           " -x/--proxy <host[:port]>  Use proxy. (Default port is 1080)\n"
    
           "    --random-file <file> File to use for reading random data from (SSL)\n"
    
           " -X/--request <command> Specific request command to use");
      puts(" -y/--speed-time    Time needed to trig speed-limit abort. Defaults to 30\n"
    
           " -Y/--speed-limit   Stop transfer if below speed-limit for 'speed-time' secs\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -z/--time-cond <time> Includes a time condition to the server (H)\n"
    
           " -Z/--max-redirs <num> Set maximum number of redirections allowed (H)\n"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
           " -2/--sslv2         Force usage of SSLv2 (H)\n"
    
           " -3/--sslv3         Force usage of SSLv3 (H)");
      puts(" -#/--progress-bar  Display transfer progress as a progress bar\n"
    
           "    --crlf          Convert LF to CRLF in upload. Useful for MVS (OS/390)");
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    }
    
    struct LongShort {
    
      const char *letter;
      const char *lname;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      bool extraparam;
    };
    
    struct Configurable {
    
      char *random_file;
      char *egd_file;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      char *useragent;
      char *cookie;
      bool use_resume;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      int resume_from;
      char *postfields;
    
      long postfieldsize;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      char *referer;
      long timeout;
    
      long connecttimeout;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      char *headerfile;
      char *ftpport;
    
      char *iface;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      unsigned short porttouse;
      char *range;
      int low_speed_limit;
      int low_speed_time;
      bool showerror;
      char *infile;
      char *userpwd;
      char *proxyuserpwd;
      char *proxy;
      bool configread;
    
      bool proxytunnel;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      long conf;
    
    
      struct getout *url_list; /* point to the first node */
      struct getout *url_last; /* point to the last/current node */
    
      struct getout *url_get;  /* point to the node to fill in URL */
      struct getout *url_out;  /* point to the node to fill in outfile */
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      char *cert;
    
      char *cacert;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      char *cert_passwd;
      bool crlf;
      char *cookiefile;
      char *customrequest;
    
      char *krb4level;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      bool progressmode;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
      char *writeout; /* %-styled format string to output */
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      FILE *errors; /* if stderr redirect is requested */
    
      struct curl_slist *quote;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      struct curl_slist *postquote;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      long ssl_version;
      TimeCond timecond;
      time_t condtime;
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      struct HttpPost *httppost;
      struct HttpPost *last_post;
    
      struct curl_slist *telnet_options;
            
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    };
    
    static int parseconfig(char *filename,
    		       struct Configurable *config);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    static void GetStr(char **string,
    		   char *value)
    {
      if(*string)
        free(*string);
    
      if(value && *value)
        *string = strdup(value);
      else
        *string = NULL;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    }
    
    static char *file2string(FILE *file)
    {
      char buffer[256];
      char *ptr;
      char *string=NULL;
      int len=0;
      int stringlen;
    
      if(file) {
        while(fgets(buffer, sizeof(buffer), file)) {
          ptr= strchr(buffer, '\r');
          if(ptr)
            *ptr=0;
          ptr= strchr(buffer, '\n');
          if(ptr)
            *ptr=0;
          stringlen=strlen(buffer);
          if(string)
            string = realloc(string, len+stringlen+1);
          else
            string = malloc(stringlen+1);
    
          strcpy(string+len, buffer);
    
          len+=stringlen;
        }
        return string;
      }
      else
        return NULL; /* no string */
    }
    
    
    static char *file2memory(FILE *file, long *size)
    {
      char buffer[1024];
      char *string=NULL;
      char *newstring=NULL;
      long len=0;
      long stringlen=0;
    
      if(file) {
    
        while((len = fread(buffer, 1, sizeof(buffer), file))) {
    
          if(string) {
            newstring = realloc(string, len+stringlen);
            if(newstring)
              string = newstring;
            else
              break; /* no more strings attached! :-) */
          }
          else
            string = malloc(len);
          memcpy(&string[stringlen], buffer, len);
          stringlen+=len;
        }
        *size = stringlen;
        return string;
      }
      else
        return NULL; /* no string */
    }
    
    
    void clean_getout(struct Configurable *config)
    {
      struct getout *node=config->url_list;
      struct getout *next;
    
      while(node) {
        next = node->next;
        if(node->url)
          free(node->url);
        if(node->outfile)
          free(node->outfile);
        free(node);
    
        node = next; /* GOTO next */
      }
    }
    
    
    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;
      }
      return node;
    }
    
    
    
    
    
    typedef enum {
      PARAM_OK,
      PARAM_OPTION_AMBIGUOUS,
      PARAM_OPTION_UNKNOWN,
      PARAM_REQUIRES_PARAMETER,  
      PARAM_BAD_USE,
      PARAM_HELP_REQUESTED,
      PARAM_GOT_EXTRA_PARAMETER,
    
      PARAM_LAST
    } ParameterError;
    
    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)
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    {
      char letter;
    
      char subletter=0; /* subletters can only occur on long options */
    
    
      const char *parse=NULL;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      int res;
    
      unsigned int j;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      time_t now;
      int hit=-1;
    
      bool longopt=FALSE;
    
      bool singleopt=FALSE; /* when true means '-o foo' used '-ofoo' */
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      /* single-letter,
         long-name,
         boolean whether it takes an additional argument
         */
      struct LongShort aliases[]= {
        {"9", "crlf",        FALSE},
        {"8", "stderr",      TRUE},
    
        {"7", "interface",   TRUE},
    
        {"6", "krb4",        TRUE},
    
        {"5a", "random-file", TRUE},
        {"5b", "egd-file",   TRUE},
    
        {"5c", "connect-timeout", TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
        {"2", "sslv2",       FALSE},
        {"3", "sslv3",       FALSE},
        {"a", "append",      FALSE},
        {"A", "user-agent",  TRUE},
        {"b", "cookie",      TRUE},
    
        {"B", "ftp-ascii",   FALSE}, /* this long format is OBSOLETE now! */
    
        {"B", "use-ascii",   FALSE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"c", "continue",    FALSE},
        {"C", "continue-at", TRUE},
        {"d", "data",        TRUE},
    
        {"da", "data-ascii", TRUE},
        {"db", "data-binary", TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"D", "dump-header", TRUE},
        {"e", "referer",     TRUE},
        {"E", "cert",        TRUE},
    
        {"Ea", "cacert",     TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"f", "fail",        FALSE},
        {"F", "form",        TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"h", "help",        FALSE},
        {"H", "header",      TRUE},
        {"i", "include",     FALSE},
        {"I", "head",        FALSE},
        {"K", "config",      TRUE},
        {"l", "list-only",   FALSE},
        {"L", "location",    FALSE},
        {"m", "max-time",    TRUE},
        {"M", "manual",      FALSE},
        {"n", "netrc",       FALSE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"o", "output",      TRUE},
        {"O", "remote-name", FALSE},
    
        {"p", "proxytunnel", FALSE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"P", "ftpport",     TRUE},
        {"q", "disable",     FALSE},
        {"Q", "quote",       TRUE},
        {"r", "range",       TRUE},
        {"s", "silent",      FALSE},
        {"S", "show-error",  FALSE},
    
        {"t", "telnet-options", TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"T", "upload-file", TRUE},
        {"u", "user",        TRUE},
        {"U", "proxy-user",  TRUE},
        {"v", "verbose",     FALSE},
        {"V", "version",     FALSE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"x", "proxy",       TRUE},
        {"X", "request",     TRUE},
        {"X", "http-request", TRUE}, /* OBSOLETE VERSION */
    
        {"Y", "speed-limit",  TRUE},
        {"y", "speed-time", TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"z", "time-cond",   TRUE},
    
        {"Z", "max-redirs",   TRUE},
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        {"#", "progress-bar",FALSE},
      };
    
    
      if(('-' != flag[0]) ||
         (('-' == flag[0]) && ('-' == flag[1]))) {
        /* this should be a long name */
        char *word=('-' == flag[0])?flag+2:flag;
        int fnam=strlen(word);
    
        int numhits=0;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
    
          if(strnequal(aliases[j].lname, word, fnam)) {
    
            longopt = TRUE;
    
            numhits++;
    
            if(strequal(aliases[j].lname, word)) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
              parse = aliases[j].letter;
              hit = j;
    
              numhits = 1; /* a single unique hit */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
              break;
            }
    	parse = aliases[j].letter;
    	hit = j;
          }
        }
    
        if(numhits>1) {
          /* this is at least the second match! */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        if(hit < 0) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }    
      }
      else {
    
        flag++; /* prefixed with one dash, pass it */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        hit=-1;
        parse = flag;
      }
    
      do {
        /* we can loop here if we have multiple single-letters */
    
    
        if(!longopt)
          letter = parse?*parse:'\0';
        else {
          letter = parse[0];
          subletter = parse[1];
        }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        *usedarg = FALSE; /* default is that we don't use the arg */
    
    #if 0
        fprintf(stderr, "OPTION: %c %s\n", letter, nextarg?nextarg:"<null>");
    #endif
        if(hit < 0) {
          for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
    
    	if(letter == aliases[j].letter[0]) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    	  hit = j;
    	  break;
    	}
          }
          if(hit < 0) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
        }
        if(hit < 0) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }    
    
        if(!longopt && aliases[hit].extraparam && parse[1]) {
    
          nextarg=(char *)&parse[1]; /* this is the actual extra parameter */
    
          singleopt=TRUE;   /* don't loop anymore after this */
        }
        else if((!nextarg || !*nextarg) && aliases[hit].extraparam) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }
        else if(nextarg && aliases[hit].extraparam)
          *usedarg = TRUE; /* mark it as used */
    
        switch(letter) {
        case '9': /* there is no short letter for this */
          /* LF -> CRLF conversinon? */
          config->crlf = TRUE;
          break;
        case '8': /* there is no short letter for this */
          if(strcmp(nextarg, "-"))
            config->errors = fopen(nextarg, "wt");
          else
            config->errors = stdout;
          break;
    
        case '7': /* there is no short letter for this */
          /* interface */
    
          GetStr(&config->iface, nextarg);
          break;
        case '6': /* there is no short letter for this */
          /* krb4 level string */
          GetStr(&config->krb4level, nextarg);
          break;
    
          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 */
            config->connecttimeout=atoi(nextarg);
            break;
    
          default: /* the URL! */
            {
              struct getout *url;
              if(config->url_get || (config->url_get=config->url_list)) {
                /* 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;
              }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        case '#': /* added 19990617 larsa */
          config->progressmode ^= CURL_PROGRESS_BAR;
          break;
        case '2': 
          /* SSL version 2 */
          config->ssl_version = 2;
          break;
        case '3': 
          /* SSL version 2 */
          config->ssl_version = 3;
          break;
        case 'a':
          /* This makes the FTP sessions use APPE instead of STOR */
          config->conf ^= CONF_FTPAPPEND;
          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, '=')) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
            /* A cookie string must have a =-letter */
            GetStr(&config->cookie, nextarg);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
    
          /* We have a cookie file to read from! */
          GetStr(&config->cookiefile, nextarg);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
        case 'B':
    
          /* use ASCII/text when transfering */
          config->conf ^= CONF_GETTEXT;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
        case 'c':
          /* This makes us continue an ftp transfer */
          config->use_resume^=TRUE;
    
          fprintf(stderr, "-c is a deprecated switch, use '-C -' instead!\n");
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
        case 'C':
          /* This makes us continue an ftp transfer at given position */
    
            config->resume_from= atoi(nextarg);
    
            config->resume_from_current = FALSE;
          }
          else {
            config->resume_from_current = TRUE;
            config->resume_from = 0;
          }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          config->use_resume=TRUE;
          break;
        case 'd':
          /* postfield data */
    
          {
            char *postdata=NULL;
    
            if('@' == *nextarg) {
              /* the data begins with a '@' letter, it means that a file name
                 or - (stdin) follows */
              FILE *file;
    
              nextarg++; /* pass the @ */
    
              if(strequal("-", nextarg))
                file = stdin;
              else 
                file = fopen(nextarg, "r");
    
              if(subletter == 'b') /* forced binary */
                postdata = file2memory(file, &config->postfieldsize);
              else
                postdata = file2string(file);
              if(file && (file != stdin))
                fclose(stdin);
            }
            else {
              GetStr(&postdata, nextarg);
            }
    
            if(config->postfields && *config->postfields) {
              /* we already have a string, we append this one
                 with a separating &-letter */
              char *oldpost=config->postfields;
    
              config->postfields=aprintf("%s&%s", oldpost, postdata);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
    
    /*      if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
            return PARAM_BAD_USE;*/
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          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->conf |= CONF_AUTO_REFERER;
              *ptr = 0; /* zero terminate here */
            }
            GetStr(&config->referer, nextarg);
          }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
        case 'E':
    
          if(subletter == 'a') {
            /* CA info PEM file */
            GetStr(&config->cacert, nextarg);
          }
          else {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    	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] == '\\') &&
               (isalpha((int)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) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    	  /* we have a password too */
    	  *ptr=0;
    	  ptr++;
    	  GetStr(&config->cert_passwd, ptr);
    	}
    	GetStr(&config->cert, nextarg);
          }
          break;
        case 'f':
          /* fail hard on errors  */
          config->conf ^= CONF_FAILONERROR;
          break;
        case 'F':
          /* "form data" simulation, this is a little advanced so lets do our best
    	 to sort this out slowly and carefully */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
                            &config->httppost,
                            &config->last_post))
    
          if(SetHTTPrequest(HTTPREQ_POST, &config->httpreq))
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
    
    
        case 'g': /* g disables URLglobbing */
          config->globoff ^= TRUE;
          break;
    
    
        case 'G': /* HTTP GET */
          config->use_httpget = TRUE;
          break;
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        case 'h': /* h for help */
          help();
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        case 'H':
    
          /* A custom header to append to a list */
          config->headers = curl_slist_append(config->headers, nextarg);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
        case 'i':
          config->conf ^= CONF_HEADER; /* include the HTTP header as well */
          break;
        case 'I':
          config->conf ^= CONF_HEADER; /* include the HTTP header in the output */
          config->conf ^= CONF_NOBODY; /* don't fetch the body at all */
    
          if(SetHTTPrequest(HTTPREQ_HEAD, &config->httpreq))
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          break;
        case 'K':
          res = parseconfig(nextarg, config);
          config->configread = TRUE;
          if(res)
    	return res;
          break;
        case 'l':
          config->conf ^= CONF_FTPLISTONLY; /* only list the names of the FTP dir */
          break;
        case 'L':
          config->conf ^= CONF_FOLLOWLOCATION; /* Follow Location: HTTP headers */
          break;
        case 'm':
          /* specified max time */
          config->timeout = atoi(nextarg);
          break;
        case 'M': /* M for manual, huge help */
          hugehelp();
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        case 'n':
          /* pick info from .netrc, if this is used for http, curl will
    	 automatically enfore user+password with the request */
          config->conf ^= CONF_NETRC;
          break;
    
        case 'N':
          /* disable the output I/O buffering */
          config->nobuffer ^= 1;
          break;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        case 'o':
        case 'O':
          /* output file */
    
          {
            struct getout *url;
            if(config->url_out || (config->url_out=config->url_list)) {
              /* there's a node here, if it already is filled-in continue to find
                 an "empty" node */