1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2021, 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 #if defined(HAVE_STRCASECMP) && defined(HAVE_STRINGS_H)
24 #include <strings.h>
25 #endif
26 #define ENABLE_CURLX_PRINTF
27 /* use our own printf() functions */
28 #include "curlx.h"
29
30 #include "tool_panykey.h"
31 #include "tool_help.h"
32 #include "tool_libinfo.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
41 /*
42 * The bitmask output is generated with the following command
43 ------------------------------------------------------------
44 cd $srcroot/docs/cmdline-opts
45 ./gen.pl listcats *.d
46 */
47
48 #define CURLHELP_HIDDEN 1u << 0u
49 #define CURLHELP_AUTH 1u << 1u
50 #define CURLHELP_CONNECTION 1u << 2u
51 #define CURLHELP_CURL 1u << 3u
52 #define CURLHELP_DNS 1u << 4u
53 #define CURLHELP_FILE 1u << 5u
54 #define CURLHELP_FTP 1u << 6u
55 #define CURLHELP_HTTP 1u << 7u
56 #define CURLHELP_IMAP 1u << 8u
57 #define CURLHELP_IMPORTANT 1u << 9u
58 #define CURLHELP_MISC 1u << 10u
59 #define CURLHELP_OUTPUT 1u << 11u
60 #define CURLHELP_POP3 1u << 12u
61 #define CURLHELP_POST 1u << 13u
62 #define CURLHELP_PROXY 1u << 14u
63 #define CURLHELP_SCP 1u << 15u
64 #define CURLHELP_SFTP 1u << 16u
65 #define CURLHELP_SMTP 1u << 17u
66 #define CURLHELP_SSH 1u << 18u
67 #define CURLHELP_TELNET 1u << 19u
68 #define CURLHELP_TFTP 1u << 20u
69 #define CURLHELP_TLS 1u << 21u
70 #define CURLHELP_UPLOAD 1u << 22u
71 #define CURLHELP_VERBOSE 1u << 23u
72
73 typedef unsigned int curlhelp_t;
74
75 struct category_descriptors {
76 const char *opt;
77 const char *desc;
78 curlhelp_t category;
79 };
80
81 static const struct category_descriptors categories[] = {
82 {"auth", "Different types of authentication methods", CURLHELP_AUTH},
83 {"connection", "Low level networking operations",
84 CURLHELP_CONNECTION},
85 {"curl", "The command line tool itself", CURLHELP_CURL},
86 {"dns", "General DNS options", CURLHELP_DNS},
87 {"file", "FILE protocol options", CURLHELP_FILE},
88 {"ftp", "FTP protocol options", CURLHELP_FTP},
89 {"http", "HTTP and HTTPS protocol options", CURLHELP_HTTP},
90 {"imap", "IMAP protocol options", CURLHELP_IMAP},
91 /* important is left out because it is the default help page */
92 {"misc", "Options that don't fit into any other category", CURLHELP_MISC},
93 {"output", "Filesystem output", CURLHELP_OUTPUT},
94 {"pop3", "POP3 protocol options", CURLHELP_POP3},
95 {"post", "HTTP Post specific options", CURLHELP_POST},
96 {"proxy", "All options related to proxies", CURLHELP_PROXY},
97 {"scp", "SCP protocol options", CURLHELP_SCP},
98 {"sftp", "SFTP protocol options", CURLHELP_SFTP},
99 {"smtp", "SMTP protocol options", CURLHELP_SMTP},
100 {"ssh", "SSH protocol options", CURLHELP_SSH},
101 {"telnet", "TELNET protocol options", CURLHELP_TELNET},
102 {"tftp", "TFTP protocol options", CURLHELP_TFTP},
103 {"tls", "All TLS/SSL related options", CURLHELP_TLS},
104 {"upload", "All options for uploads",
105 CURLHELP_UPLOAD},
106 {"verbose", "Options related to any kind of command line output of curl",
107 CURLHELP_VERBOSE},
108 {NULL, NULL, CURLHELP_HIDDEN}
109 };
110
111 /*
112 * The help output is generated with the following command
113 ---------------------------------------------------------
114
115 cd $srcroot/docs/cmdline-opts
116 ./gen.pl listhelp *.d
117 */
118
119 struct helptxt {
120 const char *opt;
121 const char *desc;
122 curlhelp_t categories;
123 };
124
125
126 static const struct helptxt helptext[] = {
127 {" --abstract-unix-socket <path>",
128 "Connect via abstract Unix domain socket",
129 CURLHELP_CONNECTION},
130 {" --alt-svc <file name>",
131 "Enable alt-svc with this cache file",
132 CURLHELP_HTTP},
133 {" --anyauth",
134 "Pick any authentication method",
135 CURLHELP_HTTP | CURLHELP_PROXY | CURLHELP_AUTH},
136 {"-a, --append",
137 "Append to target file when uploading",
138 CURLHELP_FTP | CURLHELP_SFTP},
139 {" --aws-sigv4 <provider1[:provider2[:region[:service]]]>",
140 "Use AWS V4 signature authentication",
141 CURLHELP_AUTH | CURLHELP_HTTP},
142 {" --basic",
143 "Use HTTP Basic Authentication",
144 CURLHELP_AUTH},
145 {" --cacert <file>",
146 "CA certificate to verify peer against",
147 CURLHELP_TLS},
148 {" --capath <dir>",
149 "CA directory to verify peer against",
150 CURLHELP_TLS},
151 {"-E, --cert <certificate[:password]>",
152 "Client certificate file and password",
153 CURLHELP_TLS},
154 {" --cert-status",
155 "Verify the status of the server cert via OCSP-staple",
156 CURLHELP_TLS},
157 {" --cert-type <type>",
158 "Certificate type (DER/PEM/ENG)",
159 CURLHELP_TLS},
160 {" --ciphers <list of ciphers>",
161 "SSL ciphers to use",
162 CURLHELP_TLS},
163 {" --compressed",
164 "Request compressed response",
165 CURLHELP_HTTP},
166 {" --compressed-ssh",
167 "Enable SSH compression",
168 CURLHELP_SCP | CURLHELP_SSH},
169 {"-K, --config <file>",
170 "Read config from a file",
171 CURLHELP_CURL},
172 {" --connect-timeout <seconds>",
173 "Maximum time allowed for connection",
174 CURLHELP_CONNECTION},
175 {" --connect-to <HOST1:PORT1:HOST2:PORT2>",
176 "Connect to host",
177 CURLHELP_CONNECTION},
178 {"-C, --continue-at <offset>",
179 "Resumed transfer offset",
180 CURLHELP_CONNECTION},
181 {"-b, --cookie <data|filename>",
182 "Send cookies from string/file",
183 CURLHELP_HTTP},
184 {"-c, --cookie-jar <filename>",
185 "Write cookies to <filename> after operation",
186 CURLHELP_HTTP},
187 {" --create-dirs",
188 "Create necessary local directory hierarchy",
189 CURLHELP_CURL},
190 {" --create-file-mode <mode>",
191 "File mode (octal) for created files",
192 CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_FILE | CURLHELP_UPLOAD},
193 {" --crlf",
194 "Convert LF to CRLF in upload",
195 CURLHELP_FTP | CURLHELP_SMTP},
196 {" --crlfile <file>",
197 "Get a CRL list in PEM format from the given file",
198 CURLHELP_TLS},
199 {" --curves <algorithm list>",
200 "(EC) TLS key exchange algorithm(s) to request",
201 CURLHELP_TLS},
202 {"-d, --data <data>",
203 "HTTP POST data",
204 CURLHELP_IMPORTANT | CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
205 {" --data-ascii <data>",
206 "HTTP POST ASCII data",
207 CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
208 {" --data-binary <data>",
209 "HTTP POST binary data",
210 CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
211 {" --data-raw <data>",
212 "HTTP POST data, '@' allowed",
213 CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
214 {" --data-urlencode <data>",
215 "HTTP POST data url encoded",
216 CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
217 {" --delegation <LEVEL>",
218 "GSS-API delegation permission",
219 CURLHELP_AUTH},
220 {" --digest",
221 "Use HTTP Digest Authentication",
222 CURLHELP_PROXY | CURLHELP_AUTH | CURLHELP_HTTP},
223 {"-q, --disable",
224 "Disable .curlrc",
225 CURLHELP_CURL},
226 {" --disable-eprt",
227 "Inhibit using EPRT or LPRT",
228 CURLHELP_FTP},
229 {" --disable-epsv",
230 "Inhibit using EPSV",
231 CURLHELP_FTP},
232 {" --disallow-username-in-url",
233 "Disallow username in url",
234 CURLHELP_CURL | CURLHELP_HTTP},
235 {" --dns-interface <interface>",
236 "Interface to use for DNS requests",
237 CURLHELP_DNS},
238 {" --dns-ipv4-addr <address>",
239 "IPv4 address to use for DNS requests",
240 CURLHELP_DNS},
241 {" --dns-ipv6-addr <address>",
242 "IPv6 address to use for DNS requests",
243 CURLHELP_DNS},
244 {" --dns-servers <addresses>",
245 "DNS server addrs to use",
246 CURLHELP_DNS},
247 {" --doh-cert-status",
248 "Verify the status of the DoH server cert via OCSP-staple",
249 CURLHELP_DNS | CURLHELP_TLS},
250 {" --doh-insecure",
251 "Allow insecure DoH server connections",
252 CURLHELP_DNS | CURLHELP_TLS},
253 {" --doh-url <URL>",
254 "Resolve host names over DoH",
255 CURLHELP_DNS},
256 {"-D, --dump-header <filename>",
257 "Write the received headers to <filename>",
258 CURLHELP_HTTP | CURLHELP_FTP},
259 {" --egd-file <file>",
260 "EGD socket path for random data",
261 CURLHELP_TLS},
262 {" --engine <name>",
263 "Crypto engine to use",
264 CURLHELP_TLS},
265 {" --etag-compare <file>",
266 "Pass an ETag from a file as a custom header",
267 CURLHELP_HTTP},
268 {" --etag-save <file>",
269 "Parse ETag from a request and save it to a file",
270 CURLHELP_HTTP},
271 {" --expect100-timeout <seconds>",
272 "How long to wait for 100-continue",
273 CURLHELP_HTTP},
274 {"-f, --fail",
275 "Fail silently (no output at all) on HTTP errors",
276 CURLHELP_IMPORTANT | CURLHELP_HTTP},
277 {" --fail-early",
278 "Fail on first transfer error, do not continue",
279 CURLHELP_CURL},
280 {" --fail-with-body",
281 "Fail on HTTP errors but save the body",
282 CURLHELP_HTTP | CURLHELP_OUTPUT},
283 {" --false-start",
284 "Enable TLS False Start",
285 CURLHELP_TLS},
286 {"-F, --form <name=content>",
287 "Specify multipart MIME data",
288 CURLHELP_HTTP | CURLHELP_UPLOAD},
289 {" --form-string <name=string>",
290 "Specify multipart MIME data",
291 CURLHELP_HTTP | CURLHELP_UPLOAD},
292 {" --ftp-account <data>",
293 "Account data string",
294 CURLHELP_FTP | CURLHELP_AUTH},
295 {" --ftp-alternative-to-user <command>",
296 "String to replace USER [name]",
297 CURLHELP_FTP},
298 {" --ftp-create-dirs",
299 "Create the remote dirs if not present",
300 CURLHELP_FTP | CURLHELP_SFTP | CURLHELP_CURL},
301 {" --ftp-method <method>",
302 "Control CWD usage",
303 CURLHELP_FTP},
304 {" --ftp-pasv",
305 "Use PASV/EPSV instead of PORT",
306 CURLHELP_FTP},
307 {"-P, --ftp-port <address>",
308 "Use PORT instead of PASV",
309 CURLHELP_FTP},
310 {" --ftp-pret",
311 "Send PRET before PASV",
312 CURLHELP_FTP},
313 {" --ftp-skip-pasv-ip",
314 "Skip the IP address for PASV",
315 CURLHELP_FTP},
316 {" --ftp-ssl-ccc",
317 "Send CCC after authenticating",
318 CURLHELP_FTP | CURLHELP_TLS},
319 {" --ftp-ssl-ccc-mode <active/passive>",
320 "Set CCC mode",
321 CURLHELP_FTP | CURLHELP_TLS},
322 {" --ftp-ssl-control",
323 "Require SSL/TLS for FTP login, clear for transfer",
324 CURLHELP_FTP | CURLHELP_TLS},
325 {"-G, --get",
326 "Put the post data in the URL and use GET",
327 CURLHELP_HTTP | CURLHELP_UPLOAD},
328 {"-g, --globoff",
329 "Disable URL sequences and ranges using {} and []",
330 CURLHELP_CURL},
331 {" --happy-eyeballs-timeout-ms <milliseconds>",
332 "Time for IPv6 before trying IPv4",
333 CURLHELP_CONNECTION},
334 {" --haproxy-protocol",
335 "Send HAProxy PROXY protocol v1 header",
336 CURLHELP_HTTP | CURLHELP_PROXY},
337 {"-I, --head",
338 "Show document info only",
339 CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_FILE},
340 {"-H, --header <header/@file>",
341 "Pass custom header(s) to server",
342 CURLHELP_HTTP},
343 {"-h, --help <category>",
344 "Get help for commands",
345 CURLHELP_IMPORTANT | CURLHELP_CURL},
346 {" --hostpubmd5 <md5>",
347 "Acceptable MD5 hash of the host public key",
348 CURLHELP_SFTP | CURLHELP_SCP},
349 {" --hsts <file name>",
350 "Enable HSTS with this cache file",
351 CURLHELP_HTTP},
352 {" --http0.9",
353 "Allow HTTP 0.9 responses",
354 CURLHELP_HTTP},
355 {"-0, --http1.0",
356 "Use HTTP 1.0",
357 CURLHELP_HTTP},
358 {" --http1.1",
359 "Use HTTP 1.1",
360 CURLHELP_HTTP},
361 {" --http2",
362 "Use HTTP 2",
363 CURLHELP_HTTP},
364 {" --http2-prior-knowledge",
365 "Use HTTP 2 without HTTP/1.1 Upgrade",
366 CURLHELP_HTTP},
367 {" --http3",
368 "Use HTTP v3",
369 CURLHELP_HTTP},
370 {" --ignore-content-length",
371 "Ignore the size of the remote resource",
372 CURLHELP_HTTP | CURLHELP_FTP},
373 {"-i, --include",
374 "Include protocol response headers in the output",
375 CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
376 {"-k, --insecure",
377 "Allow insecure server connections when using SSL",
378 CURLHELP_TLS},
379 {" --interface <name>",
380 "Use network INTERFACE (or address)",
381 CURLHELP_CONNECTION},
382 {"-4, --ipv4",
383 "Resolve names to IPv4 addresses",
384 CURLHELP_CONNECTION | CURLHELP_DNS},
385 {"-6, --ipv6",
386 "Resolve names to IPv6 addresses",
387 CURLHELP_CONNECTION | CURLHELP_DNS},
388 {"-j, --junk-session-cookies",
389 "Ignore session cookies read from file",
390 CURLHELP_HTTP},
391 {" --keepalive-time <seconds>",
392 "Interval time for keepalive probes",
393 CURLHELP_CONNECTION},
394 {" --key <key>",
395 "Private key file name",
396 CURLHELP_TLS | CURLHELP_SSH},
397 {" --key-type <type>",
398 "Private key file type (DER/PEM/ENG)",
399 CURLHELP_TLS},
400 {" --krb <level>",
401 "Enable Kerberos with security <level>",
402 CURLHELP_FTP},
403 {" --libcurl <file>",
404 "Dump libcurl equivalent code of this command line",
405 CURLHELP_CURL},
406 {" --limit-rate <speed>",
407 "Limit transfer speed to RATE",
408 CURLHELP_CONNECTION},
409 {"-l, --list-only",
410 "List only mode",
411 CURLHELP_FTP | CURLHELP_POP3},
412 {" --local-port <num/range>",
413 "Force use of RANGE for local port numbers",
414 CURLHELP_CONNECTION},
415 {"-L, --location",
416 "Follow redirects",
417 CURLHELP_HTTP},
418 {" --location-trusted",
419 "Like --location, and send auth to other hosts",
420 CURLHELP_HTTP | CURLHELP_AUTH},
421 {" --login-options <options>",
422 "Server login options",
423 CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP | CURLHELP_AUTH},
424 {" --mail-auth <address>",
425 "Originator address of the original email",
426 CURLHELP_SMTP},
427 {" --mail-from <address>",
428 "Mail from this address",
429 CURLHELP_SMTP},
430 {" --mail-rcpt <address>",
431 "Mail to this address",
432 CURLHELP_SMTP},
433 {" --mail-rcpt-allowfails",
434 "Allow RCPT TO command to fail for some recipients",
435 CURLHELP_SMTP},
436 {"-M, --manual",
437 "Display the full manual",
438 CURLHELP_CURL},
439 {" --max-filesize <bytes>",
440 "Maximum file size to download",
441 CURLHELP_CONNECTION},
442 {" --max-redirs <num>",
443 "Maximum number of redirects allowed",
444 CURLHELP_HTTP},
445 {"-m, --max-time <seconds>",
446 "Maximum time allowed for the transfer",
447 CURLHELP_CONNECTION},
448 {" --metalink",
449 "Process given URLs as metalink XML file",
450 CURLHELP_MISC},
451 {" --negotiate",
452 "Use HTTP Negotiate (SPNEGO) authentication",
453 CURLHELP_AUTH | CURLHELP_HTTP},
454 {"-n, --netrc",
455 "Must read .netrc for user name and password",
456 CURLHELP_CURL},
457 {" --netrc-file <filename>",
458 "Specify FILE for netrc",
459 CURLHELP_CURL},
460 {" --netrc-optional",
461 "Use either .netrc or URL",
462 CURLHELP_CURL},
463 {"-:, --next",
464 "Make next URL use its separate set of options",
465 CURLHELP_CURL},
466 {" --no-alpn",
467 "Disable the ALPN TLS extension",
468 CURLHELP_TLS | CURLHELP_HTTP},
469 {"-N, --no-buffer",
470 "Disable buffering of the output stream",
471 CURLHELP_CURL},
472 {" --no-keepalive",
473 "Disable TCP keepalive on the connection",
474 CURLHELP_CONNECTION},
475 {" --no-npn",
476 "Disable the NPN TLS extension",
477 CURLHELP_TLS | CURLHELP_HTTP},
478 {" --no-progress-meter",
479 "Do not show the progress meter",
480 CURLHELP_VERBOSE},
481 {" --no-sessionid",
482 "Disable SSL session-ID reusing",
483 CURLHELP_TLS},
484 {" --noproxy <no-proxy-list>",
485 "List of hosts which do not use proxy",
486 CURLHELP_PROXY},
487 {" --ntlm",
488 "Use HTTP NTLM authentication",
489 CURLHELP_AUTH | CURLHELP_HTTP},
490 {" --ntlm-wb",
491 "Use HTTP NTLM authentication with winbind",
492 CURLHELP_AUTH | CURLHELP_HTTP},
493 {" --oauth2-bearer <token>",
494 "OAuth 2 Bearer Token",
495 CURLHELP_AUTH},
496 {"-o, --output <file>",
497 "Write to file instead of stdout",
498 CURLHELP_IMPORTANT | CURLHELP_CURL},
499 {" --output-dir <dir>",
500 "Directory to save files in",
501 CURLHELP_CURL},
502 {"-Z, --parallel",
503 "Perform transfers in parallel",
504 CURLHELP_CONNECTION | CURLHELP_CURL},
505 {" --parallel-immediate",
506 "Do not wait for multiplexing (with --parallel)",
507 CURLHELP_CONNECTION | CURLHELP_CURL},
508 {" --parallel-max <num>",
509 "Maximum concurrency for parallel transfers",
510 CURLHELP_CONNECTION | CURLHELP_CURL},
511 {" --pass <phrase>",
512 "Pass phrase for the private key",
513 CURLHELP_SSH | CURLHELP_TLS | CURLHELP_AUTH},
514 {" --path-as-is",
515 "Do not squash .. sequences in URL path",
516 CURLHELP_CURL},
517 {" --pinnedpubkey <hashes>",
518 "FILE/HASHES Public key to verify peer against",
519 CURLHELP_TLS},
520 {" --post301",
521 "Do not switch to GET after following a 301",
522 CURLHELP_HTTP | CURLHELP_POST},
523 {" --post302",
524 "Do not switch to GET after following a 302",
525 CURLHELP_HTTP | CURLHELP_POST},
526 {" --post303",
527 "Do not switch to GET after following a 303",
528 CURLHELP_HTTP | CURLHELP_POST},
529 {" --preproxy [protocol://]host[:port]",
530 "Use this proxy first",
531 CURLHELP_PROXY},
532 {"-#, --progress-bar",
533 "Display transfer progress as a bar",
534 CURLHELP_VERBOSE},
535 {" --proto <protocols>",
536 "Enable/disable PROTOCOLS",
537 CURLHELP_CONNECTION | CURLHELP_CURL},
538 {" --proto-default <protocol>",
539 "Use PROTOCOL for any URL missing a scheme",
540 CURLHELP_CONNECTION | CURLHELP_CURL},
541 {" --proto-redir <protocols>",
542 "Enable/disable PROTOCOLS on redirect",
543 CURLHELP_CONNECTION | CURLHELP_CURL},
544 {"-x, --proxy [protocol://]host[:port]",
545 "Use this proxy",
546 CURLHELP_PROXY},
547 {" --proxy-anyauth",
548 "Pick any proxy authentication method",
549 CURLHELP_PROXY | CURLHELP_AUTH},
550 {" --proxy-basic",
551 "Use Basic authentication on the proxy",
552 CURLHELP_PROXY | CURLHELP_AUTH},
553 {" --proxy-cacert <file>",
554 "CA certificate to verify peer against for proxy",
555 CURLHELP_PROXY | CURLHELP_TLS},
556 {" --proxy-capath <dir>",
557 "CA directory to verify peer against for proxy",
558 CURLHELP_PROXY | CURLHELP_TLS},
559 {" --proxy-cert <cert[:passwd]>",
560 "Set client certificate for proxy",
561 CURLHELP_PROXY | CURLHELP_TLS},
562 {" --proxy-cert-type <type>",
563 "Client certificate type for HTTPS proxy",
564 CURLHELP_PROXY | CURLHELP_TLS},
565 {" --proxy-ciphers <list>",
566 "SSL ciphers to use for proxy",
567 CURLHELP_PROXY | CURLHELP_TLS},
568 {" --proxy-crlfile <file>",
569 "Set a CRL list for proxy",
570 CURLHELP_PROXY | CURLHELP_TLS},
571 {" --proxy-digest",
572 "Use Digest authentication on the proxy",
573 CURLHELP_PROXY | CURLHELP_TLS},
574 {" --proxy-header <header/@file>",
575 "Pass custom header(s) to proxy",
576 CURLHELP_PROXY},
577 {" --proxy-insecure",
578 "Do HTTPS proxy connections without verifying the proxy",
579 CURLHELP_PROXY | CURLHELP_TLS},
580 {" --proxy-key <key>",
581 "Private key for HTTPS proxy",
582 CURLHELP_PROXY | CURLHELP_TLS},
583 {" --proxy-key-type <type>",
584 "Private key file type for proxy",
585 CURLHELP_PROXY | CURLHELP_TLS},
586 {" --proxy-negotiate",
587 "Use HTTP Negotiate (SPNEGO) authentication on the proxy",
588 CURLHELP_PROXY | CURLHELP_AUTH},
589 {" --proxy-ntlm",
590 "Use NTLM authentication on the proxy",
591 CURLHELP_PROXY | CURLHELP_AUTH},
592 {" --proxy-pass <phrase>",
593 "Pass phrase for the private key for HTTPS proxy",
594 CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
595 {" --proxy-pinnedpubkey <hashes>",
596 "FILE/HASHES public key to verify proxy with",
597 CURLHELP_PROXY | CURLHELP_TLS},
598 {" --proxy-service-name <name>",
599 "SPNEGO proxy service name",
600 CURLHELP_PROXY | CURLHELP_TLS},
601 {" --proxy-ssl-allow-beast",
602 "Allow security flaw for interop for HTTPS proxy",
603 CURLHELP_PROXY | CURLHELP_TLS},
604 {" --proxy-ssl-auto-client-cert",
605 "Use auto client certificate for proxy (Schannel)",
606 CURLHELP_PROXY | CURLHELP_TLS},
607 {" --proxy-tls13-ciphers <ciphersuite list>",
608 "TLS 1.3 proxy cipher suites",
609 CURLHELP_PROXY | CURLHELP_TLS},
610 {" --proxy-tlsauthtype <type>",
611 "TLS authentication type for HTTPS proxy",
612 CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
613 {" --proxy-tlspassword <string>",
614 "TLS password for HTTPS proxy",
615 CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
616 {" --proxy-tlsuser <name>",
617 "TLS username for HTTPS proxy",
618 CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
619 {" --proxy-tlsv1",
620 "Use TLSv1 for HTTPS proxy",
621 CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
622 {"-U, --proxy-user <user:password>",
623 "Proxy user and password",
624 CURLHELP_PROXY | CURLHELP_AUTH},
625 {" --proxy1.0 <host[:port]>",
626 "Use HTTP/1.0 proxy on given port",
627 CURLHELP_PROXY},
628 {"-p, --proxytunnel",
629 "Operate through an HTTP proxy tunnel (using CONNECT)",
630 CURLHELP_PROXY},
631 {" --pubkey <key>",
632 "SSH Public key file name",
633 CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_AUTH},
634 {"-Q, --quote <command>",
635 "Send command(s) to server before transfer",
636 CURLHELP_FTP | CURLHELP_SFTP},
637 {" --random-file <file>",
638 "File for reading random data from",
639 CURLHELP_MISC},
640 {"-r, --range <range>",
641 "Retrieve only the bytes within RANGE",
642 CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_SFTP | CURLHELP_FILE},
643 {" --raw",
644 "Do HTTP \"raw\"; no transfer decoding",
645 CURLHELP_HTTP},
646 {"-e, --referer <URL>",
647 "Referrer URL",
648 CURLHELP_HTTP},
649 {"-J, --remote-header-name",
650 "Use the header-provided filename",
651 CURLHELP_OUTPUT},
652 {"-O, --remote-name",
653 "Write output to a file named as the remote file",
654 CURLHELP_IMPORTANT | CURLHELP_OUTPUT},
655 {" --remote-name-all",
656 "Use the remote file name for all URLs",
657 CURLHELP_OUTPUT},
658 {"-R, --remote-time",
659 "Set the remote file's time on the local output",
660 CURLHELP_OUTPUT},
661 {"-X, --request <command>",
662 "Specify request command to use",
663 CURLHELP_CONNECTION},
664 {" --request-target <path>",
665 "Specify the target for this request",
666 CURLHELP_HTTP},
667 {" --resolve <[+]host:port:addr[,addr]...>",
668 "Resolve the host+port to this address",
669 CURLHELP_CONNECTION},
670 {" --retry <num>",
671 "Retry request if transient problems occur",
672 CURLHELP_CURL},
673 {" --retry-all-errors",
674 "Retry all errors (use with --retry)",
675 CURLHELP_CURL},
676 {" --retry-connrefused",
677 "Retry on connection refused (use with --retry)",
678 CURLHELP_CURL},
679 {" --retry-delay <seconds>",
680 "Wait time between retries",
681 CURLHELP_CURL},
682 {" --retry-max-time <seconds>",
683 "Retry only within this period",
684 CURLHELP_CURL},
685 {" --sasl-authzid <identity>",
686 "Identity for SASL PLAIN authentication",
687 CURLHELP_AUTH},
688 {" --sasl-ir",
689 "Enable initial response in SASL authentication",
690 CURLHELP_AUTH},
691 {" --service-name <name>",
692 "SPNEGO service name",
693 CURLHELP_MISC},
694 {"-S, --show-error",
695 "Show error even when -s is used",
696 CURLHELP_CURL},
697 {"-s, --silent",
698 "Silent mode",
699 CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
700 {" --socks4 <host[:port]>",
701 "SOCKS4 proxy on given host + port",
702 CURLHELP_PROXY},
703 {" --socks4a <host[:port]>",
704 "SOCKS4a proxy on given host + port",
705 CURLHELP_PROXY},
706 {" --socks5 <host[:port]>",
707 "SOCKS5 proxy on given host + port",
708 CURLHELP_PROXY},
709 {" --socks5-basic",
710 "Enable username/password auth for SOCKS5 proxies",
711 CURLHELP_PROXY | CURLHELP_AUTH},
712 {" --socks5-gssapi",
713 "Enable GSS-API auth for SOCKS5 proxies",
714 CURLHELP_PROXY | CURLHELP_AUTH},
715 {" --socks5-gssapi-nec",
716 "Compatibility with NEC SOCKS5 server",
717 CURLHELP_PROXY | CURLHELP_AUTH},
718 {" --socks5-gssapi-service <name>",
719 "SOCKS5 proxy service name for GSS-API",
720 CURLHELP_PROXY | CURLHELP_AUTH},
721 {" --socks5-hostname <host[:port]>",
722 "SOCKS5 proxy, pass host name to proxy",
723 CURLHELP_PROXY},
724 {"-Y, --speed-limit <speed>",
725 "Stop transfers slower than this",
726 CURLHELP_CONNECTION},
727 {"-y, --speed-time <seconds>",
728 "Trigger 'speed-limit' abort after this time",
729 CURLHELP_CONNECTION},
730 {" --ssl",
731 "Try SSL/TLS",
732 CURLHELP_TLS},
733 {" --ssl-allow-beast",
734 "Allow security flaw to improve interop",
735 CURLHELP_TLS},
736 {" --ssl-auto-client-cert",
737 "Use auto client certificate (Schannel)",
738 CURLHELP_TLS},
739 {" --ssl-no-revoke",
740 "Disable cert revocation checks (Schannel)",
741 CURLHELP_TLS},
742 {" --ssl-reqd",
743 "Require SSL/TLS",
744 CURLHELP_TLS},
745 {" --ssl-revoke-best-effort",
746 "Ignore missing/offline cert CRL dist points",
747 CURLHELP_TLS},
748 {"-2, --sslv2",
749 "Use SSLv2",
750 CURLHELP_TLS},
751 {"-3, --sslv3",
752 "Use SSLv3",
753 CURLHELP_TLS},
754 {" --stderr <file>",
755 "Where to redirect stderr",
756 CURLHELP_VERBOSE},
757 {" --styled-output",
758 "Enable styled output for HTTP headers",
759 CURLHELP_VERBOSE},
760 {" --suppress-connect-headers",
761 "Suppress proxy CONNECT response headers",
762 CURLHELP_PROXY},
763 {" --tcp-fastopen",
764 "Use TCP Fast Open",
765 CURLHELP_CONNECTION},
766 {" --tcp-nodelay",
767 "Use the TCP_NODELAY option",
768 CURLHELP_CONNECTION},
769 {"-t, --telnet-option <opt=val>",
770 "Set telnet option",
771 CURLHELP_TELNET},
772 {" --tftp-blksize <value>",
773 "Set TFTP BLKSIZE option",
774 CURLHELP_TFTP},
775 {" --tftp-no-options",
776 "Do not send any TFTP options",
777 CURLHELP_TFTP},
778 {"-z, --time-cond <time>",
779 "Transfer based on a time condition",
780 CURLHELP_HTTP | CURLHELP_FTP},
781 {" --tls-max <VERSION>",
782 "Set maximum allowed TLS version",
783 CURLHELP_TLS},
784 {" --tls13-ciphers <ciphersuite list>",
785 "TLS 1.3 cipher suites to use",
786 CURLHELP_TLS},
787 {" --tlsauthtype <type>",
788 "TLS authentication type",
789 CURLHELP_TLS | CURLHELP_AUTH},
790 {" --tlspassword <string>",
791 "TLS password",
792 CURLHELP_TLS | CURLHELP_AUTH},
793 {" --tlsuser <name>",
794 "TLS user name",
795 CURLHELP_TLS | CURLHELP_AUTH},
796 {"-1, --tlsv1",
797 "Use TLSv1.0 or greater",
798 CURLHELP_TLS},
799 {" --tlsv1.0",
800 "Use TLSv1.0 or greater",
801 CURLHELP_TLS},
802 {" --tlsv1.1",
803 "Use TLSv1.1 or greater",
804 CURLHELP_TLS},
805 {" --tlsv1.2",
806 "Use TLSv1.2 or greater",
807 CURLHELP_TLS},
808 {" --tlsv1.3",
809 "Use TLSv1.3 or greater",
810 CURLHELP_TLS},
811 {" --tr-encoding",
812 "Request compressed transfer encoding",
813 CURLHELP_HTTP},
814 {" --trace <file>",
815 "Write a debug trace to FILE",
816 CURLHELP_VERBOSE},
817 {" --trace-ascii <file>",
818 "Like --trace, but without hex output",
819 CURLHELP_VERBOSE},
820 {" --trace-time",
821 "Add time stamps to trace/verbose output",
822 CURLHELP_VERBOSE},
823 {" --unix-socket <path>",
824 "Connect through this Unix domain socket",
825 CURLHELP_CONNECTION},
826 {"-T, --upload-file <file>",
827 "Transfer local FILE to destination",
828 CURLHELP_IMPORTANT | CURLHELP_UPLOAD},
829 {" --url <url>",
830 "URL to work with",
831 CURLHELP_CURL},
832 {"-B, --use-ascii",
833 "Use ASCII/text transfer",
834 CURLHELP_MISC},
835 {"-u, --user <user:password>",
836 "Server user and password",
837 CURLHELP_IMPORTANT | CURLHELP_AUTH},
838 {"-A, --user-agent <name>",
839 "Send User-Agent <name> to server",
840 CURLHELP_IMPORTANT | CURLHELP_HTTP},
841 {"-v, --verbose",
842 "Make the operation more talkative",
843 CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
844 {"-V, --version",
845 "Show version number and quit",
846 CURLHELP_IMPORTANT | CURLHELP_CURL},
847 {"-w, --write-out <format>",
848 "Use output FORMAT after completion",
849 CURLHELP_VERBOSE},
850 {" --xattr",
851 "Store metadata in extended file attributes",
852 CURLHELP_MISC},
853 { NULL, NULL, CURLHELP_HIDDEN }
854 };
855
856 struct feat {
857 const char *name;
858 int bitmask;
859 };
860
861 static const struct feat feats[] = {
862 {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
863 {"Debug", CURL_VERSION_DEBUG},
864 {"TrackMemory", CURL_VERSION_CURLDEBUG},
865 {"IDN", CURL_VERSION_IDN},
866 {"IPv6", CURL_VERSION_IPV6},
867 {"Largefile", CURL_VERSION_LARGEFILE},
868 {"Unicode", CURL_VERSION_UNICODE},
869 {"SSPI", CURL_VERSION_SSPI},
870 {"GSS-API", CURL_VERSION_GSSAPI},
871 {"Kerberos", CURL_VERSION_KERBEROS5},
872 {"SPNEGO", CURL_VERSION_SPNEGO},
873 {"NTLM", CURL_VERSION_NTLM},
874 {"NTLM_WB", CURL_VERSION_NTLM_WB},
875 {"SSL", CURL_VERSION_SSL},
876 {"libz", CURL_VERSION_LIBZ},
877 {"brotli", CURL_VERSION_BROTLI},
878 {"zstd", CURL_VERSION_ZSTD},
879 {"CharConv", CURL_VERSION_CONV},
880 {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
881 {"HTTP2", CURL_VERSION_HTTP2},
882 {"HTTP3", CURL_VERSION_HTTP3},
883 {"UnixSockets", CURL_VERSION_UNIX_SOCKETS},
884 {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
885 {"MultiSSL", CURL_VERSION_MULTI_SSL},
886 {"PSL", CURL_VERSION_PSL},
887 {"alt-svc", CURL_VERSION_ALTSVC},
888 {"HSTS", CURL_VERSION_HSTS},
889 {"gsasl", CURL_VERSION_GSASL},
890 };
891
print_category(curlhelp_t category)892 static void print_category(curlhelp_t category)
893 {
894 unsigned int i;
895 for(i = 0; helptext[i].opt; ++i)
896 if(helptext[i].categories & category) {
897 printf(" %-18s %s\n", helptext[i].opt, helptext[i].desc);
898 }
899 }
900
901 /* Prints category if found. If not, it returns 1 */
get_category_content(const char * category)902 static int get_category_content(const char *category)
903 {
904 unsigned int i;
905 for(i = 0; categories[i].opt; ++i)
906 if(curl_strequal(categories[i].opt, category)) {
907 printf("%s: %s\n", categories[i].opt, categories[i].desc);
908 print_category(categories[i].category);
909 return 0;
910 }
911 return 1;
912 }
913
914 /* Prints all categories and their description */
get_categories(void)915 static void get_categories(void)
916 {
917 unsigned int i;
918 for(i = 0; categories[i].opt; ++i)
919 printf(" %-11s %s\n", categories[i].opt, categories[i].desc);
920 }
921
922
tool_help(char * category)923 void tool_help(char *category)
924 {
925 puts("Usage: curl [options...] <url>");
926 /* If no category was provided */
927 if(!category) {
928 const char *category_note = "\nThis is not the full help, this "
929 "menu is stripped into categories.\nUse \"--help category\" to get "
930 "an overview of all categories.\nFor all options use the manual"
931 " or \"--help all\".";
932 print_category(CURLHELP_IMPORTANT);
933 puts(category_note);
934 }
935 /* Lets print everything if "all" was provided */
936 else if(curl_strequal(category, "all"))
937 /* Print everything except hidden */
938 print_category(~(CURLHELP_HIDDEN));
939 /* Lets handle the string "category" differently to not print an errormsg */
940 else if(curl_strequal(category, "category"))
941 get_categories();
942 /* Otherwise print category and handle the case if the cat was not found */
943 else if(get_category_content(category)) {
944 puts("Invalid category provided, here is a list of all categories:\n");
945 get_categories();
946 }
947 free(category);
948 }
949
950 static int
featcomp(const void * p1,const void * p2)951 featcomp(const void *p1, const void *p2)
952 {
953 /* The arguments to this function are "pointers to pointers to char", but
954 the comparison arguments are "pointers to char", hence the following cast
955 plus dereference */
956 #ifdef HAVE_STRCASECMP
957 return strcasecmp(* (char * const *) p1, * (char * const *) p2);
958 #elif defined(HAVE_STRCMPI)
959 return strcmpi(* (char * const *) p1, * (char * const *) p2);
960 #else
961 return strcmp(* (char * const *) p1, * (char * const *) p2);
962 #endif
963 }
964
tool_version_info(void)965 void tool_version_info(void)
966 {
967 const char *const *proto;
968
969 printf(CURL_ID "%s\n", curl_version());
970 #ifdef CURL_PATCHSTAMP
971 printf("Release-Date: %s, security patched: %s\n",
972 LIBCURL_TIMESTAMP, CURL_PATCHSTAMP);
973 #else
974 printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
975 #endif
976 if(curlinfo->protocols) {
977 printf("Protocols: ");
978 for(proto = curlinfo->protocols; *proto; ++proto) {
979 printf("%s ", *proto);
980 }
981 puts(""); /* newline */
982 }
983 if(curlinfo->features) {
984 char *featp[ sizeof(feats) / sizeof(feats[0]) + 1];
985 size_t numfeat = 0;
986 unsigned int i;
987 printf("Features:");
988 for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
989 if(curlinfo->features & feats[i].bitmask)
990 featp[numfeat++] = (char *)feats[i].name;
991 }
992 qsort(&featp[0], numfeat, sizeof(char *), featcomp);
993 for(i = 0; i< numfeat; i++)
994 printf(" %s", featp[i]);
995 puts(""); /* newline */
996 }
997 if(strcmp(CURL_VERSION, curlinfo->version)) {
998 printf("WARNING: curl and libcurl versions do not match. "
999 "Functionality may be affected.\n");
1000 }
1001 }
1002
tool_list_engines(void)1003 void tool_list_engines(void)
1004 {
1005 CURL *curl = curl_easy_init();
1006 struct curl_slist *engines = NULL;
1007
1008 /* Get the list of engines */
1009 curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
1010
1011 puts("Build-time engines:");
1012 if(engines) {
1013 for(; engines; engines = engines->next)
1014 printf(" %s\n", engines->data);
1015 }
1016 else {
1017 puts(" <none>");
1018 }
1019
1020 /* Cleanup the list of engines */
1021 curl_slist_free_all(engines);
1022 curl_easy_cleanup(curl);
1023 }
1024