blob: 65a1f43dfa4e94480ebc56cd7dd6f9e8d55ec194 [file] [log] [blame]
xf.li6c8fc1e2023-08-12 00:11:09 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, 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_panykey.h"
30#include "tool_help.h"
31#include "tool_libinfo.h"
32#include "tool_util.h"
33#include "tool_version.h"
34
35#include "memdebug.h" /* keep this as LAST include */
36
37#ifdef MSDOS
38# define USE_WATT32
39#endif
40
41struct category_descriptors {
42 const char *opt;
43 const char *desc;
44 curlhelp_t category;
45};
46
47static const struct category_descriptors categories[] = {
48 {"auth", "Different types of authentication methods", CURLHELP_AUTH},
49 {"connection", "Low level networking operations",
50 CURLHELP_CONNECTION},
51 {"curl", "The command line tool itself", CURLHELP_CURL},
52 {"dns", "General DNS options", CURLHELP_DNS},
53 {"file", "FILE protocol options", CURLHELP_FILE},
54 {"ftp", "FTP protocol options", CURLHELP_FTP},
55 {"http", "HTTP and HTTPS protocol options", CURLHELP_HTTP},
56 {"imap", "IMAP protocol options", CURLHELP_IMAP},
57 /* important is left out because it is the default help page */
58 {"misc", "Options that don't fit into any other category", CURLHELP_MISC},
59 {"output", "Filesystem output", CURLHELP_OUTPUT},
60 {"pop3", "POP3 protocol options", CURLHELP_POP3},
61 {"post", "HTTP Post specific options", CURLHELP_POST},
62 {"proxy", "All options related to proxies", CURLHELP_PROXY},
63 {"scp", "SCP protocol options", CURLHELP_SCP},
64 {"sftp", "SFTP protocol options", CURLHELP_SFTP},
65 {"smtp", "SMTP protocol options", CURLHELP_SMTP},
66 {"ssh", "SSH protocol options", CURLHELP_SSH},
67 {"telnet", "TELNET protocol options", CURLHELP_TELNET},
68 {"tftp", "TFTP protocol options", CURLHELP_TFTP},
69 {"tls", "All TLS/SSL related options", CURLHELP_TLS},
70 {"upload", "All options for uploads",
71 CURLHELP_UPLOAD},
72 {"verbose", "Options related to any kind of command line output of curl",
73 CURLHELP_VERBOSE},
74 {NULL, NULL, CURLHELP_HIDDEN}
75};
76
77extern const struct helptxt helptext[];
78
79struct feat {
80 const char *name;
81 int bitmask;
82};
83
84static const struct feat feats[] = {
85 {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
86 {"Debug", CURL_VERSION_DEBUG},
87 {"TrackMemory", CURL_VERSION_CURLDEBUG},
88 {"IDN", CURL_VERSION_IDN},
89 {"IPv6", CURL_VERSION_IPV6},
90 {"Largefile", CURL_VERSION_LARGEFILE},
91 {"Unicode", CURL_VERSION_UNICODE},
92 {"SSPI", CURL_VERSION_SSPI},
93 {"GSS-API", CURL_VERSION_GSSAPI},
94 {"Kerberos", CURL_VERSION_KERBEROS5},
95 {"SPNEGO", CURL_VERSION_SPNEGO},
96 {"NTLM", CURL_VERSION_NTLM},
97 {"NTLM_WB", CURL_VERSION_NTLM_WB},
98 {"SSL", CURL_VERSION_SSL},
99 {"libz", CURL_VERSION_LIBZ},
100 {"brotli", CURL_VERSION_BROTLI},
101 {"zstd", CURL_VERSION_ZSTD},
102 {"CharConv", CURL_VERSION_CONV},
103 {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
104 {"HTTP2", CURL_VERSION_HTTP2},
105 {"HTTP3", CURL_VERSION_HTTP3},
106 {"UnixSockets", CURL_VERSION_UNIX_SOCKETS},
107 {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
108 {"MultiSSL", CURL_VERSION_MULTI_SSL},
109 {"PSL", CURL_VERSION_PSL},
110 {"alt-svc", CURL_VERSION_ALTSVC},
111 {"HSTS", CURL_VERSION_HSTS},
112 {"gsasl", CURL_VERSION_GSASL},
113 {"threadsafe", CURL_VERSION_THREADSAFE},
114};
115
116static void print_category(curlhelp_t category)
117{
118 unsigned int i;
119 size_t longopt = 5;
120 size_t longdesc = 5;
121
122 for(i = 0; helptext[i].opt; ++i) {
123 size_t len;
124 if(!(helptext[i].categories & category))
125 continue;
126 len = strlen(helptext[i].opt);
127 if(len > longopt)
128 longopt = len;
129 len = strlen(helptext[i].desc);
130 if(len > longdesc)
131 longdesc = len;
132 }
133 if(longopt + longdesc > 80)
134 longopt = 80 - longdesc;
135
136 for(i = 0; helptext[i].opt; ++i)
137 if(helptext[i].categories & category) {
138 printf(" %-*s %s\n", (int)longopt, helptext[i].opt, helptext[i].desc);
139 }
140}
141
142/* Prints category if found. If not, it returns 1 */
143static int get_category_content(const char *category)
144{
145 unsigned int i;
146 for(i = 0; categories[i].opt; ++i)
147 if(curl_strequal(categories[i].opt, category)) {
148 printf("%s: %s\n", categories[i].opt, categories[i].desc);
149 print_category(categories[i].category);
150 return 0;
151 }
152 return 1;
153}
154
155/* Prints all categories and their description */
156static void get_categories(void)
157{
158 unsigned int i;
159 for(i = 0; categories[i].opt; ++i)
160 printf(" %-11s %s\n", categories[i].opt, categories[i].desc);
161}
162
163
164void tool_help(char *category)
165{
166 puts("Usage: curl [options...] <url>");
167 /* If no category was provided */
168 if(!category) {
169 const char *category_note = "\nThis is not the full help, this "
170 "menu is stripped into categories.\nUse \"--help category\" to get "
171 "an overview of all categories.\nFor all options use the manual"
172 " or \"--help all\".";
173 print_category(CURLHELP_IMPORTANT);
174 puts(category_note);
175 }
176 /* Lets print everything if "all" was provided */
177 else if(curl_strequal(category, "all"))
178 /* Print everything except hidden */
179 print_category(~(CURLHELP_HIDDEN));
180 /* Lets handle the string "category" differently to not print an errormsg */
181 else if(curl_strequal(category, "category"))
182 get_categories();
183 /* Otherwise print category and handle the case if the cat was not found */
184 else if(get_category_content(category)) {
185 puts("Invalid category provided, here is a list of all categories:\n");
186 get_categories();
187 }
188 free(category);
189}
190
191
192void tool_version_info(void)
193{
194 const char *const *proto;
195
196 printf(CURL_ID "%s\n", curl_version());
197#ifdef CURL_PATCHSTAMP
198 printf("Release-Date: %s, security patched: %s\n",
199 LIBCURL_TIMESTAMP, CURL_PATCHSTAMP);
200#else
201 printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
202#endif
203 if(curlinfo->protocols) {
204 printf("Protocols: ");
205 for(proto = curlinfo->protocols; *proto; ++proto) {
206 /* Special case: do not list rtmp?* protocols.
207 They may only appear together with "rtmp" */
208 if(!curl_strnequal(*proto, "rtmp", 4) || !proto[0][4])
209 printf("%s ", *proto);
210 }
211 puts(""); /* newline */
212 }
213 if(curlinfo->features) {
214 char *featp[ sizeof(feats) / sizeof(feats[0]) + 1];
215 size_t numfeat = 0;
216 unsigned int i;
217 printf("Features:");
218 for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
219 if(curlinfo->features & feats[i].bitmask)
220 featp[numfeat++] = (char *)feats[i].name;
221 }
222 qsort(&featp[0], numfeat, sizeof(char *), struplocompare4sort);
223 for(i = 0; i< numfeat; i++)
224 printf(" %s", featp[i]);
225 puts(""); /* newline */
226 }
227 if(strcmp(CURL_VERSION, curlinfo->version)) {
228 printf("WARNING: curl and libcurl versions do not match. "
229 "Functionality may be affected.\n");
230 }
231}
232
233void tool_list_engines(void)
234{
235 CURL *curl = curl_easy_init();
236 struct curl_slist *engines = NULL;
237
238 /* Get the list of engines */
239 curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
240
241 puts("Build-time engines:");
242 if(engines) {
243 for(; engines; engines = engines->next)
244 printf(" %s\n", engines->data);
245 }
246 else {
247 puts(" <none>");
248 }
249
250 /* Cleanup the list of engines */
251 curl_slist_free_all(engines);
252 curl_easy_cleanup(curl);
253}