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