quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tool_help.c (12529B)


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