1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 #include "tool_setup.h"
23 
24 #define ENABLE_CURLX_PRINTF
25 /* use our own printf() functions */
26 #include "curlx.h"
27 
28 #include "tool_cfgable.h"
29 #include "tool_msgs.h"
30 
31 #include "memdebug.h" /* keep this as LAST include */
32 
33 #define WARN_PREFIX "Warning: "
34 #define NOTE_PREFIX "Note: "
35 #define ERROR_PREFIX "curl: "
36 
voutf(struct GlobalConfig * config,const char * prefix,const char * fmt,va_list ap)37 static void voutf(struct GlobalConfig *config,
38                   const char *prefix,
39                   const char *fmt,
40                   va_list ap)
41 {
42   size_t width = (79 - strlen(prefix));
43   if(!config->mute) {
44     size_t len;
45     char *ptr;
46     char *print_buffer;
47 
48     print_buffer = curlx_mvaprintf(fmt, ap);
49     if(!print_buffer)
50       return;
51     len = strlen(print_buffer);
52 
53     ptr = print_buffer;
54     while(len > 0) {
55       fputs(prefix, config->errors);
56 
57       if(len > width) {
58         size_t cut = width-1;
59 
60         while(!ISSPACE(ptr[cut]) && cut) {
61           cut--;
62         }
63         if(0 == cut)
64           /* not a single cutting position was found, just cut it at the
65              max text width then! */
66           cut = width-1;
67 
68         (void)fwrite(ptr, cut + 1, 1, config->errors);
69         fputs("\n", config->errors);
70         ptr += cut + 1; /* skip the space too */
71         len -= cut + 1;
72       }
73       else {
74         fputs(ptr, config->errors);
75         len = 0;
76       }
77     }
78     curl_free(print_buffer);
79   }
80 }
81 
82 /*
83  * Emit 'note' formatted message on configured 'errors' stream, if verbose was
84  * selected.
85  */
notef(struct GlobalConfig * config,const char * fmt,...)86 void notef(struct GlobalConfig *config, const char *fmt, ...)
87 {
88   va_list ap;
89   va_start(ap, fmt);
90   if(config->tracetype)
91     voutf(config, NOTE_PREFIX, fmt, ap);
92   va_end(ap);
93 }
94 
95 /*
96  * Emit warning formatted message on configured 'errors' stream unless
97  * mute (--silent) was selected.
98  */
99 
warnf(struct GlobalConfig * config,const char * fmt,...)100 void warnf(struct GlobalConfig *config, const char *fmt, ...)
101 {
102   va_list ap;
103   va_start(ap, fmt);
104   voutf(config, WARN_PREFIX, fmt, ap);
105   va_end(ap);
106 }
107 /*
108  * Emit help formatted message on given stream. This is for errors with or
109  * related to command line arguments.
110  */
helpf(FILE * errors,const char * fmt,...)111 void helpf(FILE *errors, const char *fmt, ...)
112 {
113   if(fmt) {
114     va_list ap;
115     va_start(ap, fmt);
116     fputs("curl: ", errors); /* prefix it */
117     vfprintf(errors, fmt, ap);
118     va_end(ap);
119   }
120   fprintf(errors, "curl: try 'curl --help' "
121 #ifdef USE_MANUAL
122           "or 'curl --manual' "
123 #endif
124           "for more information\n");
125 }
126 
127 /*
128  * Emit error message on error stream if not muted. When errors are not tied
129  * to command line arguments, use helpf() for such errors.
130  */
errorf(struct GlobalConfig * config,const char * fmt,...)131 void errorf(struct GlobalConfig *config, const char *fmt, ...)
132 {
133   if(!config->mute) {
134     va_list ap;
135     va_start(ap, fmt);
136     voutf(config, ERROR_PREFIX, fmt, ap);
137     va_end(ap);
138   }
139 }
140