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