Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/src/tool_getparam.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
#include "tool_binmode.h"
28
#include "tool_cfgable.h"
29
#include "tool_cb_prg.h"
30
#include "tool_filetime.h"
31
#include "tool_formparse.h"
32
#include "tool_getparam.h"
33
#include "tool_helpers.h"
34
#include "tool_libinfo.h"
35
#include "tool_msgs.h"
36
#include "tool_paramhlp.h"
37
#include "tool_parsecfg.h"
38
#include "tool_main.h"
39
#include "tool_stderr.h"
40
#include "tool_help.h"
41
#include "var.h"
42
43
#include <memdebug.h> /* keep this as LAST include */
44
45
#define ALLOW_BLANK TRUE
46
#define DENY_BLANK FALSE
47
48
static ParameterError getstr(char **str, const char *val, bool allowblank)
49
{
50
if(*str) {
51
free(*str);
52
*str = NULL;
53
}
54
DEBUGASSERT(val);
55
if(!allowblank && !val[0])
56
return PARAM_BLANK_STRING;
57
58
*str = strdup(val);
59
if(!*str)
60
return PARAM_NO_MEM;
61
62
return PARAM_OK;
63
}
64
65
static ParameterError getstrn(char **str, const char *val,
66
size_t len, bool allowblank)
67
{
68
if(*str) {
69
free(*str);
70
*str = NULL;
71
}
72
DEBUGASSERT(val);
73
if(!allowblank && !val[0])
74
return PARAM_BLANK_STRING;
75
76
*str = malloc(len + 1);
77
if(!*str)
78
return PARAM_NO_MEM;
79
80
memcpy(*str, val, len);
81
(*str)[len] = 0; /* null-terminate */
82
83
return PARAM_OK;
84
}
85
86
/* this array MUST be alphasorted based on the 'lname' */
87
static const struct LongShort aliases[]= {
88
{"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET},
89
{"alpn", ARG_BOOL|ARG_NO|ARG_TLS, ' ', C_ALPN},
90
{"alt-svc", ARG_STRG, ' ', C_ALT_SVC},
91
{"anyauth", ARG_NONE, ' ', C_ANYAUTH},
92
{"append", ARG_BOOL, 'a', C_APPEND},
93
{"aws-sigv4", ARG_STRG, ' ', C_AWS_SIGV4},
94
{"basic", ARG_BOOL, ' ', C_BASIC},
95
{"buffer", ARG_BOOL|ARG_NO, 'N', C_BUFFER},
96
{"ca-native", ARG_BOOL|ARG_TLS, ' ', C_CA_NATIVE},
97
{"cacert", ARG_FILE|ARG_TLS, ' ', C_CACERT},
98
{"capath", ARG_FILE|ARG_TLS, ' ', C_CAPATH},
99
{"cert", ARG_FILE|ARG_TLS|ARG_CLEAR, 'E', C_CERT},
100
{"cert-status", ARG_BOOL|ARG_TLS, ' ', C_CERT_STATUS},
101
{"cert-type", ARG_STRG|ARG_TLS, ' ', C_CERT_TYPE},
102
{"ciphers", ARG_STRG|ARG_TLS, ' ', C_CIPHERS},
103
{"clobber", ARG_BOOL|ARG_NO, ' ', C_CLOBBER},
104
{"compressed", ARG_BOOL, ' ', C_COMPRESSED},
105
{"compressed-ssh", ARG_BOOL, ' ', C_COMPRESSED_SSH},
106
{"config", ARG_FILE, 'K', C_CONFIG},
107
{"connect-timeout", ARG_STRG, ' ', C_CONNECT_TIMEOUT},
108
{"connect-to", ARG_STRG, ' ', C_CONNECT_TO},
109
{"continue-at", ARG_STRG, 'C', C_CONTINUE_AT},
110
{"cookie", ARG_STRG, 'b', C_COOKIE},
111
{"cookie-jar", ARG_STRG, 'c', C_COOKIE_JAR},
112
{"create-dirs", ARG_BOOL, ' ', C_CREATE_DIRS},
113
{"create-file-mode", ARG_STRG, ' ', C_CREATE_FILE_MODE},
114
{"crlf", ARG_BOOL, ' ', C_CRLF},
115
{"crlfile", ARG_FILE|ARG_TLS, ' ', C_CRLFILE},
116
{"curves", ARG_STRG|ARG_TLS, ' ', C_CURVES},
117
{"data", ARG_STRG, 'd', C_DATA},
118
{"data-ascii", ARG_STRG, ' ', C_DATA_ASCII},
119
{"data-binary", ARG_STRG, ' ', C_DATA_BINARY},
120
{"data-raw", ARG_STRG, ' ', C_DATA_RAW},
121
{"data-urlencode", ARG_STRG, ' ', C_DATA_URLENCODE},
122
{"delegation", ARG_STRG, ' ', C_DELEGATION},
123
{"digest", ARG_BOOL, ' ', C_DIGEST},
124
{"disable", ARG_BOOL, 'q', C_DISABLE},
125
{"disable-eprt", ARG_BOOL, ' ', C_DISABLE_EPRT},
126
{"disable-epsv", ARG_BOOL, ' ', C_DISABLE_EPSV},
127
{"disallow-username-in-url", ARG_BOOL, ' ', C_DISALLOW_USERNAME_IN_URL},
128
{"dns-interface", ARG_STRG, ' ', C_DNS_INTERFACE},
129
{"dns-ipv4-addr", ARG_STRG, ' ', C_DNS_IPV4_ADDR},
130
{"dns-ipv6-addr", ARG_STRG, ' ', C_DNS_IPV6_ADDR},
131
{"dns-servers", ARG_STRG, ' ', C_DNS_SERVERS},
132
{"doh-cert-status", ARG_BOOL|ARG_TLS, ' ', C_DOH_CERT_STATUS},
133
{"doh-insecure", ARG_BOOL|ARG_TLS, ' ', C_DOH_INSECURE},
134
{"doh-url" , ARG_STRG, ' ', C_DOH_URL},
135
{"dump-ca-embed", ARG_NONE|ARG_TLS, ' ', C_DUMP_CA_EMBED},
136
{"dump-header", ARG_FILE, 'D', C_DUMP_HEADER},
137
{"ech", ARG_STRG|ARG_TLS, ' ', C_ECH},
138
{"egd-file", ARG_STRG|ARG_DEPR, ' ', C_EGD_FILE},
139
{"engine", ARG_STRG|ARG_TLS, ' ', C_ENGINE},
140
{"eprt", ARG_BOOL, ' ', C_EPRT},
141
{"epsv", ARG_BOOL, ' ', C_EPSV},
142
{"etag-compare", ARG_FILE, ' ', C_ETAG_COMPARE},
143
{"etag-save", ARG_FILE, ' ', C_ETAG_SAVE},
144
{"expect100-timeout", ARG_STRG, ' ', C_EXPECT100_TIMEOUT},
145
{"fail", ARG_BOOL, 'f', C_FAIL},
146
{"fail-early", ARG_BOOL, ' ', C_FAIL_EARLY},
147
{"fail-with-body", ARG_BOOL, ' ', C_FAIL_WITH_BODY},
148
{"false-start", ARG_BOOL, ' ', C_FALSE_START},
149
{"form", ARG_STRG, 'F', C_FORM},
150
{"form-escape", ARG_BOOL, ' ', C_FORM_ESCAPE},
151
{"form-string", ARG_STRG, ' ', C_FORM_STRING},
152
{"ftp-account", ARG_STRG, ' ', C_FTP_ACCOUNT},
153
{"ftp-alternative-to-user", ARG_STRG, ' ', C_FTP_ALTERNATIVE_TO_USER},
154
{"ftp-create-dirs", ARG_BOOL, ' ', C_FTP_CREATE_DIRS},
155
{"ftp-method", ARG_STRG, ' ', C_FTP_METHOD},
156
{"ftp-pasv", ARG_BOOL, ' ', C_FTP_PASV},
157
{"ftp-port", ARG_STRG, 'P', C_FTP_PORT},
158
{"ftp-pret", ARG_BOOL, ' ', C_FTP_PRET},
159
{"ftp-skip-pasv-ip", ARG_BOOL, ' ', C_FTP_SKIP_PASV_IP},
160
{"ftp-ssl", ARG_BOOL|ARG_TLS, ' ', C_FTP_SSL},
161
{"ftp-ssl-ccc", ARG_BOOL|ARG_TLS, ' ', C_FTP_SSL_CCC},
162
{"ftp-ssl-ccc-mode", ARG_STRG|ARG_TLS, ' ', C_FTP_SSL_CCC_MODE},
163
{"ftp-ssl-control", ARG_BOOL|ARG_TLS, ' ', C_FTP_SSL_CONTROL},
164
{"ftp-ssl-reqd", ARG_BOOL|ARG_TLS, ' ', C_FTP_SSL_REQD},
165
{"get", ARG_BOOL, 'G', C_GET},
166
{"globoff", ARG_BOOL, 'g', C_GLOBOFF},
167
{"happy-eyeballs-timeout-ms", ARG_STRG, ' ', C_HAPPY_EYEBALLS_TIMEOUT_MS},
168
{"haproxy-clientip", ARG_STRG, ' ', C_HAPROXY_CLIENTIP},
169
{"haproxy-protocol", ARG_BOOL, ' ', C_HAPROXY_PROTOCOL},
170
{"head", ARG_BOOL, 'I', C_HEAD},
171
{"header", ARG_STRG, 'H', C_HEADER},
172
{"help", ARG_STRG, 'h', C_HELP},
173
{"hostpubmd5", ARG_STRG, ' ', C_HOSTPUBMD5},
174
{"hostpubsha256", ARG_STRG, ' ', C_HOSTPUBSHA256},
175
{"hsts", ARG_STRG|ARG_TLS, ' ', C_HSTS},
176
{"http0.9", ARG_BOOL, ' ', C_HTTP0_9},
177
{"http1.0", ARG_NONE, '0', C_HTTP1_0},
178
{"http1.1", ARG_NONE, ' ', C_HTTP1_1},
179
{"http2", ARG_NONE, ' ', C_HTTP2},
180
{"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE},
181
{"http3", ARG_NONE|ARG_TLS, ' ', C_HTTP3},
182
{"http3-only", ARG_NONE|ARG_TLS, ' ', C_HTTP3_ONLY},
183
{"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH},
184
{"include", ARG_BOOL, ' ', C_INCLUDE},
185
{"insecure", ARG_BOOL, 'k', C_INSECURE},
186
{"interface", ARG_STRG, ' ', C_INTERFACE},
187
{"ip-tos", ARG_STRG, ' ', C_IP_TOS},
188
#ifndef CURL_DISABLE_IPFS
189
{"ipfs-gateway", ARG_STRG, ' ', C_IPFS_GATEWAY},
190
#endif /* !CURL_DISABLE_IPFS */
191
{"ipv4", ARG_NONE, '4', C_IPV4},
192
{"ipv6", ARG_NONE, '6', C_IPV6},
193
{"json", ARG_STRG, ' ', C_JSON},
194
{"junk-session-cookies", ARG_BOOL, 'j', C_JUNK_SESSION_COOKIES},
195
{"keepalive", ARG_BOOL|ARG_NO, ' ', C_KEEPALIVE},
196
{"keepalive-cnt", ARG_STRG, ' ', C_KEEPALIVE_CNT},
197
{"keepalive-time", ARG_STRG, ' ', C_KEEPALIVE_TIME},
198
{"key", ARG_FILE, ' ', C_KEY},
199
{"key-type", ARG_STRG|ARG_TLS, ' ', C_KEY_TYPE},
200
{"krb", ARG_STRG, ' ', C_KRB},
201
{"krb4", ARG_STRG, ' ', C_KRB4},
202
{"libcurl", ARG_STRG, ' ', C_LIBCURL},
203
{"limit-rate", ARG_STRG, ' ', C_LIMIT_RATE},
204
{"list-only", ARG_BOOL, 'l', C_LIST_ONLY},
205
{"local-port", ARG_STRG, ' ', C_LOCAL_PORT},
206
{"location", ARG_BOOL, 'L', C_LOCATION},
207
{"location-trusted", ARG_BOOL, ' ', C_LOCATION_TRUSTED},
208
{"login-options", ARG_STRG, ' ', C_LOGIN_OPTIONS},
209
{"mail-auth", ARG_STRG, ' ', C_MAIL_AUTH},
210
{"mail-from", ARG_STRG, ' ', C_MAIL_FROM},
211
{"mail-rcpt", ARG_STRG, ' ', C_MAIL_RCPT},
212
{"mail-rcpt-allowfails", ARG_BOOL, ' ', C_MAIL_RCPT_ALLOWFAILS},
213
{"manual", ARG_BOOL, 'M', C_MANUAL},
214
{"max-filesize", ARG_STRG, ' ', C_MAX_FILESIZE},
215
{"max-redirs", ARG_STRG, ' ', C_MAX_REDIRS},
216
{"max-time", ARG_STRG, 'm', C_MAX_TIME},
217
{"metalink", ARG_BOOL|ARG_DEPR, ' ', C_METALINK},
218
{"mptcp", ARG_BOOL, ' ', C_MPTCP},
219
{"negotiate", ARG_BOOL, ' ', C_NEGOTIATE},
220
{"netrc", ARG_BOOL, 'n', C_NETRC},
221
{"netrc-file", ARG_FILE, ' ', C_NETRC_FILE},
222
{"netrc-optional", ARG_BOOL, ' ', C_NETRC_OPTIONAL},
223
{"next", ARG_NONE, ':', C_NEXT},
224
{"noproxy", ARG_STRG, ' ', C_NOPROXY},
225
{"npn", ARG_BOOL|ARG_DEPR, ' ', C_NPN},
226
{"ntlm", ARG_BOOL, ' ', C_NTLM},
227
{"ntlm-wb", ARG_BOOL|ARG_DEPR, ' ', C_NTLM_WB},
228
{"oauth2-bearer", ARG_STRG|ARG_CLEAR, ' ', C_OAUTH2_BEARER},
229
{"output", ARG_FILE, 'o', C_OUTPUT},
230
{"output-dir", ARG_STRG, ' ', C_OUTPUT_DIR},
231
{"parallel", ARG_BOOL, 'Z', C_PARALLEL},
232
{"parallel-immediate", ARG_BOOL, ' ', C_PARALLEL_IMMEDIATE},
233
{"parallel-max", ARG_STRG, ' ', C_PARALLEL_MAX},
234
{"pass", ARG_STRG|ARG_CLEAR, ' ', C_PASS},
235
{"path-as-is", ARG_BOOL, ' ', C_PATH_AS_IS},
236
{"pinnedpubkey", ARG_STRG|ARG_TLS, ' ', C_PINNEDPUBKEY},
237
{"post301", ARG_BOOL, ' ', C_POST301},
238
{"post302", ARG_BOOL, ' ', C_POST302},
239
{"post303", ARG_BOOL, ' ', C_POST303},
240
{"preproxy", ARG_STRG, ' ', C_PREPROXY},
241
{"progress-bar", ARG_BOOL, '#', C_PROGRESS_BAR},
242
{"progress-meter", ARG_BOOL|ARG_NO, ' ', C_PROGRESS_METER},
243
{"proto", ARG_STRG, ' ', C_PROTO},
244
{"proto-default", ARG_STRG, ' ', C_PROTO_DEFAULT},
245
{"proto-redir", ARG_STRG, ' ', C_PROTO_REDIR},
246
{"proxy", ARG_STRG, 'x', C_PROXY},
247
{"proxy-anyauth", ARG_BOOL, ' ', C_PROXY_ANYAUTH},
248
{"proxy-basic", ARG_BOOL, ' ', C_PROXY_BASIC},
249
{"proxy-ca-native", ARG_BOOL|ARG_TLS, ' ', C_PROXY_CA_NATIVE},
250
{"proxy-cacert", ARG_FILE|ARG_TLS, ' ', C_PROXY_CACERT},
251
{"proxy-capath", ARG_FILE|ARG_TLS, ' ', C_PROXY_CAPATH},
252
{"proxy-cert", ARG_FILE|ARG_TLS|ARG_CLEAR, ' ', C_PROXY_CERT},
253
{"proxy-cert-type", ARG_STRG|ARG_TLS, ' ', C_PROXY_CERT_TYPE},
254
{"proxy-ciphers", ARG_STRG|ARG_TLS, ' ', C_PROXY_CIPHERS},
255
{"proxy-crlfile", ARG_FILE|ARG_TLS, ' ', C_PROXY_CRLFILE},
256
{"proxy-digest", ARG_BOOL, ' ', C_PROXY_DIGEST},
257
{"proxy-header", ARG_STRG, ' ', C_PROXY_HEADER},
258
{"proxy-http2", ARG_BOOL, ' ', C_PROXY_HTTP2},
259
{"proxy-insecure", ARG_BOOL, ' ', C_PROXY_INSECURE},
260
{"proxy-key", ARG_FILE|ARG_TLS, ' ', C_PROXY_KEY},
261
{"proxy-key-type", ARG_STRG|ARG_TLS, ' ', C_PROXY_KEY_TYPE},
262
{"proxy-negotiate", ARG_BOOL, ' ', C_PROXY_NEGOTIATE},
263
{"proxy-ntlm", ARG_BOOL, ' ', C_PROXY_NTLM},
264
{"proxy-pass", ARG_STRG|ARG_CLEAR, ' ', C_PROXY_PASS},
265
{"proxy-pinnedpubkey", ARG_STRG|ARG_TLS, ' ', C_PROXY_PINNEDPUBKEY},
266
{"proxy-service-name", ARG_STRG, ' ', C_PROXY_SERVICE_NAME},
267
{"proxy-ssl-allow-beast", ARG_BOOL|ARG_TLS, ' ',
268
C_PROXY_SSL_ALLOW_BEAST},
269
{"proxy-ssl-auto-client-cert", ARG_BOOL|ARG_TLS, ' ',
270
C_PROXY_SSL_AUTO_CLIENT_CERT},
271
{"proxy-tls13-ciphers", ARG_STRG|ARG_TLS, ' ', C_PROXY_TLS13_CIPHERS},
272
{"proxy-tlsauthtype", ARG_STRG|ARG_TLS, ' ', C_PROXY_TLSAUTHTYPE},
273
{"proxy-tlspassword", ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_PROXY_TLSPASSWORD},
274
{"proxy-tlsuser", ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_PROXY_TLSUSER},
275
{"proxy-tlsv1", ARG_NONE|ARG_TLS, ' ', C_PROXY_TLSV1},
276
{"proxy-user", ARG_STRG|ARG_CLEAR, 'U', C_PROXY_USER},
277
{"proxy1.0", ARG_STRG, ' ', C_PROXY1_0},
278
{"proxytunnel", ARG_BOOL, 'p', C_PROXYTUNNEL},
279
{"pubkey", ARG_STRG, ' ', C_PUBKEY},
280
{"quote", ARG_STRG, 'Q', C_QUOTE},
281
{"random-file", ARG_FILE|ARG_DEPR, ' ', C_RANDOM_FILE},
282
{"range", ARG_STRG, 'r', C_RANGE},
283
{"rate", ARG_STRG, ' ', C_RATE},
284
{"raw", ARG_BOOL, ' ', C_RAW},
285
{"referer", ARG_STRG, 'e', C_REFERER},
286
{"remote-header-name", ARG_BOOL, 'J', C_REMOTE_HEADER_NAME},
287
{"remote-name", ARG_BOOL, 'O', C_REMOTE_NAME},
288
{"remote-name-all", ARG_BOOL, ' ', C_REMOTE_NAME_ALL},
289
{"remote-time", ARG_BOOL, 'R', C_REMOTE_TIME},
290
{"remove-on-error", ARG_BOOL, ' ', C_REMOVE_ON_ERROR},
291
{"request", ARG_STRG, 'X', C_REQUEST},
292
{"request-target", ARG_STRG, ' ', C_REQUEST_TARGET},
293
{"resolve", ARG_STRG, ' ', C_RESOLVE},
294
{"retry", ARG_STRG, ' ', C_RETRY},
295
{"retry-all-errors", ARG_BOOL, ' ', C_RETRY_ALL_ERRORS},
296
{"retry-connrefused", ARG_BOOL, ' ', C_RETRY_CONNREFUSED},
297
{"retry-delay", ARG_STRG, ' ', C_RETRY_DELAY},
298
{"retry-max-time", ARG_STRG, ' ', C_RETRY_MAX_TIME},
299
{"sasl-authzid", ARG_STRG, ' ', C_SASL_AUTHZID},
300
{"sasl-ir", ARG_BOOL, ' ', C_SASL_IR},
301
{"service-name", ARG_STRG, ' ', C_SERVICE_NAME},
302
{"sessionid", ARG_BOOL|ARG_NO, ' ', C_SESSIONID},
303
{"show-error", ARG_BOOL, 'S', C_SHOW_ERROR},
304
{"show-headers", ARG_BOOL, 'i', C_SHOW_HEADERS},
305
{"sigalgs", ARG_STRG|ARG_TLS, ' ',
306
C_SIGNATURE_ALGORITHMS},
307
{"silent", ARG_BOOL, 's', C_SILENT},
308
{"skip-existing", ARG_BOOL, ' ', C_SKIP_EXISTING},
309
{"socks4", ARG_STRG, ' ', C_SOCKS4},
310
{"socks4a", ARG_STRG, ' ', C_SOCKS4A},
311
{"socks5", ARG_STRG, ' ', C_SOCKS5},
312
{"socks5-basic", ARG_BOOL, ' ', C_SOCKS5_BASIC},
313
{"socks5-gssapi", ARG_BOOL, ' ', C_SOCKS5_GSSAPI},
314
{"socks5-gssapi-nec", ARG_BOOL, ' ', C_SOCKS5_GSSAPI_NEC},
315
{"socks5-gssapi-service", ARG_STRG, ' ', C_SOCKS5_GSSAPI_SERVICE},
316
{"socks5-hostname", ARG_STRG, ' ', C_SOCKS5_HOSTNAME},
317
{"speed-limit", ARG_STRG, 'Y', C_SPEED_LIMIT},
318
{"speed-time", ARG_STRG, 'y', C_SPEED_TIME},
319
{"ssl", ARG_BOOL|ARG_TLS, ' ', C_SSL},
320
{"ssl-allow-beast", ARG_BOOL|ARG_TLS, ' ', C_SSL_ALLOW_BEAST},
321
{"ssl-auto-client-cert", ARG_BOOL|ARG_TLS, ' ',
322
C_SSL_AUTO_CLIENT_CERT},
323
{"ssl-no-revoke", ARG_BOOL|ARG_TLS, ' ', C_SSL_NO_REVOKE},
324
{"ssl-reqd", ARG_BOOL|ARG_TLS, ' ', C_SSL_REQD},
325
{"ssl-revoke-best-effort", ARG_BOOL|ARG_TLS, ' ',
326
C_SSL_REVOKE_BEST_EFFORT},
327
{"ssl-sessions", ARG_FILE|ARG_TLS, ' ', C_SSL_SESSIONS},
328
{"sslv2", ARG_NONE|ARG_DEPR, '2', C_SSLV2},
329
{"sslv3", ARG_NONE|ARG_DEPR, '3', C_SSLV3},
330
{"stderr", ARG_FILE, ' ', C_STDERR},
331
{"styled-output", ARG_BOOL, ' ', C_STYLED_OUTPUT},
332
{"suppress-connect-headers", ARG_BOOL, ' ', C_SUPPRESS_CONNECT_HEADERS},
333
{"tcp-fastopen", ARG_BOOL, ' ', C_TCP_FASTOPEN},
334
{"tcp-nodelay", ARG_BOOL, ' ', C_TCP_NODELAY},
335
{"telnet-option", ARG_STRG, 't', C_TELNET_OPTION},
336
#ifdef DEBUGBUILD
337
{"test-duphandle", ARG_BOOL, ' ', C_TEST_DUPHANDLE},
338
{"test-event", ARG_BOOL, ' ', C_TEST_EVENT},
339
#endif
340
{"tftp-blksize", ARG_STRG, ' ', C_TFTP_BLKSIZE},
341
{"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS},
342
{"time-cond", ARG_STRG, 'z', C_TIME_COND},
343
{"tls-earlydata", ARG_BOOL|ARG_TLS, ' ', C_TLS_EARLYDATA},
344
{"tls-max", ARG_STRG|ARG_TLS, ' ', C_TLS_MAX},
345
{"tls13-ciphers", ARG_STRG|ARG_TLS, ' ', C_TLS13_CIPHERS},
346
{"tlsauthtype", ARG_STRG|ARG_TLS, ' ', C_TLSAUTHTYPE},
347
{"tlspassword", ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_TLSPASSWORD},
348
{"tlsuser", ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_TLSUSER},
349
{"tlsv1", ARG_NONE|ARG_TLS, '1', C_TLSV1},
350
{"tlsv1.0", ARG_NONE|ARG_TLS, ' ', C_TLSV1_0},
351
{"tlsv1.1", ARG_NONE|ARG_TLS, ' ', C_TLSV1_1},
352
{"tlsv1.2", ARG_NONE|ARG_TLS, ' ', C_TLSV1_2},
353
{"tlsv1.3", ARG_NONE|ARG_TLS, ' ', C_TLSV1_3},
354
{"tr-encoding", ARG_BOOL, ' ', C_TR_ENCODING},
355
{"trace", ARG_FILE, ' ', C_TRACE},
356
{"trace-ascii", ARG_FILE, ' ', C_TRACE_ASCII},
357
{"trace-config", ARG_STRG, ' ', C_TRACE_CONFIG},
358
{"trace-ids", ARG_BOOL, ' ', C_TRACE_IDS},
359
{"trace-time", ARG_BOOL, ' ', C_TRACE_TIME},
360
{"unix-socket", ARG_FILE, ' ', C_UNIX_SOCKET},
361
{"upload-file", ARG_FILE, 'T', C_UPLOAD_FILE},
362
{"upload-flags", ARG_STRG, ' ', C_UPLOAD_FLAGS},
363
{"url", ARG_STRG, ' ', C_URL},
364
{"url-query", ARG_STRG, ' ', C_URL_QUERY},
365
{"use-ascii", ARG_BOOL, 'B', C_USE_ASCII},
366
{"user", ARG_STRG|ARG_CLEAR, 'u', C_USER},
367
{"user-agent", ARG_STRG, 'A', C_USER_AGENT},
368
{"variable", ARG_STRG, ' ', C_VARIABLE},
369
{"verbose", ARG_BOOL, 'v', C_VERBOSE},
370
{"version", ARG_BOOL, 'V', C_VERSION},
371
{"vlan-priority", ARG_STRG, ' ', C_VLAN_PRIORITY},
372
#ifdef USE_WATT32
373
{"wdebug", ARG_BOOL, ' ', C_WDEBUG},
374
#endif
375
{"write-out", ARG_STRG, 'w', C_WRITE_OUT},
376
{"xattr", ARG_BOOL, ' ', C_XATTR},
377
};
378
379
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
380
* We allow ':' and '\' to be escaped by '\' so that we can use certificate
381
* nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
382
* for details. */
383
#ifndef UNITTESTS
384
static
385
#endif
386
void parse_cert_parameter(const char *cert_parameter,
387
char **certname,
388
char **passphrase)
389
{
390
size_t param_length = strlen(cert_parameter);
391
size_t span;
392
const char *param_place = NULL;
393
char *certname_place = NULL;
394
*certname = NULL;
395
*passphrase = NULL;
396
397
/* most trivial assumption: cert_parameter is empty */
398
if(param_length == 0)
399
return;
400
401
/* next less trivial: cert_parameter starts 'pkcs11:' and thus
402
* looks like a RFC7512 PKCS#11 URI which can be used as-is.
403
* Also if cert_parameter contains no colon nor backslash, this
404
* means no passphrase was given and no characters escaped */
405
if(curl_strnequal(cert_parameter, "pkcs11:", 7) ||
406
!strpbrk(cert_parameter, ":\\")) {
407
*certname = strdup(cert_parameter);
408
return;
409
}
410
/* deal with escaped chars; find unescaped colon if it exists */
411
certname_place = malloc(param_length + 1);
412
if(!certname_place)
413
return;
414
415
*certname = certname_place;
416
param_place = cert_parameter;
417
while(*param_place) {
418
span = strcspn(param_place, ":\\");
419
memcpy(certname_place, param_place, span);
420
param_place += span;
421
certname_place += span;
422
/* we just ate all the non-special chars. now we are on either a special
423
* char or the end of the string. */
424
switch(*param_place) {
425
case '\0':
426
break;
427
case '\\':
428
param_place++;
429
switch(*param_place) {
430
case '\0':
431
*certname_place++ = '\\';
432
break;
433
case '\\':
434
*certname_place++ = '\\';
435
param_place++;
436
break;
437
case ':':
438
*certname_place++ = ':';
439
param_place++;
440
break;
441
default:
442
*certname_place++ = '\\';
443
*certname_place++ = *param_place;
444
param_place++;
445
break;
446
}
447
break;
448
case ':':
449
/* Since we live in a world of weirdness and confusion, the Windows
450
dudes can use : when using drive letters and thus c:\file:password
451
needs to work. In order not to break compatibility, we still use : as
452
separator, but we try to detect when it is used for a filename! On
453
Windows. */
454
#ifdef _WIN32
455
if((param_place == &cert_parameter[1]) &&
456
(cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
457
(ISALPHA(cert_parameter[0])) ) {
458
/* colon in the second column, followed by a backslash, and the
459
first character is an alphabetic letter:
460
461
this is a drive letter colon */
462
*certname_place++ = ':';
463
param_place++;
464
break;
465
}
466
#endif
467
/* escaped colons and Windows drive letter colons were handled
468
* above; if we are still here, this is a separating colon */
469
param_place++;
470
if(*param_place) {
471
*passphrase = strdup(param_place);
472
}
473
goto done;
474
}
475
}
476
done:
477
*certname_place = '\0';
478
}
479
480
/* Replace (in-place) '%20' by '+' according to RFC1866 */
481
static size_t replace_url_encoded_space_by_plus(char *url)
482
{
483
size_t orig_len = strlen(url);
484
size_t orig_index = 0;
485
size_t new_index = 0;
486
487
while(orig_index < orig_len) {
488
if((url[orig_index] == '%') &&
489
(url[orig_index + 1] == '2') &&
490
(url[orig_index + 2] == '0')) {
491
url[new_index] = '+';
492
orig_index += 3;
493
}
494
else{
495
if(new_index != orig_index) {
496
url[new_index] = url[orig_index];
497
}
498
orig_index++;
499
}
500
new_index++;
501
}
502
503
url[new_index] = 0; /* terminate string */
504
505
return new_index; /* new size */
506
}
507
508
static void
509
GetFileAndPassword(const char *nextarg, char **file, char **password)
510
{
511
char *certname, *passphrase;
512
/* nextarg is never NULL here */
513
parse_cert_parameter(nextarg, &certname, &passphrase);
514
free(*file);
515
*file = certname;
516
if(passphrase) {
517
free(*password);
518
*password = passphrase;
519
}
520
}
521
522
/* Get a size parameter for '--limit-rate' or '--max-filesize'.
523
* We support a 'G', 'M' or 'K' suffix too.
524
*/
525
static ParameterError GetSizeParameter(struct GlobalConfig *global,
526
const char *arg,
527
const char *which,
528
curl_off_t *value_out)
529
{
530
const char *unit = arg;
531
curl_off_t value;
532
533
if(curlx_str_number(&unit, &value, CURL_OFF_T_MAX)) {
534
warnf(global, "invalid number specified for %s", which);
535
return PARAM_BAD_USE;
536
}
537
538
if(!*unit)
539
unit = "b";
540
else if(strlen(unit) > 1)
541
unit = "w"; /* unsupported */
542
543
switch(*unit) {
544
case 'G':
545
case 'g':
546
if(value > (CURL_OFF_T_MAX / (1024*1024*1024)))
547
return PARAM_NUMBER_TOO_LARGE;
548
value *= 1024*1024*1024;
549
break;
550
case 'M':
551
case 'm':
552
if(value > (CURL_OFF_T_MAX / (1024*1024)))
553
return PARAM_NUMBER_TOO_LARGE;
554
value *= 1024*1024;
555
break;
556
case 'K':
557
case 'k':
558
if(value > (CURL_OFF_T_MAX / 1024))
559
return PARAM_NUMBER_TOO_LARGE;
560
value *= 1024;
561
break;
562
case 'b':
563
case 'B':
564
/* for plain bytes, leave as-is */
565
break;
566
default:
567
warnf(global, "unsupported %s unit. Use G, M, K or B", which);
568
return PARAM_BAD_USE;
569
}
570
*value_out = value;
571
return PARAM_OK;
572
}
573
574
#ifdef HAVE_WRITABLE_ARGV
575
static void cleanarg(char *str)
576
{
577
/* now that getstr has copied the contents of nextarg, wipe the next
578
* argument out so that the username:password is not displayed in the
579
* system process list */
580
if(str) {
581
size_t len = strlen(str);
582
memset(str, '*', len);
583
}
584
}
585
#else
586
#define cleanarg(x) tool_nop_stmt
587
#endif
588
589
/* the maximum size we allow the dynbuf generated string */
590
#define MAX_DATAURLENCODE (500*1024*1024)
591
592
/* --data-urlencode */
593
static ParameterError data_urlencode(struct GlobalConfig *global,
594
const char *nextarg,
595
char **postp,
596
size_t *lenp)
597
{
598
/* [name]=[content], we encode the content part only
599
* [name]@[filename]
600
*
601
* Case 2: we first load the file using that name and then encode
602
* the content.
603
*/
604
ParameterError err;
605
const char *p = strchr(nextarg, '=');
606
size_t nlen;
607
char is_file;
608
char *postdata = NULL;
609
size_t size = 0;
610
if(!p)
611
/* there was no '=' letter, check for a '@' instead */
612
p = strchr(nextarg, '@');
613
if(p) {
614
nlen = p - nextarg; /* length of the name part */
615
is_file = *p++; /* pass the separator */
616
}
617
else {
618
/* neither @ nor =, so no name and it is not a file */
619
nlen = 0;
620
is_file = 0;
621
p = nextarg;
622
}
623
if('@' == is_file) {
624
FILE *file;
625
/* a '@' letter, it means that a filename or - (stdin) follows */
626
if(!strcmp("-", p)) {
627
file = stdin;
628
CURL_SET_BINMODE(stdin);
629
}
630
else {
631
file = fopen(p, "rb");
632
if(!file) {
633
errorf(global, "Failed to open %s", p);
634
return PARAM_READ_ERROR;
635
}
636
}
637
638
err = file2memory(&postdata, &size, file);
639
640
if(file && (file != stdin))
641
fclose(file);
642
if(err)
643
return err;
644
}
645
else {
646
err = getstr(&postdata, p, ALLOW_BLANK);
647
if(err)
648
goto error;
649
size = strlen(postdata);
650
}
651
652
if(!postdata) {
653
/* no data from the file, point to a zero byte string to make this
654
get sent as a POST anyway */
655
postdata = strdup("");
656
if(!postdata)
657
return PARAM_NO_MEM;
658
size = 0;
659
}
660
else {
661
char *enc = curl_easy_escape(NULL, postdata, (int)size);
662
tool_safefree(postdata); /* no matter if it worked or not */
663
if(enc) {
664
char *n;
665
replace_url_encoded_space_by_plus(enc);
666
if(nlen > 0) { /* only append '=' if we have a name */
667
struct dynbuf dyn;
668
curlx_dyn_init(&dyn, MAX_DATAURLENCODE);
669
if(curlx_dyn_addn(&dyn, nextarg, nlen) ||
670
curlx_dyn_addn(&dyn, "=", 1) ||
671
curlx_dyn_add(&dyn, enc)) {
672
curl_free(enc);
673
return PARAM_NO_MEM;
674
}
675
curl_free(enc);
676
n = curlx_dyn_ptr(&dyn);
677
size = curlx_dyn_len(&dyn);
678
}
679
else {
680
n = enc;
681
size = strlen(n);
682
}
683
postdata = n;
684
}
685
else
686
return PARAM_NO_MEM;
687
}
688
*postp = postdata;
689
*lenp = size;
690
return PARAM_OK;
691
error:
692
return err;
693
}
694
695
static void sethttpver(struct GlobalConfig *global,
696
struct OperationConfig *config,
697
long httpversion)
698
{
699
if(config->httpversion &&
700
(config->httpversion != httpversion))
701
warnf(global, "Overrides previous HTTP version option");
702
703
config->httpversion = httpversion;
704
}
705
706
static CURLcode set_trace_config(struct GlobalConfig *global,
707
const char *token)
708
{
709
CURLcode result = CURLE_OK;
710
const char *next, *name;
711
bool toggle;
712
713
while(token) {
714
size_t len;
715
next = strchr(token, ',');
716
717
if(next)
718
len = next - token;
719
else
720
len = strlen(token);
721
722
switch(*token) {
723
case '-':
724
toggle = FALSE;
725
name = token + 1;
726
len--;
727
break;
728
case '+':
729
toggle = TRUE;
730
name = token + 1;
731
len--;
732
break;
733
default:
734
toggle = TRUE;
735
name = token;
736
break;
737
}
738
739
if((len == 3) && curl_strnequal(name, "all", 3)) {
740
global->traceids = toggle;
741
global->tracetime = toggle;
742
result = curl_global_trace(token);
743
if(result)
744
goto out;
745
}
746
else if((len == 3) && curl_strnequal(name, "ids", 3)) {
747
global->traceids = toggle;
748
}
749
else if((len == 4) && curl_strnequal(name, "time", 4)) {
750
global->tracetime = toggle;
751
}
752
else {
753
char buffer[32];
754
msnprintf(buffer, sizeof(buffer), "%c%.*s", toggle ? '+' : '-',
755
(int)len, name);
756
result = curl_global_trace(buffer);
757
if(result)
758
goto out;
759
}
760
if(next) {
761
next++;
762
if(*next == ' ')
763
next++;
764
}
765
token = next;
766
}
767
out:
768
return result;
769
}
770
771
static int findarg(const void *a, const void *b)
772
{
773
const struct LongShort *aa = a;
774
const struct LongShort *bb = b;
775
return strcmp(aa->lname, bb->lname);
776
}
777
778
const struct LongShort *findshortopt(char letter)
779
{
780
static const struct LongShort *singles[128 - ' ']; /* ASCII => pointer */
781
static bool singles_done = FALSE;
782
if((letter >= 127) || (letter <= ' '))
783
return NULL;
784
785
if(!singles_done) {
786
unsigned int j;
787
for(j = 0; j < CURL_ARRAYSIZE(aliases); j++) {
788
if(aliases[j].letter != ' ') {
789
unsigned char l = (unsigned char)aliases[j].letter;
790
singles[l - ' '] = &aliases[j];
791
}
792
}
793
singles_done = TRUE;
794
}
795
return singles[letter - ' '];
796
}
797
798
struct TOSEntry {
799
const char *name;
800
unsigned char value;
801
};
802
803
static const struct TOSEntry tos_entries[] = {
804
{"AF11", 0x28},
805
{"AF12", 0x30},
806
{"AF13", 0x38},
807
{"AF21", 0x48},
808
{"AF22", 0x50},
809
{"AF23", 0x58},
810
{"AF31", 0x68},
811
{"AF32", 0x70},
812
{"AF33", 0x78},
813
{"AF41", 0x88},
814
{"AF42", 0x90},
815
{"AF43", 0x98},
816
{"CE", 0x03},
817
{"CS0", 0x00},
818
{"CS1", 0x20},
819
{"CS2", 0x40},
820
{"CS3", 0x60},
821
{"CS4", 0x80},
822
{"CS5", 0xa0},
823
{"CS6", 0xc0},
824
{"CS7", 0xe0},
825
{"ECT0", 0x02},
826
{"ECT1", 0x01},
827
{"EF", 0xb8},
828
{"LE", 0x04},
829
{"LOWCOST", 0x02},
830
{"LOWDELAY", 0x10},
831
{"MINCOST", 0x02},
832
{"RELIABILITY", 0x04},
833
{"THROUGHPUT", 0x08},
834
{"VOICE-ADMIT", 0xb0}
835
};
836
837
static int find_tos(const void *a, const void *b)
838
{
839
const struct TOSEntry *aa = a;
840
const struct TOSEntry *bb = b;
841
return strcmp(aa->name, bb->name);
842
}
843
844
#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
845
static ParameterError url_query(const char *nextarg,
846
struct GlobalConfig *global,
847
struct OperationConfig *config)
848
{
849
size_t size = 0;
850
ParameterError err = PARAM_OK;
851
char *query;
852
struct dynbuf dyn;
853
curlx_dyn_init(&dyn, MAX_QUERY_LEN);
854
855
if(*nextarg == '+') {
856
/* use without encoding */
857
query = strdup(&nextarg[1]);
858
if(!query)
859
err = PARAM_NO_MEM;
860
}
861
else
862
err = data_urlencode(global, nextarg, &query, &size);
863
864
if(!err) {
865
if(config->query) {
866
CURLcode result = curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
867
free(query);
868
if(result)
869
err = PARAM_NO_MEM;
870
else {
871
free(config->query);
872
config->query = curlx_dyn_ptr(&dyn);
873
}
874
}
875
else
876
config->query = query;
877
}
878
return err;
879
}
880
881
static ParameterError set_data(cmdline_t cmd,
882
const char *nextarg,
883
struct GlobalConfig *global,
884
struct OperationConfig *config)
885
{
886
char *postdata = NULL;
887
FILE *file;
888
size_t size = 0;
889
ParameterError err = PARAM_OK;
890
891
if(cmd == C_DATA_URLENCODE) { /* --data-urlencode */
892
err = data_urlencode(global, nextarg, &postdata, &size);
893
if(err)
894
return err;
895
}
896
else if('@' == *nextarg && (cmd != C_DATA_RAW)) {
897
/* the data begins with a '@' letter, it means that a filename
898
or - (stdin) follows */
899
nextarg++; /* pass the @ */
900
901
if(!strcmp("-", nextarg)) {
902
file = stdin;
903
if(cmd == C_DATA_BINARY) /* forced data-binary */
904
CURL_SET_BINMODE(stdin);
905
}
906
else {
907
file = fopen(nextarg, "rb");
908
if(!file) {
909
errorf(global, "Failed to open %s", nextarg);
910
return PARAM_READ_ERROR;
911
}
912
}
913
914
if((cmd == C_DATA_BINARY) || /* --data-binary */
915
(cmd == C_JSON) /* --json */)
916
/* forced binary */
917
err = file2memory(&postdata, &size, file);
918
else {
919
err = file2string(&postdata, file);
920
if(postdata)
921
size = strlen(postdata);
922
}
923
924
if(file && (file != stdin))
925
fclose(file);
926
if(err)
927
return err;
928
929
if(!postdata) {
930
/* no data from the file, point to a zero byte string to make this
931
get sent as a POST anyway */
932
postdata = strdup("");
933
if(!postdata)
934
return PARAM_NO_MEM;
935
}
936
}
937
else {
938
err = getstr(&postdata, nextarg, ALLOW_BLANK);
939
if(err)
940
return err;
941
size = strlen(postdata);
942
}
943
if(cmd == C_JSON)
944
config->jsoned = TRUE;
945
946
if(curlx_dyn_len(&config->postdata)) {
947
/* skip separator append for --json */
948
if(!err && (cmd != C_JSON) &&
949
curlx_dyn_addn(&config->postdata, "&", 1))
950
err = PARAM_NO_MEM;
951
}
952
953
if(!err && curlx_dyn_addn(&config->postdata, postdata, size))
954
err = PARAM_NO_MEM;
955
956
tool_safefree(postdata);
957
958
config->postfields = curlx_dyn_ptr(&config->postdata);
959
return err;
960
}
961
962
static ParameterError set_rate(struct GlobalConfig *global,
963
const char *nextarg)
964
{
965
/* --rate */
966
/* support a few different suffixes, extract the suffix first, then
967
get the number and convert to per hour.
968
/s == per second
969
/m == per minute
970
/h == per hour (default)
971
/d == per day (24 hours)
972
*/
973
ParameterError err = PARAM_OK;
974
const char *div = strchr(nextarg, '/');
975
char number[26];
976
long denominator;
977
long numerator = 60*60*1000; /* default per hour */
978
size_t numlen = div ? (size_t)(div - nextarg) : strlen(nextarg);
979
if(numlen > sizeof(number) -1)
980
return PARAM_NUMBER_TOO_LARGE;
981
982
memcpy(number, nextarg, numlen);
983
number[numlen] = 0;
984
err = str2unum(&denominator, number);
985
if(err)
986
return err;
987
988
if(denominator < 1)
989
return PARAM_BAD_USE;
990
991
if(div) {
992
curl_off_t numunits;
993
div++;
994
995
if(curlx_str_number(&div, &numunits, CURL_OFF_T_MAX))
996
numunits = 1;
997
998
switch(*div) {
999
case 's': /* per second */
1000
numerator = 1000;
1001
break;
1002
case 'm': /* per minute */
1003
numerator = 60*1000;
1004
break;
1005
case 'h': /* per hour */
1006
break;
1007
case 'd': /* per day */
1008
numerator = 24*60*60*1000;
1009
break;
1010
default:
1011
errorf(global, "unsupported --rate unit");
1012
err = PARAM_BAD_USE;
1013
break;
1014
}
1015
1016
if((LONG_MAX / numerator) < numunits) {
1017
/* overflow, too large number */
1018
errorf(global, "too large --rate unit");
1019
err = PARAM_NUMBER_TOO_LARGE;
1020
}
1021
/* this typecast is okay based on the check above */
1022
numerator *= (long)numunits;
1023
}
1024
1025
if(err)
1026
;
1027
else if(denominator > numerator)
1028
err = PARAM_NUMBER_TOO_LARGE;
1029
else
1030
global->ms_per_transfer = numerator/denominator;
1031
1032
return err;
1033
}
1034
1035
const struct LongShort *findlongopt(const char *opt)
1036
{
1037
struct LongShort key;
1038
key.lname = opt;
1039
1040
return bsearch(&key, aliases, CURL_ARRAYSIZE(aliases),
1041
sizeof(aliases[0]), findarg);
1042
}
1043
1044
static ParameterError add_url(struct GlobalConfig *global,
1045
struct OperationConfig *config,
1046
const char *thisurl,
1047
bool remote_noglob)
1048
{
1049
ParameterError err = PARAM_OK;
1050
struct getout *url;
1051
1052
if(!config->url_get)
1053
config->url_get = config->url_list;
1054
1055
if(config->url_get) {
1056
/* there is a node here, if it already is filled-in continue to find
1057
an "empty" node */
1058
while(config->url_get && config->url_get->urlset)
1059
config->url_get = config->url_get->next;
1060
}
1061
1062
/* now there might or might not be an available node to fill in! */
1063
1064
if(config->url_get)
1065
/* existing node */
1066
url = config->url_get;
1067
else
1068
/* there was no free node, create one! */
1069
config->url_get = url = new_getout(config);
1070
1071
if(!url)
1072
return PARAM_NO_MEM;
1073
else {
1074
/* fill in the URL */
1075
err = getstr(&url->url, thisurl, DENY_BLANK);
1076
url->urlset = TRUE;
1077
if(remote_noglob)
1078
url->useremote = url->noglob = TRUE;
1079
if(!err && (++config->num_urls > 1) &&
1080
(config->etag_save_file || config->etag_compare_file)) {
1081
errorf(global, "The etag options only work on a single URL");
1082
return PARAM_BAD_USE;
1083
}
1084
}
1085
return err;
1086
}
1087
1088
static ParameterError parse_url(struct GlobalConfig *global,
1089
struct OperationConfig *config,
1090
const char *nextarg)
1091
{
1092
/* nextarg is never NULL here */
1093
if(nextarg[0] == '@') {
1094
/* read URLs from a file, treat all as -O */
1095
struct dynbuf line;
1096
ParameterError err = PARAM_OK;
1097
bool error = FALSE;
1098
bool fromstdin = !strcmp("-", &nextarg[1]);
1099
FILE *f;
1100
1101
if(fromstdin)
1102
f = stdin;
1103
else
1104
f = fopen(&nextarg[1], FOPEN_READTEXT);
1105
if(f) {
1106
curlx_dyn_init(&line, 8092);
1107
while(my_get_line(f, &line, &error)) {
1108
const char *ptr = curlx_dyn_ptr(&line);
1109
err = add_url(global, config, ptr, TRUE);
1110
if(err)
1111
break;
1112
}
1113
if(!fromstdin)
1114
fclose(f);
1115
curlx_dyn_free(&line);
1116
if(error || err)
1117
return PARAM_READ_ERROR;
1118
return PARAM_OK;
1119
}
1120
return PARAM_READ_ERROR; /* file not found */
1121
}
1122
return add_url(global, config, nextarg, FALSE);
1123
}
1124
1125
1126
static ParameterError parse_localport(struct OperationConfig *config,
1127
const char *nextarg)
1128
{
1129
const char *pp = NULL;
1130
const char *p = nextarg;
1131
char buffer[22];
1132
size_t plen = 0;
1133
while(ISDIGIT(*p))
1134
p++;
1135
plen = p - nextarg;
1136
if(*p) {
1137
pp = p;
1138
/* check for ' - [end]' */
1139
if(ISBLANK(*pp))
1140
pp++;
1141
if(*pp != '-')
1142
return PARAM_BAD_USE;
1143
pp++;
1144
if(ISBLANK(*pp))
1145
pp++;
1146
}
1147
msnprintf(buffer, sizeof(buffer), "%.*s", (int)plen, nextarg);
1148
if(str2unummax(&config->localport, buffer, 65535))
1149
return PARAM_BAD_USE;
1150
if(!pp)
1151
config->localportrange = 1; /* default number of ports to try */
1152
else {
1153
if(str2unummax(&config->localportrange, pp, 65535))
1154
return PARAM_BAD_USE;
1155
config->localportrange -= (config->localport-1);
1156
if(config->localportrange < 1)
1157
return PARAM_BAD_USE;
1158
}
1159
return PARAM_OK;
1160
}
1161
1162
static ParameterError parse_continue_at(struct GlobalConfig *global,
1163
struct OperationConfig *config,
1164
const char *nextarg)
1165
{
1166
ParameterError err = PARAM_OK;
1167
if(config->range) {
1168
errorf(global, "--continue-at is mutually exclusive with --range");
1169
return PARAM_BAD_USE;
1170
}
1171
if(config->rm_partial) {
1172
errorf(config->global,
1173
"--continue-at is mutually exclusive with --remove-on-error");
1174
return PARAM_BAD_USE;
1175
}
1176
if(config->file_clobber_mode == CLOBBER_NEVER) {
1177
errorf(config->global,
1178
"--continue-at is mutually exclusive with --no-clobber");
1179
return PARAM_BAD_USE;
1180
}
1181
/* This makes us continue an ftp transfer at given position */
1182
if(strcmp(nextarg, "-")) {
1183
err = str2offset(&config->resume_from, nextarg);
1184
config->resume_from_current = FALSE;
1185
}
1186
else {
1187
config->resume_from_current = TRUE;
1188
config->resume_from = 0;
1189
}
1190
config->use_resume = TRUE;
1191
return err;
1192
}
1193
1194
static ParameterError parse_ech(struct GlobalConfig *global,
1195
struct OperationConfig *config,
1196
const char *nextarg)
1197
{
1198
ParameterError err = PARAM_OK;
1199
if(!feature_ech)
1200
err = PARAM_LIBCURL_DOESNT_SUPPORT;
1201
else if(strlen(nextarg) > 4 && curl_strnequal("pn:", nextarg, 3)) {
1202
/* a public_name */
1203
err = getstr(&config->ech_public, nextarg, DENY_BLANK);
1204
}
1205
else if(strlen(nextarg) > 5 && curl_strnequal("ecl:", nextarg, 4)) {
1206
/* an ECHConfigList */
1207
if('@' != *(nextarg + 4)) {
1208
err = getstr(&config->ech_config, nextarg, DENY_BLANK);
1209
}
1210
else {
1211
/* Indirect case: @filename or @- for stdin */
1212
char *tmpcfg = NULL;
1213
FILE *file;
1214
1215
nextarg += 5; /* skip over 'ecl:@' */
1216
if(!strcmp("-", nextarg)) {
1217
file = stdin;
1218
}
1219
else {
1220
file = fopen(nextarg, FOPEN_READTEXT);
1221
}
1222
if(!file) {
1223
warnf(global,
1224
"Couldn't read file \"%s\" "
1225
"specified for \"--ech ecl:\" option",
1226
nextarg);
1227
return PARAM_BAD_USE; /* */
1228
}
1229
err = file2string(&tmpcfg, file);
1230
if(file != stdin)
1231
fclose(file);
1232
if(err)
1233
return err;
1234
config->ech_config = aprintf("ecl:%s",tmpcfg);
1235
free(tmpcfg);
1236
if(!config->ech_config)
1237
return PARAM_NO_MEM;
1238
} /* file done */
1239
}
1240
else {
1241
/* Simple case: just a string, with a keyword */
1242
err = getstr(&config->ech, nextarg, DENY_BLANK);
1243
}
1244
return err;
1245
}
1246
1247
static ParameterError parse_header(struct GlobalConfig *global,
1248
struct OperationConfig *config,
1249
cmdline_t cmd,
1250
const char *nextarg)
1251
{
1252
ParameterError err = PARAM_OK;
1253
1254
/* A custom header to append to a list */
1255
if(nextarg[0] == '@') {
1256
/* read many headers from a file or stdin */
1257
bool use_stdin = !strcmp(&nextarg[1], "-");
1258
FILE *file = use_stdin ? stdin : fopen(&nextarg[1], FOPEN_READTEXT);
1259
if(!file) {
1260
errorf(global, "Failed to open %s", &nextarg[1]);
1261
err = PARAM_READ_ERROR;
1262
}
1263
else {
1264
struct dynbuf line;
1265
bool error = FALSE;
1266
curlx_dyn_init(&line, 1024*100);
1267
while(my_get_line(file, &line, &error)) {
1268
const char *ptr = curlx_dyn_ptr(&line);
1269
err = add2list(cmd == C_PROXY_HEADER ? /* --proxy-header? */
1270
&config->proxyheaders :
1271
&config->headers, ptr);
1272
if(err)
1273
break;
1274
}
1275
if(error)
1276
err = PARAM_READ_ERROR;
1277
curlx_dyn_free(&line);
1278
if(!use_stdin)
1279
fclose(file);
1280
}
1281
}
1282
else {
1283
if(cmd == C_PROXY_HEADER) /* --proxy-header */
1284
err = add2list(&config->proxyheaders, nextarg);
1285
else
1286
err = add2list(&config->headers, nextarg);
1287
}
1288
return err;
1289
}
1290
1291
static ParameterError parse_output(struct OperationConfig *config,
1292
const char *nextarg)
1293
{
1294
ParameterError err = PARAM_OK;
1295
struct getout *url;
1296
1297
/* output file */
1298
if(!config->url_out)
1299
config->url_out = config->url_list;
1300
if(config->url_out) {
1301
/* there is a node here, if it already is filled-in continue to find
1302
an "empty" node */
1303
while(config->url_out && config->url_out->outset)
1304
config->url_out = config->url_out->next;
1305
}
1306
1307
/* now there might or might not be an available node to fill in! */
1308
1309
if(config->url_out)
1310
/* existing node */
1311
url = config->url_out;
1312
else {
1313
/* there was no free node, create one! */
1314
config->url_out = url = new_getout(config);
1315
}
1316
1317
if(!url)
1318
return PARAM_NO_MEM;
1319
1320
/* fill in the outfile */
1321
err = getstr(&url->outfile, nextarg, DENY_BLANK);
1322
url->useremote = FALSE; /* switch off */
1323
url->outset = TRUE;
1324
return err;
1325
}
1326
1327
static ParameterError parse_remote_name(struct OperationConfig *config,
1328
bool toggle)
1329
{
1330
ParameterError err = PARAM_OK;
1331
struct getout *url;
1332
1333
if(!toggle && !config->remote_name_all)
1334
return err; /* nothing to do */
1335
1336
/* output file */
1337
if(!config->url_out)
1338
config->url_out = config->url_list;
1339
if(config->url_out) {
1340
/* there is a node here, if it already is filled-in continue to find
1341
an "empty" node */
1342
while(config->url_out && config->url_out->outset)
1343
config->url_out = config->url_out->next;
1344
}
1345
1346
/* now there might or might not be an available node to fill in! */
1347
1348
if(config->url_out)
1349
/* existing node */
1350
url = config->url_out;
1351
else {
1352
/* there was no free node, create one! */
1353
config->url_out = url = new_getout(config);
1354
}
1355
1356
if(!url)
1357
return PARAM_NO_MEM;
1358
1359
url->outfile = NULL; /* leave it */
1360
url->useremote = toggle;
1361
url->outset = TRUE;
1362
return PARAM_OK;
1363
}
1364
1365
static ParameterError parse_quote(struct OperationConfig *config,
1366
const char *nextarg)
1367
{
1368
ParameterError err = PARAM_OK;
1369
1370
/* QUOTE command to send to FTP server */
1371
switch(nextarg[0]) {
1372
case '-':
1373
/* prefixed with a dash makes it a POST TRANSFER one */
1374
nextarg++;
1375
err = add2list(&config->postquote, nextarg);
1376
break;
1377
case '+':
1378
/* prefixed with a plus makes it a just-before-transfer one */
1379
nextarg++;
1380
err = add2list(&config->prequote, nextarg);
1381
break;
1382
default:
1383
err = add2list(&config->quote, nextarg);
1384
break;
1385
}
1386
return err;
1387
}
1388
1389
static ParameterError parse_range(struct GlobalConfig *global,
1390
struct OperationConfig *config,
1391
const char *nextarg)
1392
{
1393
ParameterError err = PARAM_OK;
1394
curl_off_t value;
1395
const char *orig = nextarg;
1396
1397
if(config->use_resume) {
1398
errorf(global, "--continue-at is mutually exclusive with --range");
1399
return PARAM_BAD_USE;
1400
}
1401
if(!curlx_str_number(&nextarg, &value, CURL_OFF_T_MAX) &&
1402
curlx_str_single(&nextarg, '-')) {
1403
/* Specifying a range WITHOUT A DASH will create an illegal HTTP range
1404
(and will not actually be range by definition). The manpage previously
1405
claimed that to be a good way, why this code is added to work-around
1406
it. */
1407
char buffer[32];
1408
warnf(global, "A specified range MUST include at least one dash (-). "
1409
"Appending one for you");
1410
msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-",
1411
value);
1412
free(config->range);
1413
config->range = strdup(buffer);
1414
if(!config->range)
1415
err = PARAM_NO_MEM;
1416
}
1417
else {
1418
/* byte range requested */
1419
while(*nextarg) {
1420
if(!ISDIGIT(*nextarg) && *nextarg != '-' && *nextarg != ',') {
1421
warnf(global, "Invalid character is found in given range. "
1422
"A specified range MUST have only digits in "
1423
"\'start\'-\'stop\'. The server's response to this "
1424
"request is uncertain.");
1425
break;
1426
}
1427
nextarg++;
1428
}
1429
err = getstr(&config->range, orig, DENY_BLANK);
1430
}
1431
return err;
1432
}
1433
1434
static ParameterError parse_upload_file(struct OperationConfig *config,
1435
const char *nextarg)
1436
{
1437
ParameterError err = PARAM_OK;
1438
struct getout *url;
1439
1440
/* we are uploading */
1441
if(!config->url_ul)
1442
config->url_ul = config->url_list;
1443
if(config->url_ul) {
1444
/* there is a node here, if it already is filled-in continue to find
1445
an "empty" node */
1446
while(config->url_ul && config->url_ul->uploadset)
1447
config->url_ul = config->url_ul->next;
1448
}
1449
1450
/* now there might or might not be an available node to fill in! */
1451
1452
if(config->url_ul)
1453
/* existing node */
1454
url = config->url_ul;
1455
else
1456
/* there was no free node, create one! */
1457
config->url_ul = url = new_getout(config);
1458
1459
if(!url)
1460
return PARAM_NO_MEM;
1461
1462
url->uploadset = TRUE; /* mark -T used */
1463
if(!*nextarg)
1464
url->noupload = TRUE;
1465
else {
1466
/* "-" equals stdin, but keep the string around for now */
1467
err = getstr(&url->infile, nextarg, DENY_BLANK);
1468
}
1469
return err;
1470
}
1471
1472
static size_t verbose_nopts;
1473
1474
static ParameterError parse_verbose(struct GlobalConfig *global,
1475
bool toggle)
1476
{
1477
ParameterError err = PARAM_OK;
1478
1479
/* This option is a super-boolean with side effect when applied
1480
* more than once in the same argument flag, like `-vvv`. */
1481
if(!toggle) {
1482
global->verbosity = 0;
1483
if(set_trace_config(global, "-all"))
1484
err = PARAM_NO_MEM;
1485
global->tracetype = TRACE_NONE;
1486
return err;
1487
}
1488
else if(!verbose_nopts) {
1489
/* fist `-v` in an argument resets to base verbosity */
1490
global->verbosity = 0;
1491
if(set_trace_config(global, "-all"))
1492
return PARAM_NO_MEM;
1493
}
1494
/* the '%' thing here will cause the trace get sent to stderr */
1495
switch(global->verbosity) {
1496
case 0:
1497
global->verbosity = 1;
1498
free(global->trace_dump);
1499
global->trace_dump = strdup("%");
1500
if(!global->trace_dump)
1501
err = PARAM_NO_MEM;
1502
else {
1503
if(global->tracetype && (global->tracetype != TRACE_PLAIN))
1504
warnf(global,
1505
"-v, --verbose overrides an earlier trace option");
1506
global->tracetype = TRACE_PLAIN;
1507
}
1508
break;
1509
case 1:
1510
global->verbosity = 2;
1511
if(set_trace_config(global, "ids,time,protocol"))
1512
err = PARAM_NO_MEM;
1513
break;
1514
case 2:
1515
global->verbosity = 3;
1516
global->tracetype = TRACE_ASCII;
1517
if(set_trace_config(global, "ssl,read,write"))
1518
err = PARAM_NO_MEM;
1519
break;
1520
case 3:
1521
global->verbosity = 4;
1522
if(set_trace_config(global, "network"))
1523
err = PARAM_NO_MEM;
1524
break;
1525
default:
1526
/* no effect for now */
1527
break;
1528
}
1529
return err;
1530
}
1531
1532
static ParameterError parse_writeout(struct GlobalConfig *global,
1533
struct OperationConfig *config,
1534
const char *nextarg)
1535
{
1536
ParameterError err = PARAM_OK;
1537
1538
/* get the output string */
1539
if('@' == *nextarg) {
1540
/* the data begins with a '@' letter, it means that a filename
1541
or - (stdin) follows */
1542
FILE *file;
1543
const char *fname;
1544
nextarg++; /* pass the @ */
1545
if(!strcmp("-", nextarg)) {
1546
fname = "<stdin>";
1547
file = stdin;
1548
}
1549
else {
1550
fname = nextarg;
1551
file = fopen(fname, FOPEN_READTEXT);
1552
if(!file) {
1553
errorf(global, "Failed to open %s", fname);
1554
return PARAM_READ_ERROR;
1555
}
1556
}
1557
tool_safefree(config->writeout);
1558
err = file2string(&config->writeout, file);
1559
if(file && (file != stdin))
1560
fclose(file);
1561
if(err)
1562
return err;
1563
if(!config->writeout)
1564
warnf(global, "Failed to read %s", fname);
1565
}
1566
else
1567
err = getstr(&config->writeout, nextarg, ALLOW_BLANK);
1568
1569
return err;
1570
}
1571
1572
static ParameterError parse_time_cond(struct GlobalConfig *global,
1573
struct OperationConfig *config,
1574
const char *nextarg)
1575
{
1576
ParameterError err = PARAM_OK;
1577
1578
switch(*nextarg) {
1579
case '+':
1580
nextarg++;
1581
FALLTHROUGH();
1582
default:
1583
/* If-Modified-Since: (section 14.28 in RFC2068) */
1584
config->timecond = CURL_TIMECOND_IFMODSINCE;
1585
break;
1586
case '-':
1587
/* If-Unmodified-Since: (section 14.24 in RFC2068) */
1588
config->timecond = CURL_TIMECOND_IFUNMODSINCE;
1589
nextarg++;
1590
break;
1591
case '=':
1592
/* Last-Modified: (section 14.29 in RFC2068) */
1593
config->timecond = CURL_TIMECOND_LASTMOD;
1594
nextarg++;
1595
break;
1596
}
1597
config->condtime = (curl_off_t)curl_getdate(nextarg, NULL);
1598
if(-1 == config->condtime) {
1599
curl_off_t value;
1600
/* now let's see if it is a filename to get the time from instead! */
1601
int rc = getfiletime(nextarg, global, &value);
1602
if(!rc)
1603
/* pull the time out from the file */
1604
config->condtime = value;
1605
else {
1606
/* failed, remove time condition */
1607
config->timecond = CURL_TIMECOND_NONE;
1608
warnf(global,
1609
"Illegal date format for -z, --time-cond (and not "
1610
"a filename). Disabling time condition. "
1611
"See curl_getdate(3) for valid date syntax.");
1612
}
1613
}
1614
return err;
1615
}
1616
1617
struct flagmap {
1618
const char *name;
1619
size_t len;
1620
unsigned char flag;
1621
};
1622
1623
static const struct flagmap flag_table[] = {
1624
{"answered", 8, CURLULFLAG_ANSWERED},
1625
{"deleted", 7, CURLULFLAG_DELETED},
1626
{"draft", 5, CURLULFLAG_DRAFT},
1627
{"flagged", 7, CURLULFLAG_FLAGGED},
1628
{"seen", 4, CURLULFLAG_SEEN},
1629
{NULL, 0, 0}
1630
};
1631
1632
static ParameterError parse_upload_flags(struct OperationConfig *config,
1633
const char *flag)
1634
{
1635
ParameterError err = PARAM_OK;
1636
1637
while(flag) {
1638
bool negate;
1639
const struct flagmap *map;
1640
size_t len;
1641
char *next = strchr(flag, ','); /* Find next comma or end */
1642
if(next)
1643
len = next - flag;
1644
else
1645
len = strlen(flag);
1646
1647
negate = (*flag == '-');
1648
if(negate) {
1649
flag++;
1650
len--;
1651
}
1652
1653
for(map = flag_table; map->name; map++) {
1654
if((len == map->len) && !strncmp(flag, map->name, map->len)) {
1655
if(negate)
1656
config->upload_flags &= (unsigned char)~map->flag;
1657
else
1658
config->upload_flags |= map->flag;
1659
break;
1660
}
1661
}
1662
1663
if(!map->name) {
1664
err = PARAM_OPTION_UNKNOWN;
1665
break;
1666
}
1667
1668
if(next)
1669
/* move over the comma */
1670
next++;
1671
flag = next;
1672
}
1673
1674
return err;
1675
}
1676
1677
/* if 'toggle' is TRUE, set the 'bits' in 'modify'.
1678
if 'toggle' is FALSE, clear the 'bits' in 'modify'
1679
*/
1680
static void togglebit(bool toggle, unsigned long *modify, unsigned long bits)
1681
{
1682
if(toggle)
1683
*modify |= bits;
1684
else
1685
*modify &= ~bits;
1686
}
1687
1688
/* opt_depr is the function that handles ARG_DEPR options */
1689
static void opt_depr(struct GlobalConfig *global,
1690
const struct LongShort *a)
1691
{
1692
warnf(global, "--%s is deprecated and has no function anymore", a->lname);
1693
}
1694
1695
/* opt_none is the function that handles ARG_NONE options */
1696
static ParameterError opt_none(struct GlobalConfig *global,
1697
struct OperationConfig *config,
1698
const struct LongShort *a)
1699
{
1700
switch(a->cmd) {
1701
case C_ANYAUTH: /* --anyauth */
1702
config->authtype = CURLAUTH_ANY;
1703
break;
1704
case C_DUMP_CA_EMBED: /* --dump-ca-embed */
1705
return PARAM_CA_EMBED_REQUESTED;
1706
1707
case C_HTTP1_0: /* --http1.0 */
1708
/* HTTP version 1.0 */
1709
sethttpver(global, config, CURL_HTTP_VERSION_1_0);
1710
break;
1711
case C_HTTP1_1: /* --http1.1 */
1712
/* HTTP version 1.1 */
1713
sethttpver(global, config, CURL_HTTP_VERSION_1_1);
1714
break;
1715
case C_HTTP2: /* --http2 */
1716
/* HTTP version 2.0 */
1717
if(!feature_http2)
1718
return PARAM_LIBCURL_DOESNT_SUPPORT;
1719
sethttpver(global, config, CURL_HTTP_VERSION_2_0);
1720
break;
1721
case C_HTTP2_PRIOR_KNOWLEDGE: /* --http2-prior-knowledge */
1722
/* HTTP version 2.0 over clean TCP */
1723
if(!feature_http2)
1724
return PARAM_LIBCURL_DOESNT_SUPPORT;
1725
sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
1726
break;
1727
case C_HTTP3: /* --http3: */
1728
/* Try HTTP/3, allow fallback */
1729
if(!feature_http3)
1730
return PARAM_LIBCURL_DOESNT_SUPPORT;
1731
else
1732
sethttpver(global, config, CURL_HTTP_VERSION_3);
1733
break;
1734
case C_HTTP3_ONLY: /* --http3-only */
1735
/* Try HTTP/3 without fallback */
1736
if(!feature_http3)
1737
return PARAM_LIBCURL_DOESNT_SUPPORT;
1738
else
1739
sethttpver(global, config, CURL_HTTP_VERSION_3ONLY);
1740
break;
1741
case C_TLSV1: /* --tlsv1 */
1742
config->ssl_version = CURL_SSLVERSION_TLSv1;
1743
break;
1744
case C_TLSV1_0: /* --tlsv1.0 */
1745
config->ssl_version = CURL_SSLVERSION_TLSv1_0;
1746
break;
1747
case C_TLSV1_1: /* --tlsv1.1 */
1748
config->ssl_version = CURL_SSLVERSION_TLSv1_1;
1749
break;
1750
case C_TLSV1_2: /* --tlsv1.2 */
1751
config->ssl_version = CURL_SSLVERSION_TLSv1_2;
1752
break;
1753
case C_TLSV1_3: /* --tlsv1.3 */
1754
config->ssl_version = CURL_SSLVERSION_TLSv1_3;
1755
break;
1756
case C_IPV4: /* --ipv4 */
1757
config->ip_version = CURL_IPRESOLVE_V4;
1758
break;
1759
case C_IPV6: /* --ipv6 */
1760
config->ip_version = CURL_IPRESOLVE_V6;
1761
break;
1762
case C_NEXT: /* --next */
1763
return PARAM_NEXT_OPERATION;
1764
case C_PROXY_TLSV1: /* --proxy-tlsv1 */
1765
/* TLS version 1 for proxy */
1766
config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
1767
break;
1768
}
1769
return PARAM_OK;
1770
}
1771
1772
/* opt_bool is the function that handles boolean options */
1773
static ParameterError opt_bool(struct GlobalConfig *global,
1774
struct OperationConfig *config,
1775
const struct LongShort *a,
1776
bool toggle)
1777
{
1778
switch(a->cmd) {
1779
case C_ALPN: /* --alpn */
1780
config->noalpn = !toggle;
1781
break;
1782
case C_DISABLE_EPSV: /* --disable-epsv */
1783
config->disable_epsv = toggle;
1784
break;
1785
case C_DISALLOW_USERNAME_IN_URL: /* --disallow-username-in-url */
1786
config->disallow_username_in_url = toggle;
1787
break;
1788
case C_EPSV: /* --epsv */
1789
config->disable_epsv = !toggle;
1790
break;
1791
case C_COMPRESSED: /* --compressed */
1792
if(toggle && !(feature_libz || feature_brotli || feature_zstd))
1793
return PARAM_LIBCURL_DOESNT_SUPPORT;
1794
else
1795
config->encoding = toggle;
1796
break;
1797
case C_TR_ENCODING: /* --tr-encoding */
1798
config->tr_encoding = toggle;
1799
break;
1800
case C_DIGEST: /* --digest */
1801
togglebit(toggle, &config->authtype, CURLAUTH_DIGEST);
1802
break;
1803
case C_FTP_CREATE_DIRS: /* --ftp-create-dirs */
1804
config->ftp_create_dirs = toggle;
1805
break;
1806
case C_CREATE_DIRS: /* --create-dirs */
1807
config->create_dirs = toggle;
1808
break;
1809
case C_PROXY_NTLM: /* --proxy-ntlm */
1810
if(!feature_ntlm)
1811
return PARAM_LIBCURL_DOESNT_SUPPORT;
1812
else
1813
config->proxyntlm = toggle;
1814
break;
1815
case C_CRLF: /* --crlf */
1816
config->crlf = toggle;
1817
break;
1818
case C_HAPROXY_PROTOCOL: /* --haproxy-protocol */
1819
config->haproxy_protocol = toggle;
1820
break;
1821
case C_NEGOTIATE: /* --negotiate */
1822
if(!feature_spnego && toggle)
1823
return PARAM_LIBCURL_DOESNT_SUPPORT;
1824
togglebit(toggle, &config->authtype, CURLAUTH_NEGOTIATE);
1825
break;
1826
case C_NTLM: /* --ntlm */
1827
if(!feature_ntlm && toggle)
1828
return PARAM_LIBCURL_DOESNT_SUPPORT;
1829
togglebit(toggle, &config->authtype, CURLAUTH_NTLM);
1830
break;
1831
case C_BASIC: /* --basic */
1832
togglebit(toggle, &config->authtype, CURLAUTH_BASIC);
1833
break;
1834
#ifdef USE_WATT32
1835
case C_WDEBUG: /* --wdebug */
1836
dbug_init();
1837
break;
1838
#endif
1839
case C_DISABLE_EPRT: /* --disable-eprt */
1840
config->disable_eprt = toggle;
1841
break;
1842
case C_EPRT: /* --eprt */
1843
config->disable_eprt = !toggle;
1844
break;
1845
case C_XATTR: /* --xattr */
1846
config->xattr = toggle;
1847
break;
1848
case C_FTP_SSL: /* --ftp-ssl */
1849
case C_SSL: /* --ssl */
1850
config->ftp_ssl = toggle;
1851
if(config->ftp_ssl)
1852
warnf(global, "--%s is an insecure option, consider --ssl-reqd instead",
1853
a->lname);
1854
break;
1855
case C_FTP_SSL_CCC: /* --ftp-ssl-ccc */
1856
config->ftp_ssl_ccc = toggle;
1857
if(!config->ftp_ssl_ccc_mode)
1858
config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
1859
break;
1860
case C_TCP_NODELAY: /* --tcp-nodelay */
1861
config->tcp_nodelay = toggle;
1862
break;
1863
case C_PROXY_DIGEST: /* --proxy-digest */
1864
config->proxydigest = toggle;
1865
break;
1866
case C_PROXY_BASIC: /* --proxy-basic */
1867
config->proxybasic = toggle;
1868
break;
1869
case C_RETRY_CONNREFUSED: /* --retry-connrefused */
1870
config->retry_connrefused = toggle;
1871
break;
1872
case C_RETRY_ALL_ERRORS: /* --retry-all-errors */
1873
config->retry_all_errors = toggle;
1874
break;
1875
case C_PROXY_NEGOTIATE: /* --proxy-negotiate */
1876
if(!feature_spnego)
1877
return PARAM_LIBCURL_DOESNT_SUPPORT;
1878
else
1879
config->proxynegotiate = toggle;
1880
break;
1881
case C_FORM_ESCAPE: /* --form-escape */
1882
togglebit(toggle, &config->mime_options, CURLMIMEOPT_FORMESCAPE);
1883
break;
1884
case C_PROXY_ANYAUTH: /* --proxy-anyauth */
1885
config->proxyanyauth = toggle;
1886
break;
1887
case C_TRACE_TIME: /* --trace-time */
1888
global->tracetime = toggle;
1889
break;
1890
case C_IGNORE_CONTENT_LENGTH: /* --ignore-content-length */
1891
config->ignorecl = toggle;
1892
break;
1893
case C_FTP_SKIP_PASV_IP: /* --ftp-skip-pasv-ip */
1894
config->ftp_skip_ip = toggle;
1895
break;
1896
case C_FTP_SSL_REQD: /* --ftp-ssl-reqd */
1897
case C_SSL_REQD: /* --ssl-reqd */
1898
config->ftp_ssl_reqd = toggle;
1899
break;
1900
case C_SESSIONID: /* --sessionid */
1901
config->disable_sessionid = !toggle;
1902
break;
1903
case C_FTP_SSL_CONTROL: /* --ftp-ssl-control */
1904
config->ftp_ssl_control = toggle;
1905
break;
1906
case C_RAW: /* --raw */
1907
config->raw = toggle;
1908
break;
1909
case C_KEEPALIVE: /* --keepalive */
1910
config->nokeepalive = !toggle;
1911
break;
1912
case C_POST301: /* --post301 */
1913
config->post301 = toggle;
1914
break;
1915
case C_POST302: /* --post302 */
1916
config->post302 = toggle;
1917
break;
1918
case C_POST303: /* --post303 */
1919
config->post303 = toggle;
1920
break;
1921
case C_SOCKS5_GSSAPI_NEC: /* --socks5-gssapi-nec */
1922
config->socks5_gssapi_nec = toggle;
1923
break;
1924
case C_FTP_PRET: /* --ftp-pret */
1925
config->ftp_pret = toggle;
1926
break;
1927
case C_SASL_IR: /* --sasl-ir */
1928
config->sasl_ir = toggle;
1929
break;
1930
#ifdef DEBUGBUILD
1931
case C_TEST_DUPHANDLE: /* --test-duphandle */
1932
global->test_duphandle = toggle;
1933
break;
1934
case C_TEST_EVENT: /* --test-event */
1935
global->test_event_based = toggle;
1936
break;
1937
#endif
1938
case C_PATH_AS_IS: /* --path-as-is */
1939
config->path_as_is = toggle;
1940
break;
1941
case C_TFTP_NO_OPTIONS: /* --tftp-no-options */
1942
config->tftp_no_options = toggle;
1943
break;
1944
case C_TLS_EARLYDATA: /* --tls-earlydata */
1945
config->ssl_allow_earlydata = toggle;
1946
break;
1947
case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */
1948
config->suppress_connect_headers = toggle;
1949
break;
1950
case C_COMPRESSED_SSH: /* --compressed-ssh */
1951
config->ssh_compression = toggle;
1952
break;
1953
case C_TRACE_IDS: /* --trace-ids */
1954
global->traceids = toggle;
1955
break;
1956
case C_PROGRESS_METER: /* --progress-meter */
1957
global->noprogress = !toggle;
1958
break;
1959
case C_PROGRESS_BAR: /* --progress-bar */
1960
global->progressmode = toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
1961
break;
1962
case C_HTTP0_9: /* --http0.9 */
1963
config->http09_allowed = toggle;
1964
break;
1965
case C_PROXY_HTTP2: /* --proxy-http2 */
1966
if(!feature_httpsproxy || !feature_http2)
1967
return PARAM_LIBCURL_DOESNT_SUPPORT;
1968
1969
config->proxyver = toggle ? CURLPROXY_HTTPS2 : CURLPROXY_HTTPS;
1970
break;
1971
case C_APPEND: /* --append */
1972
config->ftp_append = toggle;
1973
break;
1974
case C_USE_ASCII: /* --use-ascii */
1975
config->use_ascii = toggle;
1976
break;
1977
case C_CA_NATIVE: /* --ca-native */
1978
config->native_ca_store = toggle;
1979
break;
1980
case C_PROXY_CA_NATIVE: /* --proxy-ca-native */
1981
config->proxy_native_ca_store = toggle;
1982
break;
1983
case C_SSL_ALLOW_BEAST: /* --ssl-allow-beast */
1984
config->ssl_allow_beast = toggle;
1985
break;
1986
case C_SSL_AUTO_CLIENT_CERT: /* --ssl-auto-client-cert */
1987
config->ssl_auto_client_cert = toggle;
1988
break;
1989
case C_PROXY_SSL_AUTO_CLIENT_CERT: /* --proxy-ssl-auto-client-cert */
1990
config->proxy_ssl_auto_client_cert = toggle;
1991
break;
1992
case C_CERT_STATUS: /* --cert-status */
1993
config->verifystatus = toggle;
1994
break;
1995
case C_DOH_CERT_STATUS: /* --doh-cert-status */
1996
config->doh_verifystatus = toggle;
1997
break;
1998
case C_FALSE_START: /* --false-start */
1999
config->falsestart = toggle;
2000
break;
2001
case C_SSL_NO_REVOKE: /* --ssl-no-revoke */
2002
config->ssl_no_revoke = toggle;
2003
break;
2004
case C_SSL_REVOKE_BEST_EFFORT: /* --ssl-revoke-best-effort */
2005
config->ssl_revoke_best_effort = toggle;
2006
break;
2007
case C_TCP_FASTOPEN: /* --tcp-fastopen */
2008
config->tcp_fastopen = toggle;
2009
break;
2010
case C_PROXY_SSL_ALLOW_BEAST: /* --proxy-ssl-allow-beast */
2011
config->proxy_ssl_allow_beast = toggle;
2012
break;
2013
case C_PROXY_INSECURE: /* --proxy-insecure */
2014
config->proxy_insecure_ok = toggle;
2015
break;
2016
case C_SOCKS5_BASIC: /* --socks5-basic */
2017
togglebit(toggle, &config->socks5_auth, CURLAUTH_BASIC);
2018
break;
2019
case C_SOCKS5_GSSAPI: /* --socks5-gssapi */
2020
togglebit(toggle, &config->socks5_auth, CURLAUTH_GSSAPI);
2021
break;
2022
case C_FAIL_EARLY: /* --fail-early */
2023
global->fail_early = toggle;
2024
break;
2025
case C_STYLED_OUTPUT: /* --styled-output */
2026
global->styled_output = toggle;
2027
break;
2028
case C_MAIL_RCPT_ALLOWFAILS: /* --mail-rcpt-allowfails */
2029
config->mail_rcpt_allowfails = toggle;
2030
break;
2031
case C_FAIL_WITH_BODY: /* --fail-with-body */
2032
config->failwithbody = toggle;
2033
if(config->failonerror && config->failwithbody) {
2034
errorf(config->global, "You must select either --fail or "
2035
"--fail-with-body, not both.");
2036
return PARAM_BAD_USE;
2037
}
2038
break;
2039
case C_REMOVE_ON_ERROR: /* --remove-on-error */
2040
if(config->use_resume && toggle) {
2041
errorf(config->global,
2042
"--continue-at is mutually exclusive with --remove-on-error");
2043
return PARAM_BAD_USE;
2044
}
2045
config->rm_partial = toggle;
2046
break;
2047
case C_FAIL: /* --fail */
2048
config->failonerror = toggle;
2049
if(config->failonerror && config->failwithbody) {
2050
errorf(config->global, "You must select either --fail or "
2051
"--fail-with-body, not both.");
2052
return PARAM_BAD_USE;
2053
}
2054
break;
2055
case C_GLOBOFF: /* --globoff */
2056
config->globoff = toggle;
2057
break;
2058
case C_GET: /* --get */
2059
config->use_httpget = toggle;
2060
break;
2061
case C_INCLUDE: /* --include */
2062
case C_SHOW_HEADERS: /* --show-headers */
2063
config->show_headers = toggle;
2064
break;
2065
case C_JUNK_SESSION_COOKIES: /* --junk-session-cookies */
2066
config->cookiesession = toggle;
2067
break;
2068
case C_HEAD: /* --head */
2069
config->no_body = toggle;
2070
config->show_headers = toggle;
2071
if(SetHTTPrequest(config, (config->no_body) ? TOOL_HTTPREQ_HEAD :
2072
TOOL_HTTPREQ_GET, &config->httpreq))
2073
return PARAM_BAD_USE;
2074
break;
2075
case C_REMOTE_HEADER_NAME: /* --remote-header-name */
2076
config->content_disposition = toggle;
2077
break;
2078
case C_INSECURE: /* --insecure */
2079
config->insecure_ok = toggle;
2080
break;
2081
case C_DOH_INSECURE: /* --doh-insecure */
2082
config->doh_insecure_ok = toggle;
2083
break;
2084
case C_LIST_ONLY: /* --list-only */
2085
config->dirlistonly = toggle; /* only list the names of the FTP dir */
2086
break;
2087
case C_LOCATION_TRUSTED: /* --location-trusted */
2088
config->unrestricted_auth = toggle;
2089
FALLTHROUGH();
2090
case C_LOCATION: /* --location */
2091
config->followlocation = toggle; /* Follow Location: HTTP headers */
2092
break;
2093
case C_MANUAL: /* --manual */
2094
if(toggle) /* --no-manual shows no manual... */
2095
return PARAM_MANUAL_REQUESTED;
2096
break;
2097
case C_NETRC_OPTIONAL: /* --netrc-optional */
2098
config->netrc_opt = toggle;
2099
break;
2100
case C_NETRC: /* --netrc */
2101
config->netrc = toggle;
2102
break;
2103
case C_BUFFER: /* --buffer */
2104
config->nobuffer = !toggle;
2105
break;
2106
case C_REMOTE_NAME_ALL: /* --remote-name-all */
2107
config->remote_name_all = toggle;
2108
break;
2109
case C_CLOBBER: /* --clobber */
2110
if(config->use_resume && !toggle) {
2111
errorf(config->global,
2112
"--continue-at is mutually exclusive with --no-clobber");
2113
return PARAM_BAD_USE;
2114
}
2115
config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
2116
break;
2117
case C_REMOTE_NAME: /* --remote-name */
2118
return parse_remote_name(config, toggle);
2119
break;
2120
case C_PROXYTUNNEL: /* --proxytunnel */
2121
config->proxytunnel = toggle;
2122
break;
2123
case C_DISABLE: /* --disable */
2124
/* if used first, already taken care of, we do it like this so we do not
2125
cause an error! */
2126
break;
2127
case C_REMOTE_TIME: /* --remote-time */
2128
config->remote_time = toggle;
2129
break;
2130
case C_SILENT: /* --silent */
2131
global->silent = toggle;
2132
break;
2133
case C_SKIP_EXISTING: /* --skip-existing */
2134
config->skip_existing = toggle;
2135
break;
2136
case C_SHOW_ERROR: /* --show-error */
2137
global->showerror = toggle;
2138
break;
2139
case C_VERBOSE: /* --verbose */
2140
return parse_verbose(global, toggle);
2141
break;
2142
case C_VERSION: /* --version */
2143
if(toggle) /* --no-version yields no output! */
2144
return PARAM_VERSION_INFO_REQUESTED;
2145
break;
2146
case C_PARALLEL: /* --parallel */
2147
global->parallel = toggle;
2148
break;
2149
case C_PARALLEL_IMMEDIATE: /* --parallel-immediate */
2150
global->parallel_connect = toggle;
2151
break;
2152
case C_MPTCP: /* --mptcp */
2153
config->mptcp = toggle;
2154
break;
2155
default:
2156
return PARAM_OPTION_UNKNOWN;
2157
}
2158
return PARAM_OK;
2159
}
2160
2161
2162
/* opt_filestring handles string and file options */
2163
static ParameterError opt_filestring(struct GlobalConfig *global,
2164
struct OperationConfig *config,
2165
const struct LongShort *a,
2166
const char *nextarg)
2167
{
2168
ParameterError err = PARAM_OK;
2169
curl_off_t value;
2170
static const char *redir_protos[] = {
2171
"http",
2172
"https",
2173
"ftp",
2174
"ftps",
2175
NULL
2176
};
2177
if(!nextarg)
2178
nextarg = "";
2179
2180
switch(a->cmd) {
2181
case C_DNS_IPV4_ADDR: /* --dns-ipv4-addr */
2182
if(!curlinfo->ares_num) /* c-ares is needed for this */
2183
return PARAM_LIBCURL_DOESNT_SUPPORT;
2184
/* addr in dot notation */
2185
return getstr(&config->dns_ipv4_addr, nextarg, DENY_BLANK);
2186
2187
case C_DNS_IPV6_ADDR: /* --dns-ipv6-addr */
2188
if(!curlinfo->ares_num) /* c-ares is needed for this */
2189
return PARAM_LIBCURL_DOESNT_SUPPORT;
2190
/* addr in dot notation */
2191
return getstr(&config->dns_ipv6_addr, nextarg, DENY_BLANK);
2192
2193
case C_OAUTH2_BEARER: /* --oauth2-bearer */
2194
config->authtype |= CURLAUTH_BEARER;
2195
return getstr(&config->oauth_bearer, nextarg, DENY_BLANK);
2196
2197
case C_CONNECT_TIMEOUT: /* --connect-timeout */
2198
return secs2ms(&config->connecttimeout_ms, nextarg);
2199
2200
case C_DOH_URL: /* --doh-url */
2201
err = getstr(&config->doh_url, nextarg, ALLOW_BLANK);
2202
if(!err && config->doh_url && !config->doh_url[0])
2203
/* if given a blank string, make it NULL again */
2204
tool_safefree(config->doh_url);
2205
break;
2206
2207
case C_CIPHERS: /* -- ciphers */
2208
err = getstr(&config->cipher_list, nextarg, DENY_BLANK);
2209
break;
2210
2211
case C_DNS_INTERFACE: /* --dns-interface */
2212
if(!curlinfo->ares_num) /* c-ares is needed for this */
2213
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2214
else
2215
/* interface name */
2216
err = getstr(&config->dns_interface, nextarg, DENY_BLANK);
2217
break;
2218
case C_DNS_SERVERS: /* --dns-servers */
2219
if(!curlinfo->ares_num) /* c-ares is needed for this */
2220
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2221
else
2222
/* IP addrs of DNS servers */
2223
err = getstr(&config->dns_servers, nextarg, DENY_BLANK);
2224
break;
2225
case C_TRACE: /* --trace */
2226
err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
2227
if(!err) {
2228
if(global->tracetype && (global->tracetype != TRACE_BIN))
2229
warnf(global, "--trace overrides an earlier trace/verbose option");
2230
global->tracetype = TRACE_BIN;
2231
}
2232
break;
2233
case C_TRACE_ASCII: /* --trace-ascii */
2234
err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
2235
if(!err) {
2236
if(global->tracetype && (global->tracetype != TRACE_ASCII))
2237
warnf(global,
2238
"--trace-ascii overrides an earlier trace/verbose option");
2239
global->tracetype = TRACE_ASCII;
2240
}
2241
break;
2242
case C_LIMIT_RATE: /* --limit-rate */
2243
err = GetSizeParameter(global, nextarg, "rate", &value);
2244
if(!err) {
2245
config->recvpersecond = value;
2246
config->sendpersecond = value;
2247
}
2248
break;
2249
case C_RATE:
2250
err = set_rate(global, nextarg);
2251
break;
2252
case C_CREATE_FILE_MODE: /* --create-file-mode */
2253
err = oct2nummax(&config->create_file_mode, nextarg, 0777);
2254
break;
2255
case C_MAX_REDIRS: /* --max-redirs */
2256
/* specified max no of redirects (http(s)), this accepts -1 as a
2257
special condition */
2258
err = str2num(&config->maxredirs, nextarg);
2259
if(!err && (config->maxredirs < -1))
2260
err = PARAM_BAD_NUMERIC;
2261
break;
2262
#ifndef CURL_DISABLE_IPFS
2263
case C_IPFS_GATEWAY: /* --ipfs-gateway */
2264
err = getstr(&config->ipfs_gateway, nextarg, DENY_BLANK);
2265
break;
2266
#endif /* !CURL_DISABLE_IPFS */
2267
case C_AWS_SIGV4: /* --aws-sigv4 */
2268
config->authtype |= CURLAUTH_AWS_SIGV4;
2269
err = getstr(&config->aws_sigv4, nextarg, ALLOW_BLANK);
2270
break;
2271
case C_STDERR: /* --stderr */
2272
tool_set_stderr_file(global, nextarg);
2273
break;
2274
case C_INTERFACE: /* --interface */
2275
/* interface */
2276
err = getstr(&config->iface, nextarg, DENY_BLANK);
2277
break;
2278
case C_KRB: /* --krb */
2279
/* kerberos level string */
2280
if(!feature_spnego)
2281
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2282
else
2283
err = getstr(&config->krblevel, nextarg, DENY_BLANK);
2284
break;
2285
case C_HAPROXY_CLIENTIP: /* --haproxy-clientip */
2286
err = getstr(&config->haproxy_clientip, nextarg, DENY_BLANK);
2287
break;
2288
case C_MAX_FILESIZE: /* --max-filesize */
2289
err = GetSizeParameter(global, nextarg, "max-filesize", &value);
2290
if(!err)
2291
config->max_filesize = value;
2292
break;
2293
case C_URL: /* --url */
2294
err = parse_url(global, config, nextarg);
2295
break;
2296
case C_FTP_PASV: /* --ftp-pasv */
2297
tool_safefree(config->ftpport);
2298
break;
2299
case C_SOCKS5: /* --socks5 */
2300
/* socks5 proxy to use, and resolves the name locally and passes on the
2301
resolved address */
2302
err = getstr(&config->proxy, nextarg, DENY_BLANK);
2303
config->proxyver = CURLPROXY_SOCKS5;
2304
break;
2305
case C_SOCKS4: /* --socks4 */
2306
err = getstr(&config->proxy, nextarg, DENY_BLANK);
2307
config->proxyver = CURLPROXY_SOCKS4;
2308
break;
2309
case C_SOCKS4A: /* --socks4a */
2310
err = getstr(&config->proxy, nextarg, DENY_BLANK);
2311
config->proxyver = CURLPROXY_SOCKS4A;
2312
break;
2313
case C_SOCKS5_HOSTNAME: /* --socks5-hostname */
2314
err = getstr(&config->proxy, nextarg, DENY_BLANK);
2315
config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
2316
break;
2317
case C_IP_TOS: { /* --ip-tos */
2318
struct TOSEntry find;
2319
const struct TOSEntry *entry;
2320
find.name = nextarg;
2321
entry = bsearch(&find, tos_entries,
2322
CURL_ARRAYSIZE(tos_entries),
2323
sizeof(*tos_entries), find_tos);
2324
if(entry)
2325
config->ip_tos = entry->value;
2326
else /* numeric tos value */
2327
err = str2unummax(&config->ip_tos, nextarg, 0xFF);
2328
break;
2329
}
2330
case C_VLAN_PRIORITY: /* --vlan-priority */
2331
err = str2unummax(&config->vlan_priority, nextarg, 7);
2332
break;
2333
case C_RETRY: /* --retry */
2334
err = str2unum(&config->req_retry, nextarg);
2335
break;
2336
case C_RETRY_DELAY: /* --retry-delay */
2337
err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
2338
break;
2339
case C_RETRY_MAX_TIME: /* --retry-max-time */
2340
err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
2341
break;
2342
case C_FTP_ACCOUNT: /* --ftp-account */
2343
err = getstr(&config->ftp_account, nextarg, DENY_BLANK);
2344
break;
2345
case C_FTP_METHOD: /* --ftp-method */
2346
config->ftp_filemethod = ftpfilemethod(config, nextarg);
2347
break;
2348
case C_LOCAL_PORT: /* --local-port */
2349
err = parse_localport(config, nextarg);
2350
break;
2351
case C_FTP_ALTERNATIVE_TO_USER: /* --ftp-alternative-to-user */
2352
err = getstr(&config->ftp_alternative_to_user, nextarg, DENY_BLANK);
2353
break;
2354
case C_LIBCURL: /* --libcurl */
2355
#ifdef CURL_DISABLE_LIBCURL_OPTION
2356
warnf(global,
2357
"--libcurl option was disabled at build-time");
2358
err = PARAM_OPTION_UNKNOWN;
2359
#else
2360
err = getstr(&global->libcurl, nextarg, DENY_BLANK);
2361
#endif
2362
break;
2363
case C_KEEPALIVE_TIME: /* --keepalive-time */
2364
err = str2unum(&config->alivetime, nextarg);
2365
break;
2366
case C_KEEPALIVE_CNT: /* --keepalive-cnt */
2367
err = str2unum(&config->alivecnt, nextarg);
2368
break;
2369
case C_NOPROXY: /* --noproxy */
2370
/* This specifies the noproxy list */
2371
err = getstr(&config->noproxy, nextarg, ALLOW_BLANK);
2372
break;
2373
case C_PROXY1_0: /* --proxy1.0 */
2374
/* http 1.0 proxy */
2375
err = getstr(&config->proxy, nextarg, DENY_BLANK);
2376
config->proxyver = CURLPROXY_HTTP_1_0;
2377
break;
2378
case C_TFTP_BLKSIZE: /* --tftp-blksize */
2379
err = str2unum(&config->tftp_blksize, nextarg);
2380
break;
2381
case C_MAIL_FROM: /* --mail-from */
2382
err = getstr(&config->mail_from, nextarg, DENY_BLANK);
2383
break;
2384
case C_MAIL_RCPT: /* --mail-rcpt */
2385
/* append receiver to a list */
2386
err = add2list(&config->mail_rcpt, nextarg);
2387
break;
2388
case C_PROTO: /* --proto */
2389
config->proto_present = TRUE;
2390
err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
2391
break;
2392
case C_PROTO_REDIR: /* --proto-redir */
2393
config->proto_redir_present = TRUE;
2394
if(proto2num(config, redir_protos, &config->proto_redir_str,
2395
nextarg))
2396
err = PARAM_BAD_USE;
2397
break;
2398
case C_RESOLVE: /* --resolve */
2399
err = add2list(&config->resolve, nextarg);
2400
break;
2401
case C_DELEGATION: /* --delegation */
2402
config->gssapi_delegation = delegation(config, nextarg);
2403
break;
2404
case C_MAIL_AUTH: /* --mail-auth */
2405
err = getstr(&config->mail_auth, nextarg, DENY_BLANK);
2406
break;
2407
case C_SASL_AUTHZID: /* --sasl-authzid */
2408
err = getstr(&config->sasl_authzid, nextarg, DENY_BLANK);
2409
break;
2410
case C_UNIX_SOCKET: /* --unix-socket */
2411
config->abstract_unix_socket = FALSE;
2412
err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
2413
break;
2414
case C_PROXY_SERVICE_NAME: /* --proxy-service-name */
2415
err = getstr(&config->proxy_service_name, nextarg, DENY_BLANK);
2416
break;
2417
case C_SERVICE_NAME: /* --service-name */
2418
err = getstr(&config->service_name, nextarg, DENY_BLANK);
2419
break;
2420
case C_PROTO_DEFAULT: /* --proto-default */
2421
err = getstr(&config->proto_default, nextarg, DENY_BLANK);
2422
if(!err)
2423
err = check_protocol(config->proto_default);
2424
break;
2425
case C_EXPECT100_TIMEOUT: /* --expect100-timeout */
2426
err = secs2ms(&config->expect100timeout_ms, nextarg);
2427
break;
2428
case C_CONNECT_TO: /* --connect-to */
2429
err = add2list(&config->connect_to, nextarg);
2430
break;
2431
case C_ABSTRACT_UNIX_SOCKET: /* --abstract-unix-socket */
2432
config->abstract_unix_socket = TRUE;
2433
err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
2434
break;
2435
case C_TLS_MAX: /* --tls-max */
2436
err = str2tls_max(&config->ssl_version_max, nextarg);
2437
break;
2438
case C_HAPPY_EYEBALLS_TIMEOUT_MS: /* --happy-eyeballs-timeout-ms */
2439
err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
2440
/* 0 is a valid value for this timeout */
2441
break;
2442
case C_TRACE_CONFIG: /* --trace-config */
2443
if(set_trace_config(global, nextarg))
2444
err = PARAM_NO_MEM;
2445
break;
2446
case C_VARIABLE: /* --variable */
2447
err = setvariable(global, nextarg);
2448
break;
2449
case C_TLS13_CIPHERS: /* --tls13-ciphers */
2450
err = getstr(&config->cipher13_list, nextarg, DENY_BLANK);
2451
break;
2452
case C_PROXY_TLS13_CIPHERS: /* --proxy-tls13-ciphers */
2453
err = getstr(&config->proxy_cipher13_list, nextarg, DENY_BLANK);
2454
break;
2455
case C_USER_AGENT: /* --user-agent */
2456
err = getstr(&config->useragent, nextarg, ALLOW_BLANK);
2457
break;
2458
case C_ALT_SVC: /* --alt-svc */
2459
if(!feature_altsvc)
2460
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2461
else
2462
err = getstr(&config->altsvc, nextarg, ALLOW_BLANK);
2463
break;
2464
case C_HSTS: /* --hsts */
2465
if(!feature_hsts)
2466
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2467
else
2468
err = getstr(&config->hsts, nextarg, ALLOW_BLANK);
2469
break;
2470
case C_COOKIE: /* --cookie */
2471
if(strchr(nextarg, '=')) {
2472
/* A cookie string must have a =-letter */
2473
err = add2list(&config->cookies, nextarg);
2474
break;
2475
}
2476
else {
2477
/* We have a cookie file to read from! */
2478
err = add2list(&config->cookiefiles, nextarg);
2479
}
2480
break;
2481
case C_COOKIE_JAR: /* --cookie-jar */
2482
err = getstr(&config->cookiejar, nextarg, DENY_BLANK);
2483
break;
2484
case C_CONTINUE_AT: /* --continue-at */
2485
err = parse_continue_at(global, config, nextarg);
2486
break;
2487
case C_DATA: /* --data */
2488
case C_DATA_ASCII: /* --data-ascii */
2489
case C_DATA_BINARY: /* --data-binary */
2490
case C_DATA_URLENCODE: /* --data-urlencode */
2491
case C_JSON: /* --json */
2492
case C_DATA_RAW: /* --data-raw */
2493
err = set_data((cmdline_t)a->cmd, nextarg, global, config);
2494
break;
2495
case C_URL_QUERY: /* --url-query */
2496
err = url_query(nextarg, global, config);
2497
break;
2498
case C_DUMP_HEADER: /* --dump-header */
2499
err = getstr(&config->headerfile, nextarg, DENY_BLANK);
2500
break;
2501
case C_REFERER: { /* --referer */
2502
size_t len = strlen(nextarg);
2503
/* does it end with ;auto ? */
2504
if(len >= 5 && !strcmp(";auto", &nextarg[len - 5])) {
2505
/* Automatic referer requested, this may be combined with a set initial
2506
one */
2507
config->autoreferer = TRUE;
2508
len -= 5;
2509
}
2510
else
2511
config->autoreferer = FALSE;
2512
2513
if(len)
2514
err = getstrn(&config->referer, nextarg, len, ALLOW_BLANK);
2515
else
2516
tool_safefree(config->referer);
2517
}
2518
break;
2519
case C_CERT: /* --cert */
2520
GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
2521
break;
2522
case C_CACERT: /* --cacert */
2523
err = getstr(&config->cacert, nextarg, DENY_BLANK);
2524
break;
2525
case C_CERT_TYPE: /* --cert-type */
2526
err = getstr(&config->cert_type, nextarg, DENY_BLANK);
2527
break;
2528
case C_KEY: /* --key */
2529
err = getstr(&config->key, nextarg, DENY_BLANK);
2530
break;
2531
case C_KEY_TYPE: /* --key-type */
2532
err = getstr(&config->key_type, nextarg, DENY_BLANK);
2533
break;
2534
case C_PASS: /* --pass */
2535
err = getstr(&config->key_passwd, nextarg, DENY_BLANK);
2536
break;
2537
case C_ENGINE: /* --engine */
2538
err = getstr(&config->engine, nextarg, DENY_BLANK);
2539
if(!err &&
2540
config->engine && !strcmp(config->engine, "list")) {
2541
err = PARAM_ENGINES_REQUESTED;
2542
}
2543
break;
2544
case C_ECH: /* --ech */
2545
err = parse_ech(global, config, nextarg);
2546
break;
2547
case C_CAPATH: /* --capath */
2548
err = getstr(&config->capath, nextarg, DENY_BLANK);
2549
break;
2550
case C_PUBKEY: /* --pubkey */
2551
err = getstr(&config->pubkey, nextarg, DENY_BLANK);
2552
break;
2553
case C_HOSTPUBMD5: /* --hostpubmd5 */
2554
err = getstr(&config->hostpubmd5, nextarg, DENY_BLANK);
2555
if(!err) {
2556
if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
2557
err = PARAM_BAD_USE;
2558
}
2559
break;
2560
case C_HOSTPUBSHA256: /* --hostpubsha256 */
2561
if(!feature_libssh2)
2562
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2563
else
2564
err = getstr(&config->hostpubsha256, nextarg, DENY_BLANK);
2565
break;
2566
case C_CRLFILE: /* --crlfile */
2567
err = getstr(&config->crlfile, nextarg, DENY_BLANK);
2568
break;
2569
case C_TLSUSER: /* --tlsuser */
2570
if(!feature_tls_srp)
2571
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2572
else
2573
err = getstr(&config->tls_username, nextarg, DENY_BLANK);
2574
break;
2575
case C_TLSPASSWORD: /* --tlspassword */
2576
if(!feature_tls_srp)
2577
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2578
else
2579
err = getstr(&config->tls_password, nextarg, ALLOW_BLANK);
2580
break;
2581
case C_TLSAUTHTYPE: /* --tlsauthtype */
2582
if(!feature_tls_srp)
2583
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2584
else {
2585
err = getstr(&config->tls_authtype, nextarg, DENY_BLANK);
2586
if(!err && config->tls_authtype && strcmp(config->tls_authtype, "SRP"))
2587
err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
2588
}
2589
break;
2590
case C_PINNEDPUBKEY: /* --pinnedpubkey */
2591
err = getstr(&config->pinnedpubkey, nextarg, DENY_BLANK);
2592
break;
2593
case C_PROXY_PINNEDPUBKEY: /* --proxy-pinnedpubkey */
2594
err = getstr(&config->proxy_pinnedpubkey, nextarg, DENY_BLANK);
2595
break;
2596
case C_SSL_SESSIONS: /* --ssl-sessions */
2597
if(feature_ssls_export)
2598
err = getstr(&global->ssl_sessions, nextarg, DENY_BLANK);
2599
else
2600
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2601
break;
2602
case C_PROXY_TLSUSER: /* --proxy-tlsuser */
2603
if(!feature_tls_srp)
2604
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2605
else
2606
err = getstr(&config->proxy_tls_username, nextarg, ALLOW_BLANK);
2607
break;
2608
case C_PROXY_TLSPASSWORD: /* --proxy-tlspassword */
2609
if(!feature_tls_srp)
2610
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2611
else
2612
err = getstr(&config->proxy_tls_password, nextarg, DENY_BLANK);
2613
break;
2614
case C_PROXY_TLSAUTHTYPE: /* --proxy-tlsauthtype */
2615
if(!feature_tls_srp)
2616
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2617
else {
2618
err = getstr(&config->proxy_tls_authtype, nextarg, DENY_BLANK);
2619
if(!err && config->proxy_tls_authtype &&
2620
strcmp(config->proxy_tls_authtype, "SRP"))
2621
err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
2622
}
2623
break;
2624
case C_PROXY_CERT: /* --proxy-cert */
2625
GetFileAndPassword(nextarg, &config->proxy_cert,
2626
&config->proxy_key_passwd);
2627
break;
2628
case C_PROXY_CERT_TYPE: /* --proxy-cert-type */
2629
err = getstr(&config->proxy_cert_type, nextarg, DENY_BLANK);
2630
break;
2631
case C_PROXY_KEY: /* --proxy-key */
2632
err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK);
2633
break;
2634
case C_PROXY_KEY_TYPE: /* --proxy-key-type */
2635
err = getstr(&config->proxy_key_type, nextarg, DENY_BLANK);
2636
break;
2637
case C_PROXY_PASS: /* --proxy-pass */
2638
err = getstr(&config->proxy_key_passwd, nextarg, ALLOW_BLANK);
2639
break;
2640
case C_PROXY_CIPHERS: /* --proxy-ciphers */
2641
err = getstr(&config->proxy_cipher_list, nextarg, DENY_BLANK);
2642
break;
2643
case C_PROXY_CRLFILE: /* --proxy-crlfile */
2644
err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK);
2645
break;
2646
case C_LOGIN_OPTIONS: /* --login-options */
2647
err = getstr(&config->login_options, nextarg, ALLOW_BLANK);
2648
break;
2649
case C_PROXY_CACERT: /* --proxy-cacert */
2650
err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK);
2651
break;
2652
case C_PROXY_CAPATH: /* --proxy-capath */
2653
err = getstr(&config->proxy_capath, nextarg, DENY_BLANK);
2654
break;
2655
case C_ETAG_SAVE: /* --etag-save */
2656
if(config->num_urls > 1) {
2657
errorf(global, "The etag options only work on a single URL");
2658
err = PARAM_BAD_USE;
2659
}
2660
else
2661
err = getstr(&config->etag_save_file, nextarg, DENY_BLANK);
2662
break;
2663
case C_ETAG_COMPARE: /* --etag-compare */
2664
if(config->num_urls > 1) {
2665
errorf(global, "The etag options only work on a single URL");
2666
err = PARAM_BAD_USE;
2667
}
2668
else
2669
err = getstr(&config->etag_compare_file, nextarg, DENY_BLANK);
2670
break;
2671
case C_CURVES: /* --curves */
2672
err = getstr(&config->ssl_ec_curves, nextarg, DENY_BLANK);
2673
break;
2674
case C_SIGNATURE_ALGORITHMS: /* --sigalgs */
2675
err = getstr(&config->ssl_signature_algorithms, nextarg, DENY_BLANK);
2676
break;
2677
case C_FORM: /* --form */
2678
case C_FORM_STRING: /* --form-string */
2679
/* "form data" simulation, this is a little advanced so lets do our best
2680
to sort this out slowly and carefully */
2681
if(formparse(config,
2682
nextarg,
2683
&config->mimeroot,
2684
&config->mimecurrent,
2685
(a->cmd == C_FORM_STRING))) /* literal string */
2686
err = PARAM_BAD_USE;
2687
else if(SetHTTPrequest(config, TOOL_HTTPREQ_MIMEPOST, &config->httpreq))
2688
err = PARAM_BAD_USE;
2689
break;
2690
case C_REQUEST_TARGET: /* --request-target */
2691
err = getstr(&config->request_target, nextarg, DENY_BLANK);
2692
break;
2693
case C_HEADER: /* --header */
2694
case C_PROXY_HEADER: /* --proxy-header */
2695
err = parse_header(global, config, (cmdline_t)a->cmd, nextarg);
2696
break;
2697
case C_CONFIG: /* --config */
2698
if(parseconfig(nextarg, global)) {
2699
errorf(global, "cannot read config from '%s'", nextarg);
2700
err = PARAM_READ_ERROR;
2701
}
2702
break;
2703
case C_MAX_TIME: /* --max-time */
2704
/* specified max time */
2705
err = secs2ms(&config->timeout_ms, nextarg);
2706
break;
2707
case C_NETRC_FILE: /* --netrc-file */
2708
err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
2709
break;
2710
case C_OUTPUT_DIR: /* --output-dir */
2711
err = getstr(&config->output_dir, nextarg, DENY_BLANK);
2712
break;
2713
case C_OUTPUT: /* --output */
2714
err = parse_output(config, nextarg);
2715
break;
2716
case C_FTP_PORT: /* --ftp-port */
2717
/* This makes the FTP sessions use PORT instead of PASV */
2718
/* use <eth0> or <192.168.10.10> style addresses. Anything except
2719
this will make us try to get the "default" address.
2720
NOTE: this is a changed behavior since the released 4.1!
2721
*/
2722
err = getstr(&config->ftpport, nextarg, DENY_BLANK);
2723
break;
2724
case C_FTP_SSL_CCC_MODE: /* --ftp-ssl-ccc-mode */
2725
config->ftp_ssl_ccc = TRUE;
2726
config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
2727
break;
2728
case C_QUOTE: /* --quote */
2729
err = parse_quote(config, nextarg);
2730
break;
2731
case C_RANGE: /* --range */
2732
err = parse_range(global, config, nextarg);
2733
break;
2734
case C_TELNET_OPTION: /* --telnet-option */
2735
/* Telnet options */
2736
err = add2list(&config->telnet_options, nextarg);
2737
break;
2738
case C_UPLOAD_FILE: /* --upload-file */
2739
err = parse_upload_file(config, nextarg);
2740
break;
2741
case C_USER: /* --user */
2742
/* user:password */
2743
err = getstr(&config->userpwd, nextarg, ALLOW_BLANK);
2744
break;
2745
case C_PROXY_USER: /* --proxy-user */
2746
/* Proxy user:password */
2747
err = getstr(&config->proxyuserpwd, nextarg, ALLOW_BLANK);
2748
break;
2749
case C_WRITE_OUT: /* --write-out */
2750
err = parse_writeout(global, config, nextarg);
2751
break;
2752
case C_PREPROXY: /* --preproxy */
2753
err = getstr(&config->preproxy, nextarg, DENY_BLANK);
2754
break;
2755
case C_PROXY: /* --proxy */
2756
/* --proxy */
2757
err = getstr(&config->proxy, nextarg, ALLOW_BLANK);
2758
if(config->proxyver != CURLPROXY_HTTPS2)
2759
config->proxyver = CURLPROXY_HTTP;
2760
break;
2761
case C_REQUEST: /* --request */
2762
/* set custom request */
2763
err = getstr(&config->customrequest, nextarg, DENY_BLANK);
2764
break;
2765
case C_SPEED_TIME: /* --speed-time */
2766
/* low speed time */
2767
err = str2unum(&config->low_speed_time, nextarg);
2768
if(!err && !config->low_speed_limit)
2769
config->low_speed_limit = 1;
2770
break;
2771
case C_SPEED_LIMIT: /* --speed-limit */
2772
/* low speed limit */
2773
err = str2unum(&config->low_speed_limit, nextarg);
2774
if(!err && !config->low_speed_time)
2775
config->low_speed_time = 30;
2776
break;
2777
case C_PARALLEL_MAX: { /* --parallel-max */
2778
long val;
2779
err = str2unum(&val, nextarg);
2780
if(err)
2781
break;
2782
if(val > MAX_PARALLEL)
2783
global->parallel_max = MAX_PARALLEL;
2784
else if(val < 1)
2785
global->parallel_max = PARALLEL_DEFAULT;
2786
else
2787
global->parallel_max = (unsigned short)val;
2788
break;
2789
}
2790
case C_TIME_COND: /* --time-cond */
2791
err = parse_time_cond(global, config, nextarg);
2792
break;
2793
case C_UPLOAD_FLAGS: /* --upload-flags */
2794
err = parse_upload_flags(config, nextarg);
2795
break;
2796
}
2797
return err;
2798
}
2799
2800
ParameterError getparameter(const char *flag, /* f or -long-flag */
2801
const char *nextarg, /* NULL if unset */
2802
bool *usedarg, /* set to TRUE if the arg
2803
has been used */
2804
struct GlobalConfig *global,
2805
struct OperationConfig *config)
2806
{
2807
const char *parse = NULL;
2808
bool longopt = FALSE;
2809
bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
2810
ParameterError err = PARAM_OK;
2811
bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
2812
by using --OPTION or --no-OPTION */
2813
bool nextalloc = FALSE; /* if nextarg is allocated */
2814
const struct LongShort *a = NULL;
2815
verbose_nopts = 0; /* options processed in `flag`*/
2816
2817
*usedarg = FALSE; /* default is that we do not use the arg */
2818
2819
if(('-' != flag[0]) || ('-' == flag[1])) {
2820
/* this should be a long name */
2821
const char *word = ('-' == flag[0]) ? flag + 2 : flag;
2822
bool noflagged = FALSE;
2823
bool expand = FALSE;
2824
2825
if(!strncmp(word, "no-", 3)) {
2826
/* disable this option but ignore the "no-" part when looking for it */
2827
word += 3;
2828
toggle = FALSE;
2829
noflagged = TRUE;
2830
}
2831
else if(!strncmp(word, "expand-", 7)) {
2832
/* variable expansions is to be done on the argument */
2833
word += 7;
2834
expand = TRUE;
2835
}
2836
2837
a = findlongopt(word);
2838
if(a) {
2839
longopt = TRUE;
2840
}
2841
else {
2842
err = PARAM_OPTION_UNKNOWN;
2843
goto error;
2844
}
2845
if(noflagged && (ARGTYPE(a->desc) != ARG_BOOL)) {
2846
/* --no- prefixed an option that is not boolean! */
2847
err = PARAM_NO_PREFIX;
2848
goto error;
2849
}
2850
else if(expand && nextarg) {
2851
struct dynbuf nbuf;
2852
bool replaced;
2853
2854
if((ARGTYPE(a->desc) != ARG_STRG) &&
2855
(ARGTYPE(a->desc) != ARG_FILE)) {
2856
/* --expand on an option that is not a string or a filename */
2857
err = PARAM_EXPAND_ERROR;
2858
goto error;
2859
}
2860
err = varexpand(global, nextarg, &nbuf, &replaced);
2861
if(err) {
2862
curlx_dyn_free(&nbuf);
2863
goto error;
2864
}
2865
if(replaced) {
2866
nextarg = curlx_dyn_ptr(&nbuf);
2867
nextalloc = TRUE;
2868
}
2869
}
2870
}
2871
else {
2872
flag++; /* prefixed with one dash, pass it */
2873
parse = flag;
2874
}
2875
2876
do {
2877
/* we can loop here if we have multiple single-letters */
2878
if(!longopt) {
2879
a = findshortopt(*parse);
2880
if(!a) {
2881
err = PARAM_OPTION_UNKNOWN;
2882
break;
2883
}
2884
toggle = !(a->desc & ARG_NO);
2885
}
2886
if((a->desc & ARG_TLS) && !feature_ssl) {
2887
err = PARAM_LIBCURL_DOESNT_SUPPORT;
2888
break;
2889
}
2890
else if(ARGTYPE(a->desc) >= ARG_STRG) {
2891
/* this option requires an extra parameter */
2892
if(!longopt && parse[1]) {
2893
nextarg = &parse[1]; /* this is the actual extra parameter */
2894
singleopt = TRUE; /* do not loop anymore after this */
2895
}
2896
else if(a->cmd == C_HELP) {
2897
/* --help is special */
2898
tool_help((nextarg && *nextarg) ? nextarg : NULL);
2899
err = PARAM_HELP_REQUESTED;
2900
break;
2901
}
2902
else if(!nextarg) {
2903
err = PARAM_REQUIRES_PARAMETER;
2904
break;
2905
}
2906
else {
2907
*usedarg = TRUE; /* mark it as used */
2908
}
2909
if(a->desc & ARG_DEPR) {
2910
opt_depr(global, a);
2911
break;
2912
}
2913
2914
if((ARGTYPE(a->desc) == ARG_FILE) &&
2915
(nextarg[0] == '-') && nextarg[1]) {
2916
/* if the filename looks like a command line option */
2917
warnf(global, "The filename argument '%s' looks like a flag.",
2918
nextarg);
2919
}
2920
else if(!strncmp("\xe2\x80\x9c", nextarg, 3)) {
2921
warnf(global, "The argument '%s' starts with a Unicode quote where "
2922
"maybe an ASCII \" was intended?",
2923
nextarg);
2924
}
2925
/* ARG_FILE | ARG_STRG */
2926
err = opt_filestring(global, config, a, nextarg);
2927
if(a->desc & ARG_CLEAR)
2928
cleanarg(CURL_UNCONST(nextarg));
2929
}
2930
else {
2931
if(a->desc & ARG_DEPR) {
2932
opt_depr(global, a);
2933
break;
2934
}
2935
/* ARG_NONE | ARG_BOOL */
2936
if(ARGTYPE(a->desc) == ARG_BOOL)
2937
err = opt_bool(global, config, a, toggle);
2938
else
2939
err = opt_none(global, config, a);
2940
}
2941
2942
++verbose_nopts; /* processed one option from `flag` input, loop for
2943
more */
2944
} while(!longopt && !singleopt && *++parse && !*usedarg && !err);
2945
2946
error:
2947
if(nextalloc)
2948
free(CURL_UNCONST(nextarg));
2949
return err;
2950
}
2951
2952
ParameterError parse_args(struct GlobalConfig *global, int argc,
2953
argv_item_t argv[])
2954
{
2955
int i;
2956
bool stillflags;
2957
const char *orig_opt = NULL;
2958
ParameterError result = PARAM_OK;
2959
struct OperationConfig *config = global->first;
2960
2961
for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
2962
orig_opt = convert_tchar_to_UTF8(argv[i]);
2963
if(!orig_opt)
2964
return PARAM_NO_MEM;
2965
2966
if(stillflags && ('-' == orig_opt[0])) {
2967
bool passarg;
2968
2969
if(!strcmp("--", orig_opt))
2970
/* This indicates the end of the flags and thus enables the
2971
following (URL) argument to start with -. */
2972
stillflags = FALSE;
2973
else {
2974
const char *nextarg = NULL;
2975
if(i < (argc - 1)) {
2976
nextarg = convert_tchar_to_UTF8(argv[i + 1]);
2977
if(!nextarg) {
2978
unicodefree(orig_opt);
2979
return PARAM_NO_MEM;
2980
}
2981
}
2982
2983
result = getparameter(orig_opt, nextarg, &passarg, global, config);
2984
2985
unicodefree(nextarg);
2986
config = global->last;
2987
if(result == PARAM_NEXT_OPERATION) {
2988
/* Reset result as PARAM_NEXT_OPERATION is only used here and not
2989
returned from this function */
2990
result = PARAM_OK;
2991
2992
if(config->url_list && config->url_list->url) {
2993
/* Allocate the next config */
2994
config->next = malloc(sizeof(struct OperationConfig));
2995
if(config->next) {
2996
/* Initialise the newly created config */
2997
config_init(config->next);
2998
2999
/* Set the global config pointer */
3000
config->next->global = global;
3001
3002
/* Update the last config pointer */
3003
global->last = config->next;
3004
3005
/* Move onto the new config */
3006
config->next->prev = config;
3007
config = config->next;
3008
}
3009
else
3010
result = PARAM_NO_MEM;
3011
}
3012
else {
3013
errorf(global, "missing URL before --next");
3014
result = PARAM_BAD_USE;
3015
}
3016
}
3017
else if(!result && passarg)
3018
i++; /* we are supposed to skip this */
3019
}
3020
}
3021
else {
3022
bool used;
3023
3024
/* Just add the URL please */
3025
result = getparameter("--url", orig_opt, &used, global, config);
3026
}
3027
3028
if(!result) {
3029
unicodefree(orig_opt);
3030
orig_opt = NULL;
3031
}
3032
}
3033
3034
if(!result && config->content_disposition) {
3035
if(config->resume_from_current)
3036
result = PARAM_CONTDISP_RESUME_FROM;
3037
}
3038
3039
if(result && result != PARAM_HELP_REQUESTED &&
3040
result != PARAM_MANUAL_REQUESTED &&
3041
result != PARAM_VERSION_INFO_REQUESTED &&
3042
result != PARAM_ENGINES_REQUESTED &&
3043
result != PARAM_CA_EMBED_REQUESTED) {
3044
const char *reason = param2text(result);
3045
3046
if(orig_opt && strcmp(":", orig_opt))
3047
helpf(tool_stderr, "option %s: %s", orig_opt, reason);
3048
else
3049
helpf(tool_stderr, "%s", reason);
3050
}
3051
3052
unicodefree(orig_opt);
3053
return result;
3054
}
3055
3056