Skip to content
Snippets Groups Projects
main.c 50.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •     char *aline;
        char *option;
        char *param;
        int lineno=0;
        bool alloced_param;
    
    #define isseparator(x) (((x)=='=') || ((x) == ':'))
    
        while (NULL != (aline = my_get_line(file))) {
          lineno++;
          line = aline;
          alloced_param=FALSE;
    
    
          /* lines with # in the fist column is a comment! */
    
          while(isspace((int)*line))
    
            line++;
    
          switch(*line) {
          case '#':
          case '/':
          case '\r':
          case '\n':
          case '*':
          case '\0':
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
          /* the option keywords starts here */
          option = line;
    
          while(*line && !isspace((int)*line) && !isseparator(*line))
    
            line++;
          /* ... and has ended here */
    
          *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(isspace((int)*line) || isseparator(*line))
    
            line++;
          
          /* the parameter starts here (unless quoted) */
          if(*line == '\"') {
            char *ptr;
            /* quoted parameter, do the qoute dance */
            line++;
            param=strdup(line); /* parameter */
            alloced_param=TRUE;
    
            ptr=param;
            while(*line && (*line != '\"')) {
              if(*line == '\\') {
    
    
                /* default is to output the letter after the backslah */
                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';
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
    
          else {
            param=line; /* parameter starts here */
    
            while(*line && !isspace((int)*line))
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
    
    #ifdef DEBUG_CONFIG
          fprintf(stderr, "PARAM: \"%s\"\n", param);
    #endif
          res = getparameter(option, param, &usedarg, config);
    
          if(*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="<stdin>";
            }
            if(PARAM_HELP_REQUESTED != res) {
              char *reason;
              switch(res) {
              default:
              case PARAM_GOT_EXTRA_PARAMETER:
                reason = "had unsupported trailing garbage";
                break;
              case PARAM_OPTION_UNKNOWN:
                reason = "is unknown";
                break;
              case PARAM_OPTION_AMBIGUOUS:
                reason = "is ambiguous";
                break;
              case PARAM_REQUIRES_PARAMETER:
                reason = "requires parameter";
                break;
              case PARAM_BAD_USE:
                reason = "is badly used here";
    
              fprintf(stderr, "%s:%d: warning: '%s' %s\n",
                      filename, lineno, option, reason);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }
        if(file != stdin)
          fclose(file);
      }
    
      if(home)
        free(home);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    }
    
    struct OutStruct {
      char *filename;
      FILE *stream;
    
      struct Configurable *config;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    };
    
    int my_fwrite(void *buffer, size_t size, size_t nmemb, FILE *stream)
    {
      struct OutStruct *out=(struct OutStruct *)stream;
      if(out && !out->stream) {
        /* open file for writing */
        out->stream=fopen(out->filename, "wb");
        if(!out->stream)
          return -1; /* failure */
    
        if(out->config->nobuffer) {
    
          /* disable output buffering */
    #ifdef HAVE_SETVBUF
          setvbuf(out->stream, NULL, _IONBF, 0);
    #endif
        }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      }
      return fwrite(buffer, size, nmemb, out->stream);
    }
    
    
    struct ProgressData {
      size_t total;
      size_t prev;
      size_t point;
      int width;
    };
    
    int myprogress (void *clientp,
                    size_t dltotal,
                    size_t dlnow,
                    size_t ultotal,
                    size_t ulnow)
    {
      /* The original progress-bar source code was written for curl by Lars Aas,
         and this new edition inherites some of his concepts. */
      
      char line[256];
      char outline[256];
      char format[40];
      float frac;
      float percent;
      int barwidth;
      int num;
      int i;
    
      struct ProgressData *bar = (struct ProgressData *)clientp;
      size_t total = dltotal + ultotal;
    
      bar->point = dlnow + ulnow; /* we've come this far */
    
      if(0 == total) {
        int prevblock = bar->prev / 1024;
        int thisblock = bar->point / 1024;
        while ( thisblock > prevblock ) {
          fprintf( stderr, "#" );
          prevblock++;
        }
      }
      else {
        frac = (float) bar->point / (float) total;
        percent = frac * 100.0f;
        barwidth = bar->width - 7;
        num = (int) (((float)barwidth) * frac);
        i = 0;
        for ( i = 0; i < num; i++ ) {
          line[i] = '#';
        }
        line[i] = '\0';
        sprintf( format, "%%-%ds %%5.1f%%%%", barwidth );
        sprintf( outline, format, line, percent );
        fprintf( stderr, "\r%s", outline );
      }
      bar->prev = bar->point;
    
      return 0;
    }
    
    void progressbarinit(struct ProgressData *bar)
    {
    #ifdef __EMX__
      /* 20000318 mgs */
      int scr_size [2];
    #endif
      char *colp;
    
      memset(bar, 0, sizeof(struct ProgressData));
    
    /* TODO: get terminal width through ansi escapes or something similar.
             try to update width when xterm is resized... - 19990617 larsa */
    #ifndef __EMX__
      /* 20000318 mgs
       * OS/2 users most likely won't have this env var set, and besides that
       * we're using our own way to determine screen width */
      colp = curl_getenv("COLUMNS");
      if (colp != NULL) {
        bar->width = atoi(colp);
        free(colp);
      }
      else
        bar->width = 79;
    #else
      /* 20000318 mgs
       * We use this emx library call to get the screen width, and subtract
       * one from what we got in order to avoid a problem with the cursor
       * advancing to the next line if we print a string that is as long as
       * the screen is wide. */
     
      _scrsize(scr_size);
      bar->width = scr_size[0] - 1;
    #endif
    
    }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
    void free_config_fields(struct Configurable *config)
    
      if(config->url)
        free(config->url);
      if(config->userpwd)
        free(config->userpwd);
      if(config->postfields)
        free(config->postfields);
      if(config->proxy)
        free(config->proxy);
      if(config->proxyuserpwd)
        free(config->proxyuserpwd);
      if(config->cookie)
        free(config->cookie);
      if(config->cookiefile)
        free(config->cookiefile);
      if(config->krb4level)
        free(config->krb4level);
      if(config->headerfile)
        free(config->headerfile);
      if(config->outfile)
        free(config->outfile);
      if(config->ftpport)
        free(config->ftpport);
      if(config->infile)
        free(config->infile);
      if(config->range)
        free(config->range);
      if(config->customrequest)
        free(config->customrequest);
      if(config->writeout)
        free(config->writeout);
      if(config->httppost)
        curl_formfree(config->httppost);
      if(config->cacert)
        free(config->cacert);
    
      curl_slist_free_all(config->quote); /* checks for config->quote == NULL */
      curl_slist_free_all(config->postquote); /*  */
      curl_slist_free_all(config->headers); /*  */
    
    operate(struct Configurable *config, int argc, char *argv[])
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    {
    
      char errorbuffer[CURL_ERROR_SIZE];
    
      char useragent[128]; /* buah, we don't want a larger default user agent */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      struct OutStruct outs;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      char *url = NULL;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      URLGlob *urls;
      int urlnum;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      int separator = 0;
      
      FILE *infd = stdin;
      FILE *headerfilep = NULL;
      char *urlbuffer=NULL;
      int infilesize=-1; /* -1 means unknown */
      bool stillflags=TRUE;
    
    
      bool allocuseragent=FALSE;
    
    
      CURL *curl;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      int i;
    
      outs.stream = stdout;
    
      outs.config = config;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
    #ifdef MALLOCDEBUG
      /* this sends all memory debug messages to a logfile named memdump */
      curl_memdebug("memdump");
    #endif
    
    
      config->showerror=TRUE;
      config->conf=CONF_DEFAULT;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #if 0
    
      config->crlf=FALSE;
      config->quote=NULL;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #endif
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      if(argc>1 &&
         (!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!
         */
    #if 0
        fprintf(stderr, "I TURNED OFF THE CRAP\n");
    #endif
        ;
      }
      else {
    
        res = parseconfig(NULL, config);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        if(res)
          return res;
      }
    
    
      if ((argc < 2)  && !config->url) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        helpf(NULL);
    
        return CURLE_FAILED_INIT;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      }
    
      /* Parse options */
      for (i = 1; i < argc; i++) {
        if(stillflags &&
           ('-' == argv[i][0])) {
          char *nextarg;
          bool passarg;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
          if(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) {
              switch(res) {
              case PARAM_OPTION_AMBIGUOUS:
                helpf("option %s is ambiguous\n", origopt);
                break;
              case PARAM_OPTION_UNKNOWN:
                helpf("option %s is unknown\n", origopt);
                break;
              case PARAM_REQUIRES_PARAMETER:
                helpf("option %s requires an extra argument!\n", origopt);
                break;
              case PARAM_BAD_USE:
                helpf("option %s was wrongly used!\n", origopt);
                break;
              case PARAM_HELP_REQUESTED:
                /* no text */
                break;
              }
    	  return CURLE_FAILED_INIT;
            }
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    	if(passarg) /* we're supposed to skip this */
    	  i++;
          }
        }
        else {
          if(url) {
    	helpf("only one URL is supported!\n");
    
    	return CURLE_FAILED_INIT;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
          url = argv[i];
        }
      }
    
      /* if no URL was specified and there was one in the config file, get that
         one */
    
      if(!url && config->url)
        url = config->url;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      
      if(!url) {
        helpf("no URL specified!\n");
    
        return CURLE_FAILED_INIT;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      }
    
      if(NULL == config->useragent) {
    
        /* set non-zero default values: */
        snprintf(useragent, sizeof(useragent),
                 CURL_NAME "/" CURL_VERSION " (" OS ") " "%s", curl_version());
    
        config->useragent= useragent;
    
      else
        allocuseragent = TRUE;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #if 0
    
      fprintf(stderr, "URL: %s PROXY: %s\n", url, config->proxy?config->proxy:"none");
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #endif
    
    
      /* expand '{...}' and '[...]' expressions and return total number of URLs
         in pattern set */
      res = glob_url(&urls, url, &urlnum);
    
      if(res != CURLE_OK)
    
      /* save outfile pattern befor expansion */
    
      outfiles = config->outfile?strdup(config->outfile):NULL;
    
      if (!outfiles && !config->remotefile && urlnum > 1) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifdef CURL_SEPARATORS
        /* multiple files extracted to stdout, insert separators! */
        separator = 1;
    #endif
    #ifdef MIME_SEPARATORS
        /* multiple files extracted to stdout, insert MIME separators! */
        separator = 1;
        printf("MIME-Version: 1.0\n");
        printf("Content-Type: multipart/mixed; boundary=%s\n\n", MIMEseparator);
    #endif
      }
      for (i = 0; (url = next_url(urls)); ++i) {
    
        if (outfiles) {
    
          free(config->outfile);
          config->outfile = outfiles;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     
    
        if (config->outfile || config->remotefile) {
    
          /* 
           * We have specified a file name to store the result in, or we have
           * decided we want to use the remote file name.
           */
          
    
          if(!config->outfile && config->remotefile) {
    
            /* Find and get the remote file name */
    
            config->outfile=strstr(url, "://");
            if(config->outfile)
              config->outfile+=3;
    
              config->outfile=url;
            config->outfile = strdup(strrchr(config->outfile, '/'));
            if(!config->outfile || !strlen(++config->outfile)) {
    
              helpf("Remote file name has no length!\n");
              return CURLE_WRITE_ERROR;
            }
          }
          else {
    	/* fill '#1' ... '#9' terms from URL pattern */
    
            char *outfile = config->outfile;
            config->outfile = match_url(config->outfile, *urls);
    
          if((0 == config->resume_from) && config->use_resume) {
    
            /* we're told to continue where we are now, then we get the size of the
               file as it is now and open it for append instead */
            struct stat fileinfo;
    
    
            if(0 == stat(config->outfile, &fileinfo)) {
    
              /* set offset to current file size: */
    
              config->resume_from = fileinfo.st_size;
    
            }
            /* else let offset remain 0 */
          }
          
    
          if(config->resume_from) {
    
            /* open file for output: */
    
            outs.stream=(FILE *) fopen(config->outfile, config->resume_from?"ab":"wb");
    
            if (!outs.stream) {
    
              helpf("Can't open '%s'!\n", config->outfile);
    
              return CURLE_WRITE_ERROR;
            }
          }
          else {
    
            outs.filename = config->outfile;
    
            outs.stream = NULL; /* open when needed */
    
        if (config->infile) {
    
          /*
           * We have specified a file to upload
           */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          struct stat fileinfo;
    
    
          /* 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.*/
    
    
            urlbuffer=(char *)malloc(strlen(url) + strlen(config->infile) + 3);
    
            if(!urlbuffer) {
              helpf("out of memory\n");
              return CURLE_OUT_OF_MEMORY;
            }
            if(ptr)
              /* there is a trailing slash on the URL */
    
              sprintf(urlbuffer, "%s%s", url, config->infile);
    
            else
              /* thers is no trailing slash on the URL */
    
              sprintf(urlbuffer, "%s/%s", url, config->infile);
    
            
            url = urlbuffer; /* use our new URL instead! */
    
          infd=(FILE *) fopen(config->infile, "rb");
          if (!infd || stat(config->infile, &fileinfo)) {
            helpf("Can't open '%s'!\n", config->infile);
    
            return CURLE_READ_ERROR;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
    
          infilesize=fileinfo.st_size;
          
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }
    
        if((config->conf&CONF_UPLOAD) &&
           config->use_resume &&
           (0==config->resume_from)) {
          config->resume_from = -1; /* -1 will then force get-it-yourself */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }
    
        if(config->headerfile) {
    
          /* open file for output: */
    
          if(strcmp(config->headerfile,"-")) {
            heads.filename = config->headerfile;
    
            headerfilep=NULL;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          }
          else
    
            headerfilep=stdout;
          heads.stream = headerfilep;
    
          heads.config = config;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        }
    
        
        if(outs.stream && isatty(fileno(outs.stream)) &&
    
           !(config->conf&(CONF_UPLOAD|CONF_HTTPPOST)))
    
          /* we send the output to a tty and it isn't an upload operation,
             therefore we switch off the progress meter */
    
          config->conf |= CONF_NOPROGRESS;
    
        if (urlnum > 1) {
          fprintf(stderr, "\n[%d/%d]: %s --> %s\n",
    
                  i+1, urlnum, url, config->outfile ? config->outfile : "<stdout>");
    
          if (separator) {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifdef CURL_SEPARATORS
    
            printf("%s%s\n", CURLseparator, url);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #endif
    #ifdef MIME_SEPARATORS
    
            printf("--%s\n", MIMEseparator);
            printf("Content-ID: %s\n\n", url); 
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #endif
    
        if(!config->errors)
          config->errors = stderr;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
        if(!config->outfile && !(config->conf & CONF_GETTEXT)) {
    
          /* We get the output to stdout and we have not got the ASCII/text flag,
             then set stdout to be binary */
          setmode( 1, O_BINARY );
    
        main_init();
    
        /* The new, v7-style easy-interface! */
        curl = curl_easy_init();
        if(curl) {
          curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
          /* what call to write: */
          curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
          curl_easy_setopt(curl, CURLOPT_INFILE, infd); /* for uploads */
          /* size of uploaded file: */
          curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);
          curl_easy_setopt(curl, CURLOPT_URL, url);     /* what to fetch */
    
          curl_easy_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
          curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE);
          curl_easy_setopt(curl, CURLOPT_HEADER, config->conf&CONF_HEADER);
          curl_easy_setopt(curl, CURLOPT_NOPROGRESS, config->conf&CONF_NOPROGRESS);
          curl_easy_setopt(curl, CURLOPT_NOBODY, config->conf&CONF_NOBODY);
    
          curl_easy_setopt(curl, CURLOPT_FAILONERROR,
    
                           config->conf&CONF_FAILONERROR);
          curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD);
          curl_easy_setopt(curl, CURLOPT_POST, config->conf&CONF_POST);
    
          curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
    
                           config->conf&CONF_FTPLISTONLY);
          curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
          curl_easy_setopt(curl, CURLOPT_NETRC, config->conf&CONF_NETRC);
    
          curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
    
                           config->conf&CONF_FOLLOWLOCATION);
          curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
          curl_easy_setopt(curl, CURLOPT_PUT, config->conf&CONF_PUT);
          curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
          curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
          curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
          curl_easy_setopt(curl, CURLOPT_RANGE, config->range);
    
          curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
    
          curl_easy_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
          curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config->postfields);
    
          
          /* new in libcurl 7.2: */
    
          curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, config->postfieldsize);
    
          curl_easy_setopt(curl, CURLOPT_REFERER, config->referer);
    
          curl_easy_setopt(curl, CURLOPT_AUTOREFERER,
    
                           config->conf&CONF_AUTO_REFERER);
          curl_easy_setopt(curl, CURLOPT_USERAGENT, config->useragent);
          curl_easy_setopt(curl, CURLOPT_FTPPORT, config->ftpport);
          curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
          curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
    
          curl_easy_setopt(curl, CURLOPT_RESUME_FROM,
    
                           config->use_resume?config->resume_from:0);
          curl_easy_setopt(curl, CURLOPT_COOKIE, config->cookie);
          curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
          curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
          curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
          curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config->cert_passwd);
    
    
          if(config->cacert) {
            /* available from libcurl 7.5: */
            curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
          }
    
          if(config->conf&(CONF_NOBODY|CONF_USEREMOTETIME)) {
            /* no body or use remote time */
            /* new in 7.5 */
            curl_easy_setopt(curl, CURLOPT_FILETIME, TRUE);
          }
    
    
          curl_easy_setopt(curl, CURLOPT_CRLF, config->crlf);
          curl_easy_setopt(curl, CURLOPT_QUOTE, config->quote);
          curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config->postquote);
    
          curl_easy_setopt(curl, CURLOPT_WRITEHEADER,
    
                           config->headerfile?&heads:NULL);
          curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile);
          curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
          curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
          curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
          curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
          curl_easy_setopt(curl, CURLOPT_STDERR, config->errors);
    
          
          /* three new ones in libcurl 7.3: */
    
          curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
          curl_easy_setopt(curl, CURLOPT_INTERFACE, config->iface);
          curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level);
    
          if((config->progressmode == CURL_PROGRESS_BAR) &&
             !(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) {
    
            /* we want the alternative style, then we have to implement it
               ourselves! */
            progressbarinit(&progressbar);
            curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress);
            curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
          }
    
          res = curl_easy_perform(curl);
    
          if(config->writeout) {
            ourWriteOut(curl, config->writeout);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
          /* always cleanup */
          curl_easy_cleanup(curl);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
          if((res!=CURLE_OK) && config->showerror)
            fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer);
    
          fprintf(config->errors, "curl: failed to init libcurl!\n");
    
        main_free();
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
        if((config->errors != stderr) &&
           (config->errors != stdout))
    
          /* it wasn't directed to stdout or stderr so close the file! */
    
          fclose(config->errors);
    
        if(config->headerfile && !headerfilep && heads.stream)
    
          fclose(heads.stream);
    
        if(urlbuffer)
          free(urlbuffer);
    
        if (config->outfile && outs.stream)
    
          fclose(outs.stream);
    
        if (config->infile)
    
          fclose(infd);
        if(headerfilep)
          fclose(headerfilep);
        
        if(url)
          free(url);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
      }
    #ifdef MIME_SEPARATORS
      if (separator)
        printf("--%s--\n", MIMEseparator);
    #endif
    
    
      if(allocuseragent)
    
        free(config->useragent);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      /* cleanup memory used for URL globbing patterns */
      glob_cleanup(urls);
    
    
      struct Configurable config;
    
      memset(&config, 0, sizeof(struct Configurable));
      
    
      res = operate(&config, argc, argv);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
      return res;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    }
    
    
    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);
          else
          {
             if (NULL == (retval = realloc(retval,
                                           strlen(retval) + strlen(buf) + 1)))
                break;
             strcat(retval, buf);
          }
       }
       while (NULL == (nl = strchr(retval, '\n')));
    
       if (NULL != nl)
         *nl = '\0';
    
       return retval;
    }