]> granicus.if.org Git - curl/commitdiff
Added more verbose "warning" messages to the curl client for cases where it
authorDaniel Stenberg <daniel@haxx.se>
Mon, 15 Aug 2005 21:48:28 +0000 (21:48 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 15 Aug 2005 21:48:28 +0000 (21:48 +0000)
fails to open/read files etc to help users diagnose why it doesn't do what
you'd expect it to. Converted lots of old messages to use the new generic
function I wrote for this purpose.

src/main.c

index 26b95a65609ed37a978fbeaf25b1fbab91443dc5..07f133b3ed750911aed2e613dba774e9e7c19eab 100644 (file)
@@ -243,6 +243,161 @@ static int ftruncate64 (int fd, curl_off_t where)
 #define ftruncate(fd,where) ftruncate64(fd,where)
 #endif
 
+typedef enum {
+    TRACE_BIN,   /* tcpdump inspired look */
+    TRACE_ASCII, /* like *BIN but without the hex output */
+    TRACE_PLAIN  /* -v/--verbose type */
+} trace;
+
+struct Configurable {
+  bool remote_time;
+  char *random_file;
+  char *egd_file;
+  char *useragent;
+  char *cookie;     /* single line with specified cookies */
+  char *cookiejar;  /* write to this file */
+  char *cookiefile; /* read from this file */
+  bool cookiesession; /* new session? */
+  bool encoding;    /* Accept-Encoding please */
+  long authtype;    /* auth bitmask */
+  bool use_resume;
+  bool resume_from_current;
+  bool disable_epsv;
+  bool disable_eprt;
+  curl_off_t resume_from;
+  char *postfields;
+  long postfieldsize;
+  char *referer;
+  long timeout;
+  long connecttimeout;
+  long maxredirs;
+  curl_off_t max_filesize;
+  char *headerfile;
+  char *ftpport;
+  char *iface;
+  unsigned short porttouse;
+  char *range;
+  long low_speed_limit;
+  long low_speed_time;
+  bool showerror;
+  char *userpwd;
+  char *proxyuserpwd;
+  char *proxy;
+  bool proxytunnel;
+  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 */
+  char *cipher_list;
+  char *cert;
+  char *cert_type;
+  char *cacert;
+  char *capath;
+  char *key;
+  char *key_type;
+  char *key_passwd;
+  char *engine;
+  bool list_engines;
+  bool crlf;
+  char *customrequest;
+  char *krb4level;
+  char *trace_dump; /* file to dump the network trace to, or NULL */
+  FILE *trace_stream;
+  bool trace_fopened;
+  trace tracetype;
+  bool tracetime; /* include timestamp? */
+  long httpversion;
+  bool progressmode;
+  bool nobuffer;
+  bool globoff;
+  bool use_httpget;
+  bool insecure_ok; /* set TRUE to allow insecure SSL connects */
+  bool create_dirs;
+  bool ftp_create_dirs;
+  bool proxyntlm;
+  bool proxydigest;
+  bool proxybasic;
+  bool proxyanyauth;
+  char *writeout; /* %-styled format string to output */
+  bool writeenv; /* write results to environment, if available */
+  FILE *errors; /* if stderr redirect is requested */
+  bool errors_fopened;
+  struct curl_slist *quote;
+  struct curl_slist *postquote;
+  struct curl_slist *prequote;
+  long ssl_version;
+  long ip_version;
+  curl_TimeCond timecond;
+  time_t condtime;
+  struct curl_slist *headers;
+  struct curl_httppost *httppost;
+  struct curl_httppost *last_post;
+  struct curl_slist *telnet_options;
+  HttpReq httpreq;
+
+  /* for bandwidth limiting features: */
+  curl_off_t sendpersecond; /* send to peer */
+  curl_off_t recvpersecond; /* receive from peer */
+  struct timeval lastsendtime;
+  size_t lastsendsize;
+  struct timeval lastrecvtime;
+  size_t lastrecvsize;
+  bool ftp_ssl;
+  char *socks5proxy;
+  bool tcp_nodelay;
+  long req_retry;   /* number of retries */
+  long retry_delay; /* delay between retries (in seconds) */
+  long retry_maxtime; /* maximum time to keep retrying */
+
+  char *tp_url; /* third party URL */
+  char *tp_user; /* third party userpwd */
+  struct curl_slist *tp_quote;
+  struct curl_slist *tp_postquote;
+  struct curl_slist *tp_prequote;
+  char *ftp_account; /* for ACCT */
+};
+
+#define WARN_PREFIX "Warning: "
+#define WARN_TEXTWIDTH (79 - strlen(WARN_PREFIX))
+/* produce this text message to the user unless mute was selected */
+static void warnf(struct Configurable *config, const char *fmt, ...)
+{
+  if(!(config->conf & CONF_MUTE)) {
+    va_list ap;
+    int len;
+    char *ptr;
+    char print_buffer[256];
+
+    va_start(ap, fmt);
+    va_start(ap, fmt);
+    len = vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+    va_end(ap);
+
+    ptr = print_buffer;
+    while(len > 0) {
+      fputs(WARN_PREFIX, config->errors);
+
+      if(len > (int)WARN_TEXTWIDTH) {
+        int cut = WARN_TEXTWIDTH-1;
+
+        while(!isspace(ptr[cut]) && cut) {
+          cut--;
+        }
+
+        fwrite(ptr, cut + 1, 1, config->errors);
+        fputs("\n", config->errors);
+        ptr += cut+1; /* skip the space too */
+        len -= cut;
+      }
+      else {
+        fputs(ptr, config->errors);
+        len = 0;
+      }
+    }
+  }
+}
+
 /*
  * This is the main global constructor for the app. Call this before
  * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
@@ -262,14 +417,15 @@ static void main_free(void)
   curl_global_cleanup();
 }
 
-static int SetHTTPrequest(HttpReq req, HttpReq *store)
+static int SetHTTPrequest(struct Configurable *config,
+                          HttpReq req, HttpReq *store)
 {
   if((*store == HTTPREQ_UNSPEC) ||
      (*store == req)) {
     *store = req;
     return 0;
   }
-  fprintf(stderr, "You can only select one HTTP request!\n");
+  warnf(config, "You can only select one HTTP request!\n");
   return 1;
 }
 
@@ -306,12 +462,6 @@ struct getout {
 #define GETOUT_UPLOAD  (1<<3)   /* if set, -T has been used */
 #define GETOUT_NOUPLOAD  (1<<4) /* if set, -T "" has been used */
 
-typedef enum {
-    TRACE_BIN,   /* tcpdump inspired look */
-    TRACE_ASCII, /* like *BIN but without the hex output */
-    TRACE_PLAIN  /* -v/--verbose type */
-} trace;
-
 static void help(void)
 {
   int i;
@@ -450,115 +600,6 @@ struct LongShort {
   bool extraparam;
 };
 
-struct Configurable {
-  bool remote_time;
-  char *random_file;
-  char *egd_file;
-  char *useragent;
-  char *cookie;     /* single line with specified cookies */
-  char *cookiejar;  /* write to this file */
-  char *cookiefile; /* read from this file */
-  bool cookiesession; /* new session? */
-  bool encoding;    /* Accept-Encoding please */
-  long authtype;    /* auth bitmask */
-  bool use_resume;
-  bool resume_from_current;
-  bool disable_epsv;
-  bool disable_eprt;
-  curl_off_t resume_from;
-  char *postfields;
-  long postfieldsize;
-  char *referer;
-  long timeout;
-  long connecttimeout;
-  long maxredirs;
-  curl_off_t max_filesize;
-  char *headerfile;
-  char *ftpport;
-  char *iface;
-  unsigned short porttouse;
-  char *range;
-  long low_speed_limit;
-  long low_speed_time;
-  bool showerror;
-  char *userpwd;
-  char *proxyuserpwd;
-  char *proxy;
-  bool proxytunnel;
-  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 */
-  char *cipher_list;
-  char *cert;
-  char *cert_type;
-  char *cacert;
-  char *capath;
-  char *key;
-  char *key_type;
-  char *key_passwd;
-  char *engine;
-  bool list_engines;
-  bool crlf;
-  char *customrequest;
-  char *krb4level;
-  char *trace_dump; /* file to dump the network trace to, or NULL */
-  FILE *trace_stream;
-  bool trace_fopened;
-  trace tracetype;
-  bool tracetime; /* include timestamp? */
-  long httpversion;
-  bool progressmode;
-  bool nobuffer;
-  bool globoff;
-  bool use_httpget;
-  bool insecure_ok; /* set TRUE to allow insecure SSL connects */
-  bool create_dirs;
-  bool ftp_create_dirs;
-  bool proxyntlm;
-  bool proxydigest;
-  bool proxybasic;
-  bool proxyanyauth;
-  char *writeout; /* %-styled format string to output */
-  bool writeenv; /* write results to environment, if available */
-  FILE *errors; /* if stderr redirect is requested */
-  bool errors_fopened;
-  struct curl_slist *quote;
-  struct curl_slist *postquote;
-  struct curl_slist *prequote;
-  long ssl_version;
-  long ip_version;
-  curl_TimeCond timecond;
-  time_t condtime;
-  struct curl_slist *headers;
-  struct curl_httppost *httppost;
-  struct curl_httppost *last_post;
-  struct curl_slist *telnet_options;
-  HttpReq httpreq;
-
-  /* for bandwidth limiting features: */
-  curl_off_t sendpersecond; /* send to peer */
-  curl_off_t recvpersecond; /* receive from peer */
-  struct timeval lastsendtime;
-  size_t lastsendsize;
-  struct timeval lastrecvtime;
-  size_t lastrecvsize;
-  bool ftp_ssl;
-  char *socks5proxy;
-  bool tcp_nodelay;
-  long req_retry;   /* number of retries */
-  long retry_delay; /* delay between retries (in seconds) */
-  long retry_maxtime; /* maximum time to keep retrying */
-
-  char *tp_url; /* third party URL */
-  char *tp_user; /* third party userpwd */
-  struct curl_slist *tp_quote;
-  struct curl_slist *tp_postquote;
-  struct curl_slist *tp_prequote;
-  char *ftp_account; /* for ACCT */
-};
-
 /* global variable to hold info about libcurl */
 static curl_version_info_data *curlinfo;
 
@@ -814,7 +855,8 @@ static void list_engines (const struct curl_slist *engines)
 #define FORM_FILE_SEPARATOR ','
 #define FORM_TYPE_SEPARATOR ';'
 
-static int formparse(char *input,
+static int formparse(struct Configurable *config,
+                     char *input,
                      struct curl_httppost **httppost,
                      struct curl_httppost **last_post,
                      bool literal_value)
@@ -890,7 +932,7 @@ static int formparse(char *input,
               /* verify that this is a fine type specifier */
               if(2 != sscanf(type, "%127[^/]/%127[^;,\n]",
                              major, minor)) {
-                fprintf(stderr, "Illegally formatted content-type field!\n");
+                warnf(config, "Illegally formatted content-type field!\n");
                 free(contents);
                 FreeMultiInfo (multi_start);
                 return 2; /* illegal content-type syntax! */
@@ -939,7 +981,7 @@ static int formparse(char *input,
 
         if (!AddMultiFiles (contp, type, filename, &multi_start,
                             &multi_current)) {
-          fprintf(stderr, "Error building form post!\n");
+          warnf(config, "Error building form post!\n");
           free(contents);
           FreeMultiInfo (multi_start);
           return 3;
@@ -976,7 +1018,7 @@ static int formparse(char *input,
         if (curl_formadd(httppost, last_post,
                          CURLFORM_COPYNAME, name,
                          CURLFORM_ARRAY, forms, CURLFORM_END) != 0) {
-          fprintf(stderr, "curl_formadd failed!\n");
+          warnf(config, "curl_formadd failed!\n");
           free(forms);
           free(contents);
           return 5;
@@ -1008,8 +1050,8 @@ static int formparse(char *input,
 
         if (curl_formadd(httppost, last_post,
                          CURLFORM_ARRAY, info, CURLFORM_END ) != 0) {
-          fprintf(stderr, "curl_formadd failed, possibly the file %s is bad!\n",
-                  contp+1);
+          warnf(config, "curl_formadd failed, possibly the file %s is bad!\n",
+                contp+1);
           free(contents);
           return 6;
         }
@@ -1021,7 +1063,7 @@ static int formparse(char *input,
         info[i].option = CURLFORM_END;
         if (curl_formadd(httppost, last_post,
                          CURLFORM_ARRAY, info, CURLFORM_END) != 0) {
-          fprintf(stderr, "curl_formadd failed!\n");
+          warnf(config, "curl_formadd failed!\n");
           free(contents);
           return 7;
         }
@@ -1030,7 +1072,7 @@ static int formparse(char *input,
 
   }
   else {
-    fprintf(stderr, "Illegally formatted input field!\n");
+    warnf(config, "Illegally formatted input field!\n");
     return 1;
   }
   free(contents);
@@ -1387,9 +1429,6 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     }
     *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]) {
@@ -1533,8 +1572,13 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
 
       case 'v': /* --stderr */
         if(strcmp(nextarg, "-")) {
-          config->errors = fopen(nextarg, "wt");
-          config->errors_fopened = TRUE;
+          FILE *newfile = fopen(nextarg, "wt");
+          if(!config->errors)
+            warnf(config, "Failed to open %s!\n", nextarg);
+          else {
+            config->errors = newfile;
+            config->errors_fopened = TRUE;
+          }
         }
         else
           config->errors = stdout;
@@ -1742,8 +1786,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
 
           if(curlx_strequal("-", nextarg))
             file = stdin;
-          else
+          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 */
             postdata = file2memory(file, &config->postfieldsize);
@@ -1863,12 +1911,13 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     case 'F':
       /* "form data" simulation, this is a little advanced so lets do our best
          to sort this out slowly and carefully */
-      if(formparse(nextarg,
+      if(formparse(config,
+                   nextarg,
                    &config->httppost,
                    &config->last_post,
                    subletter=='s')) /* 's' means literal string */
         return PARAM_BAD_USE;
-      if(SetHTTPrequest(HTTPREQ_POST, &config->httpreq))
+      if(SetHTTPrequest(config, HTTPREQ_POST, &config->httpreq))
         return PARAM_BAD_USE;
       break;
 
@@ -1904,13 +1953,13 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
          (config->conf&(CONF_HEADER|CONF_NOBODY)) ) {
         /* one of them weren't set, set both */
         config->conf |= (CONF_HEADER|CONF_NOBODY);
-        if(SetHTTPrequest(HTTPREQ_HEAD, &config->httpreq))
+        if(SetHTTPrequest(config, HTTPREQ_HEAD, &config->httpreq))
           return PARAM_BAD_USE;
       }
       else {
         /* both were set, clear both */
         config->conf &= ~(CONF_HEADER|CONF_NOBODY);
-        if(SetHTTPrequest(HTTPREQ_GET, &config->httpreq))
+        if(SetHTTPrequest(config, HTTPREQ_GET, &config->httpreq))
           return PARAM_BAD_USE;
       }
       break;
@@ -1943,8 +1992,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
       hugehelp();
       return PARAM_HELP_REQUESTED;
 #else
-      fprintf(stderr,
-              "curl: built-in manual was disabled at build-time!\n");
+      warnf(config,
+            "built-in manual was disabled at build-time!\n");
       return PARAM_OPTION_UNKNOWN;
 #endif
     case 'n':
@@ -2157,6 +2206,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
         else
           file = fopen(nextarg, "r");
         config->writeout = file2string(file);
+        if(!config->writeout)
+          warnf(config, "Failed to read %s", file);
         if(file && (file != stdin))
           fclose(file);
       }
@@ -2212,11 +2263,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
         if(-1 == stat(nextarg, &statbuf)) {
           /* failed, remove time condition */
           config->timecond = CURL_TIMECOND_NONE;
-          if(!(config->conf & CONF_MUTE))
-            fprintf(stderr,
-                    "Warning: Illegal date format for -z/--timecond and not "
-                    "a file name.\n"
-                    "         See curl_getdate(3) for valid date syntax.\n");
+          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 */
@@ -2429,8 +2479,8 @@ static void parseconfig(const char *filename,
         }
         if(PARAM_HELP_REQUESTED != res) {
           const char *reason = param2text(res);
-          fprintf(stderr, "%s:%d: warning: '%s' %s\n",
-                  filename, lineno, option, reason);
+          warnf(config, "%s:%d: warning: '%s' %s\n",
+                filename, lineno, option, reason);
         }
       }
 
@@ -2493,8 +2543,10 @@ static int my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
   if(out && !out->stream) {
     /* open file for writing */
     out->stream=fopen(out->filename, "wb");
-    if(!out->stream)
+    if(!out->stream) {
+      warnf(config, "Failed to create the file %s\n", out->filename);
       return -1; /* failure */
+    }
   }
 
   if(config->recvpersecond) {
@@ -3241,14 +3293,15 @@ operate(struct Configurable *config, int argc, char *argv[])
       httpgetfields = strdup(config->postfields);
       free(config->postfields);
       config->postfields = NULL;
-      if(SetHTTPrequest((config->conf&CONF_NOBODY?HTTPREQ_HEAD:HTTPREQ_GET),
+      if(SetHTTPrequest(config,
+                        (config->conf&CONF_NOBODY?HTTPREQ_HEAD:HTTPREQ_GET),
                         &config->httpreq)) {
         free(httpgetfields);
         return PARAM_BAD_USE;
       }
     }
     else {
-      if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
+      if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq))
         return PARAM_BAD_USE;
     }
   }
@@ -3415,7 +3468,7 @@ operate(struct Configurable *config, int argc, char *argv[])
             free(storefile);
             if(!outfile) {
               /* bad globbing */
-              fprintf(stderr, "bad output glob!\n");
+              warnf(config, "bad output glob!\n");
               free(url);
               res = CURLE_FAILED_INIT;
               break;
@@ -3909,19 +3962,18 @@ operate(struct Configurable *config, int argc, char *argv[])
             }
 
             if(retry) {
-              if(!(config->conf&CONF_MUTE)) {
-                static const char * const m[]={NULL,
-                                              "timeout",
-                                              "HTTP error",
-                                              "FTP error"
-                };
-                fprintf(stderr, "Transient problem: %s\n"
-                        "Will retry in %ld seconds. "
-                        "%ld retries left.\n",
-                        m[retry],
-                        retry_sleep/1000,
-                        retry_numretries);
-              }
+              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/1000,
+                    retry_numretries);
+
               go_sleep(retry_sleep);
               retry_numretries--;
               if(!config->retry_delay) {
@@ -4135,6 +4187,8 @@ int main(int argc, char *argv[])
   struct Configurable config;
   memset(&config, 0, sizeof(struct Configurable));
 
+  config.errors = stderr; /* default errors to stderr */
+
   checkfds();
 
   res = operate(&config, argc, argv);