• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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