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#define ENABLE_CURLX_PRINTF 26/* use our own printf() functions */ 27#include "curlx.h" 28 29#include "tool_help.h" 30#include "tool_libinfo.h" 31#include "tool_util.h" 32#include "tool_version.h" 33 34#include "memdebug.h" /* keep this as LAST include */ 35 36#ifdef MSDOS 37# define USE_WATT32 38#endif 39 40struct category_descriptors { 41 const char *opt; 42 const char *desc; 43 curlhelp_t category; 44}; 45 46static const struct category_descriptors categories[] = { 47 {"auth", "Different types of authentication methods", CURLHELP_AUTH}, 48 {"connection", "Low level networking operations", 49 CURLHELP_CONNECTION}, 50 {"curl", "The command line tool itself", CURLHELP_CURL}, 51 {"dns", "General DNS options", CURLHELP_DNS}, 52 {"file", "FILE protocol options", CURLHELP_FILE}, 53 {"ftp", "FTP protocol options", CURLHELP_FTP}, 54 {"http", "HTTP and HTTPS protocol options", CURLHELP_HTTP}, 55 {"imap", "IMAP protocol options", CURLHELP_IMAP}, 56 /* important is left out because it is the default help page */ 57 {"misc", "Options that don't fit into any other category", CURLHELP_MISC}, 58 {"output", "Filesystem output", CURLHELP_OUTPUT}, 59 {"pop3", "POP3 protocol options", CURLHELP_POP3}, 60 {"post", "HTTP Post specific options", CURLHELP_POST}, 61 {"proxy", "All options related to proxies", CURLHELP_PROXY}, 62 {"scp", "SCP protocol options", CURLHELP_SCP}, 63 {"sftp", "SFTP protocol options", CURLHELP_SFTP}, 64 {"smtp", "SMTP protocol options", CURLHELP_SMTP}, 65 {"ssh", "SSH protocol options", CURLHELP_SSH}, 66 {"telnet", "TELNET protocol options", CURLHELP_TELNET}, 67 {"tftp", "TFTP protocol options", CURLHELP_TFTP}, 68 {"tls", "All TLS/SSL related options", CURLHELP_TLS}, 69 {"upload", "All options for uploads", 70 CURLHELP_UPLOAD}, 71 {"verbose", "Options related to any kind of command line output of curl", 72 CURLHELP_VERBOSE}, 73 {NULL, NULL, CURLHELP_HIDDEN} 74}; 75 76 77static void print_category(curlhelp_t category) 78{ 79 unsigned int i; 80 size_t longopt = 5; 81 size_t longdesc = 5; 82 83 for(i = 0; helptext[i].opt; ++i) { 84 size_t len; 85 if(!(helptext[i].categories & category)) 86 continue; 87 len = strlen(helptext[i].opt); 88 if(len > longopt) 89 longopt = len; 90 len = strlen(helptext[i].desc); 91 if(len > longdesc) 92 longdesc = len; 93 } 94 if(longopt + longdesc > 80) 95 longopt = 80 - longdesc; 96 97 for(i = 0; helptext[i].opt; ++i) 98 if(helptext[i].categories & category) { 99 printf(" %-*s %s\n", (int)longopt, helptext[i].opt, helptext[i].desc); 100 } 101} 102 103/* Prints category if found. If not, it returns 1 */ 104static int get_category_content(const char *category) 105{ 106 unsigned int i; 107 for(i = 0; categories[i].opt; ++i) 108 if(curl_strequal(categories[i].opt, category)) { 109 printf("%s: %s\n", categories[i].opt, categories[i].desc); 110 print_category(categories[i].category); 111 return 0; 112 } 113 return 1; 114} 115 116/* Prints all categories and their description */ 117static void get_categories(void) 118{ 119 unsigned int i; 120 for(i = 0; categories[i].opt; ++i) 121 printf(" %-11s %s\n", categories[i].opt, categories[i].desc); 122} 123 124 125void tool_help(char *category) 126{ 127 puts("Usage: curl [options...] <url>"); 128 /* If no category was provided */ 129 if(!category) { 130 const char *category_note = "\nThis is not the full help, this " 131 "menu is stripped into categories.\nUse \"--help category\" to get " 132 "an overview of all categories.\nFor all options use the manual" 133 " or \"--help all\"."; 134 print_category(CURLHELP_IMPORTANT); 135 puts(category_note); 136 } 137 /* Lets print everything if "all" was provided */ 138 else if(curl_strequal(category, "all")) 139 /* Print everything except hidden */ 140 print_category(~(CURLHELP_HIDDEN)); 141 /* Lets handle the string "category" differently to not print an errormsg */ 142 else if(curl_strequal(category, "category")) 143 get_categories(); 144 /* Otherwise print category and handle the case if the cat was not found */ 145 else if(get_category_content(category)) { 146 puts("Invalid category provided, here is a list of all categories:\n"); 147 get_categories(); 148 } 149 free(category); 150} 151 152static bool is_debug(void) 153{ 154 const char *const *builtin; 155 for(builtin = feature_names; *builtin; ++builtin) 156 if(curl_strequal("debug", *builtin)) 157 return TRUE; 158 return FALSE; 159} 160 161void tool_version_info(void) 162{ 163 const char *const *builtin; 164 if(is_debug()) 165 fprintf(tool_stderr, "WARNING: this libcurl is Debug-enabled, " 166 "do not use in production\n\n"); 167 168 printf(CURL_ID "%s\n", curl_version()); 169#ifdef CURL_PATCHSTAMP 170 printf("Release-Date: %s, security patched: %s\n", 171 LIBCURL_TIMESTAMP, CURL_PATCHSTAMP); 172#else 173 printf("Release-Date: %s\n", LIBCURL_TIMESTAMP); 174#endif 175 if(built_in_protos[0]) { 176 const char *insert = NULL; 177 /* we have ipfs and ipns support if libcurl has http support */ 178 for(builtin = built_in_protos; *builtin; ++builtin) { 179 if(insert) { 180 /* update insertion so ipfs will be printed in alphabetical order */ 181 if(strcmp(*builtin, "ipfs") < 0) 182 insert = *builtin; 183 else 184 break; 185 } 186 else if(!strcmp(*builtin, "http")) { 187 insert = *builtin; 188 } 189 } 190 printf("Protocols:"); 191 for(builtin = built_in_protos; *builtin; ++builtin) { 192 /* Special case: do not list rtmp?* protocols. 193 They may only appear together with "rtmp" */ 194 if(!curl_strnequal(*builtin, "rtmp", 4) || !builtin[0][4]) 195 printf(" %s", *builtin); 196 if(insert && insert == *builtin) { 197 printf(" ipfs ipns"); 198 insert = NULL; 199 } 200 } 201 puts(""); /* newline */ 202 } 203 if(feature_names[0]) { 204 printf("Features:"); 205 for(builtin = feature_names; *builtin; ++builtin) 206 printf(" %s", *builtin); 207 puts(""); /* newline */ 208 } 209 if(strcmp(CURL_VERSION, curlinfo->version)) { 210 printf("WARNING: curl and libcurl versions do not match. " 211 "Functionality may be affected.\n"); 212 } 213} 214 215void tool_list_engines(void) 216{ 217 CURL *curl = curl_easy_init(); 218 struct curl_slist *engines = NULL; 219 220 /* Get the list of engines */ 221 curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines); 222 223 puts("Build-time engines:"); 224 if(engines) { 225 for(; engines; engines = engines->next) 226 printf(" %s\n", engines->data); 227 } 228 else { 229 puts(" <none>"); 230 } 231 232 /* Cleanup the list of engines */ 233 curl_slist_free_all(engines); 234 curl_easy_cleanup(curl); 235} 236