Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/src/tool_help.c
2065 views
1
/***************************************************************************
2
* _ _ ____ _
3
* Project ___| | | | _ \| |
4
* / __| | | | |_) | |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
7
*
8
* Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9
*
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at https://curl.se/docs/copyright.html.
13
*
14
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
* copies of the Software, and permit persons to whom the Software is
16
* furnished to do so, under the terms of the COPYING file.
17
*
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
20
*
21
* SPDX-License-Identifier: curl
22
*
23
***************************************************************************/
24
#include "tool_setup.h"
25
26
#include <curlx.h>
27
28
#include "tool_help.h"
29
#include "tool_libinfo.h"
30
#include "tool_util.h"
31
#include "tool_version.h"
32
#include "tool_cb_prg.h"
33
#include "tool_hugehelp.h"
34
#include "tool_getparam.h"
35
#include "tool_cfgable.h"
36
#include "terminal.h"
37
38
#include <memdebug.h> /* keep this as LAST include */
39
40
struct category_descriptors {
41
const char *opt;
42
const char *desc;
43
unsigned int category;
44
};
45
46
static const struct category_descriptors categories[] = {
47
/* important is left out because it is the default help page */
48
{"auth", "Authentication methods", CURLHELP_AUTH},
49
{"connection", "Manage connections", CURLHELP_CONNECTION},
50
{"curl", "The command line tool itself", CURLHELP_CURL},
51
{"deprecated", "Legacy", CURLHELP_DEPRECATED},
52
{"dns", "Names and resolving", CURLHELP_DNS},
53
{"file", "FILE protocol", CURLHELP_FILE},
54
{"ftp", "FTP protocol", CURLHELP_FTP},
55
{"global", "Global options", CURLHELP_GLOBAL},
56
{"http", "HTTP and HTTPS protocol", CURLHELP_HTTP},
57
{"imap", "IMAP protocol", CURLHELP_IMAP},
58
{"ldap", "LDAP protocol", CURLHELP_LDAP},
59
{"output", "Filesystem output", CURLHELP_OUTPUT},
60
{"pop3", "POP3 protocol", CURLHELP_POP3},
61
{"post", "HTTP POST specific", CURLHELP_POST},
62
{"proxy", "Options for proxies", CURLHELP_PROXY},
63
{"scp", "SCP protocol", CURLHELP_SCP},
64
{"sftp", "SFTP protocol", CURLHELP_SFTP},
65
{"smtp", "SMTP protocol", CURLHELP_SMTP},
66
{"ssh", "SSH protocol", CURLHELP_SSH},
67
{"telnet", "TELNET protocol", CURLHELP_TELNET},
68
{"tftp", "TFTP protocol", CURLHELP_TFTP},
69
{"timeout", "Timeouts and delays", CURLHELP_TIMEOUT},
70
{"tls", "TLS/SSL related", CURLHELP_TLS},
71
{"upload", "Upload, sending data", CURLHELP_UPLOAD},
72
{"verbose", "Tracing, logging etc", CURLHELP_VERBOSE}
73
};
74
75
static void print_category(unsigned int category, unsigned int cols)
76
{
77
unsigned int i;
78
size_t longopt = 5;
79
size_t longdesc = 5;
80
81
for(i = 0; helptext[i].opt; ++i) {
82
size_t len;
83
if(!(helptext[i].categories & category))
84
continue;
85
len = strlen(helptext[i].opt);
86
if(len > longopt)
87
longopt = len;
88
len = strlen(helptext[i].desc);
89
if(len > longdesc)
90
longdesc = len;
91
}
92
if(longopt + longdesc > cols)
93
longopt = cols - longdesc;
94
95
for(i = 0; helptext[i].opt; ++i)
96
if(helptext[i].categories & category) {
97
size_t opt = longopt;
98
size_t desclen = strlen(helptext[i].desc);
99
if(opt + desclen >= (cols - 2)) {
100
if(desclen < (cols - 2))
101
opt = (cols - 3) - desclen;
102
else
103
opt = 0;
104
}
105
printf(" %-*s %s\n", (int)opt, helptext[i].opt, helptext[i].desc);
106
}
107
}
108
109
/* Prints category if found. If not, it returns 1 */
110
static int get_category_content(const char *category, unsigned int cols)
111
{
112
unsigned int i;
113
for(i = 0; i < CURL_ARRAYSIZE(categories); ++i)
114
if(curl_strequal(categories[i].opt, category)) {
115
printf("%s: %s\n", categories[i].opt, categories[i].desc);
116
print_category(categories[i].category, cols);
117
return 0;
118
}
119
return 1;
120
}
121
122
/* Prints all categories and their description */
123
static void get_categories(void)
124
{
125
unsigned int i;
126
for(i = 0; i < CURL_ARRAYSIZE(categories); ++i)
127
printf(" %-11s %s\n", categories[i].opt, categories[i].desc);
128
}
129
130
/* Prints all categories as a comma-separated list of given width */
131
static void get_categories_list(unsigned int width)
132
{
133
unsigned int i;
134
size_t col = 0;
135
for(i = 0; i < CURL_ARRAYSIZE(categories); ++i) {
136
size_t len = strlen(categories[i].opt);
137
if(i == CURL_ARRAYSIZE(categories) - 1) {
138
/* final category */
139
if(col + len + 1 < width)
140
printf("%s.\n", categories[i].opt);
141
else
142
/* start a new line first */
143
printf("\n%s.\n", categories[i].opt);
144
}
145
else if(col + len + 2 < width) {
146
printf("%s, ", categories[i].opt);
147
col += len + 2;
148
}
149
else {
150
/* start a new line first */
151
printf("\n%s, ", categories[i].opt);
152
col = len + 2;
153
}
154
}
155
}
156
157
#ifdef USE_MANUAL
158
159
void inithelpscan(struct scan_ctx *ctx,
160
const char *trigger,
161
const char *arg,
162
const char *endarg)
163
{
164
ctx->trigger = trigger;
165
ctx->tlen = strlen(trigger);
166
ctx->arg = arg;
167
ctx->flen = strlen(arg);
168
ctx->endarg = endarg;
169
ctx->elen = strlen(endarg);
170
DEBUGASSERT((ctx->elen < sizeof(ctx->rbuf)) ||
171
(ctx->flen < sizeof(ctx->rbuf)));
172
ctx->show = 0;
173
ctx->olen = 0;
174
memset(ctx->rbuf, 0, sizeof(ctx->rbuf));
175
}
176
177
bool helpscan(const unsigned char *buf, size_t len, struct scan_ctx *ctx)
178
{
179
size_t i;
180
for(i = 0; i < len; i++) {
181
if(!ctx->show) {
182
/* wait for the trigger */
183
memmove(&ctx->rbuf[0], &ctx->rbuf[1], ctx->tlen - 1);
184
ctx->rbuf[ctx->tlen - 1] = buf[i];
185
if(!memcmp(ctx->rbuf, ctx->trigger, ctx->tlen))
186
ctx->show++;
187
continue;
188
}
189
/* past the trigger */
190
if(ctx->show == 1) {
191
memmove(&ctx->rbuf[0], &ctx->rbuf[1], ctx->flen - 1);
192
ctx->rbuf[ctx->flen - 1] = buf[i];
193
if(!memcmp(ctx->rbuf, ctx->arg, ctx->flen)) {
194
/* match, now output until endarg */
195
fputs(&ctx->arg[1], stdout);
196
ctx->show++;
197
}
198
continue;
199
}
200
/* show until the end */
201
memmove(&ctx->rbuf[0], &ctx->rbuf[1], ctx->elen - 1);
202
ctx->rbuf[ctx->elen - 1] = buf[i];
203
if(!memcmp(ctx->rbuf, ctx->endarg, ctx->elen))
204
return FALSE;
205
206
if(buf[i] == '\n') {
207
DEBUGASSERT(ctx->olen < sizeof(ctx->obuf));
208
if(ctx->olen == sizeof(ctx->obuf))
209
return FALSE; /* bail out */
210
ctx->obuf[ctx->olen++] = 0;
211
ctx->olen = 0;
212
puts(ctx->obuf);
213
}
214
else {
215
DEBUGASSERT(ctx->olen < sizeof(ctx->obuf));
216
if(ctx->olen == sizeof(ctx->obuf))
217
return FALSE; /* bail out */
218
ctx->obuf[ctx->olen++] = buf[i];
219
}
220
}
221
return TRUE;
222
}
223
224
#endif
225
226
void tool_help(const char *category)
227
{
228
unsigned int cols = get_terminal_columns();
229
/* If no category was provided */
230
if(!category) {
231
const char *category_note = "\nThis is not the full help; this "
232
"menu is split into categories.\nUse \"--help category\" to get "
233
"an overview of all categories, which are:";
234
const char *category_note2 =
235
"Use \"--help all\" to list all options"
236
#ifdef USE_MANUAL
237
"\nUse \"--help [option]\" to view documentation for a given option"
238
#endif
239
;
240
puts("Usage: curl [options...] <url>");
241
print_category(CURLHELP_IMPORTANT, cols);
242
puts(category_note);
243
get_categories_list(cols);
244
puts(category_note2);
245
}
246
/* Lets print everything if "all" was provided */
247
else if(curl_strequal(category, "all"))
248
/* Print everything */
249
print_category(CURLHELP_ALL, cols);
250
/* Lets handle the string "category" differently to not print an errormsg */
251
else if(curl_strequal(category, "category"))
252
get_categories();
253
else if(category[0] == '-') {
254
#ifdef USE_MANUAL
255
/* command line option help */
256
const struct LongShort *a = NULL;
257
if(category[1] == '-') {
258
const char *lookup = &category[2];
259
bool noflagged = FALSE;
260
if(!strncmp(lookup, "no-", 3)) {
261
lookup += 3;
262
noflagged = TRUE;
263
}
264
a = findlongopt(lookup);
265
if(a && noflagged && (ARGTYPE(a->desc) != ARG_BOOL))
266
/* a --no- prefix for a non-boolean is not specifying a proper
267
option */
268
a = NULL;
269
}
270
else if(!category[2])
271
a = findshortopt(category[1]);
272
if(!a) {
273
fprintf(tool_stderr, "Incorrect option name to show help for,"
274
" see curl -h\n");
275
}
276
else {
277
char cmdbuf[80];
278
if(a->letter != ' ')
279
msnprintf(cmdbuf, sizeof(cmdbuf), "\n -%c, --", a->letter);
280
else if(a->desc & ARG_NO)
281
msnprintf(cmdbuf, sizeof(cmdbuf), "\n --no-%s", a->lname);
282
else
283
msnprintf(cmdbuf, sizeof(cmdbuf), "\n %s", category);
284
#ifdef USE_MANUAL
285
if(a->cmd == C_XATTR)
286
/* this is the last option, which then ends when FILES starts */
287
showhelp("\nALL OPTIONS\n", cmdbuf, "\nFILES");
288
else
289
showhelp("\nALL OPTIONS\n", cmdbuf, "\n -");
290
#endif
291
}
292
#else
293
fprintf(tool_stderr, "Cannot comply. "
294
"This curl was built without built-in manual\n");
295
#endif
296
}
297
/* Otherwise print category and handle the case if the cat was not found */
298
else if(get_category_content(category, cols)) {
299
puts("Unknown category provided, here is a list of all categories:\n");
300
get_categories();
301
}
302
}
303
304
static bool is_debug(void)
305
{
306
const char *const *builtin;
307
for(builtin = feature_names; *builtin; ++builtin)
308
if(curl_strequal("debug", *builtin))
309
return TRUE;
310
return FALSE;
311
}
312
313
void tool_version_info(void)
314
{
315
const char *const *builtin;
316
if(is_debug())
317
fprintf(tool_stderr, "WARNING: this libcurl is Debug-enabled, "
318
"do not use in production\n\n");
319
320
printf(CURL_ID "%s\n", curl_version());
321
#ifdef CURL_PATCHSTAMP
322
printf("Release-Date: %s, security patched: %s\n",
323
LIBCURL_TIMESTAMP, CURL_PATCHSTAMP);
324
#else
325
printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
326
#endif
327
if(built_in_protos[0]) {
328
#ifndef CURL_DISABLE_IPFS
329
const char *insert = NULL;
330
/* we have ipfs and ipns support if libcurl has http support */
331
for(builtin = built_in_protos; *builtin; ++builtin) {
332
if(insert) {
333
/* update insertion so ipfs will be printed in alphabetical order */
334
if(strcmp(*builtin, "ipfs") < 0)
335
insert = *builtin;
336
else
337
break;
338
}
339
else if(!strcmp(*builtin, "http")) {
340
insert = *builtin;
341
}
342
}
343
#endif /* !CURL_DISABLE_IPFS */
344
printf("Protocols:");
345
for(builtin = built_in_protos; *builtin; ++builtin) {
346
/* Special case: do not list rtmp?* protocols.
347
They may only appear together with "rtmp" */
348
if(!curl_strnequal(*builtin, "rtmp", 4) || !builtin[0][4])
349
printf(" %s", *builtin);
350
#ifndef CURL_DISABLE_IPFS
351
if(insert && insert == *builtin) {
352
printf(" ipfs ipns");
353
insert = NULL;
354
}
355
#endif /* !CURL_DISABLE_IPFS */
356
}
357
puts(""); /* newline */
358
}
359
if(feature_names[0]) {
360
const char **feat_ext;
361
size_t feat_ext_count = feature_count;
362
#ifdef CURL_CA_EMBED
363
++feat_ext_count;
364
#endif
365
feat_ext = malloc(sizeof(*feature_names) * (feat_ext_count + 1));
366
if(feat_ext) {
367
memcpy((void *)feat_ext, feature_names,
368
sizeof(*feature_names) * feature_count);
369
feat_ext_count = feature_count;
370
#ifdef CURL_CA_EMBED
371
feat_ext[feat_ext_count++] = "CAcert";
372
#endif
373
feat_ext[feat_ext_count] = NULL;
374
qsort((void *)feat_ext, feat_ext_count, sizeof(*feat_ext),
375
struplocompare4sort);
376
printf("Features:");
377
for(builtin = feat_ext; *builtin; ++builtin)
378
printf(" %s", *builtin);
379
puts(""); /* newline */
380
free((void *)feat_ext);
381
}
382
}
383
if(strcmp(CURL_VERSION, curlinfo->version)) {
384
printf("WARNING: curl and libcurl versions do not match. "
385
"Functionality may be affected.\n");
386
}
387
}
388
389
void tool_list_engines(void)
390
{
391
CURL *curl = curl_easy_init();
392
struct curl_slist *engines = NULL;
393
394
/* Get the list of engines */
395
curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
396
397
puts("Build-time engines:");
398
if(engines) {
399
for(; engines; engines = engines->next)
400
printf(" %s\n", engines->data);
401
}
402
else {
403
puts(" <none>");
404
}
405
406
/* Cleanup the list of engines */
407
curl_slist_free_all(engines);
408
curl_easy_cleanup(curl);
409
}
410
411