xref: /third_party/curl/src/tool_libinfo.c (revision 13498266)
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 "strcase.h"
27
28#define ENABLE_CURLX_PRINTF
29/* use our own printf() functions */
30#include "curlx.h"
31
32#include "tool_libinfo.h"
33
34#include "memdebug.h" /* keep this as LAST include */
35
36/* global variable definitions, for libcurl run-time info */
37
38static const char *no_protos = NULL;
39
40curl_version_info_data *curlinfo = NULL;
41const char * const *built_in_protos = &no_protos;
42
43size_t proto_count = 0;
44
45const char *proto_file = NULL;
46const char *proto_ftp = NULL;
47const char *proto_ftps = NULL;
48const char *proto_http = NULL;
49const char *proto_https = NULL;
50const char *proto_rtsp = NULL;
51const char *proto_scp = NULL;
52const char *proto_sftp = NULL;
53const char *proto_tftp = NULL;
54const char *proto_ipfs = "ipfs";
55const char *proto_ipns = "ipns";
56
57static struct proto_name_tokenp {
58  const char   *proto_name;
59  const char  **proto_tokenp;
60} const possibly_built_in[] = {
61  { "file",     &proto_file  },
62  { "ftp",      &proto_ftp   },
63  { "ftps",     &proto_ftps  },
64  { "http",     &proto_http  },
65  { "https",    &proto_https },
66  { "rtsp",     &proto_rtsp  },
67  { "scp",      &proto_scp   },
68  { "sftp",     &proto_sftp  },
69  { "tftp",     &proto_tftp  },
70  {  NULL,      NULL         }
71};
72
73bool feature_altsvc = FALSE;
74bool feature_brotli = FALSE;
75bool feature_hsts = FALSE;
76bool feature_http2 = FALSE;
77bool feature_http3 = FALSE;
78bool feature_httpsproxy = FALSE;
79bool feature_libz = FALSE;
80bool feature_ntlm = FALSE;
81bool feature_ntlm_wb = FALSE;
82bool feature_spnego = FALSE;
83bool feature_ssl = FALSE;
84bool feature_tls_srp = FALSE;
85bool feature_zstd = FALSE;
86
87static struct feature_name_presentp {
88  const char   *feature_name;
89  bool         *feature_presentp;
90  int           feature_bitmask;
91} const maybe_feature[] = {
92  /* Keep alphabetically sorted. */
93  {"alt-svc",        &feature_altsvc,     CURL_VERSION_ALTSVC},
94  {"AsynchDNS",      NULL,                CURL_VERSION_ASYNCHDNS},
95  {"brotli",         &feature_brotli,     CURL_VERSION_BROTLI},
96  {"CharConv",       NULL,                CURL_VERSION_CONV},
97  {"Debug",          NULL,                CURL_VERSION_DEBUG},
98  {"gsasl",          NULL,                CURL_VERSION_GSASL},
99  {"GSS-API",        NULL,                CURL_VERSION_GSSAPI},
100  {"HSTS",           &feature_hsts,       CURL_VERSION_HSTS},
101  {"HTTP2",          &feature_http2,      CURL_VERSION_HTTP2},
102  {"HTTP3",          &feature_http3,      CURL_VERSION_HTTP3},
103  {"HTTPS-proxy",    &feature_httpsproxy, CURL_VERSION_HTTPS_PROXY},
104  {"IDN",            NULL,                CURL_VERSION_IDN},
105  {"IPv6",           NULL,                CURL_VERSION_IPV6},
106  {"Kerberos",       NULL,                CURL_VERSION_KERBEROS5},
107  {"Largefile",      NULL,                CURL_VERSION_LARGEFILE},
108  {"libz",           &feature_libz,       CURL_VERSION_LIBZ},
109  {"MultiSSL",       NULL,                CURL_VERSION_MULTI_SSL},
110  {"NTLM",           &feature_ntlm,       CURL_VERSION_NTLM},
111  {"NTLM_WB",        &feature_ntlm_wb,    CURL_VERSION_NTLM_WB},
112  {"PSL",            NULL,                CURL_VERSION_PSL},
113  {"SPNEGO",         &feature_spnego,     CURL_VERSION_SPNEGO},
114  {"SSL",            &feature_ssl,        CURL_VERSION_SSL},
115  {"SSPI",           NULL,                CURL_VERSION_SSPI},
116  {"threadsafe",     NULL,                CURL_VERSION_THREADSAFE},
117  {"TLS-SRP",        &feature_tls_srp,    CURL_VERSION_TLSAUTH_SRP},
118  {"TrackMemory",    NULL,                CURL_VERSION_CURLDEBUG},
119  {"Unicode",        NULL,                CURL_VERSION_UNICODE},
120  {"UnixSockets",    NULL,                CURL_VERSION_UNIX_SOCKETS},
121  {"zstd",           &feature_zstd,       CURL_VERSION_ZSTD},
122  {NULL,             NULL,                0}
123};
124
125static const char *fnames[sizeof(maybe_feature) / sizeof(maybe_feature[0])];
126const char * const *feature_names = fnames;
127
128/*
129 * libcurl_info_init: retrieves run-time information about libcurl,
130 * setting a global pointer 'curlinfo' to libcurl's run-time info
131 * struct, count protocols and flag those we are interested in.
132 * Global pointer feature_names is set to the feature names array. If
133 * the latter is not returned by curl_version_info(), it is built from
134 * the returned features bit mask.
135 */
136
137CURLcode get_libcurl_info(void)
138{
139  CURLcode result = CURLE_OK;
140  const char *const *builtin;
141
142  /* Pointer to libcurl's run-time version information */
143  curlinfo = curl_version_info(CURLVERSION_NOW);
144  if(!curlinfo)
145    return CURLE_FAILED_INIT;
146
147  if(curlinfo->protocols) {
148    const struct proto_name_tokenp *p;
149
150    built_in_protos = curlinfo->protocols;
151
152    for(builtin = built_in_protos; !result && *builtin; builtin++) {
153      /* Identify protocols we are interested in. */
154      for(p = possibly_built_in; p->proto_name; p++)
155        if(curl_strequal(p->proto_name, *builtin)) {
156          *p->proto_tokenp = *builtin;
157          break;
158        }
159    }
160    proto_count = builtin - built_in_protos;
161  }
162
163  if(curlinfo->age >= CURLVERSION_ELEVENTH && curlinfo->feature_names)
164    feature_names = curlinfo->feature_names;
165  else {
166    const struct feature_name_presentp *p;
167    const char **cpp = fnames;
168
169    for(p = maybe_feature; p->feature_name; p++)
170      if(curlinfo->features & p->feature_bitmask)
171        *cpp++ = p->feature_name;
172    *cpp = NULL;
173  }
174
175  /* Identify features we are interested in. */
176  for(builtin = feature_names; *builtin; builtin++) {
177    const struct feature_name_presentp *p;
178
179    for(p = maybe_feature; p->feature_name; p++)
180      if(curl_strequal(p->feature_name, *builtin)) {
181        if(p->feature_presentp)
182          *p->feature_presentp = TRUE;
183        break;
184      }
185  }
186
187  return CURLE_OK;
188}
189
190/* Tokenize a protocol name.
191 * Return the address of the protocol name listed by the library, or NULL if
192 * not found.
193 * Although this may seem useless, this always returns the same address for
194 * a given protocol and thus allows comparing pointers rather than strings.
195 * In addition, the returned pointer is not deallocated until the program ends.
196 */
197
198const char *proto_token(const char *proto)
199{
200  const char * const *builtin;
201
202  if(!proto)
203    return NULL;
204  for(builtin = built_in_protos; *builtin; builtin++)
205    if(curl_strequal(*builtin, proto))
206      break;
207  return *builtin;
208}
209