1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24#include "tool_setup.h" 25 26#define ENABLE_CURLX_PRINTF 27/* use our own printf() functions */ 28#include "curlx.h" 29 30#include "tool_cfgable.h" 31#include "tool_msgs.h" 32 33#include "memdebug.h" /* keep this as LAST include */ 34 35#define WARN_PREFIX "Warning: " 36#define NOTE_PREFIX "Note: " 37#define ERROR_PREFIX "curl: " 38 39static void voutf(struct GlobalConfig *config, 40 const char *prefix, 41 const char *fmt, 42 va_list ap) CURL_PRINTF(3, 0); 43 44static void voutf(struct GlobalConfig *config, 45 const char *prefix, 46 const char *fmt, 47 va_list ap) 48{ 49 size_t width = (79 - strlen(prefix)); 50 DEBUGASSERT(!strchr(fmt, '\n')); 51 if(!config->silent) { 52 size_t len; 53 char *ptr; 54 char *print_buffer; 55 56 print_buffer = curlx_mvaprintf(fmt, ap); 57 if(!print_buffer) 58 return; 59 len = strlen(print_buffer); 60 61 ptr = print_buffer; 62 while(len > 0) { 63 fputs(prefix, tool_stderr); 64 65 if(len > width) { 66 size_t cut = width-1; 67 68 while(!ISBLANK(ptr[cut]) && cut) { 69 cut--; 70 } 71 if(0 == cut) 72 /* not a single cutting position was found, just cut it at the 73 max text width then! */ 74 cut = width-1; 75 76 (void)fwrite(ptr, cut + 1, 1, tool_stderr); 77 fputs("\n", tool_stderr); 78 ptr += cut + 1; /* skip the space too */ 79 len -= cut + 1; 80 } 81 else { 82 fputs(ptr, tool_stderr); 83 fputs("\n", tool_stderr); 84 len = 0; 85 } 86 } 87 curl_free(print_buffer); 88 } 89} 90 91/* 92 * Emit 'note' formatted message on configured 'errors' stream, if verbose was 93 * selected. 94 */ 95void notef(struct GlobalConfig *config, const char *fmt, ...) 96{ 97 va_list ap; 98 va_start(ap, fmt); 99 if(config->tracetype) 100 voutf(config, NOTE_PREFIX, fmt, ap); 101 va_end(ap); 102} 103 104/* 105 * Emit warning formatted message on configured 'errors' stream unless 106 * mute (--silent) was selected. 107 */ 108void warnf(struct GlobalConfig *config, const char *fmt, ...) 109{ 110 va_list ap; 111 va_start(ap, fmt); 112 voutf(config, WARN_PREFIX, fmt, ap); 113 va_end(ap); 114} 115 116/* 117 * Emit help formatted message on given stream. This is for errors with or 118 * related to command line arguments. 119 */ 120void helpf(FILE *errors, const char *fmt, ...) 121{ 122 if(fmt) { 123 va_list ap; 124 va_start(ap, fmt); 125 DEBUGASSERT(!strchr(fmt, '\n')); 126 fputs("curl: ", errors); /* prefix it */ 127 vfprintf(errors, fmt, ap); 128 va_end(ap); 129 fputs("\n", errors); /* newline it */ 130 } 131 fprintf(errors, "curl: try 'curl --help' " 132#ifdef USE_MANUAL 133 "or 'curl --manual' " 134#endif 135 "for more information\n"); 136} 137 138/* 139 * Emit error message on error stream if not muted. When errors are not tied 140 * to command line arguments, use helpf() for such errors. 141 */ 142void errorf(struct GlobalConfig *config, const char *fmt, ...) 143{ 144 if(!config->silent || config->showerror) { 145 va_list ap; 146 va_start(ap, fmt); 147 voutf(config, ERROR_PREFIX, fmt, ap); 148 va_end(ap); 149 } 150} 151