curl/curl
curl
Active contributors: Daniel Stenberg, Viktor Szakats, Jay Satiro
Purpose
curl is the command-line tool. It parses command-line options into libcurl easy-handle configurations, drives one or many transfers via the multi interface, and writes the response bodies and metadata to disk or stdout. It is the most visible product of the project, but the heavy lifting lives in libcurl.
Directory layout
src/
├── tool_main.c # Entry point: argc/argv → main_call → curl_easy
├── tool_operate.c # Per-URL transfer orchestration & multi loop
├── tool_getparam.c # ~100KB option parser (273 long options)
├── tool_listhelp.c # Auto-generated --help table
├── tool_help.[ch] # --help and --manual implementations
├── tool_cfgable.[ch] # struct OperationConfig — the in-memory option set
├── tool_paramhlp.c # Per-option validation/parse helpers
├── tool_parsecfg.c # Reads ~/.curlrc and -K config files
├── tool_setopt.[ch] # libcurl setopt with --libcurl source emission
├── config2setopts.c # Bridges OperationConfig → curl_easy_setopt calls
├── tool_cb_*.c # libcurl callbacks (write, header, read, debug, progress, seek, sockopt)
├── tool_progress.[ch] # Progress bar / progress meter
├── tool_writeout* # --write-out templating
├── tool_urlglob.c # {a,b,c} and [1-10] URL globbing
├── tool_findfile.c # Locate ~/.curlrc, .netrc
├── tool_filetime.c # Local-file timestamping
├── tool_xattr.c # Extended attributes (--xattr) on POSIX/Windows
├── tool_doswin.c # Windows/DOS console & filesystem quirks
├── tool_ipfs.c # IPFS gateway translation
├── tool_formparse.c # -F multipart and stdin parsing
├── tool_easysrc.[ch] # --libcurl: emit C source for the equivalent program
├── tool_libinfo.c # Reads curl_version_info() at startup
├── tool_msgs.c # Logger
├── var.c # --variable (project variable substitution)
├── terminal.c # Detect TTY for color and progress
├── slist_wc.c # Wildcard-matching slist
├── curlinfo.c # curl-tool side of feature detection
├── curl.rc # Windows resource (icon, version, manifest)
└── toolx/ # Source shared between toolsCLI tooling shared with libcurl lives under lib/curlx/ (curlx).
Key abstractions
| Symbol | File | Role |
|---|---|---|
struct GlobalConfig |
src/tool_cfgable.h |
Process-wide options: stderr file, parallelism, color, progress format, --libcurl path |
struct OperationConfig |
src/tool_cfgable.h |
Per-operation options: URL, method, headers, body, auth — one per --next invocation |
getparameter() |
src/tool_getparam.c |
Long/short option parser; produces OperationConfig mutations |
single_transfer() |
src/tool_operate.c |
Sets up one easy handle for one URL |
parallel_transfers() |
src/tool_operate.c |
Drives curl_multi_socket_action for -Z/--parallel mode |
tool_setopt() |
src/tool_setopt.c |
Wrapper around curl_easy_setopt that also emits source for --libcurl |
tool_progress_* |
src/tool_progress.c |
Progress callbacks for both single and parallel transfers |
tool_help_arg |
src/tool_help.c |
Implements --help [option] and the categorised long help |
How it works
graph TD
A[main argv] --> B[parse_args via tool_getparam.c]
B --> C{multiple URLs<br/>or --next?}
C -- yes --> D[N OperationConfigs in linked list]
C -- no --> E[single OperationConfig]
D --> F{--parallel ?}
E --> G[per-URL loop<br/>tool_operate.c::single_transfer]
F -- yes --> H[multi loop<br/>parallel_transfers]
F -- no --> G
G --> I[curl_easy_setopt × many]
H --> I
I --> J[curl_easy_perform / curl_multi_*]
J --> K[tool_cb_* callbacks → stdout/file]
K --> L[tool_writeout — --write-out templates]
L --> M[exit code = mapped CURLcode]Option parsing
src/tool_getparam.c is the largest CLI source file (~103 KB) for a reason: every command-line flag is a row in a table with type info, short-form mapping, and category, and the parser walks both POSIX-style and curl's slightly extended syntax. The auto-generated table src/tool_listhelp.c mirrors docs/cmdline-opts/*.md so that --help output and the man page never drift; the helper scripts/managen regenerates both during build.
Configuration files
-K <file> and ~/.curlrc are parsed by src/tool_parsecfg.c. They use the same option syntax as the command line, with = and quoting. ~/.netrc is parsed by lib/netrc.c (so libcurl can use it programmatically too).
Variables and templating
--variable name=value and --variable name@file populate a small interpreter implemented in src/var.c. Variables can be referenced from request bodies, headers, query strings, and --write-out templates with the {{var}} syntax. --write-out itself is a separate mini-template language implemented in src/tool_writeout.c and src/tool_writeout_json.c.
URL globbing
curl accepts a small URL grammar for batch downloads:
curl https://example.com/file[1-100].txt
curl https://example.com/{red,green,blue}.htmlThe parser is src/tool_urlglob.c. Globs expand to a sequence of full URLs which the operate loop drives sequentially or in parallel.
--libcurl C source emission
When invoked with --libcurl program.c, every curl_easy_setopt the tool would do is also emitted as readable C source via src/tool_setopt.c and src/tool_easysrc.c. The result is a self-contained C program equivalent to the command line — extremely useful for porting a working command line into an application.
Parallel transfers
-Z / --parallel flips on the multi-socket loop in src/tool_operate.c::parallel_transfers. By default the parallelism is capped (CURLOPT_MAXCONNECTS × CURLMOPT_MAX_TOTAL_CONNECTIONS), but --parallel-max lets you raise or lower it. The progress meter is also reorganised in this mode (src/tool_progress.c) since the per-transfer line layout no longer makes sense.
Integration points
- libcurl: every transfer-touching feature ultimately calls into
curl_easy_*andcurl_multi_*viasrc/tool_setopt.candsrc/config2setopts.c. The CLI does not implement protocol logic itself. docs/cmdline-opts/: the canonical source for option semantics and--helpoutput. Adding an option requires both a curldown file there and a matching entry insrc/tool_getparam.c.scripts/managen: generatessrc/tool_listhelp.canddocs/curl.1from the markdown sources.tests/data/test*drive the binary directly — every option has at least one test.
Entry points for modification
- Adding a new command-line option → add a curldown file under
docs/cmdline-opts/<name>.md, add a row to the option table insrc/tool_getparam.c, plumb it intoOperationConfig(src/tool_cfgable.h), and connect it tocurl_easy_setoptinsrc/config2setopts.c. Runmaketo regeneratesrc/tool_listhelp.cand the man page. - Changing exit-code mapping →
src/tool_operate.cis where libcurlCURLcodevalues are translated. - Changing the progress meter →
src/tool_progress.c(single) andparallel_transfers(multi).
Related pages
- libcurl — the library the tool is built on
- API → easy, API → multi — the calls the tool makes
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.