pax_global_header00006660000000000000000000000064152261306310014511gustar00rootroot0000000000000052 comment=893ca35795ce78947b6dd94be0d27273410c6304 tclcurl-ng-8.0.3/000077500000000000000000000000001522613063100135735ustar00rootroot00000000000000tclcurl-ng-8.0.3/.github/000077500000000000000000000000001522613063100151335ustar00rootroot00000000000000tclcurl-ng-8.0.3/.github/workflows/000077500000000000000000000000001522613063100171705ustar00rootroot00000000000000tclcurl-ng-8.0.3/.github/workflows/linux-ci.yml000066400000000000000000000017431522613063100214500ustar00rootroot00000000000000# This is a basic workflow to help you get started with Actions name: Linux CI # Controls when the action will run. on: # Triggers the workflow on push or pull request events but only for the master branch push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install dependencies run: | sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update -qq sudo apt-get install -y gcc-11 g++-11 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 70 --slave /usr/bin/g++ g++ /usr/bin/g++-11 sudo apt-get install -y tcl8.6-dev libcurl4-openssl-dev - name: configure run: | autoreconf -vi ./configure --with-tcl=/usr/lib/tcl8.6 - name: make run: make - name: install run: sudo make install - name: test run: make test tclcurl-ng-8.0.3/.github/workflows/mac-ci.yml000066400000000000000000000010721522613063100210440ustar00rootroot00000000000000name: Mac CI on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: macos-latest steps: - uses: actions/checkout@v2 - name: Install dependencies run: | brew update brew install tcl-tk@8 autoconf curl brew link tcl-tk@8 - name: configure run: | autoreconf -vi ./configure --with-tcl=/opt/homebrew/lib --prefix=/usr/local - name: make run: make - name: install run: sudo make install - name: test run: make test tclcurl-ng-8.0.3/.github/workflows/windows-ci.yml000066400000000000000000000036431522613063100220040ustar00rootroot00000000000000name: Windows CI on: push: branches: [ master ] pull_request: branches: [ master ] workflow_dispatch: branches: [ master ] # env: # Path to the solution file relative to the root of the project. #SOLUTION_FILE_PATH: . # Configuration type to build. # You can convert this to a build matrix if you need coverage of multiple configuration types. # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix # BUILD_CONFIGURATION: Release jobs: build: runs-on: windows-latest steps: - name: Checkout tclcurl uses: actions/checkout@v2 with: path: tclcurl - name: Checkout tcl uses: actions/checkout@v2 with: repository: tcltk/tcl ref: core-8-6-11 path: tcl # Note msvc defaults to 64-bit - name: Init MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Install zlib with vcpkg run: vcpkg install zlib:x64-windows-static - name: Install curl with vcpkg run: vcpkg install curl:x64-windows-static - name: Build Tcl working-directory: tcl/win shell: cmd run: | nmake /f makefile.vc INSTALLDIR=C:\tcl nmake /f makefile.vc INSTALLDIR=C:\tcl install - name: make working-directory: tclcurl/win shell: cmd run: nmake /f makefile.vc INSTALLDIR=C:\tcl CURLDIR=C:\vcpkg\packages\curl_x64-windows-static CURLDEPSDIR=C:\vcpkg\packages\zlib_x64-windows-static - name: install working-directory: tclcurl/win shell: cmd run: nmake /f makefile.vc INSTALLDIR=C:\tcl CURLDIR=C:\vcpkg\packages\curl_x64-windows-static CURLDEPSDIR=C:\vcpkg\packages\zlib_x64-windows-static install - name: test working-directory: tclcurl/win shell: cmd run: nmake /f makefile.vc INSTALLDIR=C:\tcl CURLDIR=C:\vcpkg\packages\curl_x64-windows-static CURLDEPSDIR=C:\vcpkg\packages\zlib_x64-windows-static test tclcurl-ng-8.0.3/.gitignore000066400000000000000000000002501522613063100155600ustar00rootroot00000000000000*~ config.h* Makefile config.log config.status libTclCurl*.so libtcl9TclCurl*.so *.o pkgIndex.tcl tests/tcl_conf.tcl tags *.swp autom4te.cache .gdb_history tests/certs tclcurl-ng-8.0.3/ChangeLog000077500000000000000000001073501522613063100153560ustar00rootroot000000000000002026-07-16 Massimo Manghi * VERSION: bumping to version 8.0.3 * generic/multi.[c|h]: introduced X macro controlling internal command dispatch * doc/: update version in docs * tests/tcl_conf.tcl.in: configure input file to be filled with Tcl informations needed by the testserver and tests/all.tcl 2026-05-19 Massimo Manghi * configure.ac: Now generating also doc/tclcurl_multi.n.md and doc/tclcurl_share.n.md from theirs .in sources * doc/*.n.md.in: Complete revision of documentation now entirely in MD format * testservers/: Now test servers available. The HTTP server can also work as a basic general purpose HTTP server able to server HTML and other file types properly 2026-04-24 Massimo Manghi * Makefile.in: add support for script handling * pkgIndex.tcl.in: extending the model proposed by Tcl's sampleextension to load both binary extension and tclcurl.tcl scripts 2026-04-23 Massimo Manghi * pkgIndex.tcl.in: Adopting Tcl9 form as per Tcl's core sampleextension repository * doc/: unset -x bits from manual pages, regenerate docs * tclconfig/install-sh: update from Tcl's core tclconfig repository * VERSION: bump version number 8.0.1 2026-04-14 Massimo Manghi * tests/: test suite completed * Release tclcurl 8.0.0 2026-03-30 Massimo Manghi * tests/legacy/: moving old test file into this directory while I'm trying to implement a new test suite * tests/all.tcl: now a real hub for tests * tests/http_server.tcl: A tiny webserver taylored for the test suite * tests/http.tcl: initial set of HTTP features being tested 2026-03-28 Massimo Manghi * generic/curl_setopts.c: adhere to better code standards by removing empty lines 2026-02-01 Massimo Manghi * generic/tclcurl.c: fundamental revisions. Code subdivided into modules, adoption of X-macro patterns in order to have option tables controlled by data rather than long switch...case construct, removing obsolete macros 2011-10-03 Andres Garcia * Release version 7.22.0 2011-10-01 Andres Garcia * generic/tclcurl.c: Fix 'bodyvar' bug. 2011-09-29 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLAUTH_NTLM_WB, and CURLOPT_TELNETOPTIONS. 2011-09-29 Andres Garcia * generic/tclcurl.h,generic/tclcurl.c,tests/getInfo.tcl: Added support for the 'getinfo' options CURLINFO_PRIMARY_PORT,CURLINFO_LOCAL_IP and CURLINFO_LOCAL_PORT 2011-09-27 Andres Garcia * generic/tclcurl.h,generic/tclcurl.c: Added support for the proxy type: socks5_hostname and the new protocols for '-protocols' and '-protocolsredir' 2011-09-27 Andres Garcia * generic/tclcurl.h,generic/tclcurl.c: Added support for CURLOPT_GSSAPI_DELEGATION. * configure.in,generic/tclcurl.h, generic/tclcurl.c,generic/tclcurl.tcl: Tclcurl now reports to be version 7.22.0 2011-09-26 Andres Garcia * generic/tclcurl.h,generic/tclcurl.c: Added support for CURLOPT_RESOLVE, CURLOPT_TLSAUTH_USERNAME, CURLOPT_TLSAUTH_PASSWORD, CURLOPT_TLSAUTH_TYPE and CURLOPT_TRANSFER_ENCODING 2011-09-25 Andres Garcia * generic/tclcurl.h,generic/tclcurl.c,tests/ftpWildcard.tcl: Added support for CURLOPT_WILDCARDMATCH, CURLOPT_CHUNK_BGN_FUNCTION,CURLOPT_CHUNK_END_FUNCTION and CURLOPT_FNMATCH_FUNCTION. 2011-09-24 Andres Garcia * pkgIndex.tcl.in: Fixed the reason why 'curl::transfer' didn't work. 2011-09-09 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/pop3.tcl tests/smtp.tcl: Added support for CURLOPT_MAIL_FROM, CURLOPT_MAIL_RCPT and CURLOPT_FTP_USE_PRET 2011-09-08 Andres Garcia * configure.in, generic/tclcurl.h, generic/tclcurl.c, generic/tclcurl.tcl: Tclcurl now reports to be version 7.21.7 2011-09-05 Andres Garcia * generic/tclcurl.c: changed a 'ulong' to 'usigned long int'. * generic/tclcurl.h: removed include to 'curl/types.h'. 2009-09-30 Andres Garcia * Release version 7.19.6 2009-09-27 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for http1.0 proxies. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_NOPROXY. 2009-09-25 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Fixed CURLOPT_FTP_SSL_CC and following options * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_PROTOCOLS and CURLOPT_REDIR_PROTOCOLS * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_SSH_KNOWNHOSTS and CURLOPT_SSH_KEYFUNCTION. 2009-09-24 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_POSTREDIR * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLAUTH_DIGEST_IE * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_TFTP_BLKSIZE * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_SOCKS5_GSSAPI_SERVICE and CURLOPT_SOCKS5_GSSAPI_NEC 2009-09-23 Andres Garcia * configure.in, makefile.in: Updated to TEA 3.7 * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_CERTINFO and CURLINFO_CERTINFO. 2008-09-08 Andres Garcia * Release version 7.19.0 2008-09-07 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_ADDRESS_SCOPE 2008-08-31 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, generic/multi.h, generic/multi.c: Had to add a lot of 'CONST's to prevent warnings when compiling with Tcl 8.5.4, pretty much the same I had to remove because of 8.5.3. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLINFO_PRIMARY_IP and CURLINFO_APPCONNECT_TIME 2008-08-25 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/getInfo.tcl: Added support for CURLINFO_REDIRECT_URL. 2008-08-25 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Changed the 'anyauth rewind' to use the new CURLOPT_SEEKFUNCTION and CURLOPT_SEEKDATA. 2008-08-24 Andres Garcia * generic/tclcurl.h: Fixed the writeproc option. 2008-08-23 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/progressProcPause.tcl: Added commands 'pause' and 'resume'. 2008-08-19 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5_HOSTNAME. 2008-08-19 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, generic/multi.h, generic/multi.c: I had to remove a lot of 'CONST's from the code to prevent warnings when compiling against Tcl 8.5.3. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_PROXY_TRANSFER_MODE. 2007-11-01 Andres Garcia * Release version 7.17.1 2007-10-25 Andres Garcia * generic/tclcurl.h generic/tclcurl.c: Compensated for the options which changed names. * generic/tclcurl.h generic/tclcurl.c: Added support for CURLOPT_POST301 and CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 * generic/tclcurl.c: Use CURLOPT_COPYPOSTFIELDS instead of CURLOPT_POSTFIELDS. 2007-10-24 Andres Garcia * generic/tclcurl.h generic/tclcurl.c: Took advantage of libcurl remembering options passed as strings. 2007-07-19 Andres Garcia * Release version 7.16.4 2007-07-16 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Change krb4level to krblevel. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_NEW_FILE_PERMS and CURLOPT_NEW_DIRECTORY_PERMS. 2007-07-07 Andres Garcia * generic/multi.h, generic/multi.c: Added support for the CURLMOPT_MAXCONNECTS option. 2007-05-22 Sven Hoexter * doc/tclcurl.n: Fixed a couple of errors in the man page. 2007-04-16 Andres Garcia * Release version 7.16.2 2007-04-13 Andres Garcia * generic/tclcurl.c: When saving the headers into an array, TclCurl would only keep the last 'Set-Cookie' header. 2007-04-12 Andres Garcia * configure.in, Makefile.in: Updated the configure scripts to TEA 3.6 * generic/tclcurl.h, generic/tclcurl.c: Added support for the new SSH options. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_HTTP_CONTENT_DECODING and CURLOPT_HTTP_TRANSFER_DECODING. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FTP_SSL_CCC. * generic/tclcurl.c: Added 'CONV' to the list 'curl::versioninfo' may return. 2007-03-16 Andres Garcia * generic/tclcurl.c: Fixed a crash when changing a handle from using 'writeproc' to not using one. 2006-11-15 Andres Garcia * Release version 7.16.0 2006-11-11 Andres Garcia * generic/tclcurl.c: Use the new curl_easy_escape and curl_easy_unescape. 2006-11-07 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, generic/multi.h, generic/multi.c: Added support for CURLMOPT_PIPELINING. 2006-11-05 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Removed support for third party ftp transfers. 2006-10-22 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FTP_ALTERNATIVE_TO_USER. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLINFO_FTP_ENTRY_PATH 2006-10-22 Andres Garcia * configure.in: Changed the code to check the installed version of libcurl to use 'curl-config --checkfor' 2006-10-14 Andres Garcia * generic/tclcurl.c: Prevented a few warnings about casts to and from pointers. 2006-04-17 Andres Garcia * Release version 0.15.3 2006-04-16 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLPROXY_SOCKS4. 2006-04-15 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_LOCALPORT, and CURLOPT_LOCALPORTRANGE. 2006-04-13 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Prevented a few compiler warnings. 2006-04-12 Andres Garcia * configure.in, Makefile.in, pkIndex.tcl, tclconfig/: Updated the TEA scripts to version 3.5. 2006-01-10 Andres Garcia * Release version 0.15.1 2006-01-09 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FTP_FILEMETHOD. 2006-01-07 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FTP_SKIP_PASV_IP. 2005-12-28 Andres Garcia * packages/Windows/tclcurl.mk: Fixed the doc directory. 2005-09-04 Andres Garcia * Relase version 0.14.1 2005-09-03 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/getInfo.tcl: Added support for CURLOPT_COOKIELIST and CURLINFO_COOKIELIST. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_IGNORE_CONTENT_LENGTH. * generic/tclcurl.h, generic/tclcurl.c. tests/httpPost.tcl: Added support for CURLFORM_FILECONTENT. * generic/tclcurl.h, generic/tclcurl.c: Fixed memory leaks during http posts. 2005-06-02 Andres Garcia * Release version 0.14.0 2005-06-02 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Updated the way 'sslversion' works. 2005-06-02 Andres Garcia * configure.in, Makefile.in: Updated the scripts to the latest version of TEA 2005-05-10 Andres Garcia * generic/tclcurl.c: Fixed the options 'httpauth', 'proxyauth', 'ipresolve', 'ftpssl' and 'ftpsslauth' 2005-04-19 Andres Garcia * Released version 0.13.2 2005-04-19 Andres Garcia * Makefile.in: Daniel A. Steffen's fix for parallel builds. 2005-04-16 Andres Garcia * include/tclcurl.h: Fixed the msys-mingw build. 2005-04-12 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: When the user chooses the 'any' auth method, TclCurl will silently use CURLOPT_IOCTLFUNCTION and CURLOPT_IOCTLDATA in case libcurl needs to 'rewind' the data. 2005-04-08 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support SSPI in curl::versioninfo. 2005-04-07 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support fot CURLOPT_FTP_ACCOUNT. 2005-04-06 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/ftp3party.tcl: Removed suppport for the obsolete options "-sourcehost", "-sourcepath", "-sourceport", "-pasvhost" and added support for the new third party ftp options "-sourceurl" and "-sourcequote". * generic/tclcurl.h: Fixed the "-sourcepostquote" option. 2005-04-05 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/getInfo.tcl: Added support for CURLINFO_NUM_CONNECTS, CURLINFO_SSL_ENGINES and CURLINFO_HTTP_CONNECTCODE. 2004-10-18 Andres Garcia * Released version 0.12.2 2004-10-08 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Support for the share interface in threads. 2004-10-07 Andres Garcia * generic/tclcurl.c: Fixed the 'cookiejar' option. 2004-10-06 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/strerror.tcl: Added the 'curl::easystrerror', 'curl::sharestrerror' and 'curl::multistrerror' commands. 2004-10-04 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FTPSSLAUTH. 2004-09-30 Andres Garcia * Released version 0.12.1 2004-09-29 Andres Garcia * generic/multi.c: Used Tcl_SetMaxBlockTime to improve automatic transfers. * tests/ftpUpload: Added an example of ftp upload including commands to the server. * generic/tclcurl.h, generic/tclcurl.c, tests/ftp3party.tcl: Added support for third party ftp transfers. 2004-09-28 Andres Garcia * generic/tclcurl.c: Fixed the 'autoreferer' option. 2004-08-13 Andres Garcia * tests/debugProc.tcl: Added the ssl data types. 2004-08-13 Andres Garcia * generic/tclcurl.c: Use CURL_READFUNC_ABORT to abort uploads. 2004-08-13 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added 'reset' to the easy interface commands. 2004-08-12 Andres Garcia * generic/multi.h, generic/multi.c: Hooked the multi interface to Tcl's event loop, doesn't work that well so far. 2004-07-09 Andres Garcia * Released version 0.12.0 2004-07-05 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added incomplete support for the share interface. 2004-07-02 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_PORT, CURLOPT_TCP_NODELAY, CURLOPT_AUTOREFERER. * generic/tclcurl.h: Added 'IDN' to the features reported by 'curl::versioninfo'. 2004-04-30 Andres Garcia * packages/windows/tclcurl.mk: Uses new curl compilation. 2004-04-06 Andres Garcia * generic/tclcurl.c: Fixed ftps support. 2004-02-04 Andres Garcia * Released version 0.11.0 2004-01-15 Andres Garcia * ReadMeW32.txt: Updated instructions to compile openssl. 2004-01-08 Andres Garcia * generic/tclcurl.c, generic/tclcurl.h: Added support for CURLOP_FTP_SSL. 2004-01-02 Andres Garcia * generic/tclcurl.c: Fixed the 'netrc' option. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_NETRC_FILE. 2003-12-29 Andres Garcia * Released version 0.10.8 2003-12-19 Andres Garcia * generic/tclcurl.h: TclCurl still thought it was in version 0.10.4. 2003-12-18 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLINFO_HTTPAUTH_AVAIL. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLINFO_PROXYAUTH_AVAIL. * generic/tclcurl.c: 'curl::versioninfo' will now say if there is support for asynchronus DNS and SPNEGO. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_IPRESOLVE. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_MAXFILESIZE. 2003-12-18 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Fixed the 'httpauth' option. 2003-11-11 Andres Garcia * autoconf.in: The configure scripts would sometimes use the cURL in '/usr/bin' instead of the one in '/usr/local/bin' despite the '--with-curlprefix' tag. 2003-11-04 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLINFO_RESPONSE_CODE. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FPT_RESPONSE_TIMEOUT. 2003-09-03 Andres Garcia * Release TclCurl 0.10.7 2003-09-03 Andres Garcia * configure.in: Changed because of the new version string used by cURL. 2003-08-17 Andres Garcia * generic/tclcurl.tcl, generic/tclcurl.c, generic/tclcurl.h: Some work on hooking the multi interface to Tcl's event loop, it isn't even close to working though. 2003-08-14 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURL_FTP_CREATE_MISSING_DIRS. 2003-08-04 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_HTTPAUTH. 2003-07-31 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added 'command' option to 'configure' to execute a Tcl command after the transfer is done. So far it only works in blocking transfer which is pretty much useless. 2003-05-22 Andres Garcia * Release TclCurl 0.10.5 2003-05-20 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_FTP_USE_EPTR. * generic/tclcurl.h, generic/tclcurl.c: Added support for 'all' in the 'encoding' option. * generic/tclcurl.c: Changed the way the http header is dealt with in the 'headervar' option. 2003-05-13 Andres Garcia * generic/tclcurl.c: The 'progressproc' option would crash in windows machines. * packages/windows/tclcurl.mk: Changed for OpenSSL 0.9.7b. * ReadMeW32.txt: New instructions on how to compile OpenSSL 0.9.7b. 2003-05-12 Andres Garcia * generic/multi.c: The multihandles couldn't store the data of more than two easy handles. * generic/multi.c: The '$multiHandle active' command wasn't returning anything. 2003-04-07 Andres Garcia * Release TclCurl 0.10.4 2003-04-04 Andres Garcia * generic/tclcurl.tcl: If there is an error, the 'curl::transfer' command will now return the code of the error, without the 'Couldn't perform transfer' message. 2003-03-24 Andres Garcia * ReadMeW32.txt: Updated build instructions for Windows. * Makefile.in: Added an 'uninstall' target to the make file. 2003-03-18 Andres Garcia * generic/tclcurl.tcl: Added 'getinfo' features to 'curl::transfer'. 2003-02-20 Andres Garcia * packages/windows/tclcurl.mk: A make file to create all the Windows packages. * packages/windows/SetUp.tcl: The setup script for TclCurl in Windows. * packages/rpm/tclcurl.spec: The spec file to create the rpm package. 2003-02-04 Andres Garcia * configure.in: It will no longer choke with the version string of cURL's prereleases. 2003-02-03 Andres Garcia * tclconfig: Updated to the TEA2 scripts in the CVS. * generic/tclcurl.tcl: Alex Khassin suggested using fully qualified names to prevent problems with namespaces. 2003-01-30 Andres Garcia * Release TclCurl 0.10.3 2003-01-29 Andres Garcia * generic/multi.c: if 'curl_multi_perform' returns '-1' it will be invoked again to read all data in the queue. 2003-01-28 Andres Garcia * generic/tclcurl.c: Changed the source to use the new constant names CURLOPT_WRITEDATA, CURLOPT_READDATA and CURLOPT_HEADERDATA. * generic/tclcurl.c: When using '-headervar' in Windows you could end up with carriage returns in the name of the header. 2003-01-27 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_HTTP200ALIASES. 2003-01-25 Andres Garcia * generic/tclcurl.c, generic/multi.c: Applied Albert Chin-A-Young patch to change C++ style comments to C style. * configure.in: If 'curl' is in '/usr/bin/' or '/usr/local/bin' it will no longer be necessary to use '--with-curlprefix' in Windows. 2003-01-24 Andres Garcia * configure.in: If you want to compile TclCurl with ssl support in Windows, you can now use the '--enable-ssl' option. 2003-01-08 Andres Garcia * generic/tclcurl.c: No more crashes when using TclCurl in a threads enabled Tcl. 2002-10-14 Andres Garcia * Release version 0.10.1 2002-10-13 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for 'CURLOPT_PROXYTYPE'. * doc/tclcurl.n, doc/tclcurl.html, doc/tclcurl_multi.n, doc/tclcurl_multi.html: Updated docs. * configure.in: Updated version. * generic/tclcurl.c: Started using 'curl_free' to free memory allocated by 'curl_escape' and 'curl_unescape'. * tests/escape.tcl: Added an example for 'curl::escape' and 'curl::unescape' 2002-10-12 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Created the 'curl::versioninfo' command to support 'curl_version_info'. 2002-10-11 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for 'CURLOPT_ENCODING', it can either be 'identity' or 'deflated'. 2002-10-10 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, tests/bufferSize.tcl: Added support for CURLOPT_BUFFERSIZE. * tests/writeProc.tcl: Added a message to the write callback, so that the difference with bufferSize.tcl can be noticed. * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLOPT_NOSIGNAL. * generic/tclcurl.tcl, tests/curlConfig.tcl: Added support for the '-ca' option for the 'curl::curlConfig' command. 2002-10-06 Andres Garcia * generic/multi.h, generic/multi.c, tests/multi/single.tcl, tests/multi/double.tcl: The multi interface tests should now work as expected. 2002-10-03: Andres Garcia * configure.in, Makefile.in: Asif Haswarey reported that '--with-curlinclude' did not work and that the 'pkgIndex.tcl' generated would not do in Solaris. 2002-10-01 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c, generic/multi.h, generic/multi.c: Added a bunch of CONSTs to prevent warnings when compiling with Tcl/Tk 8.4. 2002-09-29 Andres Garcia * tests/progressProc.tcl: It will skip all that useless decimals now. * generic/tclcurl.h, generic/tclcurl.c: The buffer option to post data would not work. 2002-09-26 Andres Garcia * tests/headNoHead.tcl: removed the 'header 1' option, it is redundant if you use 'writeheader', made the output more explicit. 2002-09-24 Andres Garcia * doc/tclcurl.n, doc/tclcurl.html, tests/debugProc.tcl: The values given for the data types in the 'debugproc' options were wrong, changed the test to show it more clearly. 2002-08-14 Andres Garcia * ReadMeW32.txt: New instructions on how to compile TclCurl in Windows. * configure.in: Changed so that it will configure in msys-mingw without using a 'curl-config' 2002-06-25 Andres Garcia * Release version 0.9.8 2002-06-23 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Changed the parameters of the curlProgressCallback function from 'size_t' to 'double'. 2002-06-22 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLFORM_BUFFER. * generic/tclcurl.c: Fix a bug when duplication a curl handle, I was not allocating space before doing a memcpy. * generic/tclcurl.c: Changed all the calls to ckalloc, malloc, ckfree to Tcl_Alloc and Tcl_Free. 2002-06-13 Andres Garcia * generic/tclcurl.c: Changed the TIMECOND_IFMODSINCE and TIMECOND_IFMODSINCE, so that now they have a CURL_ prefix as they do now in libcurl. 2002-06-12 Andres Garcia * generic/tclcurl.h, generic/tclcurl.c: Added support for CURLINFO_REDIRECT_TIME and CURLINFO_REDIRECT_COUNT. 2002-05-14 Andres Garcia * generic/multi.h, generic/multi.c: Added support for the multi interface. 2002-04-30 Andres Garcia * Release version 0.9.6 2002-04-30 Andres Garcia * tclcurl.h, tclcurl.c: Changed the 'interface' field in the 'curlObjData' struct to 'interfaces', otherwise it wouldn't compile in Windows, please, don't ask me why (but if you know, please tell me). * setup.tcl: the setup script for Windows will now work with older versions of Tcl/Tk. 2002-04-23 Andres Garcia * configure.in: fixed a small incompatibility with Solaris. * tclcurl.c: fixed a seg fault when using the 'httpheader' option twice. * tclcurl.h, tclcurl.c: support for CURLOPT_DNS_CACHE_TIMEOUT and CURLOPT_DNS_USE_GLOBAL_CACHE. 2002-04-22 Andres Garcia * tclcurl.n: Updated the documentation about the error codes. 2002-04-17 Andres Garcia * tclcurl.h, tclcurl.c: added support for CURLOPT_DEBUGFUNCTION. 2002-04-16 Andres Garcia * tclcurl.c: If you set the progressproc option to the empty string the internal progress function will be restored. 2002-04-15 Andres Garcia * tclcurl.h, tclcurl.c: added support for CURLFORM_FILENAME and changed the code so that all options are passed in a CURLFORM_ARRAY. 2002-04-14 Andres Garcia * tclcurl.h: Changed the 'httpPost' structs to their new name 'curl_httppost'. 2002-04-12 Andres Garcia * configure.in, makefile.in, tclconfig/tcl.m4: changed the configure scripts to the lastest CVS version of the sample extension. * tclcurl.c, tclcurl.h, tclcurl.tcl: passed this files to the generic subdirectory as done in the sample extension. 2002-04-01 Andres Garcia * Release version 0.9.5 2002-03-29 * tclcurl.h, tclcurl.c: Support for CURLOPT_PREQUOTE * tclcurl.tcl: 'curl::transfer' now returns a '0' if everything went well. 2002-03-28 * Update the configure.in script to the new TEA scripts by Jeff Hobbs. * tclcurl.h, tclcurl.c: Added support for CURLINFO_CONTENT_TYPE. 2002-01-29 * Release version 0.9.3 2002-01-25 Andres Garcia * tclcurl.c: Added support for CURLFORM_CONTENTHEADER. 2002-01-24 Andres Garcia * tclcurl: the CURLOPT_SSL_VERIFYHOST was misspelled. * Added support for CURLOPT_SSLCERTTYPE, CURLOPT_SSLKEY, CURLOPT_SSLKEYTYPE, CURLOPT_SSLKEYPASSWD, CURLOPT_SSL_ENGINE, CURLOPT_SSL_ENGINEDEFAULT. 2002-01-17 Andres Garcia * tclcurl.h, tclcurl.c: TclCurl was not doing binary transfers right in Windows. * Makefile.in: 'checkAutoPath.tcl' will only be run if TclCurl is not going to be installed in '/usr' * checkAutoPath.tcl: The script will not try to change the 'auto_path' variable in 'init.tcl' if the user doing the install does not have write access to the file. 2002-01-16 Andres Garcia * tclcurl.c: No more seg faults for trailing options at the end of a configure command. 2001-12-09 * Release version 0.9.2 2001-12-09 Andres Garcia * tclcurl.n, tclcurl.html: Updated docs, removed the 'setopt' references. 2001-12-08 Andres Garcia * Changed the 'httpversion' configure option to libcurl 7.9.2 behaviour. * Added support for CURLOP_FTP_USE_EPVS 2001-12-07 Andres Garcia * The 'perform' command now returns the exit code form 'curl_easy_perform' * configure.in, mkIndex.tcl.in: A port to Windows. * tclcurl.c, tclcurl.h: The 'configure' command will now also return the value given for the invalid option. 2001-11-14 Andres Garcia * mkIndex.tcl.in: Domenico Andreoli noticed there was a mistyped variable name. 2001-11-05 * Release version 0.9 2001-11-04 Andres Garcia * Makefile.in: The man page will be installed compressed. 2001-10-31 Andres Garcia * Added the code to change the 'auto_path' variable in 'init.tcl' to the makefile. 2001-10-30 Andres Garcia * Changed the options to the 'timecondition' configure option to lower case. * Changed the options to the 'closepolicy' configure option to lower case. 2001-10-29 Andres Garcia * Added support for the CURLOPT_HTTP_VERSION option. * Changed the http posts the new formadd function. 2001-10-22 Andres Garcia * Added the duphandle command to duplicate a curl handle. 2001-10-21 Andres Garcia * Added support for the CURLOPT_SSL_CIPHER_LIST option. * Added support for the CURLOPT_COOKIEJAR option. * Merged Domenico Andreoli patches to ease creating the Debian package. 2001-09-03 * Release version 0.8 2001-09-01 Andres Garcia * Converted to the new 'curl::transfer' command all the tests where it fitted. 2001-08-31 Andres Garcia * Added support for CURLOPT_HTTPGET * Added support for CURLOPT_SSL_SSL_VERIFYHOST 2001-08-30 Andres Garcia * Converted all the options of the 'configure' command to lowercase. * Converted all the options of the 'getinfo' command to lowercase. 2001-08-29 Andres Garcia * Fixed the 'infile' option. * Added the 'readProc' option to the 'configure' commmand. 2001-08-28 Andres Garcia * Added the 'writeProc' option to the 'configure' command. 2001-08-15 Andres Garcia * Added the curl::transfer command. 2001-06-13 Andres Garcia * Version 0.7 released 2001-06-12 Andres Garcia * Removed support for the CURLOPT_MUTE option, it no longer does anything. * Added the '-vernum' options to 'curl::curlConfig' 2001-06-10 Andres Garcia * Used libcurl's mprintf funtions to improve TclCurl portability. * CURLOPT_TIMEOUT was defined two times. * Fixed the bug by which TclCurl would return two many possible options after using a wrong one. * Changed the way the curlObjData struct is initialized. * Changed the syntax of the 'getinfo' command options. 2001-06-08 Andres Garcia * Passed all the tests cases to the new 'configure' option. 2001-06-06 Andres Garcia * Created the 'configure' command. 2001-06-03 Andres Garcia * TclCurl won't install the 'tclcurl.h' file. 2001-05-21 Andres Garcia * It is now possible to remove the CURLOPT_FILE, CURLOPT_INFILE and CURLOPT_STDERR options between transfers in a persistant connection. 2001-05-30 Andres Garcia * Version 0.6.1 released. 2001-05-04 Andres Garcia * Trying to set a HTTPPOST would provoke a seg fault. 2001-05-03 Andres Garcia * Prevented segfault when saving to a file without the right permissions or reading for a file that does not exist. 2001-05-02 Andres Garcia * Added the CURLOPT_CANCELTRANSVAR option. * I think I removed some memory leaks by checking that strings are empty before filling them with strdup. 2001-05-01 Andres Garcia * Added the CURLOPT_PROGRESSPROC option. 2001-04-30 Andres Garcia * Added the CURLOPT_BODYVAR option to put the body of a request into a Tcl variable. * Removed the alternative strdup implementation, if the system does not have it libcurl will (I think). 2001-04-28 Andres Garcia * tclcurl.h: Added interp field to curlObjData. * Added support for the 'CURLOPT_HEADERFUNCTION' option through 'CURLOPT_HEADERVAR'. 2001-04-25 Andres Garcia * Makefile.in: Modified to be able to install tclcurl.tcl. * tclcurl.tcl: Created this file to host the curl::curlConfig procedure. 2001-04-23 Andres Garcia * tests/getinfo.tcl: Added the option CURLOPT_FILETIME so CURLINFO_FILETIME would work. 2001-04-12 Andres Garcia * First release. tclcurl-ng-8.0.3/Changes.txt000077500000000000000000001027041522613063100157130ustar00rootroot00000000000000Version 7.22.0 released 03-Oct-2011 * New configure options: * resolve: Pass a list of strings with host name resolve information to use for requests with this handle. Each single name resolve string should be written using the format HOST:PORT:ADDRESS where HOST is the name TclCurl will try to resolve, PORT is the port number of the service where TclCurl wants to connect to the HOST and ADDRESS is the numerical IP address. If libcurl is built to support IPv6, ADDRESS can be either IPv4 or IPv6 style addressing. * tlsauthusername, tlsauthpassword: Pass a string with the username or password to use for the TLS authentication method specified with the 'tlsauthtype' option. * tlsauthtype: Use it to tell TclCurl which authentication method(s) you want it to use for TLS authentication. So far the only method is 'tlsauthsrp' for TLS-SRP authentication. Secure Remote Password authentication for TLS is defined in RFC 5054 and provides mutual authentication if both sides have a shared secret. You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this to work. * transferencoding: Adds a request for compressed Transfer Encoding in the outgoing HTTP request. If the server supports this and so desires, it can respond with the HTTP resonse sent using a compressed Transfer-Encoding that will be automatically uncompressed by TclCurl on receival. Transfer-Encoding differs slightly from the Content-Encoding you ask for with 'encoding' in that a Transfer-Encoding is strictly meant to be for the transfer and thus MUST be decoded before the data arrives in the client. Traditionally, Transfer-Encoding has been much less used and supported by both HTTP clients and HTTP servers. * wildcard: Set this option to 1 if you want to transfer multiple files according to a file name pattern. The pattern can be specified as part of the url, using an fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name). So far it only works with FTP. * fnmatchfunction: Name of the procedure that will be called instead of the internal wildcard matching function, it should match the following prototype: FnMatchProc {pattern string} Returns '0' if it matches, '1' if it doesn't. * chunkbgnproc: Name of the procedure that will be called before a file will be transferred by ftp, it should match the following prototype: ChunkBgnProc {remains} Where remains is the number of files still to be transferred (or skipped) This callback makes sense only when using the 'wildcard' option. * chunkendproc: Name of the procedure that will be called after a file is transferred (or skipped) by ftp when using the wildcard option, it should match the following prototype: ChunkEndProc {} It should return '0' if everyhting is fine and '1' if some error occurred. * chunkbgnvar: Name of the variable in the global scope that will contain the data of the file about to be transferred. If you don't use this option '::fileData' will be used. The available data is: filename, filetype (file, directory, symlink, device block, device char, named pipe, socket, door or error if it couldn't be identified), time, perm, uid, gid, size, hardlinks and flags. * mailfrom: Pass a string to specify the sender address in a mail when sending an SMTP mail with TclCurl. * mailrcpt: Pass a list of recipients to pass to the server in your SMTP mail request. * ftpusepret: Set to 1 to tell TclCurl to use the EPRT (and LPRT) command when doing active FTP downloads (which is enabled by 'ftpport'). Using EPRT means that it will first attempt to use EPRT and then LPRT before using PORT, if you pass zero to this option, it will not try using EPRT or LPRT, only plain PORT. * gssapidelegation: Set the option to 'flag' to allow unconditional GSSAPI credential delegation. The delegation is disabled by default. Set the parameter to 'policyflag' to delegate only if the OK-AS-DELEGATE flag is set in the service ticket in case this feature is supported by the GSSAPI implementation and the definition of GSS_C_DELEG_POLICY_FLAG was available at compile-time. * telnetoptions: Pass a list with variables to pass to the telnet negotiations. The variables should be in the format . TclCurl supports the options'TTYPE', 'XDISPLOC' and 'NEW_ENV'. See the TELNET standard for details. * Updated configure options: * httpauth new method 'ntlmwb': NTLM delegating to winbind helper. Authentication is performed by a separate binary application that is executed when needed. The name of the application is specified at libcurl's compile time but is typically /usr/bin/ntlm_auth. * new proxy type 'socsk5h' to enable socks5 and asking the proxy to do the resolving * New info available through the 'getinfo' command: * primaryport: Returns the destination port of the most recent connection done. * localip: Returns the local (source) IP address of the most recent connection done. This string may be IPv6 if that's enabled. * localport: Returns the local (source) port of the most recent connection done. * Bug fixes: * Sven Hoexter let me know that TclCurl no longer build as curl/types.h and curl/easy.h no longer exists: * Gary Nigg noticed that 'bodyvar' had to be reconfigured for each transfer. * John Coppens got an error when he tried the 'curl::transfer' command. * Gerald Dumas reported that TclCurl wouldn't compile in FreeBSD, it so happens that the upstart type 'ulong' isn't good enough for it. Version 7.19.0 released 1-Sep-2008 * New commands: * curlHandle pause and curlHandle resume: Pause and resume a tranfer from within a progress callback procedure. * New configure options: * addressscope: Pass a number specifying the scope_id value to use when connecting to IPv6 link-local or site-local addresses. * proxytranfermode: Pass a number. If the value is set to 1 (one), it tells TclCurl to set the transfer mode (binary or ASCII) for FTP transfers done via an HTTP proxy, by appending ;type=a or ;type=i to the URL. Without this setting, or if set to 0 (zero, the default), '-tranfertext' has no effect when doing FTP via a proxy. Beware that not all proxies support this feature. * Added two new types for the '-proxytype' option: 'socks4a' and 'socks5hostname'. * New info available through the 'getinfo' command: * appconnecttime: Returns the time, in seconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed. * primaryip: Returns the IP address of the most recent connection done with this handle. * redirecturl: Returns the URL a redirect would take you to if you would enable 'followlocation'. This can come very handy if you think using the built-in redirect logic isn't good enough for you but you would still prefer to avoid implementing all the magic of figuring out the new URL. * Bug fix: The 'writeproc' option didn't work right. * Internal changes: * When compìling against Tcl 8.5.3 I had to remove a lot of CONSTs to prevent warnings, and then I had to add them back with Tcl 8.5.4, so, depending on which version you use you might get quite a few warnings while compiling, they should be harmless though. * The internal workings of the 'any' http authentication has been changed. Version 7.17.1 released 1-Nov-2007 * New configure options: * post301: A non-zero parameter tells TclCurl to respect RFC 2616/10.3.2 and not convert POST requests into GET requests when following a 301 redirection like browsers usually do. * sshhostpublickeymd5: Pass a string containing 32 hexadecimal digits. The string should be the 128 bit MD5 checksum of the remote host public key, and TclCurl will reject the connection to the host unless the md5sums match. * If you pass the magic string 'FLUSH' to the '-cookielist' option all known cookies will be written to the file specified by '-cookiejar'. * Renamed options: Some configure options have been renamed so they get more general names, the old names are deprecated even if they may be supported forever. * sslpasswd => keypasswd * ftpappend => append * ftplistonly => dirlistonly * ftpssl => usessl * Internal changes: Up until the current version when we wanted libcurl to use a value in a string, like the URL to download, we had to keep the string as long as libcurl could use it. Since 7.17.0 libcurl keeps it own copies, so I no longer make TclCurl do it. That means this is a handle-with-care release, please report any problems you may have. Version 7.16.4 released 19-July-07 * New configure options: * newfileperms: Used to set the permissions, defalt 0664, that will be assigned to newly created files on the remote server. * newdirectoryperms: Used to set the permissions, default 0755, that will be assigned to newly created directories on the remote server. They can both be used for SFTP, SCP and FILE transfers. * Changed option: The option to set the Kerberos security level for FTP is now called 'krblevel', the old name 'krb4level' will be kept for some time for compatibility. * New option for multi handles: * maxconnects: Sets the maximum amount of simultaneously open connections that TclCurl may cache. Default is 10. * Bug fix: Sven Hoexter fixed a couple of errors in the man page. Version 7.16.2 released 16-April-07 * New feature: TclCurl now supports SSH for SFTP and SCP transfers as long as libcurl has been compiled with libssh2 support. * New configure options: * publickeyfile: name of the file with the public key to use with SSH. * privatekeyfile: name of the file with the provate key to use with SSH. * sshauthtypes: Allowed types are "publickey", "password", "host", "keyboard", or "any" to let TclCurl choose one. * timeoutms and connectimeoutms: The work like 'timeout' and 'connectimeout' except the timout is given in miliseconds. * ftpsslccc: If enabled, it will make libcurl shutdown SSL/TLS after the authentication is done on a FTP-SSL operation. * httpcontentdecoding: If set to zero content decoding is disabled. * httptransferdecoding: If set to zero Set transfer decoding is disabled. TclCurl does chunked transfer decoding by default unless this option is set to zero. * ftpsslccc: If enabled, it will make libcurl shutdown SSL/TLS after the authentication is done on a FTP-SSL operation. * Bug fixes: * Olivier Lenormand reported that in case the server sends more than one 'Set-Cookie' header, TclCurl would only save the last one in the header array. Now the array will contain a list with all the cookies. * Jos Decoster reported and helped fixing a crash that happened when changing a handle from using a 'writeproc' to not using one. * I have updated the configure scripts to TEA 3.6, hope you don't bump into any regressions. Version 7.16.0 released 15-November-06 * Removed feature: TclCurl no longer supports third party FTP transfers. * New configure options: * ftpalternativetouser: Pass a string which will be used to authenticate if the usual FTP "USER user" and "PASS password" negotiation fails. This is currently only known to be required when connecting to Tumbleweed's Secure Transport FTPS server using client certificates for authentication. * ftpentrypath: Returns a string holding the path of the entry path. That is the initial path TclCurl ended up in when logging on to the remote FTP server. Returns an empty string if something is wrong. * maxsendspeed: Pass a speed in bytes per seconds. If an upload exceeds this speed on cumulative average during the transfer, the transfer will pause to keep the average rate less than or equal to the parameter value. * maxrecvspeed: Pass a speed in bytes per second. If a download exceeds this speed on cumulative average during the transfer, the transfer will pause to keep the average rate less than or equal to the parameter value. * New command for multi handles 'configure', so far the is only one option to set: * pipelining: Pass a 1 to enable or 0 to disable. Enabling pipelining on a multi handle will make it attempt to perform HTTP Pipelining as far as possible for transfers using this handle. This means that if you add a second request that can use an already existing connection, the second request will be "piped" on the same connection rather than being executed in parallel. Version 0.15.3 released 17-April-06 * I updated the autoconf scripts to TEA 3.5, this seems to prevent the warnings about how the headers files couldn't be compiled, but it may have (re)introduced other bugs. * Removed feature: TclCurl no longer supports Gopher, it probably didn't work anyway. * New configure options: * localport: Sets the local port number of the socket used for the connection. This can be used in combination with '-interface' and you are recommended to use 'localportrange' as well when this is set. * localportrange: Number of attempts TclCurl should do to find a working local port number. It starts with the given 'localport' and adds one to the number for each retry. Version 0.15.1 released 10-January-06 * New configure options: * ftpskippasvip: If set to a non-zero value, it instructs TclCurl not to use the IP address the server suggests in its 227-response to TclCurl's PASV command when TclCurl connects the data connection. Instead TclCurl will re-use the same IP address it already uses for the control connection. But it will use the port number from the 227-response. * ftpfilemethod: It allows three values: * multicwd: the default, TclCurl will do a single CWD operation for each path part in the given URL. For deep hierarchies this means very many commands. This is how RFC1738 says it should be done. * nocwd: no CWD at all is done, TclCurl will do SIZE, RETR, STOR etc and give a full path to the server. * singlecwd: make one CWD with the full target directory and then operate on the file "normally". The support for this options is still experimental, comments whether the methods work or don't with different methods are welcome. Likewise, the options, or their names, may change in future releases, so they are not yet documented elsewhere. * Bug fix: The Windows packages had defective 'doc' directories. Thanks to Alex Hisen for letting me know. Version 0.14.1 released 4-September-05 * New configure options: * ingnorecontentlength: Ignore the Content-Length header. This is useful for Apache 1.x (and similar servers) which will report incorrect content length for files over 2 gigabytes. * cookielist: Pass a string with a cookie. The cookie can be either in Netscape / Mozilla format or just regular HTTP-style header (Set-Cookie: ...) format. '$curlHandle getinfo cookielist' will return a list of all cookies TclCurl knows (expired ones, too). * When posting data, you can use the new 'filecontent' option to read a file and use its contents as data. * Bug fix: The code to post data was filled with memory leaks, I hope I have fixed them all. Version 0.14.0 released 3-June-05 * BEHAVIOUR CHANGE: To set the version SSL/TLS to use with '-sslversion' you can know use the values: * default The default action. When libcurl built with OpenSSL, this will attempt to figure out the remote SSL protocol version. Unfortunately there are a lot of ancient and broken servers in use which cannot handle this technique and will fail to connect. When libcurl is built with GnuTLS, this will mean SSLv3. * tlsv1 Force TLSv1 * sslv2 Force SSLv2 * sslv3 Force SSLv3 * Bug fix: A report by Melissa Millard made me realize that the options 'httpauth', 'proxyauth', 'ipresolve', 'ftpssl' and 'ftpsslauth' have, probably, never worked. They should now. * I updated 'configure.in' and 'Makefile.in' to the latest versions in Tcl's sample extension, unfortunately that's likely to introduce some bugs, so, please, report any problems. Version 0.13.2 released 16-April-05 * New features: * New configure options: * ftpaccount: When an FTP server asks for "account data" after user name and password has been provided. * sourceurl: When set, it enables a FTP third party transfer. * sourcequote: Exactly like '-quote', but for the source host. * The following options are now obsolete 'sourcehost', 'sourcepath', 'sourceport' and 'pasvhost'. * curl::versioninfo will indicate if there is support for SSPI. * More information can be obtained using 'curl::getinfo': * numconnects: to get the number of new connections TclCurl had to create to achieve the previous transfer. * sslengines: returns a list of the OpenSSL crypto-engines supported. * httpconnectcode: returns the last received proxy response code to a CONNECT request * Bug fix: * Fixed the "-sourcepostquote" option. * Daniel A. Steffen fixed a bug with parallel builds. Version 0.12.2 released 18-October-04 * New features: * You can now share dns and cookie information among TclCurl handles, please check the docs for details. * New configure option: 'ftpsslauth', you may need this option because of servers like BSDFTPD-SSL from won't work properly when "AUTH SSL" is issued but require "AUTH TLS" instead. * Added three new commands to the 'curl' namespace: * curl::easystrerror errorCode * curl::sharestrerror errorCode * curl::multistrerror errorCode All three will return a string explaining what the given error number means. * Bug fix: * Ralph Mitchell reported that the 'cookiejar' option wouldn't work in the latest version, it should now. Version 0.12.1 released 30-September-04 * New features: * Third party ftp support, you can now transfer a file between two different ftp servers. Check the 'ftp options' in the docs page for details. * A new command for curl handles 'reset' which re-initializes all options previously set on a specified handle to the default values. This puts back the handle to the same state as it was in when it was just created with curl::init. It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares. * Hooked the multi interface to Tcl's event loop, so you can have fire-and-forget transfers: set multiHandle [curl::multiinit] set easyHandle [curl::init] $easyHandle configure -file home.tar.gz \ -url http://127.0.0.1/~andres/HomePage.tar.gz $multiHandle addhandle $easyHandle $multiHandle auto -command "CleanUp $multiHandle $easyHandle" This support is experimental, so any comments are welcome. Thanks to Eric Boudaillier who answered my question about how to do it. * New ssl data types have been added to 'debugproc'. * In case of error when setting post data, the error will include a code about the nature of the error. * Bug fix: * The 'autoreferer' option should now work. Version 0.12.0 released 09-July-04 * New configure options: * '-port': Pass the number specifying what remote port to connect to, instead of the one specified in the URL or the default port for the used protocol. * '-tcpnodelay': To specify whether the TCP_NODELAY option should be set or cleared. Setting this option will disable TCP's Nagle algorithm. The purpose of this algorithm is to try to minimize the number of small packets on the network. * '-autoreferer': When enabled, TclCurl will automatically set the 'Referer:' field in requests where it follows a 'Location:' redirect. * Bug fix: * Thanks to Stefano Federici I noticed that the 'ftpssl' option didn't work. Version 0.11.0 released 04-febrary-04 * New configure options: * 'ftpssl': You can use ftps:// URLs to explicitly switch on SSL/TSL for the control connection and the data connection. Alternatively you can set this option to one of these values: * 'nope': Do not attempt to use SSL * 'try': Try using SSL, proceed anyway otherwise. * 'control': Use SSL for the control connection or fail. * 'all': Use SSL for all communication or fail. * 'netrcfile': Pass a string containing the full path name to the file you want to use as .netrc file. For the option to work, you have to set the 'netrc' option to 'required'. If this option is omitted, and 'netrc' is set, TclCurl will attempt to find the a .netrc file in the current user's home directory. * Bug fix: Fixed the 'netrc' option. Version 0.10.8 released 29-december-03 * New 'configure' options: * 'ftpresponsetimeout': Causes TclCurl to set a timeout period on the amount of time that the server is allowed to take in order to generate a response message for a command before the session is considered hung. * 'ipresolve': Allows an application to select what kind of IP addresses to use when resolving host names. This is only interesting when using host names that resolve addresses using more than one version of IP. * 'maxfilesize': Allows you to specify the maximum size of a file to download. * New 'getinfo' options: * 'httpauthavail': Returns a list with the authentication method(s) available. * 'proxyauthavail': Returns a list with the authentication method(s) available for your proxy athentication. * Misc: * 'curl::versioninfo' will now say if there is support for asynchronus DNS and SPNEGO. * The 'httpcode' for 'getinfo' is now called 'responsecode' since it will now work with FTP transfers. The old option name, while deprecated, will continue to work. * Bug fixes: * TclCurl still thought it was in version 0.10.4. * Fixed the 'httpauth' option. * The configure scripts would sometimes use the cURL in '/usr/bin' instead of the one in '/usr/local/bin' despite the '--with-curlprefix' tag. Version 0.10.7 released 03-September-03 * New configure options: * 'ftpcreatemissingdirs': If set to non-zero, TclCurl will attempt to create any remote directory that it fails to CWD into. CWD is the command that changes working directory. * 'httpauth': Set to the authentication method you want, the available ones are: * 'basic': HTTP Basic authentication. This is the default choice, and the only method that is in widespread use and supported virtually everywhere. It sends the user name and password over the network in plain text, easily captured by others. * 'digest': HTTP Digest authentication. Digest authentication is a more secure way to do authentication over public networks than the regular old-fashioned Basic method. * 'gssnegotiate': HTTP GSS-Negotiate authentication. The GSS-Negotiate method was designed by Microsoft and is used in their web aplications. It is primarily meant as a support for Kerberos5 authentication but may be also used along with another authenti- cation methods. * 'ntlm': HTTP NTLM authentication. A proprietary protocol invented and used by Microsoft. * 'any':TclCurl will automaticaly select the one it finds most secure. * 'anysafe': It may use anything but basic, TclCurl will automaticly select the one it finds most secure. * 'command': Executes a Tcl command after the transfer is done. So far it only works in blocking transfers which is pretty much useless. Version 0.10.5 released 21-May-03 * New configure option: * 'ftpuseeptr': Set to non-zero, to tell TclCurl to use the EPRT (and LPRT) command when doing active FTP downloads (which is enabled by 'ftpport'). Using EPRT means that it will first attempt to use EPRT and then LPRT before using PORT, if you pass zero to this option, it will not try using EPRT or LPRT, only plain PORT * Bug fixes: * The multi handles couldn't store the data of more than two easy handles. * Using the 'progressproc' option in Windows would crash Tcl. * The '$multiHandle active' command wasn't returning anything. * Misc: * Updated ssl in Windows binaries to version 0.9.7b. * Changed the way the http reponse header is dealt with in the 'headervar' option. Now the whole header is put into foo(http). ************** POTENTIAL INCOMPATIBILITY ************** Version 0.10.4 released 31-March-03 * New features: * Added 'getinfo' features to the 'curl::transfer' command. You can now do things like: curl::transfer -url http://www.curl.com \ -infohttpcode httpCode \ -infocontenttype contentType \ puts "Http code: $httpCode" puts "Content type: $contentType" * New configure option: -unrestrictedauth, a non-zero parameter tells the extension it can continue to send authentication (user+password) when following locations, even when hostname changed. Note that this is meaningful only when setting -followlocation * The makefile now has an 'uninstall' target. * The Windows packages are now zlib enabled. * Added a 'packages' directory with a makefile to create the Windows packages and the spec file for rpm. * Bug fix: * The configure script will no longer choke with the version string of cURL's prereleases. * Misc * If there is an error, the 'curl::transfer' command will now return the code of the error, without the 'Couldn't perform transfer' message. ************** POTENTIAL INCOMPATIBILITY ************** * So that they have the same name in Windows and Linux, I have changed the name of the certificate file in Windows to 'curl-ca-bundle.crt' and it will placed in the 'Windows' directory. ************** POTENTIAL INCOMPATIBILITY ************** * Alex Khassin suggested using fully qualified in 'tclcurl.tcl' names to prevent problems with namespaces. Version 0.10.3 released 30-January-03 * New configure option: * 'http200alieases': To pass a list of aliases to be treated as valid HTTP 200 responses. * Bug fixes: * When using '-headervar' in Windows you could end up with carriage returns in the name of the header. * Julian let me know that TclCurl would crash when used in a thread enabled Tcl. * Enhancements: * Since compiling TclCurl in Windows is a real pain, I will provide more packages for it, thread and ssl enabled. * Alex Khassin has written instructions on how to get TclCurl to work with AOLSever. Version 0.10.1 released 14-October-02 * New configure options: * 'proxytype': Allows you to set type of the proxy. Available options are 'http' and 'socks5', with the HTTP one being default. * 'encoding': TclCurl can now request compressed contents using the 'deflate' method. * 'buffersize': To set prefered size for the receive buffer in TclCurl, so that the write callback is called more often with smaller chunks. * 'nosignal': Tells TclCurl not use any functions that install signal handlers or any functions that cause signals to be sent to the process. * New command: * 'curl::versioninfo': Returns information about various run-time features in TclCurl. * Bug fixes: * Fixed to 'buffer' option to post data. * Asif Haswarey reported that '--with-curlinclude' wouldn't work. * The multi interface examples suddenly stopped working, they should now. Version 0.9.8 released 25-June-02 * Support for libcurl's multi interface, the main features are: * Enable a "pull" interface. The application that uses TclCurl decides where and when to get/send data. * Enable multiple simultaneous transfers in the same thread without making it complicated for the application. * Keep Tk GUIs 'alive' while transfers are taking place. * New 'httppost' options * 'bufferName' and 'buffer', the contents of buffer will be sent to the server as if they were a file whose name is in bufferName, please check the 'httpBufferPost.tcl' example. * New 'getinfo' options * redirectime: Returns the total time, in seconds, it took for all redirection steps including name lookup, connect, pretransfer and transfer before the final transaction was started, it returns the complete execution time for multiple redirections. * redirectcount: Returns the total number of redirections that were actually followed. Version 0.9.6 released 30-April-02 * New configure options: * dnscachetimeout, to set the timeout in seconds for keeping the name resolves in memory. * dnsuseglobalcache, if set to '1' the DNS cache will be shared among curl handles. * debugproc, to set a procedure that will receive the debug data produced by the 'verbose' option. * Jonathan Matthew found and fixed a seg fault when you used the 'httpheader' option twice with the same handle. * The configure scripts saw more work in this release: * I merged the latest changes to the TEA sample extension by Jeff Hobbs. * Suresh K. Sastry found and fixed an incompatibility with Solaris. * And I hope I have not forgotten any 'DESTDIR' this time. Version 0.9.5 released 01-April-2002 * I have adapted the configure scripts to the new TEA scripts released by Jeff Hobbs, for example, now it will compile 'out of the box' for freeBSD systems (well, you may need to use '--with-curlprefix' and '--with-curlinclude') * New configure option: * prequote: use it to pass a list of ftp commands to execute *just before* the transfer. * New getinfo option: * contenttype: if the servers bothers to tell you, this will return the type of the downloadad object. * Bug fix: 'curl::transfer' will return '0' if the transfer was successful. *** POTENTIAL INCOMPATIBILITY *** Version 0.9.3 released 29-Jan-2002 * Bug fix: There should no more seg faults because of trailing options in configure commands. * Bug fix: Binary transfer weren't done right in Windows, thanks to Peter Waltenberg and Darren Blee for the report. * TclCurl now supports OpenSSL engines, which allow you to keep your private key stored in external hardware. In order to manage this there are a few new configure options: * sslcerttype: Set SSL cert type (PEM/DER). * sslkey: Set SSL private key (file). * sslkeytype: Set SSL key type (PEM/DER/ENG). * sslkeypasswd: Set the passphrase for your private key. * sslengine: Set the name of the crypto engine. * sslenginedefault: Set the default engine. * You can now add a set of headers for a particular part in a multipart/form-post using the 'contentheader' option. * It is now possible to execute commands in ftp servers without transfering files, you have to set 'nobody' to '1' and 'header' to '0'. tclcurl-ng-8.0.3/Makefile.in000077500000000000000000000462171522613063100156550ustar00rootroot00000000000000# Makefile.in -- # # This file is a Makefile for Sample TEA Extension. If it has the name # "Makefile.in" then it is a template for a Makefile; to generate the # actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (c) 1999 Scriptics Corporation. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #======================================================================== # Add additional lines to handle any additional AC_SUBST cases that # have been added in a customized configure script. #======================================================================== #SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ TCLCURL_DOC_GEN = @TCLCURL_DOC_GEN@ TCLCURL_HTML_GEN = @TCLCURL_HTML_GEN@ #======================================================================== # Nothing of the variables below this line should need to be changed. # Please check the TARGETS section below to make sure the make targets # are correct. #======================================================================== #======================================================================== # The names of the source files is defined in the configure script. # The object files are used for linking into the final library. # This will be used when a dist target is added to the Makefile. # It is not important to specify the directory, as long as it is the # $(srcdir) or in the generic, win or unix subdirectory. #======================================================================== PKG_SOURCES = @PKG_SOURCES@ TCLCURL_SCRIPTS = @TCLCURL_SCRIPTS@ PKG_OBJECTS = @PKG_OBJECTS@ PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ #======================================================================== # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with # this package that need to be installed, if any. #======================================================================== PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ #======================================================================== # This is a list of public header files to be installed, if any. #======================================================================== PKG_HEADERS = @PKG_HEADERS@ #======================================================================== # "PKG_LIB_FILE" refers to the library (dynamic or static as per # configuration options) composed of the named objects. #======================================================================== PKG_LIB_FILE = @PKG_LIB_FILE@ PKG_LIB_FILE8 = @PKG_LIB_FILE8@ PKG_LIB_FILE9 = @PKG_LIB_FILE9@ PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ lib_BINARIES = $(PKG_LIB_FILE) BINARIES = $(lib_BINARIES) SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ runstatedir = @runstatedir@ datadir = @datadir@ mandir = @mandir@ DESTDIR = PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(libdir)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = @abs_top_builddir@ INSTALL_OPTIONS = INSTALL = @INSTALL@ $(INSTALL_OPTIONS) INSTALL_DATA_DIR = @INSTALL_DATA_DIR@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_LIBRARY = @INSTALL_LIBRARY@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ CC = @CC@ CCLD = @CCLD@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ EXEEXT = @EXEEXT@ MAKE_LIB = @MAKE_LIB@ MAKE_STUB_LIB = @MAKE_STUB_LIB@ OBJEXT = @OBJEXT@ RANLIB = @RANLIB@ RANLIB_STUB = @RANLIB_STUB@ SHLIB_CFLAGS = @SHLIB_CFLAGS@ SHLIB_LD = @SHLIB_LD@ SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ STLIB_LD = @STLIB_LD@ #TCL_DEFS = @TCL_DEFS@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SRC_DIR = @TCL_SRC_DIR@ #TK_BIN_DIR = @TK_BIN_DIR@ #TK_SRC_DIR = @TK_SRC_DIR@ # Not used, but retained for reference of what libs Tcl required #TCL_LIBS = @TCL_LIBS@ #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) #EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) TCLLIBPATH = $(top_builddir) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(TCLLIBPATH)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG) #WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` #WISH_PROG = @WISH_PROG@ #WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG) SHARED_BUILD = @SHARED_BUILD@ INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I. #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ # TCL_DEFS is not strictly need here, but if you remove it, then you # must make sure that configure.ac checks for the necessary components # that your library may use. TCL_DEFS can actually be a problem if # you do not compile with a similar machine setup as the Tcl core was # compiled with. #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) DEFS = @DEFS@ $(PKG_CFLAGS) # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl tests/tcl_conf.tcl CLEANFILES = @CLEANFILES@ CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \ $(CFLAGS) GDB = gdb VALGRIND = valgrind VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \ --leak-check=yes --show-reachable=yes -v .SUFFIXES: .c .$(OBJEXT) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target includes executable programs and # platform-dependent libraries. Modify these targets so that they install # the various pieces of your package. The make and install rules # for the BINARIES that you specified above have already been done. #======================================================================== all: binaries libraries doc #======================================================================== # The binaries target builds executable programs, Windows .dll's, unix # shared/static libraries, and any other platform-dependent files. # The list of targets to build for "binaries:" is specified at the top # of the Makefile, in the "BINARIES" variable. #======================================================================== binaries: $(BINARIES) libraries: scripts: $(TCLCURL_SCRIPTS) #======================================================================== # Your doc target should differentiate from doc builds (by the developer) # and doc installs (see install-doc), which just install the docs on the # end user machine when building from source. #======================================================================== doc: doc/tclcurl.n doc/tclcurl.html doc/tclcurl_share.n doc/tclcurl_share.html doc/tclcurl_multi.n doc/tclcurl_multi.html doc/tclcurl.n: doc/tclcurl.n.md @echo "Generating doc/tclcurl.n"; @if test -z "$(TCLCURL_DOC_GEN)"; then \ echo "Warning: no markdown-to-man converter available; skipping doc/tclcurl.n"; \ else \ $(TCLCURL_DOC_GEN) doc/tclcurl.n doc/tclcurl.n.md; \ fi doc/tclcurl.html: doc/tclcurl.n.md @echo "Generating doc/tclcurl.html"; @if test -z "$(TCLCURL_HTML_GEN)"; then \ echo "Warning: no markdown-to-html converter available; skipping doc/tclcurl.html"; \ else \ $(TCLCURL_HTML_GEN) doc/tclcurl.html doc/tclcurl.n.md; \ fi doc/tclcurl_share.n: doc/tclcurl_share.n.md @echo "Generating doc/tclcurl_share.n"; @if test -z "$(TCLCURL_DOC_GEN)"; then \ echo "Warning: no markdown-to-man converter available; skipping doc/tclcurl_share.n"; \ else \ $(TCLCURL_DOC_GEN) doc/tclcurl_share.n doc/tclcurl_share.n.md; \ fi doc/tclcurl_share.html: doc/tclcurl_share.n.md @echo "Generating doc/tclcurl_share.html"; @if test -z "$(TCLCURL_HTML_GEN)"; then \ echo "Warning: no markdown-to-html converter available; skipping doc/tclcurl_share.html"; \ else \ $(TCLCURL_HTML_GEN) doc/tclcurl_share.html doc/tclcurl_share.n.md; \ fi doc/tclcurl_multi.n: doc/tclcurl_multi.n.md @echo "Generating doc/tclcurl_multi.n"; @if test -z "$(TCLCURL_DOC_GEN)"; then \ echo "Warning: no markdown-to-man converter available; skipping doc/tclcurl_multi.n"; \ else \ $(TCLCURL_DOC_GEN) doc/tclcurl_multi.n doc/tclcurl_multi.n.md; \ fi doc/tclcurl_multi.html: doc/tclcurl_multi.n.md @echo "Generating doc/tclcurl_multi.html"; @if test -z "$(TCLCURL_HTML_GEN)"; then \ echo "Warning: no markdown-to-html converter available; skipping doc/tclcurl_multi.html"; \ else \ $(TCLCURL_HTML_GEN) doc/tclcurl_multi.html doc/tclcurl_multi.n.md; \ fi install: all install-binaries install-scripts install-libraries install-doc install-binaries: binaries install-lib-binaries install-bin-binaries #======================================================================== # This rule installs platform-independent files, such as header files. # The list=...; for p in $$list handles the empty list case x-platform. #======================================================================== install-libraries: libraries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(includedir)" @echo "Installing header files in $(DESTDIR)$(includedir)" @list='$(PKG_HEADERS)'; for i in $$list; do \ echo "Installing $(srcdir)/$$i" ; \ $(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \ done; #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc: doc @$(INSTALL_DATA_DIR) "$(DESTDIR)$(mandir)/mann" @echo "Installing documentation in $(DESTDIR)$(mandir)" @list='$(srcdir)/doc/*.n'; for i in $$list; do \ echo "Installing $$i"; \ $(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \ done test: binaries libraries $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ [list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]" shell: binaries libraries @$(TCLSH) $(SCRIPT) gdb: $(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT) gdb-test: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(GDB) \ --args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \ $(TESTFLAGS) -singleproc 1 \ -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ [list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]" valgrind: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \ `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) valgrindshell: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) depend: #======================================================================== # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable # mentioned above. That will ensure that this target is built when you # run "make binaries". # # The $(PKG_OBJECTS) objects are created and linked into the final # library. In most cases these object files will correspond to the # source files above. #======================================================================== $(PKG_LIB_FILE): $(PKG_OBJECTS) -rm -f $(PKG_LIB_FILE) ${MAKE_LIB} $(RANLIB) $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) -rm -f $(PKG_STUB_LIB_FILE) ${MAKE_STUB_LIB} $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) #======================================================================== # We need to enumerate the list of .c to .o lines here. # # In the following lines, $(srcdir) refers to the toplevel directory # containing your extension. If your sources are in a subdirectory, # you will have to modify the paths to reflect this: # # sample.$(OBJEXT): $(srcdir)/generic/sample.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ # # Setting the VPATH variable to a list of paths will cause the makefile # to look into these paths when resolving .c to .obj dependencies. # As necessary, add $(srcdir):$(srcdir)/compat:.... #======================================================================== VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ tclsample.@OBJEXT@: sampleUuid.h $(srcdir)/manifest.uuid: printf "git-" >$(srcdir)/manifest.uuid (cd $(srcdir); git rev-parse HEAD >>$(srcdir)/manifest.uuid || \ (printf "svn-r" >$(srcdir)/manifest.uuid ; \ svn info --show-item last-changed-revision >>$(srcdir)/manifest.uuid) || \ printf "unknown" >$(srcdir)/manifest.uuid) sampleUuid.h: $(srcdir)/manifest.uuid echo "#define SAMPLE_VERSION_UUID \\" >$@ cat $(srcdir)/manifest.uuid >>$@ echo "" >>$@ #======================================================================== # Distribution creation # You may need to tweak this target to make it work correctly. #======================================================================== #COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) DIST_ROOT = /tmp/dist DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644 DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755 dist-clean: rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* dist: dist-clean $(srcdir)/manifest.uuid $(INSTALL_DATA_DIR) $(DIST_DIR) # TEA files $(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \ $(srcdir)/aclocal.m4 $(srcdir)/configure.ac \ $(DIST_DIR)/ $(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/ $(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig $(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \ $(srcdir)/manifest.uuid \ $(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \ $(DIST_DIR)/tclconfig/ # Extension files $(DIST_INSTALL_DATA) \ $(srcdir)/ChangeLog \ $(srcdir)/README.sha \ $(srcdir)/license.terms \ $(srcdir)/README \ $(srcdir)/pkgIndex.tcl.in \ $(DIST_DIR)/ list='demos doc generic library macosx tests unix win'; \ for p in $$list; do \ if test -d $(srcdir)/$$p ; then \ $(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \ $(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \ fi; \ done (cd $(DIST_ROOT); $(COMPRESS);) #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.ac #======================================================================== clean: -test -z "$(BINARIES)" || rm -f $(BINARIES) -rm -f *.$(OBJEXT) core *.core -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean: clean -rm -f *.tab.c -rm -f $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log config.status #======================================================================== # Install binary object libraries. On Windows this includes both .dll and # .lib files. Because the .lib files are not explicitly listed anywhere, # we need to deduce their existence from the .dll file of the same name. # Library files go into the lib directory. # In addition, this will generate the pkgIndex.tcl # file in the install location (assuming it can find a usable tclsh shell) # # You should not have to modify this target. #======================================================================== install-lib-binaries: binaries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)" @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ $(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \ ext=`echo $$p|sed -e "s/.*\.//"`; \ if test "x$$ext" = "xdll"; then \ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ if test -f $$lib; then \ echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ $(INSTALL_DATA) $$lib "$(DESTDIR)$(pkglibdir)/$$lib"; \ fi; \ fi; \ fi; \ done @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ if test -f $(srcdir)/$$p; then \ destp=`basename $$p`; \ echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ $(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \ fi; \ done @if test "x$(SHARED_BUILD)" = "x1"; then \ echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ $(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \ fi #======================================================================== # Install binary executables (e.g. .exe files and dependent .dll files) # This is for files that must go in the bin directory (located next to # wish and tclsh), like dependent .dll files on Windows. # # You should not have to modify this target, except to define bin_BINARIES # above if necessary. #======================================================================== install-bin-binaries: binaries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)" @list='$(bin_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ $(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \ fi; \ done #======================================================================== # This rule installs the scripts that are part of TclCurl. #======================================================================== install-scripts: scripts @for i in generic/$(TCLCURL_SCRIPTS) ; do \ echo "Installing $$i" ; \ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(pkglibdir) ; \ done; Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status uninstall-binaries: list='$(lib_BINARIES)'; for p in $$list; do \ rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ done list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ p=`basename $$p`; \ rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ done list='$(bin_BINARIES)'; for p in $$list; do \ rm -f "$(DESTDIR)$(bindir)/$$p"; \ done .PHONY: all binaries clean depend distclean doc install libraries test .PHONY: gdb gdb-test valgrind valgrindshell # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: tclcurl-ng-8.0.3/README.md000077500000000000000000000077551522613063100150730ustar00rootroot00000000000000# TclCurl - get a URL with FTP, TELNET, LDAP, DICT, FILE, HTTP or HTTPS syntax. This project was forked from the [flightaware/tclcurl-fa](https://github.com/flightaware/tclcurl-fa) repository and then continued as an independent development effort since the upstream maintainers apparently stopped accepting or reacting to PRs. The current project status supports most options of the legacy tclcurl. Some options (see below) can be included in the build even though they might have no effect, since recent versions of libcurl discontinued removed their functionalities Some portions of this project were developed with AI-assisted drafting/editing tools under human direction, supervision, review, and approval. All accepted changes were selected, verified, and integrated by the human maintainer, who anyway instructed the AI-assistant on how code had to be reorganized ## Introduction TclCurl gives the Tcl programmer access to the facilities of libcurl. For more information about what libcurl is capable of check https://curl.se/ To make type: ./configure --with-tcl= ?--enable-threads? make make install In order to highlight the continuity with tclcurl-fa version numbering will start with version 8.0.0 to mark the possible incompatibilies due to removed options because obsoleted or deprecated in libcurl ### Configure options The configure script will deduce `$PREFIX` from the tcl installation. The generated `Makefile` uses the file `$PREFIX/lib/tclConfig.sh` that was left by the make of tcl for most of its configuration parameters. ### Tclcurl specific configure options * --with-curlprefix: base directory for the cURL install. If left unspecified the path is determined by running `curl-config --prefix` * --with-curlinclude: overrrides the curl include files directory (default $curl_prefix/include) * --with-md-converter: this options controls which MD converter has to be invoked in order to generate the man page out of the markdown source. Accepted values are `lowdown` (default) and `pandoc` * --enable-deprecated-code: starting with tclcurl 8 options and features deprecated by cURL have been removed. You can re-enable all deprecated or obsoleted options by passing the argument `--enable-deprecated-code:all`. You can also selectively enable deprecated code passing a comma separated list of the milestone versions which deprecated specific features. Accepted arguments are: + 7.11.1 - re-enable `-dnsuseglobalcache` + 7.56 - re-enable old style method to construct mime multipart/form-data messages + 7.84 - re-enable deprecated options `-randomfile` and `-egdsocket` + 8.17.0 - re-enable `-krb4level` ### OS Support On a properly Linux/Unix install the package shouldn't have problems to build and run. To build tclcurl no more than the typical packages for building applications based on libcurl and libtcl are needed. *We retained the ReadMeW32.txt that explains how to compile tclcurl on Windows, but this fork is currently tested only on Linux/Unix* ## Troubleshooting ## Usage package require TclCurl curl::transfer curl::version curl::escape $url curl::unescape $url curl::curlConfig option set curlHandle [curl::init] ### Curl Handle methods $curlHandle configure $curlHandle perform $curlHandle getinfo curlinfo_option $curlHandle duphandle $curlHandle cleanup Check the man page for details. ## Authors - Originally written by: Andres Garcia (fandom@telefonica.net) - Cloned from a repo by Steve Havelka once at: https://bitbucket.org/smh377/tclcurl/ (now broken 2026-04-07) - Code refactored and test suite developed by Massimo Manghi (massimo.manghi@rivetweb.org). Some parts were written with the help of the OpenAI/Codex assistant but every modification or AI generated code has been evaluated by the author (2024-2026) who directed step-by-step the assistant on how the code had to be reorganized ## License BSD like license, check 'license.terms' for details. tclcurl-ng-8.0.3/ReadMeW32.txt000077500000000000000000000073411522613063100157750ustar00rootroot00000000000000To install TclCurl in Windows you simply have to double-click on the 'SetUp.tcl' file, provided you already have Tcl/Tk installed, the script will take care of everything. By the way, Tcl's console doesn't seem to like the output sent by TclCurl, for example, if you type: curl::transfer -url www.scriptics.com you will only get an error, you will have to dump it to a file with the 'file' option, read it in to a variable with 'bodyvar', use Cygwin's console or use tkCon from msys-mingw. Compiling TclCurl in Windows First of all a little disclaimer: I know nothing about Windows programming, no kidding, not a thing, zip, zilch, nada. I can barely manage using tools, like Tcl/Tk and gcc, whose origin is in the Unix world, but that is just about it, so if you think that the following is just plain stupid, that is because it probably is, but in that case, don't forget to tell me all about it. To compile TclCurl in Windows you are going to need several things: - A msys-mingw enviroment, you can get it at SourceForge: http://sourceforge.net/projects/tcl/ or you can get MinGW and Msys from their project page: http://sourceforge.net/projects/mingw/ - Since you are already at Tcl's page at SF, you can download the lastest Tcl version, 8.4.13 at this writing. (These instructions won't work with 8.3.x versions) - Download zlib from http://www.gzip.org/zlib/ - Download bc from http://gnuwin32.sourceforge.net/packages/bc.htm and install it. - Extract Tcl, cURL, zlib and TclCurl in the same directory. - Copy the 'tclcurl.mk' file in TclCurl/packages/windows to this directory. - Start msys, go to the directory and type: $ make -f tclcurl.mk tclcurl-plain This command will compile and install Tcl, zlib, cURL and TclCurl, if you want to have Tk though, you will have to install it yourself. After compiling and installing all the elements, the make file will try to create the self-extracting archive using 'rar', if you don't have it installed it will fail, but don't worry, everything is already installed. If you have rar and you want to create the archives, don't forget to change the path at the end of the make file. - If you want to use TclCurl with the Tcl/Tk you have installed in c:\Program Files or anywhere else, copy the directory '/usr/local/lib/tclcurl0.110' to 'c:\Program Files\Tcl\lib' - And now you should have a working TclCurl, run Tcl/Tk and type: $ package require TclCurl. Tcl should return TclCurl's version, if it doesn't something went wrong, could you please tell me? - Wish console doesn't really like TclCurl, so if you do: $ curl::transfer -url slashdot.org It will return a '0' to tell you that the transfer was successful, but it will show you nothing, you will have to dump the page into a file to be able to read it or use Cygwin's console. Compiling TclCurl with threads support You have to do basically the same thing, except that the command to compile is: $ make -f tclcurl.mk tclcurl-threaded Compiling TclCurl with SSL support Since 1.0.0 openssl is easier to compile, you can find the instructions to it in the INSTALL.W32 file in the openssl tarball. You can get the cacert.pem at http://curl.haxx.se/ca/, you need to put in the directory from which you are going to compile - $ make -f tclcurl.mk tclcurl-ssl - If you want to have threads support: - $ make -f tclcurl.mk tclcurl-threaded-ssl Sounds like a lot of work to run a little extension, but then again, you could have downloaded the self-extracting archive file. Share the wonders, Andres fandom@telefonica.net tclcurl-ng-8.0.3/VERSION000066400000000000000000000000061522613063100146370ustar00rootroot000000000000008.0.3 tclcurl-ng-8.0.3/aclocal.m4000077500000000000000000000002231522613063100154330ustar00rootroot00000000000000# # Include the TEA standard macro set # builtin(include,tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # tclcurl-ng-8.0.3/checkAutoPath.tcl000077500000000000000000000007111522613063100170240ustar00rootroot00000000000000# This file checks that the directory where TclCurl is going to be # installed is actually in the auto_path variable, if it isn't it # modifies 'init.tcl'. set tclCurlDir [lindex $argv 0] set initTclDir [lindex $argv 1] set initFile [file join $tcl_library init.tcl] if {[file writable $initFile]==0} exit if {[lsearch $auto_path $tclCurlDir]==-1} { set handle [open "$initFile" a] puts $handle "\nlappend auto_path $tclCurlDir\n" } exit tclcurl-ng-8.0.3/configure000077500000000000000000011204541522613063100155110ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for TclCurl 8.0.3. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case e in #( e) case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else case e in #( e) exitcode=1; echo positional parameters were not saved. ;; esac fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else case e in #( e) as_have_required=no ;; esac fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi ;; esac fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: massimo.manghi@rivetweb.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi ;; esac fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' t clear :clear s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='TclCurl' PACKAGE_TARNAME='tclcurl-ng' PACKAGE_VERSION='8.0.3' PACKAGE_STRING='TclCurl 8.0.3' PACKAGE_BUGREPORT='massimo.manghi@rivetweb.org' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS TCLSH_PROG VC_MANIFEST_EMBED_EXE VC_MANIFEST_EMBED_DLL RANLIB_STUB PKG_STUB_LIB_FILE MAKE_STUB_LIB MAKE_STATIC_LIB MAKE_SHARED_LIB MAKE_LIB LDFLAGS_DEFAULT CFLAGS_DEFAULT LD_LIBRARY_PATH_VAR SHLIB_CFLAGS SHLIB_LD_LIBS SHLIB_LD STLIB_LD LDFLAGS_OPTIMIZE LDFLAGS_DEBUG CFLAGS_WARNING CFLAGS_OPTIMIZE CFLAGS_DEBUG LIBOBJS RC AR STUBS_BUILD SHARED_BUILD TCL_THREADS TCL_INCLUDES curl TCLCURL_HTML_GEN TCLCURL_DOC_GEN PANDOC LOWDOWN TCLCURL_SCRIPTS PKG_OBJECTS PKG_SOURCES RANLIB SET_MAKE CPP TCL_SHLIB_LD_LIBS TCL_LD_FLAGS TCL_EXTRA_CFLAGS TCL_DEFS TCL_LIBS CLEANFILES OBJEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG TCL_STUB_LIB_FILE TCL_LIB_SPEC TCL_LIB_FLAG TCL_LIB_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_PATCH_LEVEL TCL_VERSION INSTALL_LIBRARY INSTALL_SCRIPT INSTALL_PROGRAM INSTALL_DATA INSTALL_DATA_DIR INSTALL PKG_CFLAGS PKG_LIBS PKG_INCLUDES PKG_HEADERS PKG_TCL_SOURCES PKG_STUB_OBJECTS PKG_STUB_SOURCES PKG_LIB_FILE9 PKG_LIB_FILE8 PKG_LIB_FILE EXEEXT CYGPATH target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_tcl with_tcl8 with_md_converter with_curlprefix with_curlinclude with_libcurl with_tclinclude enable_threads enable_shared enable_stubs enable_64bit enable_64bit_vis enable_rpath enable_symbols enable_deprecated_code ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: '$ac_option' Try '$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: '$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: '$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF 'configure' configures TclCurl 8.0.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print 'checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for '--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or '..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, 'make install' will install all the files in '$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify an installation prefix other than '$ac_default_prefix' using '--prefix', for instance '--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/tclcurl-ng] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of TclCurl 8.0.3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-stubs build and link with stub libraries. Always true for shared builds (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --disable-rpath disable rpath support (default: on) --enable-symbols build with debugging symbols (default: off) --enable-deprecated-code=LIST Enable deprecated code for selected CURL versions. LIST is a comma-separated list of: v7.56,v7.84,v7.11.1,v8.17.0. Use --enable-deprecated-code (or =all) to enable all; default is none. Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tcl8 Compile for Tcl8 in Tcl9 environment --with-md-converter markdown-to-man converter to use: lowdown, pandoc, or auto --with-curlprefix base directory for the cURL install '/usr', '/usr/local',... --with-curlinclude directory containing the public libcurl header files --with-libcurl directory containing libcurl --with-tclinclude directory containing the public Tcl header files Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by 'configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF TclCurl configure 8.0.3 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_run LINENO # ---------------------- # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status ;; esac fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (void); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (void); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by TclCurl $as_me 8.0.3, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See 'config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (char **p, int i) { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* C89 style stringification. */ #define noexpand_stringify(a) #a const char *stringified = noexpand_stringify(arbitrary+token=sequence); /* C89 style token pasting. Exercises some of the corner cases that e.g. old MSVC gets wrong, but not very hard. */ #define noexpand_concat(a,b) a##b #define expand_concat(a,b) noexpand_concat(a,b) extern int vA; extern int vbee; #define aye A #define bee B int *pvA = &expand_concat(v,aye); int *pvbee = &noexpand_concat(v,bee); /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' /* Does the compiler advertise C99 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif // See if C++-style comments work. #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); extern void free (void *); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Work around memory leak warnings. free (ia); // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' /* Does the compiler advertise C11 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_VERSION="3.13" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking TEA configuration" >&5 printf %s "checking TEA configuration... " >&6; } if test x"${PACKAGE_NAME}" = x ; then as_fn_error $? " The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 printf "%s\n" "ok (TEA ${TEA_VERSION})" >&6; } # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CYGPATH+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi ;; esac fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 printf "%s\n" "$CYGPATH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 printf "%s\n" "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} # This package name must be replaced statically for AC_SUBST to work # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... # Configure the installer. INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version" >&5 printf %s "checking system version... " >&6; } if test ${tcl_cv_sys_version+y} then : printf %s "(cached) " >&6 else case e in #( e) # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 printf "%s\n" "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 printf "%s\n" "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac ac_config_headers="$ac_config_headers config.h" #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true # Check whether --with-tcl was given. if test ${with_tcl+y} then : withval=$with_tcl; with_tclconfig="${withval}" fi # Check whether --with-tcl8 was given. if test ${with_tcl8+y} then : withval=$with_tcl8; with_tcl8="${withval}" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 printf %s "checking for Tcl configuration... " >&6; } if test ${ac_cv_c_tclconfig+y} then : printf %s "(cached) " >&6 else case e in #( e) # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 printf "%s\n" "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi ;; esac fi if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf "%s\n" "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See 'config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'. # So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an '-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else case e in #( e) ac_file='' ;; esac fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See 'config.log' for more details" "$LINENO" 5; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both 'conftest.exe' and 'conftest' are 'present' (well, observable) # catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will # work properly (i.e., refer to 'conftest.exe'), while it won't with # 'rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else case e in #( e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); if (!f) return 1; return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use '--host'. See 'config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext \ conftest.o conftest.obj conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest.$ac_cv_objext conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else case e in #( e) ac_compiler_gnu=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else case e in #( e) CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 ;; esac fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf %s "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: loading" >&5 printf "%s\n" "loading" >&6; } . "${TCL_BIN_DIR}/tclConfig.sh" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf "%s\n" "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking platform" >&5 printf %s "checking platform... " >&6; } hold_cc=$CC; CC="$TCL_CC" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifdef _WIN32 #error win32 #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo else case e in #( e) TEA_PLATFORM="windows" # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CYGPATH+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi ;; esac fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 printf "%s\n" "$CYGPATH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CC=$hold_cc { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 printf "%s\n" "$TEA_PLATFORM" >&6; } # The BUILD_$pkg is to define the correct extern storage class # handling when making this package # To be able to sefely use the package name in a #define, it must not # contain anything other than alphanumeric characters and underscores SAFE_PKG_NAME=TclCurl printf "%s\n" "#define BUILD_${SAFE_PKG_NAME} /**/" >>confdefs.h # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 printf "%s\n" "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 printf "%s\n" "$as_me: --prefix defaulting to /usr/local" >&6;} prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 printf "%s\n" "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 printf "%s\n" "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} exec_prefix=$prefix fi fi #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create # the basic setup necessary to compile executables. #----------------------------------------------------------------------- # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See 'config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else case e in #( e) ac_compiler_gnu=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else case e in #( e) CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 ;; esac fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test ${ac_cv_prog_CPP+y} then : printf %s "(cached) " >&6 else case e in #( e) # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else case e in #( e) # Broken: fails on valid input. continue ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else case e in #( e) # Passes both tests. ac_preproc_ok=: break ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CPP=$CPP ;; esac fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else case e in #( e) # Broken: fails on valid input. continue ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else case e in #( e) # Passes both tests. ac_preproc_ok=: break ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else case e in #( e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See 'config.log' for more details" "$LINENO" 5; } ;; esac fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else case e in #( e) cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make ;; esac fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 printf %s "checking if the compiler understands -pipe... " >&6; } if test ${tcl_cv_cc_pipe+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_cc_pipe=yes else case e in #( e) tcl_cv_cc_pipe=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS=$hold_cflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 printf "%s\n" "$tcl_cv_cc_pipe" >&6; } if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then printf "%s\n" "#define Tcl_Size int" >>confdefs.h fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 printf %s "checking whether byte ordering is bigendian... " >&6; } if test ${ac_cv_c_bigendian+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO" then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else case e in #( e) ac_cv_c_bigendian=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else case e in #( e) ac_cv_c_bigendian=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } int main (int argc, char **argv) { /* Intimidate the compiler so that it does not optimize the arrays away. */ char *p = argv[0]; ascii_mm[1] = *p++; ebcdic_mm[1] = *p++; ascii_ii[1] = *p++; ebcdic_ii[1] = *p++; return use_ascii (argc) == use_ebcdic (*p); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if grep BIGenDianSyS conftest$ac_exeext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest$ac_exeext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_c_bigendian=no else case e in #( e) ac_cv_c_bigendian=yes ;; esac fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) # ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- vars="tclcurl.c tcl_size.c curl_mime.c curl_setopts.c curl_getinfo.c ftp.c curl_utils.c multi.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find source file '$i'" "$LINENO" 5 fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done TCLCURL_SCRIPTS=tclcurl.tcl # Extract the first word of "lowdown", so it can be a program name with args. set dummy lowdown; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_LOWDOWN+y} then : printf %s "(cached) " >&6 else case e in #( e) case $LOWDOWN in [\\/]* | ?:[\\/]*) ac_cv_path_LOWDOWN="$LOWDOWN" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_LOWDOWN="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi LOWDOWN=$ac_cv_path_LOWDOWN if test -n "$LOWDOWN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LOWDOWN" >&5 printf "%s\n" "$LOWDOWN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "pandoc", so it can be a program name with args. set dummy pandoc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PANDOC+y} then : printf %s "(cached) " >&6 else case e in #( e) case $PANDOC in [\\/]* | ?:[\\/]*) ac_cv_path_PANDOC="$PANDOC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PANDOC="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi PANDOC=$ac_cv_path_PANDOC if test -n "$PANDOC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PANDOC" >&5 printf "%s\n" "$PANDOC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Check whether --with-md-converter was given. if test ${with_md_converter+y} then : withval=$with_md_converter; case "$withval" in auto) md_converter_choice=auto ;; lowdown) if test "x$LOWDOWN" = x; then as_fn_error $? "--with-md-converter=lowdown requested, but lowdown was not found" "$LINENO" 5 fi md_converter_choice=lowdown ;; pandoc) if test "x$PANDOC" = x; then as_fn_error $? "--with-md-converter=pandoc requested, but pandoc was not found" "$LINENO" 5 fi md_converter_choice=pandoc ;; *) as_fn_error $? "bad value '$withval' for --with-md-converter: must be lowdown, pandoc, or auto" "$LINENO" 5 ;; esac else case e in #( e) md_converter_choice=auto ;; esac fi if test "x$md_converter_choice" = xauto; then if test "x$LOWDOWN" != x; then md_converter_choice=lowdown elif test "x$PANDOC" != x; then md_converter_choice=pandoc else md_converter_choice=none fi fi case "$md_converter_choice" in lowdown) TCLCURL_DOC_GEN="$LOWDOWN -s -Tman -o" TCLCURL_HTML_GEN="$LOWDOWN -s -Thtml -o" ;; pandoc) TCLCURL_DOC_GEN="$PANDOC -f markdown -t man -o" TCLCURL_HTML_GEN="$PANDOC -f markdown -t html -o" ;; none) TCLCURL_DOC_GEN= TCLCURL_HTML_GEN= ;; esac #-------------------------------------------------------------------- # Find libcurl, if it's not present, it makes no sense to compile # this. #-------------------------------------------------------------------- # Check whether --with-curlprefix was given. if test ${with_curlprefix+y} then : withval=$with_curlprefix; curlprefix=$withval curlpath=$curlprefix/bin # Extract the first word of "curl", so it can be a program name with args. set dummy curl; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_curl+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$curl"; then ac_cv_prog_curl="$curl" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $curlpath do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_curl="yes" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_curl" && ac_cv_prog_curl="no" fi ;; esac fi curl=$ac_cv_prog_curl if test -n "$curl"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl" >&5 printf "%s\n" "$curl" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$curl" = xno ; then as_fn_error $? "can not find cURL in $curlpath" "$LINENO" 5 fi else case e in #( e) # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_curl+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$curl"; then ac_cv_prog_curl="$curl" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_curl="yes" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_curl" && ac_cv_prog_curl="no" fi ;; esac fi curl=$ac_cv_prog_curl if test -n "$curl"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl" >&5 printf "%s\n" "$curl" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$curl" = xno ; then as_fn_error $? "can not find cURL or libcurl... go to http://curl.haxx.se/ to download and then install it first" "$LINENO" 5 else curlprefix=`curl-config --prefix` curlpath=$curlprefix/bin fi ;; esac fi # Check whether --with-curlinclude was given. if test ${with_curlinclude+y} then : withval=$with_curlinclude; vars="-I$withval" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done curlinclude=$withval else case e in #( e) vars="-I$curlprefix/include" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done curlinclude=$curlprefix/include ;; esac fi ac_fn_c_check_header_compile "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default" if test "x$ac_cv_header_curl_curl_h" = xyes then : headercurl=yes else case e in #( e) headercurl=no ;; esac fi if test "x$headercurl" = xno ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking checking for headers at $curlinclude" >&5 printf %s "checking checking for headers at $curlinclude... " >&6; } if test ! -r $curlinclude/curl/curl.h ; then as_fn_error $? "cURL headers not found, you may need to install a curl-devel package" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found" >&5 printf "%s\n" "found" >&6; } fi # Check whether --with-libcurl was given. if test ${with_libcurl+y} then : withval=$with_libcurl; vars="-L$withval" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done else case e in #( e) vars="-L$curlprefix/lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libcurl version is recent enough" >&5 printf %s "checking if libcurl version is recent enough... " >&6; } CURL_VERSION=`$curlpath/curl-config --checkfor 7.21.7` if test "${CURL_VERSION}" != "" ; then echo ${CURL_VERSION} as_fn_error $? "libcurl version too old, please upgrade" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } # We need to modify this original line to strip a few things # See: http://lists.debian.org/debian-devel-announce/2006/09/msg00018.html vars="`$curlpath/curl-config --libs|sed \ -e 's/\-lkrb5\>//g' \ -e 's/\-lgssapi_krb5//g' \ -e 's/\-lk5crypto//g' \ -e 's/\-lkrb5support//g' \ `" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. #CLEANFILES="pkgIndex.tcl" if test "${TEA_PLATFORM}" = "windows" ; then printf "%s\n" "#define BUILD_sample 1" >>confdefs.h CLEANFILES="$CLEANFILES *.lib *.dll *.exp *.ilk *.pdb vc*.pch" #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) else # Ensure no empty else clauses : #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) fi #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 printf %s "checking for Tcl public headers... " >&6; } # Check whether --with-tclinclude was given. if test ${with_tclinclude+y} then : withval=$with_tclinclude; with_tclinclude=${withval} fi if test ${ac_cv_c_tclh+y} then : printf %s "(cached) " >&6 else case e in #( e) # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi ;; esac fi # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 printf "%s\n" "${ac_cv_c_tclh}" >&6; } fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- # Check whether --enable-threads was given. if test ${enable_threads+y} then : enableval=$enable_threads; tcl_ok=$enableval else case e in #( e) tcl_ok=yes ;; esac fi if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention printf "%s\n" "#define USE_THREAD_ALLOC 1" >>confdefs.h printf "%s\n" "#define _REENTRANT 1" >>confdefs.h if test "`uname -s`" = "SunOS" ; then printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h fi printf "%s\n" "#define _THREAD_SAFE 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 printf %s "checking for pthread_mutex_init in -lpthread... " >&6; } if test ${ac_cv_lib_pthread_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (void); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pthread_pthread_mutex_init=yes else case e in #( e) ac_cv_lib_pthread_pthread_mutex_init=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 printf %s "checking for __pthread_mutex_init in -lpthread... " >&6; } if test ${ac_cv_lib_pthread___pthread_mutex_init+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char __pthread_mutex_init (void); int main (void) { return __pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pthread___pthread_mutex_init=yes else case e in #( e) ac_cv_lib_pthread___pthread_mutex_init=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 printf %s "checking for pthread_mutex_init in -lpthreads... " >&6; } if test ${ac_cv_lib_pthreads_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (void); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pthreads_pthread_mutex_init=yes else case e in #( e) ac_cv_lib_pthreads_pthread_mutex_init=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 printf %s "checking for pthread_mutex_init in -lc... " >&6; } if test ${ac_cv_lib_c_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (void); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_c_pthread_mutex_init=yes else case e in #( e) ac_cv_lib_c_pthread_mutex_init=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_c_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = "no"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 printf %s "checking for pthread_mutex_init in -lc_r... " >&6; } if test ${ac_cv_lib_c_r_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (void); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_c_r_pthread_mutex_init=yes else case e in #( e) ac_cv_lib_c_r_pthread_mutex_init=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 printf "%s\n" "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 printf %s "checking for building with threads... " >&6; } if test "${TCL_THREADS}" = 1; then printf "%s\n" "#define TCL_THREADS 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 printf "%s\n" "yes (default)" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&5 printf "%s\n" "$as_me: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&2;} fi ;; esac #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 printf %s "checking how to build libraries... " >&6; } # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; shared_ok=$enableval else case e in #( e) shared_ok=yes ;; esac fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi # Check whether --enable-stubs was given. if test ${enable_stubs+y} then : enableval=$enable_stubs; stubs_ok=$enableval else case e in #( e) stubs_ok=yes ;; esac fi if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5 printf "%s\n" "shared" >&6; } SHARED_BUILD=1 STUBS_BUILD=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5 printf "%s\n" "static" >&6; } SHARED_BUILD=0 printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then printf "%s\n" "#define USE_TCL_STUBS 1" >>confdefs.h printf "%s\n" "#define USE_TCLOO_STUBS 1" >>confdefs.h if test "${TEA_WINDOWINGSYSTEM}" != ""; then printf "%s\n" "#define USE_TK_STUBS 1" >>confdefs.h fi fi #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Step 0.a: Enable 64 bit support? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 printf %s "checking if 64bit support is requested... " >&6; } # Check whether --enable-64bit was given. if test ${enable_64bit+y} then : enableval=$enable_64bit; do64bit=$enableval else case e in #( e) do64bit=no ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 printf "%s\n" "$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 printf %s "checking if 64bit Sparc VIS support is requested... " >&6; } # Check whether --enable-64bit-vis was given. if test ${enable_64bit_vis+y} then : enableval=$enable_64bit_vis; do64bitVIS=$enableval else case e in #( e) do64bitVIS=no ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 printf "%s\n" "$do64bitVIS" >&6; } # Force 64bit on with VIS if test "$do64bitVIS" = "yes" then : do64bit=yes fi # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 printf %s "checking if compiler supports visibility \"hidden\"... " >&6; } if test ${tcl_cv_cc_visibility_hidden+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {} int main (void) { f(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_visibility_hidden=yes else case e in #( e) tcl_cv_cc_visibility_hidden=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 printf "%s\n" "$tcl_cv_cc_visibility_hidden" >&6; } if test $tcl_cv_cc_visibility_hidden = yes then : printf "%s\n" "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h printf "%s\n" "#define HAVE_HIDDEN 1" >>confdefs.h fi # Step 0.d: Disable -rpath support? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 printf %s "checking if rpath support is requested... " >&6; } # Check whether --enable-rpath was given. if test ${enable_rpath+y} then : enableval=$enable_rpath; doRpath=$enableval else case e in #( e) doRpath=yes ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 printf "%s\n" "$doRpath" >&6; } # Set the variable "system" to hold the name and version number # for the system. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version" >&5 printf %s "checking system version... " >&6; } if test ${tcl_cv_sys_version+y} then : printf %s "(cached) " >&6 else case e in #( e) # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 printf "%s\n" "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 printf "%s\n" "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Require ranlib early so we can override it in special cases below. # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g if test "$GCC" = yes then : CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" else case e in #( e) CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" ;; esac fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AR+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi AR=$ac_cv_prog_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_AR+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 printf "%s\n" "$ac_ct_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" if test "x$SHLIB_VERSION" = x then : SHLIB_VERSION="" else case e in #( e) SHLIB_VERSION=".$SHLIB_VERSION" ;; esac fi case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac do64bit_ok=yes fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[4-9]*) lflags="${lflags} -nodefaultlib:ucrt.lib" vars="ucrt.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 vars="bufferoverflowU.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$RC"; then ac_cv_prog_RC="$RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RC="${ac_tool_prefix}windres" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi RC=$ac_cv_prog_RC if test -n "$RC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 printf "%s\n" "$RC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RC"; then ac_ct_RC=$RC # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_RC"; then ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RC="windres" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_RC=$ac_cv_prog_ac_ct_RC if test -n "$ac_ct_RC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 printf "%s\n" "$ac_ct_RC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RC" = x; then RC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RC=$ac_ct_RC fi else RC="$ac_cv_prog_RC" fi CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 printf %s "checking for cross-compile version of gcc... " >&6; } if test ${ac_cv_cross+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef _WIN32 #error cross-compiler #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_cross=yes else case e in #( e) ac_cv_cross=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 printf "%s\n" "$ac_cv_cross" >&6; } if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) if test "$GCC" != "yes" then : # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 printf "%s\n" "Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes then : if test "$GCC" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else case e in #( e) do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" ;; esac fi fi if test "`uname -m`" = ia64 then : # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" if test "$GCC" = yes then : CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' else case e in #( e) CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' ;; esac fi LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' else case e in #( e) if test "$GCC" = yes then : SHLIB_LD='${CC} -shared -Wl,-bexpall' else case e in #( e) SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" ;; esac fi SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; esac fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 printf %s "checking for inet_ntoa in -lbind... " >&6; } if test ${ac_cv_lib_bind_inet_ntoa+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (void); int main (void) { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bind_inet_ntoa=yes else case e in #( e) ac_cv_lib_bind_inet_ntoa=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_bind_inet_ntoa" >&6; } if test "x$ac_cv_lib_bind_inet_ntoa" = xyes then : LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" if test "${TEA_PLATFORM}" = "unix" -a "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$(patsubst cyg%.dll,lib%.dll,\$@).a" else SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" fi EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 printf %s "checking for inet_ntoa in -lnetwork... " >&6; } if test ${ac_cv_lib_network_inet_ntoa+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (void); int main (void) { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_network_inet_ntoa=yes else case e in #( e) ac_cv_lib_network_inet_ntoa=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_network_inet_ntoa" >&6; } if test "x$ac_cv_lib_network_inet_ntoa" = xyes then : LIBS="$LIBS -lnetwork" fi ;; HP-UX-*.11.*) # Use updated header definitions where possible printf "%s\n" "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library if test "`uname -m`" = ia64 then : SHLIB_SUFFIX=".so" else case e in #( e) SHLIB_SUFFIX=".sl" ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char shl_load (void); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else case e in #( e) ac_cv_lib_dld_shl_load=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = yes then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi if test "$GCC" = yes then : SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else case e in #( e) CFLAGS="$CFLAGS -z" ;; esac fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" then : if test "$GCC" = yes then : case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ;; esac else case e in #( e) do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" ;; esac fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char shl_load (void); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else case e in #( e) ac_cv_lib_dld_shl_load=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : tcl_ok=yes else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = yes then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi if test "$GCC" = yes then : CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" else case e in #( e) case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" ;; esac fi ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes then : if test "$GCC" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} else case e in #( e) do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" ;; esac fi fi ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) if test "${TCL_THREADS}" = "1" then : # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS" fi ;; esac if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha" then : CFLAGS="$CFLAGS -mieee" fi if test $do64bit = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 printf %s "checking if compiler accepts -m64 flag... " >&6; } if test ${tcl_cv_cc_m64+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_m64=yes else case e in #( e) tcl_cv_cc_m64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 printf "%s\n" "$tcl_cv_cc_m64" >&6; } if test $tcl_cv_cc_m64 = yes then : CFLAGS="$CFLAGS -m64" do64bit_ok=yes fi fi # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. if test x"${USE_COMPAT}" != x then : CFLAGS="$CFLAGS -fno-inline" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" if test $do64bit = yes then : case `arch` in ppc) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 printf %s "checking if compiler accepts -arch ppc64 flag... " >&6; } if test ${tcl_cv_cc_arch_ppc64+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_arch_ppc64=yes else case e in #( e) tcl_cv_cc_arch_ppc64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 printf "%s\n" "$tcl_cv_cc_arch_ppc64" >&6; } if test $tcl_cv_cc_arch_ppc64 = yes then : CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes fi;; i386) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 printf %s "checking if compiler accepts -arch x86_64 flag... " >&6; } if test ${tcl_cv_cc_arch_x86_64+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_arch_x86_64=yes else case e in #( e) tcl_cv_cc_arch_x86_64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 printf "%s\n" "$tcl_cv_cc_arch_x86_64" >&6; } if test $tcl_cv_cc_arch_x86_64 = yes then : CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes fi;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 printf "%s\n" "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; esac else case e in #( e) # Check for combined 32-bit and 64-bit fat build if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) ' then : fat_32_64=yes fi ;; esac fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 printf %s "checking if ld accepts -search_paths_first flag... " >&6; } if test ${tcl_cv_ld_search_paths_first+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_ld_search_paths_first=yes else case e in #( e) tcl_cv_ld_search_paths_first=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 printf "%s\n" "$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes then : LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi if test "$tcl_cv_cc_visibility_hidden" != yes then : printf "%s\n" "#define MODULE_SCOPE __private_extern__" >>confdefs.h tcl_cv_cc_visibility_hidden=yes fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}" then : if test "${TEA_WINDOWINGSYSTEM}" = x11 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 printf %s "checking for 64-bit X11... " >&6; } if test ${tcl_cv_lib_x11_64+y} then : printf %s "(cached) " >&6 else case e in #( e) for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { XrmInitialize(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_lib_x11_64=yes else case e in #( e) tcl_cv_lib_x11_64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 printf "%s\n" "$tcl_cv_lib_x11_64" >&6; } fi if test "${TEA_WINDOWINGSYSTEM}" = aqua then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 printf %s "checking for 64-bit Tk... " >&6; } if test ${tcl_cv_lib_tk_64+y} then : printf %s "(cached) " >&6 else case e in #( e) for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { Tk_InitStubs(NULL, "", 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_lib_tk_64=yes else case e in #( e) tcl_cv_lib_tk_64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 printf "%s\n" "$tcl_cv_lib_tk_64" >&6; } fi # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 printf "%s\n" "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done fi fi ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy printf "%s\n" "#define _OE_SOCKETS 1" >>confdefs.h ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" if test "$SHARED_BUILD" = 1 then : SHLIB_LD='ld -shared -expect_unresolved "*"' else case e in #( e) SHLIB_LD='ld -non_shared -expect_unresolved "*"' ;; esac fi SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi if test "$GCC" = yes then : CFLAGS="$CFLAGS -mieee" else case e in #( e) CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" ;; esac fi # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` if test "$GCC" = yes then : LIBS="$LIBS -lpthread -lmach -lexc" else case e in #( e) CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; esac fi ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) if test "$GCC" = yes then : SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" else case e in #( e) SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ;; esac fi SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[0-6]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. printf "%s\n" "#define _REENTRANT 1" >>confdefs.h printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" if test "$GCC" = yes then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else case e in #( e) SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; esac fi ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. printf "%s\n" "#define _REENTRANT 1" >>confdefs.h printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes then : arch=`isainfo` if test "$arch" = "sparcv9 sparc" then : if test "$GCC" = yes then : if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} else case e in #( e) do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" ;; esac fi else case e in #( e) do64bit_ok=yes if test "$do64bitVIS" = yes then : CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" else case e in #( e) CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" ;; esac fi # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ;; esac fi else case e in #( e) if test "$arch" = "amd64 i386" then : if test "$GCC" = yes then : case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; esac else case e in #( e) do64bit_ok=yes case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac ;; esac fi else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} ;; esac fi ;; esac fi fi SHLIB_SUFFIX=".so" if test "$GCC" = yes then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "$do64bit_ok" = yes then : if test "$arch" = "sparcv9 sparc" then : # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" else case e in #( e) if test "$arch" = "amd64 i386" then : # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" fi ;; esac fi fi else case e in #( e) case $system in SunOS-5.[1-9][0-9]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ;; esac fi ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 printf %s "checking for ld accepts -Bexport flag... " >&6; } if test ${tcl_cv_ld_Bexport+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_ld_Bexport=yes else case e in #( e) tcl_cv_ld_Bexport=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 printf "%s\n" "$tcl_cv_ld_Bexport" >&6; } if test $tcl_cv_ld_Bexport = yes then : LDFLAGS="$LDFLAGS -Wl,-Bexport" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac if test "$do64bit" = yes -a "$do64bit_ok" = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 printf "%s\n" "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. if test "$GCC" = yes then : case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi if test "$tcl_cv_cc_visibility_hidden" != yes then : printf "%s\n" "#define MODULE_SCOPE extern" >>confdefs.h fi if test "$SHARED_LIB_SUFFIX" = "" then : # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = "" then : # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 printf %s "checking for SEH support in compiler... " >&6; } if test ${tcl_cv_seh+y} then : printf %s "(cached) " >&6 else case e in #( e) if test "$cross_compiling" = yes then : tcl_cv_seh=no else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } _ACEOF if ac_fn_c_try_run "$LINENO" then : tcl_cv_seh=yes else case e in #( e) tcl_cv_seh=no ;; esac fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 printf "%s\n" "$tcl_cv_seh" >&6; } if test "$tcl_cv_seh" = "no" ; then printf "%s\n" "#define HAVE_NO_SEH 1" >>confdefs.h fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 printf %s "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } if test ${tcl_cv_eh_disposition+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN int main (void) { EXCEPTION_DISPOSITION x; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_eh_disposition=yes else case e in #( e) tcl_cv_eh_disposition=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 printf "%s\n" "$tcl_cv_eh_disposition" >&6; } if test "$tcl_cv_eh_disposition" = "no" ; then printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 printf %s "checking for winnt.h that ignores VOID define... " >&6; } if test ${tcl_cv_winnt_ignore_void+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main (void) { CHAR c; SHORT s; LONG l; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_winnt_ignore_void=yes else case e in #( e) tcl_cv_winnt_ignore_void=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 printf "%s\n" "$tcl_cv_winnt_ignore_void" >&6; } if test "$tcl_cv_winnt_ignore_void" = "yes" ; then printf "%s\n" "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 printf %s "checking for cast to union support... " >&6; } if test ${tcl_cv_cast_to_union+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { union foo { int i; double d; }; union foo f = (union foo) (int) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_cast_to_union=yes else case e in #( e) tcl_cv_cast_to_union=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 printf "%s\n" "$tcl_cv_cast_to_union" >&6; } if test "$tcl_cv_cast_to_union" = "yes"; then printf "%s\n" "#define HAVE_CAST_TO_UNION 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" if test "x$ac_cv_header_stdbool_h" = xyes then : printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h fi # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 printf %s "checking for required early compiler flags... " >&6; } tcl_flags="" if test ${tcl_cv_flag__isoc99_source+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__isoc99_source=no else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main (void) { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__isoc99_source=yes else case e in #( e) tcl_cv_flag__isoc99_source=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then printf "%s\n" "#define _ISOC99_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if test "${TCL_MAJOR_VERSION}" -ne 8 ; then if test ${tcl_cv_flag__file_offset_bits+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__file_offset_bits=no else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include int main (void) { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__file_offset_bits=yes else case e in #( e) tcl_cv_flag__file_offset_bits=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h tcl_flags="$tcl_flags _FILE_OFFSET_BITS" fi fi if test "x${tcl_flags}" = "x" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 printf "%s\n" "${tcl_flags}" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 printf %s "checking for 64-bit integer type... " >&6; } if test ${tcl_cv_type_64bit+y} then : printf %s "(cached) " >&6 else case e in #( e) tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { __int64 value = (__int64) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_type_64bit=__int64 else case e in #( e) tcl_type_64bit="long long" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_type_64bit=${tcl_type_64bit} fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi if test "${tcl_cv_type_64bit}" = none ; then printf "%s\n" "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 printf "%s\n" "using Tcl header defaults" >&6; } else printf "%s\n" "#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 printf "%s\n" "${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5 printf %s "checking for 64-bit time_t... " >&6; } if test ${tcl_cv_time_t_64+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_time_t_64=yes else case e in #( e) tcl_cv_time_t_64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5 printf "%s\n" "$tcl_cv_time_t_64" >&6; } if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5 printf %s "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; } if test ${tcl_cv__time_bits+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _TIME_BITS 64 #include int main (void) { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv__time_bits=yes else case e in #( e) tcl_cv__time_bits=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5 printf "%s\n" "$tcl_cv__time_bits" >&6; } if test "x${tcl_cv__time_bits}" = "xyes" ; then printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 printf %s "checking for struct dirent64... " >&6; } if test ${tcl_cv_struct_dirent64+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct dirent64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_struct_dirent64=yes else case e in #( e) tcl_cv_struct_dirent64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 printf "%s\n" "$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5 printf %s "checking for DIR64... " >&6; } if test ${tcl_cv_DIR64+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_DIR64=yes else case e in #( e) tcl_cv_DIR64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5 printf "%s\n" "$tcl_cv_DIR64" >&6; } if test "x${tcl_cv_DIR64}" = "xyes" ; then printf "%s\n" "#define HAVE_DIR64 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 printf %s "checking for struct stat64... " >&6; } if test ${tcl_cv_struct_stat64+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { struct stat64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_struct_stat64=yes else case e in #( e) tcl_cv_struct_stat64=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 printf "%s\n" "$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_STAT64 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "open64" "ac_cv_func_open64" if test "x$ac_cv_func_open64" = xyes then : printf "%s\n" "#define HAVE_OPEN64 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "lseek64" "ac_cv_func_lseek64" if test "x$ac_cv_func_lseek64" = xyes then : printf "%s\n" "#define HAVE_LSEEK64 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 printf %s "checking for off64_t... " >&6; } if test ${tcl_cv_type_off64_t+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { off64_t offset; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_type_off64_t=yes else case e in #( e) tcl_cv_type_off64_t=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then printf "%s\n" "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 printf %s "checking for build with symbols... " >&6; } # Check whether --enable-symbols was given. if test ${enable_symbols+y} then : enableval=$enable_symbols; tcl_ok=$enableval else case e in #( e) tcl_ok=no ;; esac fi if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 printf "%s\n" "yes (standard debugging)" >&6; } fi fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 printf "%s\n" "enabled symbols mem debugging" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 printf "%s\n" "enabled $tcl_ok debugging" >&6; } fi fi #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- printf "%s\n" "#define USE_TCL_STUBS 1" >>confdefs.h #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep -e" >&5 printf %s "checking for egrep -e... " >&6; } if test ${ac_cv_path_EGREP_TRADITIONAL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$EGREP_TRADITIONAL"; then ac_path_EGREP_TRADITIONAL_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue # Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found. # Check for GNU $ac_path_EGREP_TRADITIONAL case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #( *GNU*) ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl" "$ac_path_EGREP_TRADITIONAL" -E 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_TRADITIONAL_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then : fi else ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL fi if test "$ac_cv_path_EGREP_TRADITIONAL" then : ac_cv_path_EGREP_TRADITIONAL="$ac_cv_path_EGREP_TRADITIONAL -E" else case e in #( e) if test -z "$EGREP_TRADITIONAL"; then ac_path_EGREP_TRADITIONAL_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue # Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found. # Check for GNU $ac_path_EGREP_TRADITIONAL case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #( *GNU*) ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl" "$ac_path_EGREP_TRADITIONAL" 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_TRADITIONAL_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL fi ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL" >&5 printf "%s\n" "$ac_cv_path_EGREP_TRADITIONAL" >&6; } EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP_TRADITIONAL "manifest needed" >/dev/null 2>&1 then : # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" CLEANFILES="$CLEANFILES *.manifest" fi rm -rf conftest* MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- if test "$TEA_PLATFORM" = "unix"; then PACKAGE_LIB_PREFIX8="lib" if test "$EXEEXT" = ".exe" -a "$SHARED_BUILD" != "0"; then PACKAGE_LIB_PREFIX9="cygtcl9" else PACKAGE_LIB_PREFIX9="libtcl9" fi else PACKAGE_LIB_PREFIX8="" PACKAGE_LIB_PREFIX9="tcl9" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h printf "%s\n" "#define TK_MAJOR_VERSION 8" >>confdefs.h fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker understands --disable-high-entropy-va" >&5 printf %s "checking if the linker understands --disable-high-entropy-va... " >&6; } if test ${tcl_cv_ld_high_entropy+y} then : printf %s "(cached) " >&6 else case e in #( e) hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Wl,--disable-high-entropy-va" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_ld_high_entropy=yes else case e in #( e) tcl_cv_ld_high_entropy=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_high_entropy" >&5 printf "%s\n" "$tcl_cv_ld_high_entropy" >&6; } if test $tcl_cv_ld_high_entropy = yes; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--disable-high-entropy-va" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi # Substitute STUB_LIB_FILE in case package creates a stub library too. #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 printf %s "checking for tclsh... " >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 printf "%s\n" "${TCLSH_PROG}" >&6; } #TEA_PROG_WISH #-------------------------------------------------------------------- # Temporary support for old code that still uses deprecated options # and mechanisms #-------------------------------------------------------------------- # Tcl9 defines MODULE_SCOPE, but autotools override it, so we try # to prevent to have warnings for preprocessor symbols being redefined # Check whether --enable-deprecated-code was given. if test ${enable_deprecated_code+y} then : enableval=$enable_deprecated_code; curl_depr_list=$enableval else case e in #( e) curl_depr_list=no ;; esac fi curl_pre_7_56_depr=no curl_pre_7_84_depr=no curl_pre_7_11_1_depr=no curl_pre_8_17_0_depr=no case $curl_depr_list in #( no|false|none) : : ;; #( yes|true|all) : curl_pre_7_56_depr=yes curl_pre_7_84_depr=yes curl_pre_7_11_1_depr=yes curl_pre_8_17_0_depr=yes ;; #( *) : curl_depr_list=`printf "%s\n" "$curl_depr_list" | tr -d ' '` if test "x$curl_depr_list" != x; then curl_depr_words=`printf "%s\n" "$curl_depr_list" | tr ',' ' '` for curl_ver in $curl_depr_words; do curl_ver=${curl_ver#v} case $curl_ver in #( 7.56) : curl_pre_7_56_depr=yes ;; #( 7.84) : curl_pre_7_84_depr=yes ;; #( 7.11.1) : curl_pre_7_11_1_depr=yes ;; #( 8.17.0) : curl_pre_8_17_0_depr=yes ;; #( *) : as_fn_error $? "Unsupported value '$curl_ver' for --enable-deprecated-code. Allowed: v7.56,v7.84,v7.11.1,v8.17.0 " "$LINENO" 5 ;; #( *) : ;; esac done fi ;; #( *) : ;; esac if test "x$curl_pre_7_56_depr" = xyes; then printf "%s\n" "#define CURL_PRE_7_56_DEPR 1" >>confdefs.h fi if test "x$curl_pre_7_84_depr" = xyes; then printf "%s\n" "#define CURL_PRE_7_84_DEPR 1" >>confdefs.h fi if test "x$curl_pre_7_11_1_depr" = xyes; then printf "%s\n" "#define CURL_PRE_7_11_1_DEPR 1" >>confdefs.h fi if test "x$curl_pre_8_17_0_depr" = xyes; then printf "%s\n" "#define CURL_PRE_8_17_0_DEPR 1" >>confdefs.h fi curl_depr_enabled= test "x$curl_pre_7_56_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v7.56" test "x$curl_pre_7_84_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v7.84" test "x$curl_pre_7_11_1_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v7.11.1" test "x$curl_pre_8_17_0_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v8.17.0" test "x$curl_depr_enabled" = x && curl_depr_enabled="none" if test "$curl_depr_enabled" = none; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: no deprecated curl code enabled" >&5 printf "%s\n" "$as_me: no deprecated curl code enabled" >&6;} else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: deprecated curl code enabled for: $curl_depr_enabled" >&5 printf "%s\n" "$as_me: deprecated curl code enabled for: $curl_depr_enabled" >&6;} fi #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- ac_config_files="$ac_config_files Makefile pkgIndex.tcl tests/tcl_conf.tcl doc/tclcurl.n.md doc/tclcurl_share.n.md doc/tclcurl_multi.n.md" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # 'ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* 'ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # 'set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # 'set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by TclCurl $as_me 8.0.3, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ '$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ TclCurl config.status 8.0.3 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" Copyright (C) 2023 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: '$1' Try '$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: '$1' Try '$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; "tests/tcl_conf.tcl") CONFIG_FILES="$CONFIG_FILES tests/tcl_conf.tcl" ;; "doc/tclcurl.n.md") CONFIG_FILES="$CONFIG_FILES doc/tclcurl.n.md" ;; "doc/tclcurl_share.n.md") CONFIG_FILES="$CONFIG_FILES doc/tclcurl_share.n.md" ;; "doc/tclcurl_multi.n.md") CONFIG_FILES="$CONFIG_FILES doc/tclcurl_multi.n.md" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to '$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with './config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with './config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script 'defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain ':'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is 'configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when '$srcdir' = '.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi tclcurl-ng-8.0.3/configure.ac000066400000000000000000000362101522613063100160630ustar00rootroot00000000000000#!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. #----------------------------------------------------------------------- # Sample configure.in for Tcl Extensions. The only places you should # need to modify this file are marked by the string __CHANGE__ #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # Set your package name and version numbers here. # # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- AC_INIT([TclCurl],[m4_esyscmd_s([cat VERSION])],[massimo.manghi@rivetweb.org],[tclcurl-ng]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_INIT([3.9]) AC_CONFIG_AUX_DIR(tclconfig) AC_CONFIG_HEADERS([config.h]) #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- TEA_PREFIX #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create # the basic setup necessary to compile executables. #----------------------------------------------------------------------- TEA_SETUP_COMPILER #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- TEA_ADD_SOURCES([tclcurl.c tcl_size.c curl_mime.c curl_setopts.c curl_getinfo.c ftp.c curl_utils.c multi.c]) TCLCURL_SCRIPTS=tclcurl.tcl AC_SUBST(TCLCURL_SCRIPTS) AC_PATH_PROG([LOWDOWN],[lowdown],[]) AC_PATH_PROG([PANDOC],[pandoc],[]) AC_ARG_WITH([md-converter], [ --with-md-converter markdown-to-man converter to use: lowdown, pandoc, or auto], [ case "$withval" in auto) md_converter_choice=auto ;; lowdown) if test "x$LOWDOWN" = x; then AC_MSG_ERROR([--with-md-converter=lowdown requested, but lowdown was not found]) fi md_converter_choice=lowdown ;; pandoc) if test "x$PANDOC" = x; then AC_MSG_ERROR([--with-md-converter=pandoc requested, but pandoc was not found]) fi md_converter_choice=pandoc ;; *) AC_MSG_ERROR([bad value '$withval' for --with-md-converter: must be lowdown, pandoc, or auto]) ;; esac ],[ md_converter_choice=auto ]) if test "x$md_converter_choice" = xauto; then if test "x$LOWDOWN" != x; then md_converter_choice=lowdown elif test "x$PANDOC" != x; then md_converter_choice=pandoc else md_converter_choice=none fi fi case "$md_converter_choice" in lowdown) TCLCURL_DOC_GEN="$LOWDOWN -s -Tman -o" TCLCURL_HTML_GEN="$LOWDOWN -s -Thtml -o" ;; pandoc) TCLCURL_DOC_GEN="$PANDOC -f markdown -t man -o" TCLCURL_HTML_GEN="$PANDOC -f markdown -t html -o" ;; none) TCLCURL_DOC_GEN= TCLCURL_HTML_GEN= ;; esac AC_SUBST(TCLCURL_DOC_GEN) AC_SUBST(TCLCURL_HTML_GEN) #-------------------------------------------------------------------- # Find libcurl, if it's not present, it makes no sense to compile # this. #-------------------------------------------------------------------- AC_ARG_WITH(curlprefix, [ --with-curlprefix base directory for the cURL install '/usr', '/usr/local',...], [ curlprefix=$withval curlpath=$curlprefix/bin AC_CHECK_PROG(curl,curl,yes,no,$curlpath) if test "x$curl" = xno ; then AC_MSG_ERROR([can not find cURL in $curlpath]) fi ],[ AC_CHECK_PROG(curl,curl-config,yes,no) if test "x$curl" = xno ; then AC_MSG_ERROR([can not find cURL or libcurl... go to http://curl.haxx.se/ to download and then install it first]) else curlprefix=`curl-config --prefix` curlpath=$curlprefix/bin fi ]) AC_ARG_WITH(curlinclude, [ --with-curlinclude directory containing the public libcurl header files],[ TEA_ADD_INCLUDES([-I$withval]) curlinclude=$withval ], [ TEA_ADD_INCLUDES([-I$curlprefix/include]) curlinclude=$curlprefix/include ]) AC_CHECK_HEADER(curl/curl.h,headercurl=yes, headercurl=no) if test "x$headercurl" = xno ; then AC_MSG_CHECKING([checking for headers at $curlinclude]) if test [ ! -r $curlinclude/curl/curl.h ] ; then AC_MSG_ERROR([cURL headers not found, you may need to install a curl-devel package]) fi AC_MSG_RESULT([found]) fi AC_ARG_WITH(libcurl, [ --with-libcurl directory containing libcurl],[ TEA_ADD_LIBS([-L$withval]) ], [ TEA_ADD_LIBS([-L$curlprefix/lib]) ]) AC_MSG_CHECKING([if libcurl version is recent enough]) CURL_VERSION=`$curlpath/curl-config --checkfor 7.21.7` if test "${CURL_VERSION}" != "" ; then echo ${CURL_VERSION} AC_MSG_ERROR([libcurl version too old, please upgrade]) fi AC_MSG_RESULT(yes) # We need to modify this original line to strip a few things # See: http://lists.debian.org/debian-devel-announce/2006/09/msg00018.html TEA_ADD_LIBS([`$curlpath/curl-config --libs|sed \ -e 's/\-lkrb5\>//g' \ -e 's/\-lgssapi_krb5//g' \ -e 's/\-lk5crypto//g' \ -e 's/\-lkrb5support//g' \ `]) #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. #CLEANFILES="pkgIndex.tcl" if test "${TEA_PLATFORM}" = "windows" ; then AC_DEFINE(BUILD_sample, 1, [Build windows export dll]) CLEANFILES="$CLEANFILES *.lib *.dll *.exp *.ilk *.pdb vc*.pch" #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) else # Ensure no empty else clauses : #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) fi AC_SUBST(CLEANFILES) #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- TEA_PUBLIC_TCL_HEADERS #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- TEA_ENABLE_THREADS #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- TEA_ENABLE_SHARED #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- TEA_CONFIG_CFLAGS #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- TEA_ENABLE_SYMBOLS #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- TEA_MAKE_LIB #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- TEA_PROG_TCLSH #TEA_PROG_WISH #-------------------------------------------------------------------- # Temporary support for old code that still uses deprecated options # and mechanisms #-------------------------------------------------------------------- dnl ---------------------------------------------------------------------- dnl CURL_ENABLE_DEPRECATED_CODE dnl dnl Usage (in configure.ac): dnl AC_CONFIG_HEADERS([config.h]) dnl CURL_ENABLE_DEPRECATED_CODE dnl ---------------------------------------------------------------------- AC_DEFUN([CURL_ENABLE_DEPRECATED_CODE], [ dnl Make sure symbols have descriptions even if conditionally defined AH_TEMPLATE([CURL_PRE_7_56_DEPR], [Define to 1 to enable deprecated code for CURL versions prior to 7.56.]) AH_TEMPLATE([CURL_PRE_7_84_DEPR], [Define to 1 to enable deprecated code for CURL versions prior to 7.84.]) AH_TEMPLATE([CURL_PRE_7_11_1_DEPR], [Define to 1 to enable deprecated code for CURL versions prior to 7.11.1.]) AH_TEMPLATE([CURL_PRE_8_17_0_DEPR], [Define to 1 to enable deprecated code for CURL versions prior to 8.17.0.]) AC_ARG_ENABLE([deprecated-code], [AS_HELP_STRING( [--enable-deprecated-code=LIST], [Enable deprecated code for selected CURL versions. LIST is a comma-separated list of: v7.56,v7.84,v7.11.1,v8.17.0. Use --enable-deprecated-code (or =all) to enable all; default is none.] )], [curl_depr_list=$enableval], [curl_depr_list=no] ) curl_pre_7_56_depr=no curl_pre_7_84_depr=no curl_pre_7_11_1_depr=no curl_pre_8_17_0_depr=no AS_CASE([$curl_depr_list], [no|false|none], [:], [yes|true|all], [ curl_pre_7_56_depr=yes curl_pre_7_84_depr=yes curl_pre_7_11_1_depr=yes curl_pre_8_17_0_depr=yes ], [*], [ dnl Remove spaces/tabs around commas etc. (portable enough for configure) curl_depr_list=`AS_ECHO(["$curl_depr_list"]) | tr -d ' '` dnl Empty list means "enable none" if test "x$curl_depr_list" != x; then curl_depr_words=`AS_ECHO(["$curl_depr_list"]) | tr ',' ' '` for curl_ver in $curl_depr_words; do dnl Accept optional leading "v" curl_ver=${curl_ver#v} AS_CASE([$curl_ver], [7.56], [curl_pre_7_56_depr=yes], [7.84], [curl_pre_7_84_depr=yes], [7.11.1], [curl_pre_7_11_1_depr=yes], [8.17.0], [curl_pre_8_17_0_depr=yes], [*], [AC_MSG_ERROR( [Unsupported value '$curl_ver' for --enable-deprecated-code. Allowed: v7.56,v7.84,v7.11.1,v8.17.0] )] ) done fi ] ) if test "x$curl_pre_7_56_depr" = xyes; then AC_DEFINE([CURL_PRE_7_56_DEPR], [1]) fi if test "x$curl_pre_7_84_depr" = xyes; then AC_DEFINE([CURL_PRE_7_84_DEPR], [1]) fi if test "x$curl_pre_7_11_1_depr" = xyes; then AC_DEFINE([CURL_PRE_7_11_1_DEPR], [1]) fi if test "x$curl_pre_8_17_0_depr" = xyes; then AC_DEFINE([CURL_PRE_8_17_0_DEPR], [1]) fi dnl Optional: show what was enabled curl_depr_enabled= test "x$curl_pre_7_56_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v7.56" test "x$curl_pre_7_84_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v7.84" test "x$curl_pre_7_11_1_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v7.11.1" test "x$curl_pre_8_17_0_depr" = xyes && curl_depr_enabled="$curl_depr_enabled v8.17.0" test "x$curl_depr_enabled" = x && curl_depr_enabled="none" if test "$curl_depr_enabled" = none; then AC_MSG_NOTICE([no deprecated curl code enabled]) else AC_MSG_NOTICE([deprecated curl code enabled for: $curl_depr_enabled]) fi ]) # Tcl9 defines MODULE_SCOPE, but autotools override it, so we try # to prevent to have warnings for preprocessor symbols being redefined AH_BOTTOM([#ifdef MODULE_SCOPE # undef MODULE_SCOPE #endif ]) CURL_ENABLE_DEPRECATED_CODE #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- AC_CONFIG_FILES([Makefile pkgIndex.tcl tests/tcl_conf.tcl doc/tclcurl.n.md doc/tclcurl_share.n.md doc/tclcurl_multi.n.md]) AC_OUTPUT tclcurl-ng-8.0.3/doc/000077500000000000000000000000001522613063100143405ustar00rootroot00000000000000tclcurl-ng-8.0.3/doc/OpenSSL-LICENSE.txt000066400000000000000000000142071522613063100174500ustar00rootroot00000000000000 LICENSE ISSUES ============== The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the OpenSSL License and the original SSLeay license apply to the toolkit. See below for the actual license texts. Actually both licenses are BSD-style Open Source licenses. In case of any license issues related to OpenSSL please contact openssl-core@openssl.org. OpenSSL License --------------- /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ Original SSLeay License ----------------------- /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ tclcurl-ng-8.0.3/doc/aolserver.txt000066400000000000000000000050021522613063100171000ustar00rootroot00000000000000There are a number of issues with namespaces in AOLserver 3.x, which I believe are fixed in 4.0, which should be released within a few months. But in the meantime this is what we've had to do for AOLserver 3.2 on Windows 2000. Alex Khassin 1. Under [ns_library shared] directory, create a directory called packages. 2. Register this directory as a Tcl module in nsd.tcl: ns_section "ns/server/${servername}/modules" ns_param packages Tcl 3. Place each package into a subdirectory of the same name as the package name (i.e. [ns_library shared]/packages/TclCurl) 4. Copy S:\NaviSoft\Server\modules\tcl\am\packages.init.tcl to the [ns_library shared]/packages directory and rename to just init.tcl 5. Under AOLserver 4.x (and hopefully in 3.5.x) add to the bottom of this file appropriate commands to register each package: _am_pregister shared 6. In your code, when you need to use a particular package, instead of 'package require ', execute 'am_pinit ' 7. This will use the existing package registration under AOLserver 4.x and, under AOLserver 3.2, it will first register the package in this interpreter and then use it. 8. This is necessary because in AOLserver 3.2, namespaces aren't properly imported into child interpreters. Currently dnscrub.com is set up like this for TclCurl and it works. Example usage: am_pinit TclCurl curl::transfer -url http://am.net/index.htm -file d:/test.htm FYI, the code for am_pinit and _am_pregister procs: proc am_pinit {package} { # AOLserver 3.2 package/namespace-handling is broken # (namespace/packages don't get imported into child interpreters) # so use this workaround proc instead of 'package require' to # load the package into the current interpreter # (this is obviously slower than copying from master interpeter) # Package names are case-sensitive! # Returns the version of the loaded package set library shared if {[lsearch -exact [package names] $package] == -1} { ns_log Notice "packages: registering $library/$package" _am_pregister $library $package } package require $package } proc _am_pregister {library package} { # Registers the package. library is 'shared' or 'private' set dir [ns_library $library]/packages/$package source $dir/pkgIndex.tcl } tclcurl-ng-8.0.3/doc/tclcurl.html000066400000000000000000003500161522613063100167030ustar00rootroot00000000000000 TclCurl

NAME

TclCurl - Transfer data to and from URLs using FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS, and GOPHER.

SYNOPSIS

curl::init
curl::transfer ?options?
curl::version
curl::escape url
curl::unescape url
curl::curlConfig option
curl::versioninfo option
curl::easystrerror errorCode
curlHandle configure ?options?
curlHandle perform
curlHandle getinfo curlinfo_option
curlHandle cleanup
curlHandle reset
curlHandle duphandle
curlHandle pause
curlHandle resume

DESCRIPTION

The TclCurl extension gives Tcl programmers access to the libcurl library written by Daniel Stenberg. With TclCurl, you can download from URLs, upload to them, and perform many other network transfer operations. For more information, see http://curl.haxx.se.

curl::init

This procedure must be called first. It returns a curlHandle, which you use to invoke TclCurl procedures. Calling init initializes TclCurl, and each call to init MUST have a corresponding call to cleanup when the operation is complete.

You should perform all sequential file transfers using the same curlHandle. This allows TclCurl to reuse persistent connections when possible.

RETURN VALUE

The curlHandle to use.

curlHandle configure ?OPTIONS?

configure

is used to set the options for a transfer. Most operations in TclCurl have default behavior, and you can change that behavior by setting the appropriate options as documented. Each option is specified as the option followed by a parameter.

Notes:

The options set with this procedure apply to subsequent data transfers performed when you invoke perform.

The options are not reset between transfers (except where noted), so if you want subsequent transfers with different options, you must change them between the transfers. You can optionally reset all options back to the internal default with curlHandle reset.

curlHandle is the value returned by the curl::init call.

OPTIONS

BEHAVIOUR OPTIONS

-verbose

Set this option to 1 to make the library display detailed information about its operations. This option is useful when debugging libcurl and protocol-related problems.

You will rarely want to enable this in production, but it is often helpful when debugging or reporting problems. Another useful debugging option is

-debugproc

-header

Set this option to 1 to include headers in the body output. This is relevant only for protocols that actually send headers before the data, such as HTTP.

-noprogress

Set this option to 1 to disable the progress meter completely. It also prevents progressproc from being called.

-nosignal

Set this option to 1 to make TclCurl avoid functions that install signal handlers or cause signals to be sent to the process. This option exists mainly so that multi-threaded Unix applications can still use timeout options without risking signal-related side effects.

If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while name resolution is in progress. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which allows proper timeouts for name resolution without signals.

Setting nosignal to 1 makes libcurl stop asking the system to ignore SIGPIPE signals. Such signals may otherwise be sent by the system when data is written to a socket that has been closed by the peer. libcurl tries to avoid triggering SIGPIPE, but some operating systems provide no reliable way to prevent it, and even on those that do, some corner cases remain. In addition, using ntlm_Wb authentication may cause a SIGCHLD signal to be raised.

-wildcard

Set this option to 1 to transfer multiple files that match a file name pattern. The pattern can be specified as part of the -url option, using an fnmatch-like pattern (shell pattern matching) in the last part of the URL, that is, the file name.

By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function with the -fnmatchproc option.

At present, this feature is supported only for FTP downloads.

A brief introduction of its syntax follows:

  • * - ASTERISK

ftp://example.com/some/path/***.txt** (for all .txt files from the root directory) - ? - QUESTION MARK

The question mark matches any single character.

ftp://example.com/some/path/**photo?.jpeg** - [ - BRACKET EXPRESSION

The left bracket opens a bracket expression. The question mark and asterisk have no special meaning in a bracket expression. Each bracket expression ends by the right bracket and matches exactly one character. Some examples follow:

[a-zA-Z0-9] or [f-gF-G] - character interval

[abc] - character enumeration

[^abc] or [!abc] - negation

[[:name:]] class expression. Supported classes are alnum,lower, space, alpha, digit, print, upper, blank, graph, xdigit.

[][-!^] - special case - matches only ‘-’, ‘]’, ‘[‘, ‘!’ or ‘^’. These characters have no special purpose.

[\[\]\\] - escape syntax. Matches ‘[‘, ‘]’ or ‘\‘.

Using the rules above, a file name pattern can be constructed:

ftp://example.com/some/path/**[a-z[:upper:]\\\\].jpeg**

CALLBACK OPTIONS

-writeproc

Sets a Tcl procedure that TclCurl invokes whenever received data is available to be handled. The callback procedure must have a single argument. When the procedure is invoked, that argument refers to the contents of a data buffer managed by libcurl.

NOTE: The amount of data passed on each invocation is not fixed. The callback may be invoked with an empty buffer, or with a buffer containing a large amount of data.

-file

File in which the transferred data will be saved.

-readproc

Sets a Tcl procedure that TclCurl calls whenever it needs to read data to send to the peer. The procedure must take one parameter, which contains the maximum number of bytes to read. It should return the actual number of bytes read, or 0 if you want to stop the transfer.

If you stop the current transfer by returning 0 prematurely, for example after indicating that you would upload N bytes but uploading fewer than N, the server may appear to hang while waiting for the remaining data.

When doing TFTP uploads, you must return exactly the amount of data requested by the callback. Otherwise, the server may treat it as the final packet and end the transfer.

-infile

File from which the data will be transferred.

-progressproc

Name of the Tcl procedure that TclCurl invokes at regular intervals during an operation, roughly once per second or more often, whether or not data is currently being transferred. Unknown or unused argument values passed to the callback are set to zero. For example, if you only download data, the upload size remains 0. The procedure must have the following prototype:

proc ProgressCallback {dltotal dlnow ultotal ulnow}

For this option to work, you must set the -noprogress option to 0. Setting this option to the empty string restores the original progress function.

If you transfer data with the multi interface, this procedure will not be called during periods of idleness unless you call the appropriate procedure that performs transfers.

You can pause and resume a transfer from within this procedure using the pause and resume commands.

-writeheader

Pass the file name to which the header part of the received data will be written. Headers are written to this file one by one, and only complete lines are written. This makes header parsing straightforward.

See also the -headervar option to get the headers into an array.

-debugproc

Name of the procedure that receives the debug data produced by the -verbose option. The callback procedure must have two arguments:

debugProc {infoType data}

The infoType argument identifies the kind of debug information: 0 text, 1 incoming header, 2 outgoing header, 3 incoming data, 4 outgoing data, 5 incoming SSL data, and 6 outgoing SSL data. The data argument contains the corresponding data buffer.

-chunkbgnproc

Name of the procedure that is called before a file is transferred by FTP. The callback procedure must have one argument:

ChunkBgnProc {remains}

The remains argument is the number of files left to be transferred or skipped.

This callback makes sense only when using the -wildcard option.

-chunkbgnvar

Name of the variable in the global scope that will contain the data for the file about to be transferred. If you do not use this option, ::fileData is used.

The available data is: filename, filetype (file, directory, symlink, device block, device char, named pipe, socket, door, or error if it could not be identified), time, perm, uid, gid, size, hardlinks, and flags.

-chunkendproc

Name of the procedure that is called after a file has been transferred or skipped by FTP. The callback procedure takes no arguments:

ChunkEndProc {}

It should return 0 if everything is fine and 1 if an error occurred.

-fnmatchProc

Name of the procedure that is called instead of the internal wildcard matching function. The callback procedure must have two arguments:

FnMatchProc {pattern string}

The pattern argument contains the pattern to be matched. The string argument contains the candidate string. The procedure must return 0 if the string matches the pattern and 1 otherwise.

ERROR OPTIONS

-errorbuffer

Pass the name of a variable in which TclCurl may store human-readable error messages. This can provide more information than the command return code alone.

-stderr

Pass a file name. TclCurl uses this stream instead of stderr when reporting errors.

-failonerror

Set this option to 1 to make the transfer fail if the returned HTTP status code is 400 or greater. By default, TclCurl returns the page normally and does not treat such status codes as transfer errors.

This behavior is not fail-safe, and in some cases non-successful response codes may still pass through, especially when authentication is involved, as with status codes 401 and 407.

Some header data may be transferred before this condition is detected. For example, a 100-continue response may be received for a POST or PUT request before a subsequent 401 or 407 response is returned.

NETWORK OPTIONS

-url

The URL to use for the transfer.

If the URL does not include a protocol part, such as http:// or ftp://, TclCurl attempts to guess the protocol from the host name. If the protocol specified in the URL is not supported, TclCurl returns the unsupported protocol error when you call perform. Use curl::versioninfo for detailed information about the supported protocols.

Starting with version 7.22.0, the fragment part of the URI is no longer sent as part of the path, unlike earlier versions.

NOTE: This is the only option that must be set before perform is called.

-protocols

Pass a lowercase list of protocols to limit which protocols TclCurl may use for the transfer. This allows a TclCurl build that supports a wide range of protocols to be restricted for specific transfers to a subset of them.

Accepted protocols are http, https, ftp, ftps, scp, sftp, telnet, ldap, ldaps, dict, file, tftp, imap, imaps, pop, pop3, smtp, smtps, gopher, and all.

-redirprotocols

Pass a lowercase list of accepted protocols to limit which protocols TclCurl may use when following a redirect with -followlocation enabled. This allows specific transfers to be restricted to a subset of protocols for redirections.

By default, TclCurl allows all protocols except FILE and SCP. This differs from versions before 7.19.4, which would follow redirects to all supported protocols unconditionally.

-proxy

If you need to use an HTTP proxy, set the proxy string with this option. To specify a port number in the string, append :[port] to the end of the host name. The proxy string may be prefixed with [protocol]://, although such a prefix is ignored unless noted otherwise below.

When you configure an HTTP proxy, TclCurl transparently converts operations to HTTP even if you specify an FTP URL or another protocol. This may affect which library features are available. For example, quote and similar FTP-specific features do not work unless you tunnel through the HTTP proxy. Such tunneling is enabled with -proxytunnel.

TclCurl respects the environment variables http_proxy, ftp_proxy, all_proxy, and others of the same kind, if they are set. Using this option overrides any such environment variables.

Setting the proxy string to "" explicitly disables proxy use, even if a corresponding environment variable is set.

The proxy host string can be specified in the same way as the proxy environment variables, including a protocol prefix such as http:// and embedded user name and password information.

Since 7.22.0, the proxy string may include a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://, socks5://, or socks5h:// to request a specific SOCKS version. The last form enables SOCKS5 and asks the proxy to perform name resolution. If no protocol is specified, and for http:// and all other prefixes, the proxy is treated as an HTTP proxy.

-proxyport

Use this option to set the proxy port unless it is already specified in the proxy string passed with -proxy. If not specified, TclCurl uses port 1080 by default.

-proxytype

Pass the proxy type. Available values are http, http1.0, socks4, socks4a, socks5, and socks5h. The default is http.

If you set it to http1.0, it will only affect how libcurl speaks to a proxy when CONNECT is used. The HTTP version used for ordinary HTTP requests is instead controlled by httpversion.

-noproxy

Pass a string containing a comma-separated list of hosts that should not use a proxy, if one is specified. The only wildcard is a single * character, which matches all hosts and effectively disables the proxy. Each name in this list is matched either as a domain containing the host name, or as the host name itself. For example, local.com matches local.com, local.com:80, and www.local.com, but not www.notlocal.com.

-httpproxytunnel

Set this option to 1 to tunnel all non-HTTP operations through the given HTTP proxy. Using a proxy and tunneling through a proxy are different behaviors. This option should be enabled only when that distinction is required.

-socks5gssapiservice

Pass the service name. The default service name for a SOCKS5 server is rcmd/server-fqdn. This option allows you to change it.

-socks5gssapinec

Pass 1 to enable this option or 0 to disable it. As part of the GSSAPI negotiation, a protection mode is negotiated. RFC 1961 specifies in sections 4.3 and 4.4 that this exchange should be protected, but the NEC reference implementation does not do so. When enabled, this option allows the protection mode negotiation to be exchanged unprotected.

-interface

Pass the interface name to use as the outgoing network interface. The name may be an interface name, an IP address, or a host name.

-localport

Sets the local port number of the socket used for the connection. This can be used together with -interface, and it is recommended to use -localportrange as well when this option is set. Valid port numbers are 1 through 65535.

-localportrange

Number of attempts TclCurl should make to find a working local port number. It starts with the port specified by -localport and increments it by one for each retry. Setting this value to 1 or less makes TclCurl try only one port number. Because port numbers are a limited resource and may already be in use, setting this value too low may cause unnecessary connection setup failures.

-dnscachetimeout

Pass the timeout in seconds. Name resolution results are kept in memory for this number of seconds. Set this option to 0 to disable caching completely, or to -1 to keep cached entries indefinitely. By default, TclCurl caches this information for 60 seconds.

The name resolution functions in various libc implementations do not re-read name server information unless explicitly told to do so, for example by calling res_init(3). As a result, TclCurl may continue to use older server information even after DHCP has updated it, which may appear to be a DNS cache issue.

-dnsuseglobalcache

If this option is set to 1, TclCurl uses a global DNS cache that survives the creation and deletion of curl handles. This is not thread-safe because it relies on a global variable. This option was deprecated in libcurl v7.11.1 and is disabled by default in the TclCurl build. See README.md for instructions on how to re-enable it.

WARNING: This option is obsolete. Use the share interface instead. See tclcurl_share.

-buffersize

Pass the preferred size for the TclCurl receive buffer. A smaller buffer may cause the write callback to be invoked more often with smaller chunks. This value is treated as a request, not as a guarantee.

-port

Pass the remote port number to connect to instead of the port specified in the URL or the default port for the protocol in use.

-tcpnodelay

Pass a number to specify whether the TCP_NODELAY option should be set or cleared (1 = set, 0 = clear). This option is cleared by default. It has no effect after the connection has been established.

Setting this option will disable TCP’s Nagle algorithm. The purpose of this algorithm is to try to minimize the number of small packets on the network (where “small packets” means TCP segments less than the Maximum Segment Size (MSS) for the network).

Maximizing the amount of data sent per TCP segment is good because it amortizes the overhead of the send. However, in some cases (most notably telnet or rlogin) small segments may need to be sent without delay. This is less efficient than sending larger amounts of data at a time, and can contribute to congestion on the network if overdone.

-addressscope

Pass a number specifying the scope_id value to use when connecting to IPv6 link-local or site-local addresses.

NAMES AND PASSWORDS OPTIONS

-netrc

Set this option to make TclCurl scan your ~/.netrc file for the user name and password of the remote site you are about to access. TclCurl does not verify that the file has the correct properties set, as the standard Unix ftp client does. Only machine name, user name, and password are taken into account; init macros and similar entries are not supported.

Accepted values:

optional
Use of ~/.netrc is optional, and information in the URL takes precedence. The file is searched using the host and user name, to find the password only, or using the host name alone, to find the first user name and password for that machine, depending on which information is not specified in the URL.

Undefined values for this option have the same effect.

ignored
TclCurl ignores the file and uses only the information in the URL. This is the default.
required
TclCurl requires use of the file, ignores the information in the URL, and searches the file using the host name only.
-netrcfile

Pass a string containing the full path name of the file to use as the .netrc file. For this option to work, you must set -netrc to required. If this option is omitted and -netrc is set, TclCurl attempts to find a .netrc file in the current user’s home directory.

-userpwd

Pass a string in the form [username]:[password] to use for the connection. Use -httpauth to select the authentication method.

When using NTLM, you can specify a domain by prepending it to the user name and separating the domain and name with a forward slash (/) or backward slash (\\), for example domain/user:password or domain\\user:password. Some HTTP servers on Windows also support this form for Basic authentication.

When using HTTP and -followlocation, TclCurl might perform several requests to possibly different hosts. TclCurl will only send this user and password information to hosts using the initial host name (unless -unrestrictedauth is set), so if TclCurl follows locations to other hosts it will not send the user and password to those. This is enforced to prevent accidental information leakage.

-proxyuserpwd

Pass a string in the form [username]:[password] to use for the connection to the HTTP proxy.

-username

Pass a string containing the user name to use for the transfer. It sets the user name used in protocol authentication. This option should not be used together with the older -userpwd option.

To specify the password to use together with the user name, use the -password option.

-password

Pass a string containing the password to use for the transfer.

This option should be used together with -username.

-proxyusername

Pass a string containing the user name to use for the transfer while connecting to the proxy.

This option is used in the same way as -proxyuserpwd, except that it allows the user name to contain a colon, as in sip:user@example.com.

-proxyusername is an alternative way to set the user name while connecting to the proxy. It should not be used together with -proxyuserpwd.

-proxypassword

Pass a string containing the password to use for the transfer while connecting to the proxy. This option is intended to be used together with -proxyusername.

-httpauth

Set this option to the authentication method to use. Accepted values are:

basic
HTTP Basic authentication. This is the default choice and the only method in widespread use that is supported almost everywhere. It sends the user name and password over the network in plain text.
digest
HTTP Digest authentication. Over public networks, this is generally more secure than Basic authentication.
digestie
HTTP Digest authentication with an Internet Explorer-specific variant. TclCurl uses a compatibility behavior known to have been used by Internet Explorer before version 7 and still required by some servers.
gssnegotiate
HTTP GSS-Negotiate authentication. This method, also known simply as Negotiate, was designed by Microsoft and is used in Microsoft web applications. It is primarily intended to support Kerberos 5 authentication, but it may also be used with other authentication methods.
ntlm
HTTP NTLM authentication. This is a proprietary protocol developed and used by Microsoft. It uses a challenge-response mechanism and hashing, similar to Digest, to avoid sending the password in clear text.
ntlmwb
NTLM delegated to the winbind helper. Authentication is performed by a separate binary application that is executed when needed. The name of that application is specified when libcurl is built, but it is typically /usr/bin/ntlm_auth.

Note that libcurl will fork when necessary to run the winbind application and kill it when complete, calling waitpid() to await its exit when done. On POSIX operating systems, killing the process will cause a SIGCHLD signal to be raised (regardless of whether -nosignal is set). This behavior is subject to change in future versions of libcurl.

any
TclCurl automatically selects the method it considers the most secure.
anysafe
TclCurl may use any method except Basic and automatically selects the one it considers the most secure.
-tlsauthtype

Selects the authentication method to use for TLS authentication.

Accepted values:

tlsauthsrp
Uses TLS-SRP authentication. Secure Remote Password authentication for TLS is defined in RFC 5054 and provides mutual authentication if both sides share a secret. To use this value, you must also set -tlsauthusername and -tlsauthpassword.

libcurl must be built with GnuTLS or with OpenSSL support for TLS-SRP for this to work.

-tlsauthusername

Pass a string containing the user name to use for the TLS authentication method specified with -tlsauthtype. This option requires -tlsauthpassword to be set as well.

-tlsauthpassword

Pass a string containing the password to use for the TLS authentication method specified with -tlsauthtype. This option requires -tlsauthusername to be set as well.

-proxyauth

Use this option to tell TclCurl which authentication method to use for proxy authentication. For some methods, this causes an extra network round trip. Set the actual user name and password with -proxyuserpwd.

The methods are those listed above for the httpauth option. As of this writing, only Basic and NTLM work.

HTTP OPTIONS

-autoreferer

Set this option to 1 to enable automatic updates of the Referer: header when TclCurl follows a Location: redirect.

-encoding

Sets the contents of the Accept-Encoding: header sent in an HTTP request, and enables decoding of a response when a Content-Encoding: header is received.

Accepted values:

identity
Requests no encoding.
deflate
Requests compression using the zlib algorithm.
gzip
Requests gzip compression.
all
Sends an Accept-Encoding: header containing all supported encodings.

This is a request, not a requirement; the server may or may not honor it. This option must be set or any unsolicited encoding used by the server is ignored. See lib/README.encoding in the libcurl documentation for details.

-transferencoding

Adds a request for compressed Transfer-Encoding in the outgoing HTTP request. If the server supports this and chooses to use it, the response may use a compressed Transfer-Encoding, which TclCurl then decompresses automatically when receiving the data.

Transfer-Encoding differs from the Content-Encoding requested with -encoding in that Transfer-Encoding applies strictly to the transfer and therefore must be decoded before the data reaches the client. Traditionally, Transfer-Encoding has been used less widely and is less consistently supported by HTTP clients and servers.

-followlocation

Set this option to 1 to make TclCurl follow any

Location: header

sent by the server as part of an HTTP response.

TclCurl resends the request to the new location and continues to follow further Location: headers until no more are returned. Use -maxredirs to limit the number of redirects TclCurl follows.

Since 7.19.4, TclCurl can also restrict which protocols it follows automatically. The accepted protocols are set with -redirprotocols. By default, the FILE protocol is excluded.

-unrestrictedauth

Set this option to 1 to allow TclCurl to continue sending authentication credentials when following redirects, even if the host name changes. This option is meaningful only when -followlocation is enabled.

-maxredirs

Sets the redirection limit. After that many redirects have been followed, the next redirect causes an error. This option is meaningful only when -followlocation is enabled. Set the limit to 0 to refuse all redirects. Set it to -1 for an unlimited number of redirects, which is the default.

-postredir

Controls how TclCurl acts on redirects after POST requests that receive a 301, 302, or 303 response. Accepted values are 301, 302, 303, and all. The values 301, 302, and 303 make TclCurl preserve the POST request method for the corresponding redirect status code. The value all enables all three behaviors.

The non-RFC behavior is common in web browsers, so TclCurl performs this conversion by default to maintain consistency. However, a server may require a POST to remain a POST after such a redirection.

This option is meaningful only when -followlocation is enabled.

The legacy alias -post301 is accepted for compatibility and uses the same values.

-put

Set this option to 1 to make TclCurl upload a file using HTTP PUT. The file to upload must be specified with -infile and -infilesize.

This option is deprecated as of version 0.12.1. Use -upload.

This option does not limit how much data TclCurl will actually send, as that is controlled entirely by what the read callback returns.

-post

Set this option to 1 to make TclCurl perform a regular HTTP POST request using the application/x-www-form-urlencoded format commonly used by HTML forms. Use -postfields to specify the data to post and -postfieldsize to specify its size.

Use the -postfields option to specify what data to post and -postfieldsize to set the data size. Optionally, you can also provide POST data using -readproc.

You can override the default POST Content-Type: header by setting your own with -httpheader.

Using POST with HTTP 1.1 implies the use of an Expect: 100-continue header. You can disable this header with -httpheader as usual.

If you use POST with an HTTP 1.1 server, you can send data without knowing the size in advance by using chunked encoding. Enable this by adding a header such as Transfer-Encoding: chunked with -httpheader. With HTTP 1.0, or without chunked transfer encoding, you must specify the size in the request.

Setting -post to 1 also sets -nobody to 0.

NOTE: If you have issued a POST request and later want to make a HEAD or GET request instead, you must explicitly select the new request type with -nobody, -httpget, or a similar option.

-postfields

Pass a string containing the complete data to send in an HTTP POST request. You must ensure that the data is formatted exactly as you want the server to receive it. TclCurl does not convert or encode it for you. Most web servers assume this data is URL-encoded.

This is the normal application/x-www-form-urlencoded form, which is the most commonly used one by HTML forms.

If you want to do a zero-byte POST, you need to set -postfieldsize explicitly to zero, because setting -postfields to NULL or "" effectively disables sending the specified string. TclCurl then assumes that the POST data is supplied through the read callback.

Using POST with HTTP 1.1 implies the use of an Expect: 100-continue header. You can disable this header with -httpheader as usual.

NOTE: To make multipart/form-data posts, see -httppost.

-postfieldsize

Use this option to post data without letting TclCurl call strlen() to determine the data size. This is also required if you want to post fully binary data, which would otherwise likely fail. If this size is set to zero, the library uses strlen() to determine the data size.

-httppost

Makes TclCurl perform an HTTP multipart/form-data POST request. The data to send is described through a Tcl list.

This is the only case where the data is reset after a transfer.

Each part consists of at least a NAME and a CONTENTS part. If the part is used for file upload, it may also contain CONTENT-TYPE and FILENAME information.

The list must contain a ‘name’ tag followed by the section name. The section value can then be described with ‘value’, followed by a string containing the data to post, ‘file’, followed by the name of the file to post, or ‘contenttype’, followed by the content type (text/plain, image/jpg, and so on). You can also supply an alternate file name with ‘filename’. This is useful if the server checks whether the provided file name is valid, or if you want to include the full path of the file being posted. You can also post the contents of a variable as if it were a file by using ‘bufferName’ and ‘buffer’, or use ‘filecontent’ followed by a file name to read that file and use its contents as data.

To specify additional headers for a form section, use ‘contentheader’ followed by a list of headers.

See httpPost.tcl and httpBufferPost.tcl for examples.

Return values:

1
If the memory allocation fails.
2
If one option is given twice for one form.
3
If an empty string was given.
4
If an unknown option was used.
5
If some form information is incomplete or invalid.
6
If an illegal option is used in an array.
7
If TclCurl has no HTTP support.
-referer

Pass a string to set the Referer: header in the HTTP request sent to the remote server.

The Referer: header identifies the resource from which the target URI was obtained. Servers may use it for logging, analytics, backlink generation, caching decisions, or request-flow checks.

This option is useful when a scripted client must reproduce the request context normally sent by a web browser, or when a server expects a specific referring URI.

The header value should normally be a URI identifying the referring resource. Fragments and userinfo components are not part of a valid Referer: field value.

The field name Referer is a historical misspelling of referrer, but the misspelled form is the standardized HTTP header name.

Because this header may reveal navigation context or sensitive URI data, it should be set with care. It should not be relied upon as a secure means of authentication or access control.

You can also set this header through -httpheader.

-useragent

Pass a string to set the User-Agent: header in the HTTP request sent to the remote server. You can also set custom headers with -httpheader.

-httpheader

Pass a list of HTTP headers to send in the request. If you add a header that TclCurl would otherwise generate internally, your header is used instead. If you add a header with no value, such as Accept:, the internal header is disabled. This option can therefore be used to add, replace, or remove internal headers.

This option is useful when the request must include headers not exposed by dedicated TclCurl options, or when you need exact control over the final HTTP request. Common uses include setting custom authentication-related headers, API-specific headers, cache-control directives, or overriding headers such as Content-Type: or Accept:.

The headers in the list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. If you include CRLF yourself, the server will likely ignore part of the headers you specified.

The first line of a request, containing the method, usually GET or POST, is not a header and cannot be replaced with this option. Only the lines following the request line are headers. Adding the method line to this list causes an invalid header to be sent.

NOTE: The most commonly replaced headers have dedicated shortcut options: -cookie, -useragent, and -referer.

-http200aliases

Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers return a custom response line. For example, IceCast servers may return ICY 200 OK. If you include such a string in the list, it is treated as a valid HTTP status line such as HTTP/1.0 200 OK.

NOTE: The alias itself is not parsed for a version string. Before version 7.16.3, TclCurl used the value set by -httpversion, but since 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matches.

-cookie

Pass a string to set a cookie in the HTTP request. The string should use the format [NAME]=[CONTENTS];, where NAME is the cookie name and CONTENTS is the cookie value.

If you need to set multiple cookies, you must set them all in a single option value by concatenating them into one string, for example name1=content1; name2=content2;.

This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are performed because of authentication, redirects, or similar causes, they all receive this cookie header.

If this option is used multiple times, only the last value is kept.

-cookiefile

Pass the name of a file containing cookie data. The cookie data may be in Netscape cookie file format or in regular HTTP-style headers written to a file.

If the file is empty or does not exist, this option still enables cookies for the handle, causing TclCurl to parse received cookies and use matching cookies in later requests.

If you use this option multiple times, each use adds another file to read.

-cookiejar

Pass a file name to which TclCurl writes all internally known cookies when curlHandle cleanup is called. If no cookies are known, no file is created. Specify - to write the cookies to standard output.

Using this option also enables cookies for the session, so matching cookies are sent on later requests, including those caused by redirects.

TclCurl cannot report an error if writing the cookie jar fails. If -verbose is enabled, a warning is displayed, but that is the only visible feedback in this case.

-cookiesession

Set this option to 1 to mark the current run as a new cookie session. This makes TclCurl ignore session cookies loaded from a previous session. By default, TclCurl stores and loads all cookies, including session cookies. Session cookies are cookies without an expiry date and are meant to exist only for the current session.

-cookielist

Pass a string containing a cookie. The cookie may be in Netscape/Mozilla format or in regular HTTP-style header form, such as Set-Cookie: .... If the cookie engine is not enabled, it is enabled automatically.

Special values are ALL, which erases all known cookies, and FLUSH, which writes all known cookies to the file specified by -cookiejar.

-httpget

Set this option to 1 to force the HTTP request method back to GET. This is useful if POST, PUT, or a custom request has previously been used with the same handle.

Setting -httpget to 1 also sets -nobody to 0.

-httpversion

Selects the HTTP version to use. This option should be used only when it is necessary to override the default behavior because of server-side requirements.

Accepted values:

none
Lets TclCurl use the HTTP version it considers appropriate.
1.0
Enforce HTTP 1.0 requests.
1.1
Enforce HTTP 1.1 requests.
2.0
Enforce HTTP version 2 requests.
2TLS
Enforce version 2 requests for HTTPS, version 1.1 for HTTP.
2_PRIOR_KNOWLEDGE
Enforce HTTP 2 requests without performing an HTTP/1.1 Upgrade first.
-ignorecontentlength

Ignores the Content-Length header. This is useful for Apache 1.x and similar servers, which may report an incorrect content length for files larger than 2 gigabytes. If this option is used, TclCurl cannot report progress accurately and stops the download only when the server closes the connection.

-httpcontentdecoding

Set this option to 0 to disable content decoding, or to 1 to enable it. TclCurl does not enable content decoding by default; for that, you must also use -encoding.

-httptransferencoding

Set this option to 0 to disable transfer decoding, or to 1 to enable it. The default is 1. TclCurl performs chunked transfer decoding by default unless this option is disabled.

SMTP OPTIONS

-mailfrom

Pass a string specifying the sender address to use in the SMTP envelope.

This option controls the envelope sender used at the SMTP protocol level. It does not set or modify the From: header field in the message body.

-mailrcpt

Pass a list of recipient addresses to use in the SMTP envelope.

This option controls the envelope recipients used at the SMTP protocol level. It does not set or modify message header fields such as To:, Cc:, or Bcc:.

In SMTP, recipients are specified with angle brackets (<>). If a recipient value does not begin with an angle bracket, TclCurl assumes that it is a plain email address and adds the angle brackets automatically.

TFTP OPTION

-tftpblksize

Specifies the block size to use for TFTP data transmission. According to RFC 2348, valid values range from 8 to 65464 bytes. If this option is not specified, the default block size is 512 bytes.

The requested block size is used only if the remote server supports it. If the server does not return an option acknowledgment, or if it returns an acknowledgment without a block size value, the default of 512 bytes is used.

FTP OPTIONS

-ftpport

Pass a string identifying the address to use for the FTP PORT instruction. The PORT instruction tells the remote server to connect to the specified client address. The string may be a plain IP address, a host name, a network interface name on Unix, or simply - to let the library use the system’s default IP address. By default, FTP transfers are passive, so PORT is not used.

The address can be followed by : and a port number, optionally followed by - and a port range. If the port specified is 0, the operating system chooses a free port. If a range is provided and no port in that range is available, libcurl reports CURLE_FTP_PORT_FAILED for the handle. Invalid port or port-range settings are ignored. IPv6 addresses followed by a port or port range must be enclosed in brackets. IPv6 addresses without a port or port range may also be enclosed in brackets.

Examples:

eth0:0 192.168.1.2:32000-33000 curl.se:32123 [::1]:1234-4567

To disable PORT and return to passive mode, set this option to the empty string.

-quote

Pass a list of FTP or SFTP commands to send to the server before the FTP transfer request. These commands are sent before any other FTP commands, including CWD. If you do not want to transfer any files, set -nobody to 1 and -header to 0.

Prefix a command with an asterisk (*) to make TclCurl continue even if that command fails. By default, a failure stops the transfer.

To disable this option, set it to the empty string.

The commands must be raw FTP commands. For example, to create a directory you must send mkd Test, not mkdir Test.

Valid SFTP commands are chgrp, chmod, chown, ln, mkdir, pwd, rename, rm, rmdir, and symlink.

-postquote

Pass a list of FTP commands to send to the server after the FTP transfer request. If you do not want to transfer any files, set -nobody to 1 and -header to 0.

-prequote

Pass a list of FTP or SFTP commands to send to the server after the transfer type has been set.

-dirlistonly

Set this option to 1 to list only file names in a directory instead of requesting a full directory listing with file sizes, dates, and similar information. This option works with both FTP and SFTP URLs.

For FTP, this causes an NLST command to be sent. Some FTP servers return only files in response to NLST, and may omit subdirectories and symbolic links.

Setting this option to 1 also implies a directory listing even if the URL does not end with a slash, which would otherwise be required.

Do not use this option together with -wildcardmatch, as it effectively disables that feature.

-append

Set this option to 1 to append to the remote file instead of overwriting it. This is useful only when uploading to an FTP site.

-ftpuseeprt

Set this option to 1 to make TclCurl use the EPRT and LPRT commands for active FTP transfers, which are enabled with -ftpport. When this option is enabled, TclCurl first attempts EPRT, then LPRT, and only then falls back to PORT. If this option is set to 0, only PORT is used.

-ftpuseepsv

Set this option to 1 to make TclCurl use the EPSV command for passive FTP transfers. This is the default behavior. When enabled, TclCurl first attempts EPSV before using PASV. If this option is set to 0, TclCurl uses only PASV.

-ftpusepret

Set this option to 1 to make TclCurl send a PRET command before PASV or EPSV. Some FTP servers, especially drftpd, require this non-standard command for directory listings and uploads or downloads in passive mode. This option has no effect for active FTP transfers.

-ftpcreatemissingdirs

Controls whether TclCurl should attempt to create a remote directory when the transfer requires that directory to exist, but a CWD command shows that it does not yet exist or cannot yet be entered.

This setting also applies to SFTP connections. TclCurl attempts to create the remote directory if it cannot obtain a handle to the target location. Creation fails if a file with the same name already exists, or if permissions do not allow directory creation.

Accepted values:

1
After a failed CWD, TclCurl attempts to create the missing remote directory and then continues with the transfer.
2
After a failed CWD, TclCurl attempts to create the missing remote directory. If the subsequent MKD command fails, TclCurl retries the CWD command before giving up. This is useful when multiple simultaneous connections target the same server and another connection may have created the directory in the meantime.
-ftpresponsetimeout

Sets a timeout, in seconds, for how long the server may take to return a response to an FTP command before the session is considered hung. While TclCurl is waiting for such a response, this value overrides -timeout. If both options are used, -ftpresponsetimeout should normally be set to a value smaller than -timeout.

-ftpalternativetouser

Pass a string to use for authentication if the usual FTP USER user and PASS password negotiation fails. This is known to be required in some cases when connecting to Tumbleweed Secure Transport FTPS servers that use client-certificate authentication.

-ftpskippasvip

Set this option to 1 to make TclCurl ignore the IP address suggested by the server in its 227 response to TclCurl’s PASV command when opening the data connection. TclCurl instead reuses the same IP address already in use for the control connection, while still using the port number from the 227 response.

This option has no effect if PORT, EPRT, or EPSV is used instead of PASV.

-ftpsslauth

Selects how TclCurl issues AUTH TLS or AUTH SSL when FTP over SSL is enabled with -ftpssl.

This option may be needed for servers such as BSDFTPD-SSL, which do not handle AUTH SSL correctly and require AUTH TLS instead.

Accepted values:

default
Lets TclCurl choose.
ssl
Tries AUTH SSL first, and tries AUTH TLS only if that fails.
tls
Tries AUTH TLS first, and tries AUTH SSL only if that fails.
-ftpsslccc

Controls use of CCC (Clear Command Channel). CCC shuts down the SSL/TLS layer after authentication, so the remainder of the control channel is unencrypted. This can allow NAT routers to inspect the FTP control channel.

Accepted values are:

none
Do not attempt to use CCC.
passive
Do not initiate the shutdown. Wait for the server to do so, and do not send a reply.
active
Initiate the shutdown and wait for a reply.
-ftpaccount

Pass a string containing account data, or "" to disable it. If an FTP server requests account data after the user name and password have been provided, TclCurl sends this value with the ACCT command.

-ftpfilemethod

Selects how TclCurl navigates FTP paths. Accepted values are:

multicwd
The default. TclCurl performs one CWD operation for each path component in the URL. For deep hierarchies this may require many commands. This is the method described by RFC 1738.
nocwd
TclCurl does not perform CWD at all. Instead it sends commands such as SIZE, RETR, and STOR with the full path.
singlecwd
TclCurl performs one CWD to the full target directory and then operates on the file normally. This is somewhat more standards compliant than nocwd, without the full overhead of multicwd.

PROTOCOL OPTIONS

-transfertext

Set this option to 1 to use ASCII mode for FTP transfers instead of the default binary transfer mode. On Win32 systems, this does not set stdout to binary mode. This option can be useful when transferring text data between systems that treat characters such as newlines differently.

NOTE: TclCurl does not perform full ASCII conversion during ASCII FTP transfers. It simply sets the transfer mode to ASCII and performs a normal transfer.

-proxytransfermode

Set this option to 1 to make TclCurl set the transfer mode, binary or ASCII, for FTP transfers performed through an HTTP proxy by appending ;type=a or ;type=i to the URL. If this option is omitted or set to 0, -transfertext has no effect for FTP transfers performed through an HTTP proxy. Not all proxies support this feature.

-crlf

Set this option to 1 to make TclCurl convert Unix newlines to CRLF newlines during transfers. Set it to 0 to disable this behavior.

-range

Pass a string specifying the requested range. The format is X-Y, where either X or Y may be omitted. HTTP transfers also support multiple ranges separated by commas, as in X-Y,N-M. When multiple ranges are requested over HTTP, the server returns the response document in pieces using standard MIME separation rules.

Range requests are supported only for HTTP, FTP, and FILE transfers.

-resumefrom

Pass the offset, in bytes, at which the transfer should start. Set this option to 0 to start the transfer from the beginning, which disables resume behavior.

For FTP, set this option to -1 to start from the end of the target file, which is useful when continuing an interrupted upload.

For FTP uploads, the resume position specifies where in the local source file TclCurl should resume reading. The data read from that point is then appended to the remote target file.

-customrequest

Pass a string containing the request method to use instead of the default method, such as GET or HEAD, when making an HTTP request. This is useful for methods such as DELETE and other less common HTTP requests. Use this option only when the server is known to support the specified method.

TclCurl still behaves internally according to the type of request it would otherwise have used. As a result, changing the request method with this option can produce inconsistent behavior if the corresponding request type is not selected through the usual dedicated option. For example, to make a proper HEAD request, use -nobody. To make a proper POST request, use -post or -postfields.

-filetime

Set this option to 1 to make TclCurl attempt to obtain the modification time of the remote document during the transfer. This requires the remote server either to send the time directly or to support a command for querying it. After the transfer, the filetime value can be retrieved with the getinfo procedure.

For FTP transfers, this typically means that the server must support a command for querying the remote file modification time, such as MDTM. If the server does not provide this information, the transfer can still succeed, but the retrieved filetime value remains unknown.

-nobody

Set this option to 1 to omit the body from the output. This is relevant only for protocols that distinguish between a header part and a body part. For HTTP and HTTPS, this causes TclCurl to issue a HEAD request.

To change the request back to GET, use -httpget. To switch to POST, use -post or a related option.

-infilesize

Use this option when uploading a file to specify the expected size of the input file.

This option is mandatory for uploads performed with SCP.

-upload

Set this option to 1 to prepare for an upload. The -infile and -infilesize options are also relevant for uploads. If the protocol is HTTP, uploading means using the PUT request unless you tell TclCurl otherwise.

Using PUT with HTTP 1.1 implies the use of a “Expect: 100-continue” header. You can disable this header with -httpheader as usual.

If you use PUT to a HTTP 1.1 server, you can upload data without knowing the size before starting the transfer if you use chunked encoding. You enable this by adding a header like “Transfer-Encoding: chunked” with -httpheader. With HTTP 1.0 or without chunked transfer, you must specify the size.

-maxfilesize

This allows you to specify the maximum size (in bytes) of a file to download. If the file requested is larger than this value, the transfer will not start and error ‘filesize exceeded’ (63) will be returned.

NOTE: The file size is not always known prior to download, and for such files this option has no effect even if the file transfer ends up being larger than this given limit. This concerns both FTP and HTTP transfers.

-timecondition

Defines how the timevalue value is treated. Accepted values are ifmodsince and ifunmodsince. This feature applies to HTTP, FTP, and FILE.

-timevalue

This should be the time in seconds since 1 jan 1970, and the time will be used in a condition as specified with timecondition.

CONNECTION OPTIONS

-timeout

Pass the maximum time, in seconds, that a TclCurl transfer operation may take. Name resolution alone may take a noticeable amount of time, so setting this value too low can abort otherwise normal operations.

This option may cause libcurl to use SIGALRM to interrupt blocking system calls. On Unix-like systems, signals may therefore be used unless -nosignal is enabled.

-timeoutms

Like -timeout, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity.

-lowspeedlimit

Pass the speed, in bytes per second, below which the transfer rate must remain during -lowspeedtime seconds before TclCurl considers the transfer too slow and aborts it.

-lowspeedtime

Pass the number of seconds during which the transfer speed must stay below -lowspeedlimit before TclCurl considers the transfer too slow and aborts it.

-maxsendspeed

Pass a speed in bytes per second. If an upload exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed.

-maxrecvspeed

Pass a speed in bytes per second. If a download exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed.

-maxconnects

Sets the size of the persistent connection cache for protocols that support persistent connections. This value is the maximum number of simultaneous connections TclCurl may cache in the easy handle. The default is 5.

When the maximum is reached, TclCurl closes the oldest cached connection to prevent the number of open connections from increasing further.

NOTE: If transfers have already been performed with this easy handle, reducing -maxconnects may cause existing open connections to be closed earlier than expected.

If this easy handle is added to a multi handle, this setting is ignored. In that case, configure the corresponding maxconnects option on the multi handle instead.

-connecttimeout

Pass the maximum time, in seconds, that the connection phase may take. This limits only the time required to establish the connection. Once the connection has been established, this option no longer applies. Set it to 0 to disable the connection timeout.

On Unix-like systems, signals may be used unless -nosignal is enabled.

-connecttimeoutms

Like -connecttimeout, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity.

-ipresolve

Selects which IP address families may be used when resolving host names. This option is relevant only when a host name resolves to more than one IP version.

Accepted values are:

whatever
The default. Resolves addresses using all IP versions supported by the system.
v4
Resolves only IPv4 addresses.
v6
Resolves only IPv6 addresses.
-resolve

Pass a list of host name resolution entries to use for requests made with this handle.

Each entry must use the format HOST:PORT:ADDRESS, where HOST is the name TclCurl tries to resolve, PORT is the destination service port, and ADDRESS is the numeric IP address to use. If libcurl supports IPv6, ADDRESS may be either an IPv4 or an IPv6 address.

This option effectively pre-populates the DNS cache with entries for a given HOST:PORT pair, so redirects and other requests to the same HOST:PORT use the supplied ADDRESS.

To remove an entry from the DNS cache, include a string in the form -HOST:PORT. The host name must be prefixed with a dash, and both the host name and port must exactly match an entry added earlier.

-usessl

Selects the desired level of SSL or TLS use for the transfer. This option is relevant for protocols such as FTP, SMTP, POP3, and IMAP.

You can also use ftps:// URLs to enable SSL/TLS explicitly for both the control connection and the data connection.

Accepted values:

nope
Do not attempt to use SSL.
try
Attempt to use SSL, but continue even if it cannot be negotiated.
control
Use SSL for the control connection, or fail with use ssl failed (64).
all
Use SSL for all communication, or fail with use ssl failed (64).

SSL AND SECURITY OPTIONS

-sslcert

Pass a string containing the file name of the certificate to use. The default format is PEM, and it can be changed with -sslcerttype.

When libcurl is built against NSS, this value is the nickname of the certificate to use for authentication. To use a file in the current directory in that case, prefix it with ./ to avoid confusion with a nickname.

-sslcerttype

Pass a string specifying the format of the certificate given with -sslcert.

Accepted values are:

PEM
PEM format.
DER
DER format.
-sslkey

Pass a string containing the file name of the private key to use. The default format is PEM, and it can be changed with -sslkeytype.

-sslkeytype

Pass a string specifying the format of the private key given with -sslkey.

Accepted values are:

PEM
PEM format.
DER
DER format.
ENG
Uses a crypto engine. In this case -sslkey is interpreted as an identifier passed to the engine, and -sslengine must also be set.

NOTE: The DER private-key format may not work with some OpenSSL versions because of upstream limitations.

-keypasswd

Pass a string containing the passphrase required to use the private key specified with -sslkey or -sshprivatekeyfile.

A passphrase is not needed to load a certificate itself, but it may be needed to load the corresponding private key.

This option was formerly known as -sslkeypasswd and -sslcertpasswd.

-sslengine

Pass a string containing the identifier of the crypto engine to use for private-key operations.

NOTE: If the crypto engine cannot be loaded, TclCurl returns an error.

-sslenginedefault

Set this option to 1 to make the selected crypto engine the default for asymmetric cryptographic operations.

NOTE: If the crypto engine cannot be made the default, TclCurl returns an error.

-sslversion

Selects the SSL or TLS protocol version to use.

Accepted values are:

default
Uses the default behavior. TclCurl attempts to negotiate an appropriate protocol version with the remote server.
tlsv1
Requires TLSv1 or later.
sslv2
Requires SSLv2.
sslv3
Requires SSLv3.
tlsv1_0
Requires TLSv1.0 or later.
tlsv1_1
Requires TLSv1.1 or later.
tlsv1_2
Requires TLSv1.2 or later.
tlsv1_3
Requires TLSv1.3 or later.
maxdefault
Uses the maximum TLS version supported by libcurl or by the SSL backend’s default configuration.
maxtlsv1_0
Sets the maximum supported TLS version to TLSv1.0.
maxtlsv1_1
Sets the maximum supported TLS version to TLSv1.1.
maxtlsv1_2
Sets the maximum supported TLS version to TLSv1.2.
maxtlsv1_3
Sets the maximum supported TLS version to TLSv1.3.
-sslverifypeer

Controls whether TclCurl verifies the authenticity of the peer certificate. Set this option to 1 to enable verification or to 0 to disable it. The default is 1.

During the SSL or TLS handshake, the server sends a certificate declaring its identity. TclCurl verifies that certificate against a chain of trust rooted in one or more certification authority (CA) certificates.

TclCurl uses the default CA bundle provided by libcurl, but you can specify alternate certificates with -cainfo or -capath.

If -sslverifypeer is nonzero and verification fails, the connection fails. If this option is 0, peer-certificate verification is skipped.

Certificate verification alone does not confirm that the peer is the specific host you intended to contact. Use -sslverifyhost to control host-name verification.

-cainfo

Pass the name of a file containing one or more CA certificates used to verify the peer certificate.

This option is meaningful primarily together with -sslverifypeer. If peer verification is disabled, -cainfo does not need to name an accessible file.

By default, this option is set to the system path of libcurl’s CA bundle, as determined when libcurl was built.

When libcurl is built against NSS, this value refers to the directory containing the NSS certificate database.

-issuercert

Pass the name of a file containing a CA certificate in PEM format. If this option is set, an additional check is performed to verify that the peer certificate was issued by the CA certificate provided here.

This is useful in multi-level PKI environments where the peer certificate must be constrained to a specific branch of the certificate hierarchy.

This option is meaningful only when used together with -sslverifypeer. Otherwise, failure of this additional check is not treated as a connection failure.

-capath

Pass the name of a directory containing multiple CA certificates to use when verifying the peer certificate.

When libcurl is built against OpenSSL, this directory must be prepared with the openssl c_rehash utility. This option is meaningful primarily together with -sslverifypeer. If peer verification is disabled, -capath does not need to name an accessible directory.

This option is OpenSSL-specific and has no effect when libcurl is built against GnuTLS. NSS-based libcurl provides it only for backward compatibility.

On Windows, this option may not work because of OpenSSL limitations.

-crlfile

Pass the name of a file containing one or more certificate revocation lists in PEM format to use during certificate validation.

When libcurl is built against NSS or GnuTLS, there is no supported way to influence revocation checking with this option. When libcurl is built with OpenSSL support, both X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are enabled if a CRL file is provided, so CRL checking is applied throughout the certificate chain.

This option is meaningful only when used together with -sslverifypeer.

If the CRL file cannot be loaded, the SSL exchange fails with the specific error code CURLE_SSL_CRL_BADFILE. A certificate-verification failure caused by revocation information in the CRL does not produce that specific error code.

-sslverifyhost

Controls whether TclCurl verifies that the server certificate matches the host name you intended to contact.

During the SSL or TLS handshake, the server sends a certificate declaring its identity.

When -sslverifyhost is set to 2, the certificate must identify the intended server or the connection fails. TclCurl considers the server to match when the Common Name field or a Subject Alternative Name field in the certificate matches the host name in the URL.

When this option is set to 1, the certificate must contain a Common Name field, but the specific name is not checked. This setting is generally not useful.

When this option is set to 0, the connection succeeds regardless of the names contained in the certificate.

The default value is 2.

This option verifies the host identity claimed by the certificate. To verify that the certificate itself is trusted, use -sslverifypeer. If libcurl is built against NSS and -sslverifypeer is 0, -sslverifyhost is ignored.

-certinfo

Set this option to 1 to enable collection of certificate-chain information. When enabled, TclCurl, if built against OpenSSL, extracts certificate details from the chain used in the SSL connection.

That information can be retrieved after the transfer with the getinfo command and its certinfo option.

-randomfile

Pass a file name. TclCurl uses this file as a source of randomness for the SSL random engine. This option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See README.md for instructions on how to re-enable it.

-egdsocket

Pass the path name of an Entropy Gathering Daemon socket. TclCurl uses it as a source of randomness for the SSL random engine. This option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See README.md for instructions on how to re-enable it.

-sslcipherlist

Pass a string containing the cipher list to use for the SSL or TLS connection. The list consists of one or more cipher strings separated normally by colons, although commas or spaces are also accepted. The characters !, -, and + may also be used as operators.

With OpenSSL and GnuTLS, valid examples include RC4-SHA, SHA1+DES, TLSv1, and DEFAULT. The default list is usually defined by the SSL backend at build time.

With NSS, valid examples include rsa_rc4_128_md5 and rsa_aes_128_sha. NSS does not support incremental add or remove semantics for ciphers. If this option is used, all known ciphers are disabled and only the ciphers listed here are enabled.

For details about cipher-list syntax, see: http://www.openssl.org/docs/apps/ciphers.html

For NSS-specific cipher-list details, see: http://directory.fedora.redhat.com/docs/mod_nss.html

-sslsessionidcache

Set this option to 0 to disable TclCurl’s use of SSL session-ID caching, or to 1 to enable it. The default is 1.

In normal circumstances, reusing SSL session IDs is harmless and may improve performance. However, some broken SSL implementations may require this option to be disabled.

-krblevel

Selects the Kerberos security level for FTP and thereby also enables Kerberos awareness.

Accepted values are clear, safe, confidential, and private. If the string does not match one of these values, private is used.

Set the string to NULL to disable Kerberos 4. Set it to "" to disable Kerberos support for FTP.

-gssapidelegation

Selects the GSSAPI credential delegation mode.

Accepted values are:

flag
Allows unconditional delegation.
policyflag
Delegates only if the OK-AS-DELEGATE flag is set in the service ticket, provided that this feature is supported by the GSSAPI implementation and that GSS_C_DELEG_POLICY_FLAG was available at compile time.

Delegation is disabled by default since 7.21.7.

SSH OPTIONS

-sshauthtypes

Selects the allowed SSH authentication types.

Accepted values are:

publickey
Use public-key authentication.
password
Use password authentication.
host
Use host-based authentication.
keyboard
Use keyboard-interactive authentication.
any
Let TclCurl select an authentication method automatically.
-sshhostpublickeymd5

Pass a string containing 32 hexadecimal digits. The string must be the 128-bit MD5 checksum of the remote host public key. TclCurl rejects the connection unless the checksum matches.

This option applies only to SCP and SFTP transfers.

-sshpublickeyfile

Pass the file name of the public key to use.

If this option is not used, TclCurl defaults to $HOME/.ssh/id_dsa.pub when the HOME environment variable is set, and to id_dsa.pub in the current directory otherwise.

-sshprivatekeyfile

Pass the file name of the private key to use.

If this option is not used, TclCurl defaults to $HOME/.ssh/id_dsa when the HOME environment variable is set, and to id_dsa in the current directory otherwise.

If the private key is passphrase-protected, use -keypasswd to specify the passphrase.

-sshknownhosts

Pass a string containing the file name of the known_hosts file to use. The file must use the OpenSSH known_hosts format supported by libssh2.

If this option is set, TclCurl accepts connections only to hosts that are present in that file with a matching public key. Use -sshkeyproc to override the default behavior for host and key matching.

-sshkeyproc

Pass the name of a callback procedure that TclCurl invokes after known_hosts matching has been performed, so that the application can decide how the connection should proceed.

The callback is invoked only if -sshknownhosts is also set.

The callback receives a list with three elements:

  1. A list containing the key type from the known_hosts file and the key itself.
  2. A list containing the key type presented by the remote host and the key itself.
  3. A value describing TclCurl’s matching result.

Possible key-type values are rsa, rsa1, dss, and unknown.

Possible match-result values are match, mismatch, missing, and error.

Return values:

0
Accept the host and key. TclCurl appends the host and key to the known_hosts file before continuing with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. Updating the file is done by replacing it with a new copy, so the file permissions must allow that.
1
Accept the host and key, and continue with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there.
2
Reject the host and key. TclCurl closes the connection.
3
Reject the host and key, but keep the SSH connection alive. This can be useful if the application needs to inspect the host or key state and then retry without incurring the full setup cost again.

Any other return value causes TclCurl to close the connection.

OTHER OPTIONS

-headervar

Name of the Tcl array variable in which TclCurl stores the headers returned by the server.

-bodyvar

Name of the Tcl variable in which TclCurl stores the requested file contents. The stored data may be either text or binary data.

-canceltransvarname

Name of a Tcl variable used together with -progressproc. If the progress callback sets this variable to 1, the transfer is canceled.

-command

Executes the given command after the transfer has completed.

This option works only with blocking transfers and therefore has limited practical use.

-share

Pass a share handle. The share handle must have been created previously by calling curl::shareinit.

Setting this option causes the easy handle to use data from the shared handle instead of keeping its own separate copy. See tclcurl_share for details.

-newfileperms

Pass a numeric value specifying the permissions assigned to newly created files on the remote server. The default value is 0644, but any valid value may be used.

This option applies only to sftp://, scp://, and file:// transfers.

-newdirectoryperms

Pass a numeric value specifying the permissions assigned to newly created directories on the remote server. The default value is 0755, but any valid value may be used.

This option applies only to sftp://, scp://, and file:// transfers.

TELNET OPTIONS

-telnetoptions
Pass a list with variables to pass to the telnet negotiations. The variables should be in the format . TclCurl supports the options ‘TTYPE’, ‘XDISPLOC’ and ‘NEW_ENV’. See the TELNET standard for details.

NOT SUPPORTED

Some of the options libcurl offers are not supported, I don’t think them worth supporting in TclCurl but if you need one of them don’t forget to complain:

CURLOPTFRESHCONNECT, CURLOPTFORBIDREUSE, CURLOPT_PRIVATE,

CURLOPTSSLCTXFUNCTION, CURLOPTSSLCTXDATA, CURLOPTSSLCTX_FUNCTION and

CURLOPTCONNECTONLY, CURLOPTOPENSOCKETFUNCTION, CURLOPTOPENSOCKETDATA.

curlHandle perform

This procedure is called after the

init

and all the

configure

calls are made, and will perform the transfer as described in the options.

It must be called with the same curlHandle curl::init call returned. You can do any amount of calls to perform while using the same handle. If you intend to transfer more than one file, you are even encouraged to do so. TclCurl will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources. Just note that you will have to use configure between the invokes to set options for the following perform.

You must never call this procedure simultaneously from two places using the same handle. Let it return first before invoking it another time. If you want parallel transfers, you must use several curl handles.

RETURN VALUE

0 if all went well, non-zero if it didn’t. In case of error, if the errorbuffer was set with configure there will be a readable error message. The error codes are:

1
Unsupported protocol. This build of TclCurl has no support for this protocol.
2
Very early initialization code failed. This is likely to be and internal error or a resource problem where something fundamental couldn’t get done at init time.
3
URL malformat. The syntax was not correct.
4
A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision. This means that a feature or option was not enabled or explicitly disabled when libcurl was built and in order to get it to function you have to get a rebuilt libcurl.
5
Couldn’t resolve proxy. The given proxy host could not be resolved.
6
Couldn’t resolve host. The given remote host was not resolved.
7
Failed to connect to host or proxy.
8
FTP weird server reply. The server sent data TclCurl couldn’t parse. The given remote server is probably not an OK FTP server.
9
We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory.
11
FTP weird PASS reply. TclCurl couldn’t parse the reply sent to the PASS request.
13
FTP weird PASV reply, TclCurl couldn’t parse the reply sent to the PASV or EPSV request.
14
FTP weird 227 format. TclCurl couldn’t parse the 227-line the server sent.
15
FTP can’t get host. Couldn’t resolve the host IP we got in the 227-line.
17
FTP couldn’t set type. Couldn’t change transfer method to either binary or ascii.
18
Partial file. Only a part of the file was transferred, this happens when the server first reports an expected transfer size and then delivers data that doesn’t match the given size.
19
FTP couldn’t RETR file, we either got a weird reply to a ‘RETR’ command or a zero byte transfer.
21
Quote error. A custom ‘QUOTE’ returned error code 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command.
22
HTTP returned error. This return code only appears if -failonerror is used and the HTTP server returns an error code that is 400 or higher.
23
Write error. TclCurl couldn’t write data to a local filesystem or an error was returned from a write callback.
25
Failed upload failed. For FTP, the server typcially denied the STOR command. The error buffer usually contains the server’s explanation to this.
26
Read error. There was a problem reading from a local file or an error was returned from the read callback.
27
Out of memory. A memory allocation request failed. This should never happen unless something weird is going on in your computer.
28
Operation timeout. The specified time-out period was reached according to the conditions.
30
The FTP PORT command failed, not all FTP servers support the PORT command, try doing a transfer using PASV instead!.
31
FTP couldn’t use REST. This command is used for resumed FTP transfers.
33
Range error. The server doesn’t support or accept range requests.
34
HTTP post error. Internal post-request generation error.
35
SSL connect error. The SSL handshaking failed, the error buffer may have a clue to the reason, could be certificates, passwords, …
36
The download could not be resumed because the specified offset was out of the file boundary.
37
A file given with FILE:// couldn’t be read. Did you checked the permissions?
38
LDAP cannot bind. LDAP bind operation failed.
39
LDAP search failed.
41
A required zlib function was not found.
42
Aborted by callback. An application told TclCurl to abort the operation.
43
Internal error. A function was called with a bad parameter.
45
Interface error. A specified outgoing interface could not be used.
47
Too many redirects. When following redirects, TclCurl hit the maximum amount, set your limit with –maxredirs
48
An option passed to TclCurl is not recognized/known. Refer to the appropriate documentation. This is most likely a problem in the program that uses TclCurl. The error buffer might contain more specific information about which exact option it concerns.
49
A telnet option string was illegally formatted.
51
The remote peer’s SSL certificate or SSH md5 fingerprint wasn’t ok
52
The server didn’t reply anything, which here is considered an error.
53
The specified crypto engine wasn’t found.
54
Failed setting the selected SSL crypto engine as default!
55
Failed sending network data.
56
Failure with receiving network data.
58
Problem with the local client certificate.
59
Couldn’t use specified SSL cipher.
60
Peer certificate cannot be authenticated with known CA certificates.
61
Unrecognized transfer encoding.
62
Invalid LDAP URL.
63
Maximum file size exceeded.
64
SSL use failed.
65
Sending the data requires a rewind that failed, since TclCurl should take care of it for you, it means you found a bug.
66
Failed to initialise ssl engine.
67
Failed to login, user password or similar was not accepted.
68
File not found on TFTP server.
69
There is a permission problem with the TFTP request.
70
The remote server has run out of space.
71
Illegal TFTP operation.
72
Unknown transfer ID.
73
TFTP file already exists and will not be overwritten.
74
No such user in the TFTP server and good behaving TFTP servers should never return this.
75
Character conversion failed.
77
Problem with reading the SSL CA cert (path? access rights?).
78
Remote file not found
79
Error from the SSH layer
80
Failed to shut down the SSL connection
82
Failed to load CRL file
83
Issuer check failed
84
The FTP server does not understand the PRET command at all or does not support the given argument. Be careful when using -customrequest, a custom LIST command will be sent with PRET CMD before PASV as well.
85
Mismatch of RTSP CSeq numbers.
86
Mismatch of RTSP Session Identifiers.
87
Unable to parse FTP file list (during FTP wildcard downloading).
88
Chunk callback reported error.

curlHandle getinfo OPTION

Request internal information from the curl session with this procedure. This procedure is intended to get used AFTER a performed transfer, and can be relied upon only if the perform returns 0. Use this function AFTER a performed transfer if you want to get transfer-oriented data.

The following information can be extracted:

effectiveurl

Returns the last used effective URL.

responsecode

Returns the last received HTTP or FTP code. This will be zero if no server response code has been received. Note that a proxy’s CONNECT response should be read with httpconnectcode and not this.

httpconnectcode

Returns the last received proxy response code to a CONNECT request.

filetime

Returns the remote time of the retrieved document (in number of seconds since 1 jan 1970 in the GMT/UTC time zone). If you get -1, it can be because of many reasons (unknown, the server hides it or the server doesn’t support the command that tells document time etc) and the time of the document is unknown.

In order for this to work you have to set the -filetime option before the transfer.

namelookuptime

Returns the time, in seconds, it took from the start until the name resolving was completed.

connecttime

Returns the time, in seconds, it took from the start until the connect to the remote host (or proxy) was completed.

appconnecttime

Returns the time, in seconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed. This time is most often very near to the PRETRANSFER time, except for cases such as HTTP pippelining where the pretransfer time can be delayed due to waits in line for the pipeline and more.

pretransfertime

Returns the time, in seconds, it took from the start until the file transfer is just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.

starttransfertime

Returns the time, in seconds, it took from the start until the first byte is just about to be transferred. This includes the pretransfertime, and also the time the server needs to calculate the result.

totaltime

Returns the total transaction time, in seconds, for the previous transfer, including name resolving, TCP connect etc.

redirecturl

Returns the URL a redirect would take you to if you enable followlocation. This can come very handy if you think using the built-in libcurl redirect logic isn’t good enough for you but you would still prefer to avoid implementing all the magic of figuring out the new URL.

redirecttime

Returns the total time, in seconds, it took for all redirection steps including name lookup, connect, pretransfer and transfer before the final transaction was started, it returns the complete execution time for multiple redirections, so it returns zero if no redirections were needed.

redirectcount

Returns the total number of redirections that were actually followed.

numconnects

Returns how many new connections TclCurl had to create to achieve the previous transfer (only the successful connects are counted). Combined with redirectcount you are able to know how many times TclCurl successfully reused existing connection(s) or not. See the Connection Options of setopt to see how TclCurl tries to make persistent connections to save time.

primaryip

Returns the IP address of the most recent connection done with this handle. This string may be IPv6 if that’s enabled.

primaryport

Returns the destination port of the most recent connection done with this handle.

localip

Returns the local (source) IP address of the most recent connection done with this handle. This string may be IPv6 if that’s enabled.

localport

Returns the local (source) port of the most recent connection done with this handle.

sizeupload

Returns the total amount of bytes that were uploaded.

sizedownload

Returns the total amount of bytes that were downloaded. The amount is only for the latest transfer and will be reset again for each new transfer.

speeddownload

Returns the average download speed, measured in bytes/second, for the complete download.

speedupload

Returns the average upload speed, measured in bytes/second, for the complete upload.

headersize

Returns the total size in bytes of all the headers received.

requestsize

Returns the total size of the issued requests. This is so far only for HTTP requests. Note that this may be more than one request if followLocation is true.

sslverifyresult

Returns the result of the certification verification that was requested (using the -sslverifypeer option to configure).

sslengines

Returns a list of the OpenSSL crypto-engines supported. Note that engines are normally implemented in separate dynamic libraries. Hence not all the returned engines may be available at run-time.

contentlengthdownload

Returns the content-length of the download. This is the value read from the Content-Length: field. If the size isn’t known, it returns -1.

contentlengthupload

Returns the specified size of the upload.

contenttype

Returns the content-type of the downloaded object. This is the value read from the Content-Type: field. If you get an empty string, it means the server didn’t send a valid Content-Type header or that the protocol used doesn’t support this.

httpauthavail

Returns a list with the authentication method(s) available.

proxyauthavail

Returns a list with the authentication method(s) available for your proxy athentication.

oserrno

Returns the errno value from a connect failure. This value is only set on failure, it is no reset after a successful operation.

cookielist

Returns a list of all cookies TclCurl knows (expired ones, too). If there are no cookies (cookies for the handle have not been enabled or simply none have been received) the list will be empty.

ftpentrypath

Returns a string holding the path of the entry path. That is the initial path TclCurl ended up in when logging on to the remote FTP server. Returns an empty string if something is wrong.

certinfo

Returns list with information about the certificate chain, assuming you had the -certinfo option enabled when the previous request was done. The list first item reports how many certs it found and then you can extract info for each of those certs by following the list. The info chain is provided in a series of data in the format “name:content” where the content is for the specific named data.

NOTE: this option is only available in libcurl built with OpenSSL support.

conditionunmet

Returns the number 1 if the condition provided in the previous request didn’t match (see timecondition), you will get a zero if the condition instead was met.

curlHandle cleanup

This procedure must be the last one to call for a curl session. It is the opposite of the curl::init procedure and must be called with the same curlhandle as input as the curl::init call returned. This will effectively close all connections TclCurl has used and possibly has kept open until now. Don’t call this procedure if you intend to transfer more files.

curlHandle reset

Re-initializes all options previously set on a specified handle to the default values.

This puts back the handle to the same state as it was in when it was just created with curl::init.

It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares.

curlHandle duphandle

This procedure will return a new curl handle, a duplicate, using all the options previously set in the input curl handle. Both handles can subsequently be used independently and they must both be freed with cleanup.

The new handle will not inherit any state information, connections, SSL sessions or cookies.

RETURN VALUE
A new curl handle or an error message if the copy fails.

curlHandle pause

You can use this command from within a progress callback procedure to pause the transfer.

curlHandle resume

Resumes a transfer paused with curlhandle pause

curl::transfer

In case you do not want to use persistent connections you can use this command, it takes the same arguments as the curlHandle configure and will init, configure, perform and cleanup a connection for you.

You can also get the getinfo information by using -infooption variable pairs, after the transfer variable will contain the value that would have been returned by $curlHandle getinfo option.

RETURN VALUE
The same error code perform would return.

curl::version

Returns a string with the version number of tclcurl, libcurl and some of its important components (like OpenSSL version).

RETURN VALUE
The string with the version info.

curl::escape URL

This procedure will convert the given input string to an URL encoded string and return that. All input characters that are not a-z, A-Z or 0-9 will be converted to their “URL escaped” version (%NN where NN is a two-digit hexadecimal number)

RETURN VALUE
The converted string.

curl::unescape URL

This procedure will convert the given URL encoded input string to a “plain string” and return that. All input characters that are URL encoded (%XX where XX is a two-digit hexadecimal number) will be converted to their plain text versions.

RETURN VALUE
The string unencoded.

curl::curlConfig OPTION

Returns some information about how you have cURL installed.

-prefix
Returns the directory root where you installed cURL.
-feature
Returns a list containing particular main features the installed libcurl was built with. The list may include SSL, KRB4 or IPv6, do not assume any particular order.
-vernum
Outputs version information about the installed libcurl, in numerical mode. This outputs the version number, in hexadecimal, with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e…

curl::versioninfo OPTION

Returns information about various run-time features in TclCurl.

Applications should use this information to judge if things are possible to do or not, instead of using compile-time checks, as dynamic/DLL libraries can be changed independent of applications.

-version

Returns the version of libcurl we are using.

-versionnum

Returns the version of libcurl we are using in hexadecimal with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e… Note that the initial zero might be omitted.

-host

Returns a string with the host information as discovered by a configure script or set by the build environment.

-features

Returns a list with the features compiled into libcurl, the possible elements are:

ASYNCHDNS

Libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface.

CONV

Libcurl was built with support for character conversions.

DEBUG

Libcurl was built with extra debug capabilities built-in. This is mainly of interest for libcurl hackers.

GSSNEGOTIATE

Supports HTTP GSS-Negotiate.

IDN

Supports IDNA, domain names with international letters.

IPV6

Supports IPv6.

KERBEROS4

Supports kerberos4 (when using FTP).

LARGEFILE

Libcurl was built with support for large files.

LIBZ

Supports HTTP deflate using libz.

NTML

Supports HTTP NTLM

SPNEGO

Libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478)

SSL

Supports SSL (HTTPS/FTPS)

SSPI

Libcurl was built with support for SSPI. This is only available on Windows and makes libcurl use Windows-provided functions for NTLM authentication. It also allows libcurl to use the current user and the current user’s password without the app having to pass them on.

TLSAUTH_SRP

Libcurl was built with support for TLS-SRP.

NTLM_WB

Libcurl was built with support for NTLM delegation to a winbind helper.

Do not assume any particular order.

-sslversion

Returns a string with the OpenSSL version used, like OpenSSL/0.9.6b.

-sslversionnum

Returns the numerical OpenSSL version value as defined by the OpenSSL project. If libcurl has no SSL support, this is 0.

-libzversion

Returns a string, there is no numerical version, for example: 1.1.3.

-protocols

Lists what particular protocols the installed TclCurl was built to support. At the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE, TELNET, LDAP, DICT. Do not assume any particular order. The protocols will be listed using uppercase. There may be none, one or several protocols in the list.

curl::easystrerror errorCode

This procedure returns a string describing the error code passed in the argument.

EXAMPLES

The examples in this section assume you are running from the root of the TclCurl source tree.

To start the local HTTP test server used in the examples, run:

tclsh testservers/testserver.tcl

By default, this starts an HTTP server on http://127.0.0.1:8990/.

The path http://127.0.0.1:8990/tclcurl-man returns the HTML version of this manual page from doc/tclcurl.html, which makes it a convenient target for a basic GET example.

BASIC HTTP GET

The file examples/http_get.tcl contains a minimal HTTP GET example. It performs a simple request, stores the response body in a Tcl variable, and prints both the HTTP response code and the size of the returned document.

If the request succeeds, rc is 0, responsecode is 200, and body contains the HTML document returned by the server.

AUTHORS

Andres Garcia Garcia

Massimo Manghi

SEE ALSO

curl, The art of HTTP scripting (at http://curl.haxx.se), RFC 2396,

tclcurl-ng-8.0.3/doc/tclcurl.n000066400000000000000000003047431522613063100162020ustar00rootroot00000000000000.\" -*- mode: troff; coding: utf-8 -*- .TH "TclCurl" "n" "15 May 2026" "TclCurl 8.0.3" "TclCurl Easy Interface" .SH NAME .LP TclCurl - Transfer data to and from URLs using FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS, and GOPHER. .SH SYNOPSIS .LP .EX curl::init curl::transfer ?options? curl::version curl::escape url curl::unescape url curl::curlConfig option curl::versioninfo option curl::easystrerror errorCode .EE .LP .EX curlHandle configure ?options? curlHandle perform curlHandle getinfo curlinfo_option curlHandle cleanup curlHandle reset curlHandle duphandle curlHandle pause curlHandle resume .EE .SH DESCRIPTION .LP The TclCurl extension gives Tcl programmers access to the libcurl library written by \fBDaniel Stenberg\fR. With TclCurl, you can download from URLs, upload to them, and perform many other network transfer operations. For more information, see \c .UR http://curl.haxx.se .UE \c \&. .SH curl::init .LP This procedure must be called first. It returns a \f(CRcurlHandle\fR, which you use to invoke TclCurl procedures. Calling \f(CRinit\fR initializes TclCurl, and each call to \f(CRinit\fR MUST have a corresponding call to \f(CRcleanup\fR when the operation is complete. .PP You should perform all sequential file transfers using the same \f(CRcurlHandle\fR. This allows TclCurl to reuse persistent connections when possible. .PP \fBRETURN VALUE\fR .PP The \f(CRcurlHandle\fR to use. .SH curlHandle configure ?OPTIONS? .LP \fBconfigure\fR .PP is used to set the options for a transfer. Most operations in TclCurl have default behavior, and you can change that behavior by setting the appropriate options as documented. Each option is specified as the \fIoption\fR followed by a parameter. .PP \fBNotes:\fR .PP The options set with this procedure apply to subsequent data transfers performed when you invoke \f(CRperform\fR. .PP The options are not reset between transfers (except where noted), so if you want subsequent transfers with different options, you must change them between the transfers. You can optionally reset all options back to the internal default with \fBcurlHandle reset\fR. .PP \f(CRcurlHandle\fR is the value returned by the \f(CRcurl::init\fR call. .PP \fBOPTIONS\fR .SH BEHAVIOUR OPTIONS .TP 3 \fB-verbose\fR Set this option to 1 to make the library display detailed information about its operations. This option is useful when debugging libcurl and protocol-related problems. .IP You will rarely want to enable this in production, but it is often helpful when debugging or reporting problems. Another useful debugging option is .IP \fB-debugproc\fR .TP 3 \fB-header\fR Set this option to 1 to include headers in the body output. This is relevant only for protocols that actually send headers before the data, such as HTTP. .TP 3 \fB-noprogress\fR Set this option to 1 to disable the progress meter completely. It also prevents \fIprogressproc\fR from being called. .TP 3 \fB-nosignal\fR Set this option to 1 to make TclCurl avoid functions that install signal handlers or cause signals to be sent to the process. This option exists mainly so that multi-threaded Unix applications can still use timeout options without risking signal-related side effects. .IP If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while name resolution is in progress. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which allows proper timeouts for name resolution without signals. .IP Setting \fInosignal\fR to 1 makes libcurl stop asking the system to ignore SIGPIPE signals. Such signals may otherwise be sent by the system when data is written to a socket that has been closed by the peer. libcurl tries to avoid triggering SIGPIPE, but some operating systems provide no reliable way to prevent it, and even on those that do, some corner cases remain. In addition, using \fIntlm_Wb\fR authentication may cause a SIGCHLD signal to be raised. .TP 3 \fB-wildcard\fR Set this option to 1 to transfer multiple files that match a file name pattern. The pattern can be specified as part of the \fB-url\fR option, using an fnmatch-like pattern (shell pattern matching) in the last part of the URL, that is, the file name. .IP By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function with the \fB-fnmatchproc\fR option. .IP At present, this feature is supported only for FTP downloads. .IP A brief introduction of its syntax follows: .RS .IP "\(bu" 3 * - ASTERISK .RE .IP \f(CRftp://example.com/some/path/***.txt**\fR (for all \f(CR.txt\fR files from the root directory) - ? - QUESTION MARK .IP The question mark matches any single character. .IP \f(CRftp://example.com/some/path/**photo?.jpeg**\fR - [ - BRACKET EXPRESSION .IP The left bracket opens a bracket expression. The question mark and asterisk have no special meaning in a bracket expression. Each bracket expression ends by the right bracket and matches exactly one character. Some examples follow: .IP \fB[a-zA-Z0-9]\fR or \fB[f-gF-G]\fR - character interval .IP \fB[abc]\fR - character enumeration .IP \fB[\(haabc]\fR or \fB[!abc]\fR - negation .IP \fB[[:\fR\fIname\fR\fB:]]\fR class expression. Supported classes are \fBalnum\fR,\fBlower\fR, \fBspace\fR, \fBalpha\fR, \fBdigit\fR, \fBprint\fR, \fBupper\fR, \fBblank\fR, \fBgraph\fR, \fBxdigit\fR. .IP \fB[][-!\(ha]\fR - special case - matches only \(oq-\(cq, \(oq]\(cq, \(oq[\(oq, \(oq!\(cq or \(oq\(ha\(cq. These characters have no special purpose. .IP \fB[\e[\e]\e\e]\fR - escape syntax. Matches \(oq[\(oq, \(oq]\(cq or \(oq\e\(oq. .IP Using the rules above, a file name pattern can be constructed: .IP \f(CRftp://example.com/some/path/**[a-z[:upper:]\e\e\e\e].jpeg**\fR .SH CALLBACK OPTIONS .TP 3 \fB-writeproc\fR Sets a Tcl procedure that TclCurl invokes whenever received data is available to be handled. The callback procedure must have a single argument. When the procedure is invoked, that argument refers to the contents of a data buffer managed by libcurl. .IP NOTE: The amount of data passed on each invocation is not fixed. The callback may be invoked with an empty buffer, or with a buffer containing a large amount of data. .TP 3 \fB-file\fR File in which the transferred data will be saved. .TP 3 \fB-readproc\fR Sets a Tcl procedure that TclCurl calls whenever it needs to read data to send to the peer. The procedure must take one parameter, which contains the maximum number of bytes to read. It should return the actual number of bytes read, or \f(CR0\fR if you want to stop the transfer. .IP If you stop the current transfer by returning \f(CR0\fR prematurely, for example after indicating that you would upload \fIN\fR bytes but uploading fewer than \fIN\fR, the server may appear to hang while waiting for the remaining data. .IP When doing TFTP uploads, you must return exactly the amount of data requested by the callback. Otherwise, the server may treat it as the final packet and end the transfer. .TP 3 \fB-infile\fR File from which the data will be transferred. .TP 3 \fB-progressproc\fR Name of the Tcl procedure that TclCurl invokes at regular intervals during an operation, roughly once per second or more often, whether or not data is currently being transferred. Unknown or unused argument values passed to the callback are set to zero. For example, if you only download data, the upload size remains \f(CR0\fR. The procedure must have the following prototype: .IP \fBproc ProgressCallback {dltotal dlnow ultotal ulnow}\fR .IP For this option to work, you must set the \fB-noprogress\fR option to \f(CR0\fR. Setting this option to the empty string restores the original progress function. .IP If you transfer data with the multi interface, this procedure will not be called during periods of idleness unless you call the appropriate procedure that performs transfers. .IP You can pause and resume a transfer from within this procedure using the \fBpause\fR and \fBresume\fR commands. .TP 3 \fB-writeheader\fR Pass the file name to which the header part of the received data will be written. Headers are written to this file one by one, and only complete lines are written. This makes header parsing straightforward. .IP See also the \fB-headervar\fR option to get the headers into an array. .TP 3 \fB-debugproc\fR Name of the procedure that receives the debug data produced by the \fB-verbose\fR option. The callback procedure must have two arguments: .IP \fBdebugProc {infoType data}\fR .IP The \fBinfoType\fR argument identifies the kind of debug information: \f(CR0\fR text, \f(CR1\fR incoming header, \f(CR2\fR outgoing header, \f(CR3\fR incoming data, \f(CR4\fR outgoing data, \f(CR5\fR incoming SSL data, and \f(CR6\fR outgoing SSL data. The \fBdata\fR argument contains the corresponding data buffer. .TP 3 \fB-chunkbgnproc\fR Name of the procedure that is called before a file is transferred by FTP. The callback procedure must have one argument: .IP \fBChunkBgnProc {remains}\fR .IP The \fIremains\fR argument is the number of files left to be transferred or skipped. .IP This callback makes sense only when using the \fB-wildcard\fR option. .TP 3 \fB-chunkbgnvar\fR Name of the variable in the global scope that will contain the data for the file about to be transferred. If you do not use this option, \f(CR::fileData\fR is used. .IP The available data is: \f(CRfilename\fR, \f(CRfiletype\fR (\f(CRfile\fR, \f(CRdirectory\fR, \f(CRsymlink\fR, \f(CRdevice block\fR, \f(CRdevice char\fR, \f(CRnamed pipe\fR, \f(CRsocket\fR, \f(CRdoor\fR, or \f(CRerror\fR if it could not be identified), \f(CRtime\fR, \f(CRperm\fR, \f(CRuid\fR, \f(CRgid\fR, \f(CRsize\fR, \f(CRhardlinks\fR, and \f(CRflags\fR. .TP 3 \fB-chunkendproc\fR Name of the procedure that is called after a file has been transferred or skipped by FTP. The callback procedure takes no arguments: .IP \fBChunkEndProc {}\fR .IP It should return \f(CR0\fR if everything is fine and \f(CR1\fR if an error occurred. .TP 3 \fB-fnmatchProc\fR Name of the procedure that is called instead of the internal wildcard matching function. The callback procedure must have two arguments: .IP \fBFnMatchProc {pattern string}\fR .IP The \fIpattern\fR argument contains the pattern to be matched. The \fIstring\fR argument contains the candidate string. The procedure must return \f(CR0\fR if the string matches the pattern and \f(CR1\fR otherwise. .SH ERROR OPTIONS .TP 3 \fB-errorbuffer\fR Pass the name of a variable in which TclCurl may store human-readable error messages. This can provide more information than the command return code alone. .TP 3 \fB-stderr\fR Pass a file name. TclCurl uses this stream instead of \f(CRstderr\fR when reporting errors. .TP 3 \fB-failonerror\fR Set this option to 1 to make the transfer fail if the returned HTTP status code is 400 or greater. By default, TclCurl returns the page normally and does not treat such status codes as transfer errors. .IP This behavior is not fail-safe, and in some cases non-successful response codes may still pass through, especially when authentication is involved, as with status codes 401 and 407. .IP Some header data may be transferred before this condition is detected. For example, a \f(CR100-continue\fR response may be received for a POST or PUT request before a subsequent \f(CR401\fR or \f(CR407\fR response is returned. .SH NETWORK OPTIONS .TP 3 \fB-url\fR The URL to use for the transfer. .IP If the URL does not include a protocol part, such as \f(CRhttp://\fR or \f(CRftp://\fR, TclCurl attempts to guess the protocol from the host name. If the protocol specified in the URL is not supported, TclCurl returns the \fBunsupported protocol\fR error when you call \fBperform\fR. Use \fBcurl::versioninfo\fR for detailed information about the supported protocols. .IP Starting with version 7.22.0, the fragment part of the URI is no longer sent as part of the path, unlike earlier versions. .IP \fBNOTE\fR: This is the only option that must be set before \fBperform\fR is called. .TP 3 \fB-protocols\fR Pass a lowercase list of protocols to limit which protocols TclCurl may use for the transfer. This allows a TclCurl build that supports a wide range of protocols to be restricted for specific transfers to a subset of them. .IP Accepted protocols are \f(CRhttp\fR, \f(CRhttps\fR, \f(CRftp\fR, \f(CRftps\fR, \f(CRscp\fR, \f(CRsftp\fR, \f(CRtelnet\fR, \f(CRldap\fR, \f(CRldaps\fR, \f(CRdict\fR, \f(CRfile\fR, \f(CRtftp\fR, \f(CRimap\fR, \f(CRimaps\fR, \f(CRpop\fR, \f(CRpop3\fR, \f(CRsmtp\fR, \f(CRsmtps\fR, \f(CRgopher\fR, and \f(CRall\fR. .TP 3 \fB-redirprotocols\fR Pass a lowercase list of accepted protocols to limit which protocols TclCurl may use when following a redirect with \fB-followlocation\fR enabled. This allows specific transfers to be restricted to a subset of protocols for redirections. .IP By default, TclCurl allows all protocols except \f(CRFILE\fR and \f(CRSCP\fR. This differs from versions before 7.19.4, which would follow redirects to all supported protocols unconditionally. .TP 3 \fB-proxy\fR If you need to use an HTTP proxy, set the proxy string with this option. To specify a port number in the string, append \f(CR:[port]\fR to the end of the host name. The proxy string may be prefixed with \f(CR[protocol]://\fR, although such a prefix is ignored unless noted otherwise below. .IP When you configure an HTTP proxy, TclCurl transparently converts operations to HTTP even if you specify an FTP URL or another protocol. This may affect which library features are available. For example, \fBquote\fR and similar FTP-specific features do not work unless you tunnel through the HTTP proxy. Such tunneling is enabled with \fB-proxytunnel\fR. .IP TclCurl respects the environment variables \f(CRhttp_proxy\fR, \f(CRftp_proxy\fR, \f(CRall_proxy\fR, and others of the same kind, if they are set. Using this option overrides any such environment variables. .IP Setting the proxy string to \f(CR\(dq\(dq\fR explicitly disables proxy use, even if a corresponding environment variable is set. .IP The proxy host string can be specified in the same way as the proxy environment variables, including a protocol prefix such as \f(CRhttp://\fR and embedded user name and password information. .IP Since 7.22.0, the proxy string may include a \f(CRprotocol://\fR prefix to specify alternative proxy protocols. Use \f(CRsocks4://\fR, \f(CRsocks4a://\fR, \f(CRsocks5://\fR, or \f(CRsocks5h://\fR to request a specific SOCKS version. The last form enables SOCKS5 and asks the proxy to perform name resolution. If no protocol is specified, and for \f(CRhttp://\fR and all other prefixes, the proxy is treated as an HTTP proxy. .TP 3 \fB-proxyport\fR Use this option to set the proxy port unless it is already specified in the proxy string passed with \fB-proxy\fR. If not specified, TclCurl uses port \f(CR1080\fR by default. .TP 3 \fB-proxytype\fR Pass the proxy type. Available values are \f(CRhttp\fR, \f(CRhttp1.0\fR, \f(CRsocks4\fR, \f(CRsocks4a\fR, \f(CRsocks5\fR, and \f(CRsocks5h\fR. The default is \f(CRhttp\fR. .IP If you set it to \fIhttp1.0\fR, it will only affect how libcurl speaks to a proxy when CONNECT is used. The HTTP version used for ordinary HTTP requests is instead controlled by \fIhttpversion\fR. .TP 3 \fB-noproxy\fR Pass a string containing a comma-separated list of hosts that should not use a proxy, if one is specified. The only wildcard is a single \f(CR*\fR character, which matches all hosts and effectively disables the proxy. Each name in this list is matched either as a domain containing the host name, or as the host name itself. For example, \f(CRlocal.com\fR matches \f(CRlocal.com\fR, \f(CRlocal.com:80\fR, and \f(CRwww.local.com\fR, but not \f(CRwww.notlocal.com\fR. .TP 3 \fB-httpproxytunnel\fR Set this option to 1 to tunnel all non-HTTP operations through the given HTTP proxy. Using a proxy and tunneling through a proxy are different behaviors. This option should be enabled only when that distinction is required. .TP 3 \fB-socks5gssapiservice\fR Pass the service name. The default service name for a SOCKS5 server is \f(CRrcmd/server-fqdn\fR. This option allows you to change it. .TP 3 \fB-socks5gssapinec\fR Pass \f(CR1\fR to enable this option or \f(CR0\fR to disable it. As part of the GSSAPI negotiation, a protection mode is negotiated. RFC 1961 specifies in sections 4.3 and 4.4 that this exchange should be protected, but the NEC reference implementation does not do so. When enabled, this option allows the protection mode negotiation to be exchanged unprotected. .TP 3 \fB-interface\fR Pass the interface name to use as the outgoing network interface. The name may be an interface name, an IP address, or a host name. .TP 3 \fB-localport\fR Sets the local port number of the socket used for the connection. This can be used together with \fB-interface\fR, and it is recommended to use \fB-localportrange\fR as well when this option is set. Valid port numbers are \f(CR1\fR through \f(CR65535\fR. .TP 3 \fB-localportrange\fR Number of attempts TclCurl should make to find a working local port number. It starts with the port specified by \fB-localport\fR and increments it by one for each retry. Setting this value to \f(CR1\fR or less makes TclCurl try only one port number. Because port numbers are a limited resource and may already be in use, setting this value too low may cause unnecessary connection setup failures. .TP 3 \fB-dnscachetimeout\fR Pass the timeout in seconds. Name resolution results are kept in memory for this number of seconds. Set this option to \f(CR0\fR to disable caching completely, or to \f(CR-1\fR to keep cached entries indefinitely. By default, TclCurl caches this information for \f(CR60\fR seconds. .IP The name resolution functions in various libc implementations do not re-read name server information unless explicitly told to do so, for example by calling \fIres_init(3)\fR. As a result, TclCurl may continue to use older server information even after DHCP has updated it, which may appear to be a DNS cache issue. .TP 3 \fB-dnsuseglobalcache\fR If this option is set to \f(CR1\fR, TclCurl uses a global DNS cache that survives the creation and deletion of curl handles. This is not thread-safe because it relies on a global variable. \fIThis option was deprecated in libcurl v7.11.1 and is disabled by default in the TclCurl build. See \f(CIREADME.md\fI for instructions on how to re-enable it.\fR .IP \fBWARNING:\fR This option is obsolete. Use the share interface instead. See \fItclcurl_share\fR. .TP 3 \fB-buffersize\fR Pass the preferred size for the TclCurl receive buffer. A smaller buffer may cause the write callback to be invoked more often with smaller chunks. This value is treated as a request, not as a guarantee. .TP 3 \fB-port\fR Pass the remote port number to connect to instead of the port specified in the URL or the default port for the protocol in use. .TP 3 \fB-tcpnodelay\fR Pass a number to specify whether the \f(CRTCP_NODELAY\fR option should be set or cleared (\f(CR1\fR = set, \f(CR0\fR = clear). This option is cleared by default. It has no effect after the connection has been established. .IP Setting this option will disable TCP\(cqs Nagle algorithm. The purpose of this algorithm is to try to minimize the number of small packets on the network (where \(lqsmall packets\(rq means TCP segments less than the Maximum Segment Size (MSS) for the network). .IP Maximizing the amount of data sent per TCP segment is good because it amortizes the overhead of the send. However, in some cases (most notably telnet or rlogin) small segments may need to be sent without delay. This is less efficient than sending larger amounts of data at a time, and can contribute to congestion on the network if overdone. .TP 3 \fB-addressscope\fR Pass a number specifying the \f(CRscope_id\fR value to use when connecting to IPv6 link-local or site-local addresses. .SH NAMES AND PASSWORDS OPTIONS .TP 3 \fB-netrc\fR Set this option to make TclCurl scan your \fB\(ti/.netrc\fR file for the user name and password of the remote site you are about to access. TclCurl does not verify that the file has the correct properties set, as the standard Unix \f(CRftp\fR client does. Only machine name, user name, and password are taken into account; \f(CRinit\fR macros and similar entries are not supported. .IP Accepted values: .RS .TP 3 \f(CRoptional\fR Use of \fB\(ti/.netrc\fR is optional, and information in the URL takes precedence. The file is searched using the host and user name, to find the password only, or using the host name alone, to find the first user name and password for that machine, depending on which information is not specified in the URL. .RE .IP Undefined values for this option have the same effect. .RS .TP 3 \f(CRignored\fR TclCurl ignores the file and uses only the information in the URL. This is the default. .TP 3 \f(CRrequired\fR TclCurl requires use of the file, ignores the information in the URL, and searches the file using the host name only. .RE .TP 3 \fB-netrcfile\fR Pass a string containing the full path name of the file to use as the \f(CR.netrc\fR file. For this option to work, you must set \fB-netrc\fR to \fBrequired\fR. If this option is omitted and \fB-netrc\fR is set, TclCurl attempts to find a \f(CR.netrc\fR file in the current user\(cqs home directory. .TP 3 \fB-userpwd\fR Pass a string in the form \f(CR[username]:[password]\fR to use for the connection. Use \fB-httpauth\fR to select the authentication method. .IP When using NTLM, you can specify a domain by prepending it to the user name and separating the domain and name with a forward slash (\f(CR/\fR) or backward slash (\f(CR\e\e\fR), for example \f(CRdomain/user:password\fR or \f(CRdomain\e\euser:password\fR. Some HTTP servers on Windows also support this form for Basic authentication. .IP When using HTTP and \fB-followlocation\fR, TclCurl might perform several requests to possibly different hosts. TclCurl will only send this user and password information to hosts using the initial host name (unless \fB-unrestrictedauth\fR is set), so if TclCurl follows locations to other hosts it will not send the user and password to those. This is enforced to prevent accidental information leakage. .TP 3 \fB-proxyuserpwd\fR Pass a string in the form \f(CR[username]:[password]\fR to use for the connection to the HTTP proxy. .TP 3 \fB-username\fR Pass a string containing the user name to use for the transfer. It sets the user name used in protocol authentication. This option should not be used together with the older \fB-userpwd\fR option. .IP To specify the password to use together with the user name, use the \fB-password\fR option. .TP 3 \fB-password\fR Pass a string containing the password to use for the transfer. .IP This option should be used together with \fB-username\fR. .TP 3 \fB-proxyusername\fR Pass a string containing the user name to use for the transfer while connecting to the proxy. .IP This option is used in the same way as \fB-proxyuserpwd\fR, except that it allows the user name to contain a colon, as in \f(CRsip:user@example.com\fR. .IP \fB-proxyusername\fR is an alternative way to set the user name while connecting to the proxy. It should not be used together with \fB-proxyuserpwd\fR. .TP 3 \fB-proxypassword\fR Pass a string containing the password to use for the transfer while connecting to the proxy. This option is intended to be used together with \fB-proxyusername\fR. .TP 3 \fB-httpauth\fR Set this option to the authentication method to use. Accepted values are: .RS .TP 3 \f(CRbasic\fR HTTP Basic authentication. This is the default choice and the only method in widespread use that is supported almost everywhere. It sends the user name and password over the network in plain text. .TP 3 \f(CRdigest\fR HTTP Digest authentication. Over public networks, this is generally more secure than Basic authentication. .TP 3 \f(CRdigestie\fR HTTP Digest authentication with an Internet Explorer-specific variant. TclCurl uses a compatibility behavior known to have been used by Internet Explorer before version 7 and still required by some servers. .TP 3 \f(CRgssnegotiate\fR HTTP GSS-Negotiate authentication. This method, also known simply as \f(CRNegotiate\fR, was designed by Microsoft and is used in Microsoft web applications. It is primarily intended to support Kerberos 5 authentication, but it may also be used with other authentication methods. .TP 3 \f(CRntlm\fR HTTP NTLM authentication. This is a proprietary protocol developed and used by Microsoft. It uses a challenge-response mechanism and hashing, similar to Digest, to avoid sending the password in clear text. .TP 3 \f(CRntlmwb\fR NTLM delegated to the winbind helper. Authentication is performed by a separate binary application that is executed when needed. The name of that application is specified when libcurl is built, but it is typically \f(CR/usr/bin/ntlm_auth\fR. .RE .IP Note that libcurl will fork when necessary to run the winbind application and kill it when complete, calling waitpid() to await its exit when done. On POSIX operating systems, killing the process will cause a SIGCHLD signal to be raised (regardless of whether \fB-nosignal\fR is set). This behavior is subject to change in future versions of libcurl. .RS .TP 3 \f(CRany\fR TclCurl automatically selects the method it considers the most secure. .TP 3 \f(CRanysafe\fR TclCurl may use any method except Basic and automatically selects the one it considers the most secure. .RE .TP 3 \fB-tlsauthtype\fR Selects the authentication method to use for TLS authentication. .IP Accepted values: .RS .TP 3 \f(CRtlsauthsrp\fR Uses TLS-SRP authentication. Secure Remote Password authentication for TLS is defined in RFC 5054 and provides mutual authentication if both sides share a secret. To use this value, you must also set \fB-tlsauthusername\fR and \fB-tlsauthpassword\fR. .RE .IP libcurl must be built with GnuTLS or with OpenSSL support for TLS-SRP for this to work. .TP 3 \fB-tlsauthusername\fR Pass a string containing the user name to use for the TLS authentication method specified with \fB-tlsauthtype\fR. This option requires \fB-tlsauthpassword\fR to be set as well. .TP 3 \fB-tlsauthpassword\fR Pass a string containing the password to use for the TLS authentication method specified with \fB-tlsauthtype\fR. This option requires \fB-tlsauthusername\fR to be set as well. .TP 3 \fB-proxyauth\fR Use this option to tell TclCurl which authentication method to use for proxy authentication. For some methods, this causes an extra network round trip. Set the actual user name and password with \fB-proxyuserpwd\fR. .IP The methods are those listed above for the \fBhttpauth\fR option. As of this writing, only Basic and NTLM work. .SH HTTP OPTIONS .TP 3 \fB-autoreferer\fR Set this option to \f(CR1\fR to enable automatic updates of the \f(CRReferer:\fR header when TclCurl follows a \f(CRLocation:\fR redirect. .TP 3 \fB-encoding\fR Sets the contents of the \f(CRAccept-Encoding:\fR header sent in an HTTP request, and enables decoding of a response when a \f(CRContent-Encoding:\fR header is received. .IP Accepted values: .RS .TP 3 \f(CRidentity\fR Requests no encoding. .TP 3 \f(CRdeflate\fR Requests compression using the zlib algorithm. .TP 3 \f(CRgzip\fR Requests gzip compression. .TP 3 \f(CRall\fR Sends an \f(CRAccept-Encoding:\fR header containing all supported encodings. .RE .IP This is a request, not a requirement; the server may or may not honor it. This option must be set or any unsolicited encoding used by the server is ignored. See \f(CRlib/README.encoding\fR in the libcurl documentation for details. .TP 3 \fB-transferencoding\fR Adds a request for compressed \f(CRTransfer-Encoding\fR in the outgoing HTTP request. If the server supports this and chooses to use it, the response may use a compressed \f(CRTransfer-Encoding\fR, which TclCurl then decompresses automatically when receiving the data. .IP \f(CRTransfer-Encoding\fR differs from the \f(CRContent-Encoding\fR requested with \fB-encoding\fR in that \f(CRTransfer-Encoding\fR applies strictly to the transfer and therefore must be decoded before the data reaches the client. Traditionally, \f(CRTransfer-Encoding\fR has been used less widely and is less consistently supported by HTTP clients and servers. .TP 3 \fB-followlocation\fR Set this option to \f(CR1\fR to make TclCurl follow any .IP \f(CRLocation:\fR header .IP sent by the server as part of an HTTP response. .IP TclCurl resends the request to the new location and continues to follow further \f(CRLocation:\fR headers until no more are returned. Use \fB-maxredirs\fR to limit the number of redirects TclCurl follows. .IP Since 7.19.4, TclCurl can also restrict which protocols it follows automatically. The accepted protocols are set with \fB-redirprotocols\fR. By default, the \f(CRFILE\fR protocol is excluded. .TP 3 \fB-unrestrictedauth\fR Set this option to \f(CR1\fR to allow TclCurl to continue sending authentication credentials when following redirects, even if the host name changes. This option is meaningful only when \fB-followlocation\fR is enabled. .TP 3 \fB-maxredirs\fR Sets the redirection limit. After that many redirects have been followed, the next redirect causes an error. This option is meaningful only when \fB-followlocation\fR is enabled. Set the limit to \f(CR0\fR to refuse all redirects. Set it to \f(CR-1\fR for an unlimited number of redirects, which is the default. .TP 3 -postredir Controls how TclCurl acts on redirects after POST requests that receive a \f(CR301\fR, \f(CR302\fR, or \f(CR303\fR response. Accepted values are \f(CR301\fR, \f(CR302\fR, \f(CR303\fR, and \f(CRall\fR. The values \f(CR301\fR, \f(CR302\fR, and \f(CR303\fR make TclCurl preserve the POST request method for the corresponding redirect status code. The value \f(CRall\fR enables all three behaviors. .IP The non-RFC behavior is common in web browsers, so TclCurl performs this conversion by default to maintain consistency. However, a server may require a POST to remain a POST after such a redirection. .IP This option is meaningful only when \fB-followlocation\fR is enabled. .IP The legacy alias \fB-post301\fR is accepted for compatibility and uses the same values. .TP 3 \fB-put\fR Set this option to \f(CR1\fR to make TclCurl upload a file using HTTP \f(CRPUT\fR. The file to upload must be specified with \fB-infile\fR and \fB-infilesize\fR. .IP This option is deprecated as of version 0.12.1. Use \fB-upload\fR. .IP This option does not limit how much data TclCurl will actually send, as that is controlled entirely by what the read callback returns. .TP 3 \fB-post\fR Set this option to \f(CR1\fR to make TclCurl perform a regular HTTP \f(CRPOST\fR request using the \f(CRapplication/x-www-form-urlencoded\fR format commonly used by HTML forms. Use \fB-postfields\fR to specify the data to post and \fB-postfieldsize\fR to specify its size. .IP Use the \fB-postfields\fR option to specify what data to post and \fB-postfieldsize\fR to set the data size. Optionally, you can also provide \f(CRPOST\fR data using \fB-readproc\fR. .IP You can override the default \f(CRPOST\fR \f(CRContent-Type:\fR header by setting your own with \fB-httpheader\fR. .IP Using \f(CRPOST\fR with HTTP 1.1 implies the use of an \f(CRExpect: 100-continue\fR header. You can disable this header with \fB-httpheader\fR as usual. .IP If you use \f(CRPOST\fR with an HTTP 1.1 server, you can send data without knowing the size in advance by using chunked encoding. Enable this by adding a header such as \f(CRTransfer-Encoding: chunked\fR with \fB-httpheader\fR. With HTTP 1.0, or without chunked transfer encoding, you must specify the size in the request. .IP Setting \fB-post\fR to \f(CR1\fR also sets \fB-nobody\fR to \f(CR0\fR. .IP \fBNOTE:\fR If you have issued a \f(CRPOST\fR request and later want to make a \f(CRHEAD\fR or \f(CRGET\fR request instead, you must explicitly select the new request type with \fB-nobody\fR, \fB-httpget\fR, or a similar option. .TP 3 \fB-postfields\fR Pass a string containing the complete data to send in an HTTP \f(CRPOST\fR request. You must ensure that the data is formatted exactly as you want the server to receive it. TclCurl does not convert or encode it for you. Most web servers assume this data is URL-encoded. .IP This is the normal \f(CRapplication/x-www-form-urlencoded\fR form, which is the most commonly used one by HTML forms. .IP If you want to do a zero-byte POST, you need to set \fB-postfieldsize\fR explicitly to zero, because setting \fB-postfields\fR to \f(CRNULL\fR or \f(CR\(dq\(dq\fR effectively disables sending the specified string. TclCurl then assumes that the \f(CRPOST\fR data is supplied through the read callback. .IP Using \f(CRPOST\fR with HTTP 1.1 implies the use of an \f(CRExpect: 100-continue\fR header. You can disable this header with \fB-httpheader\fR as usual. .IP \fBNOTE:\fR To make \f(CRmultipart/form-data\fR posts, see \fB-httppost\fR. .TP 3 \fB-postfieldsize\fR Use this option to post data without letting TclCurl call \f(CRstrlen()\fR to determine the data size. This is also required if you want to post fully binary data, which would otherwise likely fail. If this size is set to zero, the library uses \f(CRstrlen()\fR to determine the data size. .TP 3 \fB-httppost\fR Makes TclCurl perform an HTTP \f(CRmultipart/form-data\fR \f(CRPOST\fR request. The data to send is described through a Tcl list. .IP \fBThis is the only case where the data is reset after a transfer.\fR .IP Each part consists of at least a \fBNAME\fR and a \fBCONTENTS\fR part. If the part is used for file upload, it may also contain \fBCONTENT-TYPE\fR and \fBFILENAME\fR information. .IP The list must contain a \fB\(oqname\(cq\fR tag followed by the section name. The section value can then be described with \fB\(oqvalue\(cq\fR, followed by a string containing the data to post, \fB\(oqfile\(cq\fR, followed by the name of the file to post, or \fB\(oqcontenttype\(cq\fR, followed by the content type (\f(CRtext/plain\fR, \f(CRimage/jpg\fR, and so on). You can also supply an alternate file name with \fB\(oqfilename\(cq\fR. This is useful if the server checks whether the provided file name is valid, or if you want to include the full path of the file being posted. You can also post the contents of a variable as if it were a file by using \fB\(oqbufferName\(cq\fR and \fB\(oqbuffer\(cq\fR, or use \fB\(oqfilecontent\(cq\fR followed by a file name to read that file and use its contents as data. .IP To specify additional headers for a form section, use \fB\(oqcontentheader\(cq\fR followed by a list of headers. .IP See \f(CRhttpPost.tcl\fR and \f(CRhttpBufferPost.tcl\fR for examples. .IP Return values: .RS .TP 3 \f(CR1\fR If the memory allocation fails. .TP 3 \f(CR2\fR If one option is given twice for one form. .TP 3 \f(CR3\fR If an empty string was given. .TP 3 \f(CR4\fR If an unknown option was used. .TP 3 \f(CR5\fR If some form information is incomplete or invalid. .TP 3 \f(CR6\fR If an illegal option is used in an array. .TP 3 \f(CR7\fR If TclCurl has no HTTP support. .RE .TP 3 \fB-referer\fR Pass a string to set the \f(CRReferer:\fR header in the HTTP request sent to the remote server. .IP The \f(CRReferer:\fR header identifies the resource from which the target URI was obtained. Servers may use it for logging, analytics, backlink generation, caching decisions, or request-flow checks. .IP This option is useful when a scripted client must reproduce the request context normally sent by a web browser, or when a server expects a specific referring URI. .IP The header value should normally be a URI identifying the referring resource. Fragments and userinfo components are not part of a valid \f(CRReferer:\fR field value. .IP The field name \f(CRReferer\fR is a historical misspelling of \f(CRreferrer\fR, but the misspelled form is the standardized HTTP header name. .IP Because this header may reveal navigation context or sensitive URI data, it should be set with care. It should not be relied upon as a secure means of authentication or access control. .IP You can also set this header through \fB-httpheader\fR. .TP 3 \fB-useragent\fR Pass a string to set the \f(CRUser-Agent:\fR header in the HTTP request sent to the remote server. You can also set custom headers with \fB-httpheader\fR. .TP 3 \fB-httpheader\fR Pass a list of HTTP headers to send in the request. If you add a header that TclCurl would otherwise generate internally, your header is used instead. If you add a header with no value, such as \f(CRAccept:\fR, the internal header is disabled. This option can therefore be used to add, replace, or remove internal headers. .IP This option is useful when the request must include headers not exposed by dedicated TclCurl options, or when you need exact control over the final HTTP request. Common uses include setting custom authentication-related headers, API-specific headers, cache-control directives, or overriding headers such as \f(CRContent-Type:\fR or \f(CRAccept:\fR. .IP The headers in the list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. If you include CRLF yourself, the server will likely ignore part of the headers you specified. .IP The first line of a request, containing the method, usually \f(CRGET\fR or \f(CRPOST\fR, is not a header and cannot be replaced with this option. Only the lines following the request line are headers. Adding the method line to this list causes an invalid header to be sent. .IP \fBNOTE:\fR The most commonly replaced headers have dedicated shortcut options: \fB-cookie\fR, \fB-useragent\fR, and \fB-referer\fR. .TP 3 \fB-http200aliases\fR Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers return a custom response line. For example, IceCast servers may return \f(CRICY 200 OK\fR. If you include such a string in the list, it is treated as a valid HTTP status line such as \f(CRHTTP/1.0 200 OK\fR. .IP \fBNOTE:\fR The alias itself is not parsed for a version string. Before version 7.16.3, TclCurl used the value set by \fB-httpversion\fR, but since 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matches. .TP 3 \fB-cookie\fR Pass a string to set a cookie in the HTTP request. The string should use the format \f(CR[NAME]=[CONTENTS];\fR, where \f(CRNAME\fR is the cookie name and \f(CRCONTENTS\fR is the cookie value. .IP If you need to set multiple cookies, you must set them all in a single option value by concatenating them into one string, for example \f(CRname1=content1; name2=content2;\fR. .IP This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are performed because of authentication, redirects, or similar causes, they all receive this cookie header. .IP If this option is used multiple times, only the last value is kept. .TP 3 \fB-cookiefile\fR Pass the name of a file containing cookie data. The cookie data may be in Netscape cookie file format or in regular HTTP-style headers written to a file. .IP If the file is empty or does not exist, this option still enables cookies for the handle, causing TclCurl to parse received cookies and use matching cookies in later requests. .IP If you use this option multiple times, each use adds another file to read. .TP 3 \fB-cookiejar\fR Pass a file name to which TclCurl writes all internally known cookies when \fBcurlHandle cleanup\fR is called. If no cookies are known, no file is created. Specify \f(CR-\fR to write the cookies to standard output. .IP Using this option also enables cookies for the session, so matching cookies are sent on later requests, including those caused by redirects. .IP TclCurl cannot report an error if writing the cookie jar fails. If \fB-verbose\fR is enabled, a warning is displayed, but that is the only visible feedback in this case. .TP 3 \fB-cookiesession\fR Set this option to \f(CR1\fR to mark the current run as a new cookie session. This makes TclCurl ignore session cookies loaded from a previous session. By default, TclCurl stores and loads all cookies, including session cookies. Session cookies are cookies without an expiry date and are meant to exist only for the current session. .TP 3 \fB-cookielist\fR Pass a string containing a cookie. The cookie may be in Netscape/Mozilla format or in regular HTTP-style header form, such as \f(CRSet-Cookie: ...\fR. If the cookie engine is not enabled, it is enabled automatically. .IP Special values are \f(CRALL\fR, which erases all known cookies, and \f(CRFLUSH\fR, which writes all known cookies to the file specified by \fB-cookiejar\fR. .TP 3 \fB-httpget\fR Set this option to \f(CR1\fR to force the HTTP request method back to \f(CRGET\fR. This is useful if \f(CRPOST\fR, \f(CRPUT\fR, or a custom request has previously been used with the same handle. .IP Setting \fB-httpget\fR to \f(CR1\fR also sets \fB-nobody\fR to \f(CR0\fR. .TP 3 \fB-httpversion\fR Selects the HTTP version to use. This option should be used only when it is necessary to override the default behavior because of server-side requirements. .IP Accepted values: .RS .TP 3 \f(CRnone\fR Lets TclCurl use the HTTP version it considers appropriate. .TP 3 \f(CR1.0\fR Enforce HTTP 1.0 requests. .TP 3 \f(CR1.1\fR Enforce HTTP 1.1 requests. .TP 3 \f(CR2.0\fR Enforce HTTP version 2 requests. .TP 3 \f(CR2TLS\fR Enforce version 2 requests for HTTPS, version 1.1 for HTTP. .TP 3 \f(CR2_PRIOR_KNOWLEDGE\fR Enforce HTTP 2 requests without performing an HTTP/1.1 \f(CRUpgrade\fR first. .RE .TP 3 \fB-ignorecontentlength\fR Ignores the \f(CRContent-Length\fR header. This is useful for Apache 1.x and similar servers, which may report an incorrect content length for files larger than 2 gigabytes. If this option is used, TclCurl cannot report progress accurately and stops the download only when the server closes the connection. .TP 3 \fB-httpcontentdecoding\fR Set this option to \f(CR0\fR to disable content decoding, or to \f(CR1\fR to enable it. TclCurl does not enable content decoding by default; for that, you must also use \fB-encoding\fR. .TP 3 \fB-httptransferencoding\fR Set this option to \f(CR0\fR to disable transfer decoding, or to \f(CR1\fR to enable it. The default is \f(CR1\fR. TclCurl performs chunked transfer decoding by default unless this option is disabled. .SH SMTP OPTIONS .TP 3 \fB-mailfrom\fR Pass a string specifying the sender address to use in the SMTP envelope. .IP This option controls the envelope sender used at the SMTP protocol level. It does not set or modify the \f(CRFrom:\fR header field in the message body. .TP 3 \fB-mailrcpt\fR Pass a list of recipient addresses to use in the SMTP envelope. .IP This option controls the envelope recipients used at the SMTP protocol level. It does not set or modify message header fields such as \f(CRTo:\fR, \f(CRCc:\fR, or \f(CRBcc:\fR. .IP In SMTP, recipients are specified with angle brackets (\f(CR<>\fR). If a recipient value does not begin with an angle bracket, TclCurl assumes that it is a plain email address and adds the angle brackets automatically. .SH TFTP OPTION .TP 3 \fB-tftpblksize\fR Specifies the block size to use for TFTP data transmission. According to RFC 2348, valid values range from \f(CR8\fR to \f(CR65464\fR bytes. If this option is not specified, the default block size is \f(CR512\fR bytes. .IP The requested block size is used only if the remote server supports it. If the server does not return an option acknowledgment, or if it returns an acknowledgment without a block size value, the default of \f(CR512\fR bytes is used. .SH FTP OPTIONS .TP 3 \fB-ftpport\fR Pass a string identifying the address to use for the FTP \f(CRPORT\fR instruction. The \f(CRPORT\fR instruction tells the remote server to connect to the specified client address. The string may be a plain IP address, a host name, a network interface name on Unix, or simply \f(CR-\fR to let the library use the system\(cqs default IP address. By default, FTP transfers are passive, so \f(CRPORT\fR is not used. .IP The address can be followed by \f(CR:\fR and a port number, optionally followed by \f(CR-\fR and a port range. If the port specified is \f(CR0\fR, the operating system chooses a free port. If a range is provided and no port in that range is available, libcurl reports \f(CRCURLE_FTP_PORT_FAILED\fR for the handle. Invalid port or port-range settings are ignored. IPv6 addresses followed by a port or port range must be enclosed in brackets. IPv6 addresses without a port or port range may also be enclosed in brackets. .IP Examples: .IP \f(CReth0:0\fR \f(CR192.168.1.2:32000-33000\fR \f(CRcurl.se:32123\fR \f(CR[::1]:1234-4567\fR .IP To disable \f(CRPORT\fR and return to passive mode, set this option to the empty string. .TP 3 \fB-quote\fR Pass a list of FTP or SFTP commands to send to the server before the FTP transfer request. These commands are sent before any other FTP commands, including \f(CRCWD\fR. If you do not want to transfer any files, set \fB-nobody\fR to \f(CR1\fR and \fB-header\fR to \f(CR0\fR. .IP Prefix a command with an asterisk (\f(CR*\fR) to make TclCurl continue even if that command fails. By default, a failure stops the transfer. .IP To disable this option, set it to the empty string. .IP The commands must be raw FTP commands. For example, to create a directory you must send \f(CRmkd Test\fR, not \f(CRmkdir Test\fR. .IP Valid SFTP commands are \f(CRchgrp\fR, \f(CRchmod\fR, \f(CRchown\fR, \f(CRln\fR, \f(CRmkdir\fR, \f(CRpwd\fR, \f(CRrename\fR, \f(CRrm\fR, \f(CRrmdir\fR, and \f(CRsymlink\fR. .TP 3 \fB-postquote\fR Pass a list of FTP commands to send to the server after the FTP transfer request. If you do not want to transfer any files, set \fB-nobody\fR to \f(CR1\fR and \fB-header\fR to \f(CR0\fR. .TP 3 \fB-prequote\fR Pass a list of FTP or SFTP commands to send to the server after the transfer type has been set. .TP 3 \fB-dirlistonly\fR Set this option to \f(CR1\fR to list only file names in a directory instead of requesting a full directory listing with file sizes, dates, and similar information. This option works with both FTP and SFTP URLs. .IP For FTP, this causes an \f(CRNLST\fR command to be sent. Some FTP servers return only files in response to \f(CRNLST\fR, and may omit subdirectories and symbolic links. .IP Setting this option to \f(CR1\fR also implies a directory listing even if the URL does not end with a slash, which would otherwise be required. .IP Do not use this option together with \fB-wildcardmatch\fR, as it effectively disables that feature. .TP 3 \fB-append\fR Set this option to \f(CR1\fR to append to the remote file instead of overwriting it. This is useful only when uploading to an FTP site. .TP 3 \fB-ftpuseeprt\fR Set this option to \f(CR1\fR to make TclCurl use the \f(CREPRT\fR and \f(CRLPRT\fR commands for active FTP transfers, which are enabled with \fB-ftpport\fR. When this option is enabled, TclCurl first attempts \f(CREPRT\fR, then \f(CRLPRT\fR, and only then falls back to \f(CRPORT\fR. If this option is set to \f(CR0\fR, only \f(CRPORT\fR is used. .TP 3 \fB-ftpuseepsv\fR Set this option to \f(CR1\fR to make TclCurl use the \f(CREPSV\fR command for passive FTP transfers. This is the default behavior. When enabled, TclCurl first attempts \f(CREPSV\fR before using \f(CRPASV\fR. If this option is set to \f(CR0\fR, TclCurl uses only \f(CRPASV\fR. .TP 3 \fB-ftpusepret\fR Set this option to \f(CR1\fR to make TclCurl send a \f(CRPRET\fR command before \f(CRPASV\fR or \f(CREPSV\fR. Some FTP servers, especially \f(CRdrftpd\fR, require this non-standard command for directory listings and uploads or downloads in passive mode. This option has no effect for active FTP transfers. .TP 3 \fB-ftpcreatemissingdirs\fR Controls whether TclCurl should attempt to create a remote directory when the transfer requires that directory to exist, but a \f(CRCWD\fR command shows that it does not yet exist or cannot yet be entered. .IP This setting also applies to SFTP connections. TclCurl attempts to create the remote directory if it cannot obtain a handle to the target location. Creation fails if a file with the same name already exists, or if permissions do not allow directory creation. .IP Accepted values: .RS .TP 3 \f(CR1\fR After a failed \f(CRCWD\fR, TclCurl attempts to create the missing remote directory and then continues with the transfer. .TP 3 \f(CR2\fR After a failed \f(CRCWD\fR, TclCurl attempts to create the missing remote directory. If the subsequent \f(CRMKD\fR command fails, TclCurl retries the \f(CRCWD\fR command before giving up. This is useful when multiple simultaneous connections target the same server and another connection may have created the directory in the meantime. .RE .TP 3 \fB-ftpresponsetimeout\fR Sets a timeout, in seconds, for how long the server may take to return a response to an FTP command before the session is considered hung. While TclCurl is waiting for such a response, this value overrides \fB-timeout\fR. If both options are used, \fB-ftpresponsetimeout\fR should normally be set to a value smaller than \fB-timeout\fR. .TP 3 \fB-ftpalternativetouser\fR Pass a string to use for authentication if the usual FTP \f(CRUSER user\fR and \f(CRPASS password\fR negotiation fails. This is known to be required in some cases when connecting to Tumbleweed Secure Transport FTPS servers that use client-certificate authentication. .TP 3 \fB-ftpskippasvip\fR Set this option to \f(CR1\fR to make TclCurl ignore the IP address suggested by the server in its \f(CR227\fR response to TclCurl\(cqs \f(CRPASV\fR command when opening the data connection. TclCurl instead reuses the same IP address already in use for the control connection, while still using the port number from the \f(CR227\fR response. .IP This option has no effect if \f(CRPORT\fR, \f(CREPRT\fR, or \f(CREPSV\fR is used instead of \f(CRPASV\fR. .TP 3 \fB-ftpsslauth\fR Selects how TclCurl issues \f(CRAUTH TLS\fR or \f(CRAUTH SSL\fR when FTP over SSL is enabled with \fB-ftpssl\fR. .IP This option may be needed for servers such as BSDFTPD-SSL, which do not handle \f(CRAUTH SSL\fR correctly and require \f(CRAUTH TLS\fR instead. .IP Accepted values: .RS .TP 3 \f(CRdefault\fR Lets TclCurl choose. .TP 3 \f(CRssl\fR Tries \f(CRAUTH SSL\fR first, and tries \f(CRAUTH TLS\fR only if that fails. .TP 3 \f(CRtls\fR Tries \f(CRAUTH TLS\fR first, and tries \f(CRAUTH SSL\fR only if that fails. .RE .TP 3 \fB-ftpsslccc\fR Controls use of CCC (Clear Command Channel). CCC shuts down the SSL/TLS layer after authentication, so the remainder of the control channel is unencrypted. This can allow NAT routers to inspect the FTP control channel. .IP Accepted values are: .RS .TP 3 \f(CRnone\fR Do not attempt to use CCC. .TP 3 \f(CRpassive\fR Do not initiate the shutdown. Wait for the server to do so, and do not send a reply. .TP 3 \f(CRactive\fR Initiate the shutdown and wait for a reply. .RE .TP 3 \fB-ftpaccount\fR Pass a string containing account data, or \f(CR\(dq\(dq\fR to disable it. If an FTP server requests account data after the user name and password have been provided, TclCurl sends this value with the \f(CRACCT\fR command. .TP 3 \fB-ftpfilemethod\fR Selects how TclCurl navigates FTP paths. Accepted values are: .RS .TP 3 \f(CRmulticwd\fR The default. TclCurl performs one \f(CRCWD\fR operation for each path component in the URL. For deep hierarchies this may require many commands. This is the method described by RFC 1738. .TP 3 \f(CRnocwd\fR TclCurl does not perform \f(CRCWD\fR at all. Instead it sends commands such as \f(CRSIZE\fR, \f(CRRETR\fR, and \f(CRSTOR\fR with the full path. .TP 3 \f(CRsinglecwd\fR TclCurl performs one \f(CRCWD\fR to the full target directory and then operates on the file normally. This is somewhat more standards compliant than \f(CRnocwd\fR, without the full overhead of \f(CRmulticwd\fR. .RE .SH PROTOCOL OPTIONS .TP 3 \fB-transfertext\fR Set this option to \f(CR1\fR to use ASCII mode for FTP transfers instead of the default binary transfer mode. On Win32 systems, this does not set \f(CRstdout\fR to binary mode. This option can be useful when transferring text data between systems that treat characters such as newlines differently. .IP \fBNOTE:\fR TclCurl does not perform full ASCII conversion during ASCII FTP transfers. It simply sets the transfer mode to ASCII and performs a normal transfer. .TP 3 \fB-proxytransfermode\fR Set this option to \f(CR1\fR to make TclCurl set the transfer mode, binary or ASCII, for FTP transfers performed through an HTTP proxy by appending \f(CR;type=a\fR or \f(CR;type=i\fR to the URL. If this option is omitted or set to \f(CR0\fR, \fB-transfertext\fR has no effect for FTP transfers performed through an HTTP proxy. Not all proxies support this feature. .TP 3 \fB-crlf\fR Set this option to \f(CR1\fR to make TclCurl convert Unix newlines to CRLF newlines during transfers. Set it to \f(CR0\fR to disable this behavior. .TP 3 \fB-range\fR Pass a string specifying the requested range. The format is \f(CRX-Y\fR, where either \f(CRX\fR or \f(CRY\fR may be omitted. HTTP transfers also support multiple ranges separated by commas, as in \f(CRX-Y,N-M\fR. When multiple ranges are requested over HTTP, the server returns the response document in pieces using standard MIME separation rules. .IP Range requests are supported only for HTTP, FTP, and FILE transfers. .TP 3 \fB-resumefrom\fR Pass the offset, in bytes, at which the transfer should start. Set this option to \f(CR0\fR to start the transfer from the beginning, which disables resume behavior. .IP For FTP, set this option to \f(CR-1\fR to start from the end of the target file, which is useful when continuing an interrupted upload. .IP For FTP uploads, the resume position specifies where in the local source file TclCurl should resume reading. The data read from that point is then appended to the remote target file. .TP 3 \fB-customrequest\fR Pass a string containing the request method to use instead of the default method, such as \f(CRGET\fR or \f(CRHEAD\fR, when making an HTTP request. This is useful for methods such as \f(CRDELETE\fR and other less common HTTP requests. Use this option only when the server is known to support the specified method. .IP TclCurl still behaves internally according to the type of request it would otherwise have used. As a result, changing the request method with this option can produce inconsistent behavior if the corresponding request type is not selected through the usual dedicated option. For example, to make a proper \f(CRHEAD\fR request, use \fB-nobody\fR. To make a proper \f(CRPOST\fR request, use \fB-post\fR or \fB-postfields\fR. .TP 3 \fB-filetime\fR Set this option to \f(CR1\fR to make TclCurl attempt to obtain the modification time of the remote document during the transfer. This requires the remote server either to send the time directly or to support a command for querying it. After the transfer, the \f(CRfiletime\fR value can be retrieved with the \f(CRgetinfo\fR procedure. .IP For FTP transfers, this typically means that the server must support a command for querying the remote file modification time, such as \f(CRMDTM\fR. If the server does not provide this information, the transfer can still succeed, but the retrieved \f(CRfiletime\fR value remains unknown. .TP 3 \fB-nobody\fR Set this option to \f(CR1\fR to omit the body from the output. This is relevant only for protocols that distinguish between a header part and a body part. For HTTP and HTTPS, this causes TclCurl to issue a \f(CRHEAD\fR request. .IP To change the request back to \f(CRGET\fR, use \fB-httpget\fR. To switch to \f(CRPOST\fR, use \fB-post\fR or a related option. .TP 3 \fB-infilesize\fR Use this option when uploading a file to specify the expected size of the input file. .IP This option is mandatory for uploads performed with SCP. .TP 3 \fB-upload\fR Set this option to \f(CR1\fR to prepare for an upload. The \fB-infile\fR and \fB-infilesize\fR options are also relevant for uploads. If the protocol is HTTP, uploading means using the PUT request unless you tell TclCurl otherwise. .IP Using PUT with HTTP 1.1 implies the use of a \(lqExpect: 100-continue\(rq header. You can disable this header with \fB-httpheader\fR as usual. .IP If you use PUT to a HTTP 1.1 server, you can upload data without knowing the size before starting the transfer if you use chunked encoding. You enable this by adding a header like \(lqTransfer-Encoding: chunked\(rq with \fB-httpheader\fR. With HTTP 1.0 or without chunked transfer, you must specify the size. .TP 3 -maxfilesize This allows you to specify the maximum size (in bytes) of a file to download. If the file requested is larger than this value, the transfer will not start and error \(oqfilesize exceeded\(cq (63) will be returned. .IP NOTE: The file size is not always known prior to download, and for such files this option has no effect even if the file transfer ends up being larger than this given limit. This concerns both FTP and HTTP transfers. .TP 3 -timecondition Defines how the \fBtimevalue\fR value is treated. Accepted values are \f(CRifmodsince\fR and \f(CRifunmodsince\fR. This feature applies to HTTP, FTP, and FILE. .TP 3 -timevalue This should be the time in seconds since 1 jan 1970, and the time will be used in a condition as specified with \fBtimecondition\fR. .SH CONNECTION OPTIONS .TP 3 \fB-timeout\fR Pass the maximum time, in seconds, that a TclCurl transfer operation may take. Name resolution alone may take a noticeable amount of time, so setting this value too low can abort otherwise normal operations. .IP This option may cause libcurl to use \f(CRSIGALRM\fR to interrupt blocking system calls. On Unix-like systems, signals may therefore be used unless \fB-nosignal\fR is enabled. .TP 3 \fB-timeoutms\fR Like \fB-timeout\fR, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity. .TP 3 \fB-lowspeedlimit\fR Pass the speed, in bytes per second, below which the transfer rate must remain during \fB-lowspeedtime\fR seconds before TclCurl considers the transfer too slow and aborts it. .TP 3 \fB-lowspeedtime\fR Pass the number of seconds during which the transfer speed must stay below \fB-lowspeedlimit\fR before TclCurl considers the transfer too slow and aborts it. .TP 3 \fB-maxsendspeed\fR Pass a speed in bytes per second. If an upload exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed. .TP 3 \fB-maxrecvspeed\fR Pass a speed in bytes per second. If a download exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed. .TP 3 \fB-maxconnects\fR Sets the size of the persistent connection cache for protocols that support persistent connections. This value is the maximum number of simultaneous connections TclCurl may cache in the easy handle. The default is \f(CR5\fR. .IP When the maximum is reached, TclCurl closes the oldest cached connection to prevent the number of open connections from increasing further. .IP \fBNOTE:\fR If transfers have already been performed with this easy handle, reducing \fB-maxconnects\fR may cause existing open connections to be closed earlier than expected. .IP If this easy handle is added to a multi handle, this setting is ignored. In that case, configure the corresponding \fBmaxconnects\fR option on the multi handle instead. .TP 3 \fB-connecttimeout\fR Pass the maximum time, in seconds, that the connection phase may take. This limits only the time required to establish the connection. Once the connection has been established, this option no longer applies. Set it to \f(CR0\fR to disable the connection timeout. .IP On Unix-like systems, signals may be used unless \fB-nosignal\fR is enabled. .TP 3 \fB-connecttimeoutms\fR Like \fB-connecttimeout\fR, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity. .TP 3 \fB-ipresolve\fR Selects which IP address families may be used when resolving host names. This option is relevant only when a host name resolves to more than one IP version. .IP Accepted values are: .RS .TP 3 \f(CRwhatever\fR The default. Resolves addresses using all IP versions supported by the system. .TP 3 \f(CRv4\fR Resolves only IPv4 addresses. .TP 3 \f(CRv6\fR Resolves only IPv6 addresses. .RE .TP 3 \fB-resolve\fR Pass a list of host name resolution entries to use for requests made with this handle. .IP Each entry must use the format \f(CRHOST:PORT:ADDRESS\fR, where \f(CRHOST\fR is the name TclCurl tries to resolve, \f(CRPORT\fR is the destination service port, and \f(CRADDRESS\fR is the numeric IP address to use. If libcurl supports IPv6, \f(CRADDRESS\fR may be either an IPv4 or an IPv6 address. .IP This option effectively pre-populates the DNS cache with entries for a given \f(CRHOST:PORT\fR pair, so redirects and other requests to the same \f(CRHOST:PORT\fR use the supplied \f(CRADDRESS\fR. .IP To remove an entry from the DNS cache, include a string in the form \f(CR-HOST:PORT\fR. The host name must be prefixed with a dash, and both the host name and port must exactly match an entry added earlier. .TP 3 \fB-usessl\fR Selects the desired level of SSL or TLS use for the transfer. This option is relevant for protocols such as FTP, SMTP, POP3, and IMAP. .IP You can also use \f(CRftps://\fR URLs to enable SSL/TLS explicitly for both the control connection and the data connection. .IP Accepted values: .RS .TP 3 \f(CRnope\fR Do not attempt to use SSL. .TP 3 \f(CRtry\fR Attempt to use SSL, but continue even if it cannot be negotiated. .TP 3 \f(CRcontrol\fR Use SSL for the control connection, or fail with \f(CRuse ssl failed\fR (\f(CR64\fR). .TP 3 \f(CRall\fR Use SSL for all communication, or fail with \f(CRuse ssl failed\fR (\f(CR64\fR). .RE .SH SSL AND SECURITY OPTIONS .TP 3 \fB-sslcert\fR Pass a string containing the file name of the certificate to use. The default format is \f(CRPEM\fR, and it can be changed with \fB-sslcerttype\fR. .IP When libcurl is built against NSS, this value is the nickname of the certificate to use for authentication. To use a file in the current directory in that case, prefix it with \f(CR./\fR to avoid confusion with a nickname. .TP 3 \fB-sslcerttype\fR Pass a string specifying the format of the certificate given with \fB-sslcert\fR. .IP Accepted values are: .RS .TP 3 \f(CRPEM\fR PEM format. .TP 3 \f(CRDER\fR DER format. .RE .TP 3 \fB-sslkey\fR Pass a string containing the file name of the private key to use. The default format is \f(CRPEM\fR, and it can be changed with \fB-sslkeytype\fR. .TP 3 \fB-sslkeytype\fR Pass a string specifying the format of the private key given with \fB-sslkey\fR. .IP Accepted values are: .RS .TP 3 \f(CRPEM\fR PEM format. .TP 3 \f(CRDER\fR DER format. .TP 3 \f(CRENG\fR Uses a crypto engine. In this case \fB-sslkey\fR is interpreted as an identifier passed to the engine, and \fB-sslengine\fR must also be set. .RE .IP \fBNOTE:\fR The \f(CRDER\fR private-key format may not work with some OpenSSL versions because of upstream limitations. .TP 3 \fB-keypasswd\fR Pass a string containing the passphrase required to use the private key specified with \fB-sslkey\fR or \fB-sshprivatekeyfile\fR. .IP A passphrase is not needed to load a certificate itself, but it may be needed to load the corresponding private key. .IP This option was formerly known as \fB-sslkeypasswd\fR and \fB-sslcertpasswd\fR. .TP 3 \fB-sslengine\fR Pass a string containing the identifier of the crypto engine to use for private-key operations. .IP \fBNOTE:\fR If the crypto engine cannot be loaded, TclCurl returns an error. .TP 3 \fB-sslenginedefault\fR Set this option to \f(CR1\fR to make the selected crypto engine the default for asymmetric cryptographic operations. .IP \fBNOTE:\fR If the crypto engine cannot be made the default, TclCurl returns an error. .TP 3 \fB-sslversion\fR Selects the SSL or TLS protocol version to use. .IP Accepted values are: .RS .TP 3 \f(CRdefault\fR Uses the default behavior. TclCurl attempts to negotiate an appropriate protocol version with the remote server. .TP 3 \f(CRtlsv1\fR Requires TLSv1 or later. .TP 3 \f(CRsslv2\fR Requires SSLv2. .TP 3 \f(CRsslv3\fR Requires SSLv3. .TP 3 \f(CRtlsv1_0\fR Requires TLSv1.0 or later. .TP 3 \f(CRtlsv1_1\fR Requires TLSv1.1 or later. .TP 3 \f(CRtlsv1_2\fR Requires TLSv1.2 or later. .TP 3 \f(CRtlsv1_3\fR Requires TLSv1.3 or later. .TP 3 \f(CRmaxdefault\fR Uses the maximum TLS version supported by libcurl or by the SSL backend\(cqs default configuration. .TP 3 \f(CRmaxtlsv1_0\fR Sets the maximum supported TLS version to TLSv1.0. .TP 3 \f(CRmaxtlsv1_1\fR Sets the maximum supported TLS version to TLSv1.1. .TP 3 \f(CRmaxtlsv1_2\fR Sets the maximum supported TLS version to TLSv1.2. .TP 3 \f(CRmaxtlsv1_3\fR Sets the maximum supported TLS version to TLSv1.3. .RE .TP 3 \fB-sslverifypeer\fR Controls whether TclCurl verifies the authenticity of the peer certificate. Set this option to \f(CR1\fR to enable verification or to \f(CR0\fR to disable it. The default is \f(CR1\fR. .IP During the SSL or TLS handshake, the server sends a certificate declaring its identity. TclCurl verifies that certificate against a chain of trust rooted in one or more certification authority (CA) certificates. .IP TclCurl uses the default CA bundle provided by libcurl, but you can specify alternate certificates with \fB-cainfo\fR or \fB-capath\fR. .IP If \fB-sslverifypeer\fR is nonzero and verification fails, the connection fails. If this option is \f(CR0\fR, peer-certificate verification is skipped. .IP Certificate verification alone does not confirm that the peer is the specific host you intended to contact. Use \fB-sslverifyhost\fR to control host-name verification. .TP 3 \fB-cainfo\fR Pass the name of a file containing one or more CA certificates used to verify the peer certificate. .IP This option is meaningful primarily together with \fB-sslverifypeer\fR. If peer verification is disabled, \fB-cainfo\fR does not need to name an accessible file. .IP By default, this option is set to the system path of libcurl\(cqs CA bundle, as determined when libcurl was built. .IP When libcurl is built against NSS, this value refers to the directory containing the NSS certificate database. .TP 3 \fB-issuercert\fR Pass the name of a file containing a CA certificate in PEM format. If this option is set, an additional check is performed to verify that the peer certificate was issued by the CA certificate provided here. .IP This is useful in multi-level PKI environments where the peer certificate must be constrained to a specific branch of the certificate hierarchy. .IP This option is meaningful only when used together with \fB-sslverifypeer\fR. Otherwise, failure of this additional check is not treated as a connection failure. .TP 3 \fB-capath\fR Pass the name of a directory containing multiple CA certificates to use when verifying the peer certificate. .IP When libcurl is built against OpenSSL, this directory must be prepared with the \f(CRopenssl c_rehash\fR utility. This option is meaningful primarily together with \fB-sslverifypeer\fR. If peer verification is disabled, \fB-capath\fR does not need to name an accessible directory. .IP This option is OpenSSL-specific and has no effect when libcurl is built against GnuTLS. NSS-based libcurl provides it only for backward compatibility. .IP On Windows, this option may not work because of OpenSSL limitations. .TP 3 \fB-crlfile\fR Pass the name of a file containing one or more certificate revocation lists in PEM format to use during certificate validation. .IP When libcurl is built against NSS or GnuTLS, there is no supported way to influence revocation checking with this option. When libcurl is built with OpenSSL support, both \f(CRX509_V_FLAG_CRL_CHECK\fR and \f(CRX509_V_FLAG_CRL_CHECK_ALL\fR are enabled if a CRL file is provided, so CRL checking is applied throughout the certificate chain. .IP This option is meaningful only when used together with \fB-sslverifypeer\fR. .IP If the CRL file cannot be loaded, the SSL exchange fails with the specific error code \f(CRCURLE_SSL_CRL_BADFILE\fR. A certificate-verification failure caused by revocation information in the CRL does not produce that specific error code. .TP 3 \fB-sslverifyhost\fR Controls whether TclCurl verifies that the server certificate matches the host name you intended to contact. .IP During the SSL or TLS handshake, the server sends a certificate declaring its identity. .IP When \fB-sslverifyhost\fR is set to \f(CR2\fR, the certificate must identify the intended server or the connection fails. TclCurl considers the server to match when the Common Name field or a Subject Alternative Name field in the certificate matches the host name in the URL. .IP When this option is set to \f(CR1\fR, the certificate must contain a Common Name field, but the specific name is not checked. This setting is generally not useful. .IP When this option is set to \f(CR0\fR, the connection succeeds regardless of the names contained in the certificate. .IP The default value is \f(CR2\fR. .IP This option verifies the host identity claimed by the certificate. To verify that the certificate itself is trusted, use \fB-sslverifypeer\fR. If libcurl is built against NSS and \fB-sslverifypeer\fR is \f(CR0\fR, \fB-sslverifyhost\fR is ignored. .TP 3 \fB-certinfo\fR Set this option to \f(CR1\fR to enable collection of certificate-chain information. When enabled, TclCurl, if built against OpenSSL, extracts certificate details from the chain used in the SSL connection. .IP That information can be retrieved after the transfer with the \fBgetinfo\fR command and its \f(CRcertinfo\fR option. .TP 3 \fB-randomfile\fR Pass a file name. TclCurl uses this file as a source of randomness for the SSL random engine. \fIThis option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See \f(CIREADME.md\fI for instructions on how to re-enable it.\fR .TP 3 \fB-egdsocket\fR Pass the path name of an Entropy Gathering Daemon socket. TclCurl uses it as a source of randomness for the SSL random engine. \fIThis option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See \f(CIREADME.md\fI for instructions on how to re-enable it.\fR .TP 3 \fB-sslcipherlist\fR Pass a string containing the cipher list to use for the SSL or TLS connection. The list consists of one or more cipher strings separated normally by colons, although commas or spaces are also accepted. The characters \f(CR!\fR, \f(CR-\fR, and \f(CR+\fR may also be used as operators. .IP With OpenSSL and GnuTLS, valid examples include \f(CRRC4-SHA\fR, \f(CRSHA1+DES\fR, \f(CRTLSv1\fR, and \f(CRDEFAULT\fR. The default list is usually defined by the SSL backend at build time. .IP With NSS, valid examples include \f(CRrsa_rc4_128_md5\fR and \f(CRrsa_aes_128_sha\fR. NSS does not support incremental add or remove semantics for ciphers. If this option is used, all known ciphers are disabled and only the ciphers listed here are enabled. .IP For details about cipher-list syntax, see: .UR http://www.openssl.org/docs/apps/ciphers.html .UE .IP For NSS-specific cipher-list details, see: .UR http://directory.fedora.redhat.com/docs/mod_nss.html .UE .TP 3 \fB-sslsessionidcache\fR Set this option to \f(CR0\fR to disable TclCurl\(cqs use of SSL session-ID caching, or to \f(CR1\fR to enable it. The default is \f(CR1\fR. .IP In normal circumstances, reusing SSL session IDs is harmless and may improve performance. However, some broken SSL implementations may require this option to be disabled. .TP 3 \fB-krblevel\fR Selects the Kerberos security level for FTP and thereby also enables Kerberos awareness. .IP Accepted values are \f(CRclear\fR, \f(CRsafe\fR, \f(CRconfidential\fR, and \f(CRprivate\fR. If the string does not match one of these values, \f(CRprivate\fR is used. .IP Set the string to \f(CRNULL\fR to disable Kerberos 4. Set it to \f(CR\(dq\(dq\fR to disable Kerberos support for FTP. .TP 3 \fB-gssapidelegation\fR Selects the GSSAPI credential delegation mode. .IP Accepted values are: .RS .TP 3 \f(CRflag\fR Allows unconditional delegation. .TP 3 \f(CRpolicyflag\fR Delegates only if the \f(CROK-AS-DELEGATE\fR flag is set in the service ticket, provided that this feature is supported by the GSSAPI implementation and that \f(CRGSS_C_DELEG_POLICY_FLAG\fR was available at compile time. .RE .IP Delegation is disabled by default since 7.21.7. .SH SSH OPTIONS .TP 3 \fB-sshauthtypes\fR Selects the allowed SSH authentication types. .IP Accepted values are: .RS .TP 3 \f(CRpublickey\fR Use public-key authentication. .TP 3 \f(CRpassword\fR Use password authentication. .TP 3 \f(CRhost\fR Use host-based authentication. .TP 3 \f(CRkeyboard\fR Use keyboard-interactive authentication. .TP 3 \f(CRany\fR Let TclCurl select an authentication method automatically. .RE .TP 3 \fB-sshhostpublickeymd5\fR Pass a string containing 32 hexadecimal digits. The string must be the 128-bit MD5 checksum of the remote host public key. TclCurl rejects the connection unless the checksum matches. .IP This option applies only to SCP and SFTP transfers. .TP 3 \fB-sshpublickeyfile\fR Pass the file name of the public key to use. .IP If this option is not used, TclCurl defaults to \f(CR$HOME/.ssh/id_dsa.pub\fR when the \f(CRHOME\fR environment variable is set, and to \f(CRid_dsa.pub\fR in the current directory otherwise. .TP 3 \fB-sshprivatekeyfile\fR Pass the file name of the private key to use. .IP If this option is not used, TclCurl defaults to \f(CR$HOME/.ssh/id_dsa\fR when the \f(CRHOME\fR environment variable is set, and to \f(CRid_dsa\fR in the current directory otherwise. .IP If the private key is passphrase-protected, use \fB-keypasswd\fR to specify the passphrase. .TP 3 \fB-sshknownhosts\fR Pass a string containing the file name of the \f(CRknown_hosts\fR file to use. The file must use the OpenSSH \f(CRknown_hosts\fR format supported by libssh2. .IP If this option is set, TclCurl accepts connections only to hosts that are present in that file with a matching public key. Use \fB-sshkeyproc\fR to override the default behavior for host and key matching. .TP 3 \fB-sshkeyproc\fR Pass the name of a callback procedure that TclCurl invokes after \f(CRknown_hosts\fR matching has been performed, so that the application can decide how the connection should proceed. .IP The callback is invoked only if \fB-sshknownhosts\fR is also set. .IP The callback receives a list with three elements: .RS .IP "1." 3 A list containing the key type from the \f(CRknown_hosts\fR file and the key itself. .if n \ .sp -1 .if t \ .sp -0.25v .IP "2." 3 A list containing the key type presented by the remote host and the key itself. .if n \ .sp -1 .if t \ .sp -0.25v .IP "3." 3 A value describing TclCurl\(cqs matching result. .RE .IP Possible key-type values are \f(CRrsa\fR, \f(CRrsa1\fR, \f(CRdss\fR, and \f(CRunknown\fR. .IP Possible match-result values are \f(CRmatch\fR, \f(CRmismatch\fR, \f(CRmissing\fR, and \f(CRerror\fR. .IP Return values: .RS .TP 3 \f(CR0\fR Accept the host and key. TclCurl appends the host and key to the \f(CRknown_hosts\fR file before continuing with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. Updating the file is done by replacing it with a new copy, so the file permissions must allow that. .TP 3 \f(CR1\fR Accept the host and key, and continue with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. .TP 3 \f(CR2\fR Reject the host and key. TclCurl closes the connection. .TP 3 \f(CR3\fR Reject the host and key, but keep the SSH connection alive. This can be useful if the application needs to inspect the host or key state and then retry without incurring the full setup cost again. .RE .IP Any other return value causes TclCurl to close the connection. .SH OTHER OPTIONS .TP 3 \fB-headervar\fR Name of the Tcl array variable in which TclCurl stores the headers returned by the server. .TP 3 \fB-bodyvar\fR Name of the Tcl variable in which TclCurl stores the requested file contents. The stored data may be either text or binary data. .TP 3 \fB-canceltransvarname\fR Name of a Tcl variable used together with \fB-progressproc\fR. If the progress callback sets this variable to \f(CR1\fR, the transfer is canceled. .TP 3 \fB-command\fR Executes the given command after the transfer has completed. .IP This option works only with blocking transfers and therefore has limited practical use. .TP 3 \fB-share\fR Pass a share handle. The share handle must have been created previously by calling \fBcurl::shareinit\fR. .IP Setting this option causes the easy handle to use data from the shared handle instead of keeping its own separate copy. See \fItclcurl_share\fR for details. .TP 3 \fB-newfileperms\fR Pass a numeric value specifying the permissions assigned to newly created files on the remote server. The default value is \f(CR0644\fR, but any valid value may be used. .IP This option applies only to \f(CRsftp://\fR, \f(CRscp://\fR, and \f(CRfile://\fR transfers. .TP 3 \fB-newdirectoryperms\fR Pass a numeric value specifying the permissions assigned to newly created directories on the remote server. The default value is \f(CR0755\fR, but any valid value may be used. .IP This option applies only to \f(CRsftp://\fR, \f(CRscp://\fR, and \f(CRfile://\fR transfers. .SH TELNET OPTIONS .TP 3 -telnetoptions Pass a list with variables to pass to the telnet negotiations. The variables should be in the format . TclCurl supports the options \(oqTTYPE\(cq, \(oqXDISPLOC\(cq and \(oqNEW_ENV\(cq. See the TELNET standard for details. .SH NOT SUPPORTED .LP Some of the options libcurl offers are not supported, I don\(cqt think them worth supporting in TclCurl but if you need one of them don\(cqt forget to complain: .PP \fBCURLOPT\f(BIFRESH\fBCONNECT, CURLOPT\f(BIFORBID\fBREUSE, CURLOPT_PRIVATE,\fR .PP \fBCURLOPT\f(BISSL\fBCTX\f(BIFUNCTION, CURLOPT\fBSSL\f(BICTX\fBDATA, CURLOPT\f(BISSL\fBCTX_FUNCTION and\fR .PP \fBCURLOPT\f(BICONNECT\fBONLY, CURLOPT\f(BIOPENSOCKETFUNCTION, CURLOPT\fBOPENSOCKETDATA.\fR .SH curlHandle perform .LP This procedure is called after the .PP \fBinit\fR .PP and all the .PP \fBconfigure\fR .PP calls are made, and will perform the transfer as described in the options. .PP It must be called with the same \fIcurlHandle\fR \fBcurl::init\fR call returned. You can do any amount of calls to perform while using the same handle. If you intend to transfer more than one file, you are even encouraged to do so. TclCurl will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources. Just note that you will have to use configure between the invokes to set options for the following perform. .PP You must never call this procedure simultaneously from two places using the same handle. Let it return first before invoking it another time. If you want parallel transfers, you must use several curl handles. .TP 3 RETURN VALUE \f(CR0\fR if all went well, non-zero if it didn\(cqt. In case of error, if the errorbuffer was set with configure there will be a readable error message. The error codes are: .RS .TP 3 \fB1\fR Unsupported protocol. This build of TclCurl has no support for this protocol. .TP 3 \fB2\fR Very early initialization code failed. This is likely to be and internal error or a resource problem where something fundamental couldn\(cqt get done at init time. .TP 3 \fB3\fR URL malformat. The syntax was not correct. .TP 3 \fB4\fR A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision. This means that a feature or option was not enabled or explicitly disabled when libcurl was built and in order to get it to function you have to get a rebuilt libcurl. .TP 3 \fB5\fR Couldn\(cqt resolve proxy. The given proxy host could not be resolved. .TP 3 \fB6\fR Couldn\(cqt resolve host. The given remote host was not resolved. .TP 3 \fB7\fR Failed to connect to host or proxy. .TP 3 \fB8\fR FTP weird server reply. The server sent data TclCurl couldn\(cqt parse. The given remote server is probably not an OK FTP server. .TP 3 \fB9\fR We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory. .TP 3 \fB11\fR FTP weird PASS reply. TclCurl couldn\(cqt parse the reply sent to the PASS request. .TP 3 \fB13\fR FTP weird PASV reply, TclCurl couldn\(cqt parse the reply sent to the PASV or EPSV request. .TP 3 \fB14\fR FTP weird 227 format. TclCurl couldn\(cqt parse the 227-line the server sent. .TP 3 \fB15\fR FTP can\(cqt get host. Couldn\(cqt resolve the host IP we got in the 227-line. .TP 3 \fB17\fR FTP couldn\(cqt set type. Couldn\(cqt change transfer method to either binary or ascii. .TP 3 \fB18\fR Partial file. Only a part of the file was transferred, this happens when the server first reports an expected transfer size and then delivers data that doesn\(cqt match the given size. .TP 3 \fB19\fR FTP couldn\(cqt RETR file, we either got a weird reply to a \(oqRETR\(cq command or a zero byte transfer. .TP 3 \fB21\fR Quote error. A custom \(oqQUOTE\(cq returned error code 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command. .TP 3 \fB22\fR HTTP returned error. This return code only appears if \fB-failonerror\fR is used and the HTTP server returns an error code that is 400 or higher. .TP 3 \fB23\fR Write error. TclCurl couldn\(cqt write data to a local filesystem or an error was returned from a write callback. .TP 3 \fB25\fR Failed upload failed. For FTP, the server typcially denied the STOR command. The error buffer usually contains the server\(cqs explanation to this. .TP 3 \fB26\fR Read error. There was a problem reading from a local file or an error was returned from the read callback. .TP 3 \fB27\fR Out of memory. A memory allocation request failed. This should never happen unless something weird is going on in your computer. .TP 3 \fB28\fR Operation timeout. The specified time-out period was reached according to the conditions. .TP 3 \fB30\fR The FTP PORT command failed, not all FTP servers support the PORT command, try doing a transfer using PASV instead!. .TP 3 \fB31\fR FTP couldn\(cqt use REST. This command is used for resumed FTP transfers. .TP 3 \fB33\fR Range error. The server doesn\(cqt support or accept range requests. .TP 3 \fB34\fR HTTP post error. Internal post-request generation error. .TP 3 \fB35\fR SSL connect error. The SSL handshaking failed, the error buffer may have a clue to the reason, could be certificates, passwords, \[u2026] .TP 3 \fB36\fR The download could not be resumed because the specified offset was out of the file boundary. .TP 3 \fB37\fR A file given with FILE:// couldn\(cqt be read. Did you checked the permissions? .TP 3 \fB38\fR LDAP cannot bind. LDAP bind operation failed. .TP 3 \fB39\fR LDAP search failed. .TP 3 \fB41\fR A required zlib function was not found. .TP 3 \fB42\fR Aborted by callback. An application told TclCurl to abort the operation. .TP 3 \fB43\fR Internal error. A function was called with a bad parameter. .TP 3 \fB45\fR Interface error. A specified outgoing interface could not be used. .TP 3 \fB47\fR Too many redirects. When following redirects, TclCurl hit the maximum amount, set your limit with \(enmaxredirs .TP 3 \fB48\fR An option passed to TclCurl is not recognized/known. Refer to the appropriate documentation. This is most likely a problem in the program that uses TclCurl. The error buffer might contain more specific information about which exact option it concerns. .TP 3 \fB49\fR A telnet option string was illegally formatted. .TP 3 \fB51\fR The remote peer\(cqs SSL certificate or SSH md5 fingerprint wasn\(cqt ok .TP 3 \fB52\fR The server didn\(cqt reply anything, which here is considered an error. .TP 3 \fB53\fR The specified crypto engine wasn\(cqt found. .TP 3 \fB54\fR Failed setting the selected SSL crypto engine as default! .TP 3 \fB55\fR Failed sending network data. .TP 3 \fB56\fR Failure with receiving network data. .TP 3 \fB58\fR Problem with the local client certificate. .TP 3 \fB59\fR Couldn\(cqt use specified SSL cipher. .TP 3 \fB60\fR Peer certificate cannot be authenticated with known CA certificates. .TP 3 \fB61\fR Unrecognized transfer encoding. .TP 3 \fB62\fR Invalid LDAP URL. .TP 3 \fB63\fR Maximum file size exceeded. .TP 3 \fB64\fR SSL use failed. .TP 3 \fB65\fR Sending the data requires a rewind that failed, since TclCurl should take care of it for you, it means you found a bug. .TP 3 \fB66\fR Failed to initialise ssl engine. .TP 3 \fB67\fR Failed to login, user password or similar was not accepted. .TP 3 \fB68\fR File not found on TFTP server. .TP 3 \fB69\fR There is a permission problem with the TFTP request. .TP 3 \fB70\fR The remote server has run out of space. .TP 3 \fB71\fR Illegal TFTP operation. .TP 3 \fB72\fR Unknown transfer ID. .TP 3 \fB73\fR TFTP file already exists and will not be overwritten. .TP 3 \fB74\fR No such user in the TFTP server and good behaving TFTP servers should never return this. .TP 3 \fB75\fR Character conversion failed. .TP 3 \fB77\fR Problem with reading the SSL CA cert (path? access rights?). .TP 3 \fB78\fR Remote file not found .TP 3 \fB79\fR Error from the SSH layer .TP 3 \fB80\fR Failed to shut down the SSL connection .TP 3 \fB82\fR Failed to load CRL file .TP 3 \fB83\fR Issuer check failed .TP 3 \fB84\fR The FTP server does not understand the PRET command at all or does not support the given argument. Be careful when using \fB-customrequest\fR, a custom LIST command will be sent with PRET CMD before PASV as well. .TP 3 \fB85\fR Mismatch of RTSP CSeq numbers. .TP 3 \fB86\fR Mismatch of RTSP Session Identifiers. .TP 3 \fB87\fR Unable to parse FTP file list (during FTP wildcard downloading). .TP 3 \fB88\fR Chunk callback reported error. .RE .SH curlHandle getinfo OPTION .LP Request internal information from the curl session with this procedure. This procedure is intended to get used \fIAFTER\fR a performed transfer, and can be relied upon only if the \fBperform\fR returns 0. Use this function AFTER a performed transfer if you want to get transfer-oriented data. .PP The following information can be extracted: .TP 3 effectiveurl Returns the last used effective URL. .TP 3 responsecode Returns the last received HTTP or FTP code. This will be zero if no server response code has been received. Note that a proxy\(cqs CONNECT response should be read with \fBhttpconnectcode\fR and not this. .TP 3 httpconnectcode Returns the last received proxy response code to a CONNECT request. .TP 3 filetime Returns the remote time of the retrieved document (in number of seconds since 1 jan 1970 in the GMT/UTC time zone). If you get -1, it can be because of many reasons (unknown, the server hides it or the server doesn\(cqt support the command that tells document time etc) and the time of the document is unknown. .IP In order for this to work you have to set the \fB-filetime\fR option before the transfer. .TP 3 namelookuptime Returns the time, in seconds, it took from the start until the name resolving was completed. .TP 3 connecttime Returns the time, in seconds, it took from the start until the connect to the remote host (or proxy) was completed. .TP 3 appconnecttime Returns the time, in seconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed. This time is most often very near to the PRETRANSFER time, except for cases such as HTTP pippelining where the pretransfer time can be delayed due to waits in line for the pipeline and more. .TP 3 pretransfertime Returns the time, in seconds, it took from the start until the file transfer is just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved. .TP 3 starttransfertime Returns the time, in seconds, it took from the start until the first byte is just about to be transferred. This includes the \fBpretransfertime\fR, and also the time the server needs to calculate the result. .TP 3 totaltime Returns the total transaction time, in seconds, for the previous transfer, including name resolving, TCP connect etc. .TP 3 redirecturl Returns the URL a redirect would take you to if you enable \fBfollowlocation\fR. This can come very handy if you think using the built-in libcurl redirect logic isn\(cqt good enough for you but you would still prefer to avoid implementing all the magic of figuring out the new URL. .TP 3 redirecttime Returns the total time, in seconds, it took for all redirection steps including name lookup, connect, pretransfer and transfer before the final transaction was started, it returns the complete execution time for multiple redirections, so it returns zero if no redirections were needed. .TP 3 redirectcount Returns the total number of redirections that were actually followed. .TP 3 numconnects Returns how many new connections TclCurl had to create to achieve the previous transfer (only the successful connects are counted). Combined with \fBredirectcount\fR you are able to know how many times TclCurl successfully reused existing connection(s) or not. See the Connection Options of \fBsetopt\fR to see how TclCurl tries to make persistent connections to save time. .TP 3 primaryip Returns the IP address of the most recent connection done with this handle. This string may be IPv6 if that\(cqs enabled. .TP 3 primaryport Returns the destination port of the most recent connection done with this handle. .TP 3 localip Returns the local (source) IP address of the most recent connection done with this handle. This string may be IPv6 if that\(cqs enabled. .TP 3 localport Returns the local (source) port of the most recent connection done with this handle. .TP 3 sizeupload Returns the total amount of bytes that were uploaded. .TP 3 sizedownload Returns the total amount of bytes that were downloaded. The amount is only for the latest transfer and will be reset again for each new transfer. .TP 3 speeddownload Returns the average download speed, measured in bytes/second, for the complete download. .TP 3 speedupload Returns the average upload speed, measured in bytes/second, for the complete upload. .TP 3 headersize Returns the total size in bytes of all the headers received. .TP 3 requestsize Returns the total size of the issued requests. This is so far only for HTTP requests. Note that this may be more than one request if followLocation is true. .TP 3 sslverifyresult Returns the result of the certification verification that was requested (using the -sslverifypeer option to configure). .TP 3 sslengines Returns a \fBlist\fR of the OpenSSL crypto-engines supported. Note that engines are normally implemented in separate dynamic libraries. Hence not all the returned engines may be available at run-time. .TP 3 contentlengthdownload Returns the content-length of the download. This is the value read from the \fBContent-Length:\fR field. If the size isn\(cqt known, it returns -1. .TP 3 contentlengthupload Returns the specified size of the upload. .TP 3 contenttype Returns the content-type of the downloaded object. This is the value read from the Content-Type: field. If you get an empty string, it means the server didn\(cqt send a valid Content-Type header or that the protocol used doesn\(cqt support this. .TP 3 httpauthavail Returns a list with the authentication method(s) available. .TP 3 proxyauthavail Returns a list with the authentication method(s) available for your proxy athentication. .TP 3 oserrno Returns the errno value from a connect failure. This value is only set on failure, it is no reset after a successful operation. .TP 3 cookielist Returns a list of all cookies TclCurl knows (expired ones, too). If there are no cookies (cookies for the handle have not been enabled or simply none have been received) the list will be empty. .TP 3 ftpentrypath Returns a string holding the path of the entry path. That is the initial path TclCurl ended up in when logging on to the remote FTP server. Returns an empty string if something is wrong. .TP 3 certinfo Returns list with information about the certificate chain, assuming you had the \fB-certinfo\fR option enabled when the previous request was done. The list first item reports how many certs it found and then you can extract info for each of those certs by following the list. The info chain is provided in a series of data in the format \(lqname:content\(rq where the content is for the specific named data. .IP NOTE: this option is only available in libcurl built with OpenSSL support. .TP 3 conditionunmet Returns the number 1 if the condition provided in the previous request didn\(cqt match (see \fItimecondition\fR), you will get a zero if the condition instead was met. .SH curlHandle cleanup .LP This procedure must be the last one to call for a curl session. It is the opposite of the curl::init procedure and must be called with the same curlhandle as input as the curl::init call returned. This will effectively close all connections TclCurl has used and possibly has kept open until now. Don\(cqt call this procedure if you intend to transfer more files. .SH curlHandle reset .LP Re-initializes all options previously set on a specified handle to the default values. .PP This puts back the handle to the same state as it was in when it was just created with curl::init. .PP It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares. .SH curlHandle duphandle .LP This procedure will return a new curl handle, a duplicate, using all the options previously set in the input curl handle. Both handles can subsequently be used independently and they must both be freed with \fBcleanup\fR. .PP The new handle will not inherit any state information, connections, SSL sessions or cookies. .TP 3 RETURN VALUE A new curl handle or an error message if the copy fails. .SH curlHandle pause .LP You can use this command from within a progress callback procedure to pause the transfer. .SH curlHandle resume .LP Resumes a transfer paused with \fBcurlhandle pause\fR .SH curl::transfer .LP In case you do not want to use persistent connections you can use this command, it takes the same arguments as the \fIcurlHandle\fR \fBconfigure\fR and will init, configure, perform and cleanup a connection for you. .PP You can also get the \fIgetinfo\fR information by using \fI-infooption variable\fR pairs, after the transfer \fIvariable\fR will contain the value that would have been returned by \fI$curlHandle getinfo option\fR. .TP 3 RETURN VALUE The same error code \fBperform\fR would return. .SH curl::version .LP Returns a string with the version number of tclcurl, libcurl and some of its important components (like OpenSSL version). .TP 3 RETURN VALUE The string with the version info. .SH curl::escape URL .LP This procedure will convert the given input string to an URL encoded string and return that. All input characters that are not a-z, A-Z or 0-9 will be converted to their \(lqURL escaped\(rq version (%NN where NN is a two-digit hexadecimal number) .TP 3 RETURN VALUE The converted string. .SH curl::unescape URL .LP This procedure will convert the given URL encoded input string to a \(lqplain string\(rq and return that. All input characters that are URL encoded (%XX where XX is a two-digit hexadecimal number) will be converted to their plain text versions. .TP 3 RETURN VALUE The string unencoded. .SH curl::curlConfig OPTION .LP Returns some information about how you have \fBcURL\fR installed. .TP 3 -prefix Returns the directory root where you installed \fBcURL\fR. .TP 3 -feature Returns a list containing particular main features the installed \fBlibcurl\fR was built with. The list may include SSL, KRB4 or IPv6, do not assume any particular order. .TP 3 -vernum Outputs version information about the installed libcurl, in numerical mode. This outputs the version number, in hexadecimal, with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e\[u2026] .SH curl::versioninfo OPTION .LP Returns information about various run-time features in TclCurl. .PP Applications should use this information to judge if things are possible to do or not, instead of using compile-time checks, as dynamic/DLL libraries can be changed independent of applications. .TP 3 -version Returns the version of libcurl we are using. .TP 3 -versionnum Returns the version of libcurl we are using in hexadecimal with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e\[u2026] Note that the initial zero might be omitted. .TP 3 -host Returns a string with the host information as discovered by a configure script or set by the build environment. .TP 3 -features Returns a list with the features compiled into libcurl, the possible elements are: .TP 3 ASYNCHDNS Libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface. .TP 3 CONV Libcurl was built with support for character conversions. .TP 3 DEBUG Libcurl was built with extra debug capabilities built-in. This is mainly of interest for libcurl hackers. .TP 3 GSSNEGOTIATE Supports HTTP GSS-Negotiate. .TP 3 IDN Supports IDNA, domain names with international letters. .TP 3 IPV6 Supports IPv6. .TP 3 KERBEROS4 Supports kerberos4 (when using FTP). .TP 3 LARGEFILE Libcurl was built with support for large files. .TP 3 LIBZ Supports HTTP deflate using libz. .TP 3 NTML Supports HTTP NTLM .TP 3 SPNEGO Libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478) .TP 3 SSL Supports SSL (HTTPS/FTPS) .TP 3 SSPI Libcurl was built with support for SSPI. This is only available on Windows and makes libcurl use Windows-provided functions for NTLM authentication. It also allows libcurl to use the current user and the current user\(cqs password without the app having to pass them on. .TP 3 TLSAUTH_SRP Libcurl was built with support for TLS-SRP. .IP \fBNTLM_WB\fR .IP Libcurl was built with support for NTLM delegation to a winbind helper. .IP Do not assume any particular order. .TP 3 -sslversion Returns a string with the OpenSSL version used, like OpenSSL/0.9.6b. .TP 3 -sslversionnum Returns the numerical OpenSSL version value as defined by the OpenSSL project. If libcurl has no SSL support, this is 0. .TP 3 -libzversion Returns a string, there is no numerical version, for example: 1.1.3. .TP 3 -protocols Lists what particular protocols the installed TclCurl was built to support. At the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE, TELNET, LDAP, DICT. Do not assume any particular order. The protocols will be listed using uppercase. There may be none, one or several protocols in the list. .SH curl::easystrerror errorCode .LP This procedure returns a string describing the error code passed in the argument. .SH EXAMPLES .LP The examples in this section assume you are running from the root of the TclCurl source tree. .PP To start the local HTTP test server used in the examples, run: .LP .EX tclsh testservers/testserver.tcl .EE .PP By default, this starts an HTTP server on \f(CRhttp://127.0.0.1:8990/\fR. .PP The path \f(CRhttp://127.0.0.1:8990/tclcurl-man\fR returns the HTML version of this manual page from \f(CRdoc/tclcurl.html\fR, which makes it a convenient target for a basic \f(CRGET\fR example. .SH BASIC HTTP GET .LP The file \f(CRexamples/http_get.tcl\fR contains a minimal HTTP \f(CRGET\fR example. It performs a simple request, stores the response body in a Tcl variable, and prints both the HTTP response code and the size of the returned document. .PP If the request succeeds, \f(CRrc\fR is \f(CR0\fR, \f(CRresponsecode\fR is \f(CR200\fR, and \f(CRbody\fR contains the HTML document returned by the server. .SH AUTHORS .LP Andres Garcia Garcia .PP Massimo Manghi .SH SEE ALSO .LP curl, The art of HTTP scripting (at \c .UR http://curl.haxx.se) .UE \c , RFC 2396, tclcurl-ng-8.0.3/doc/tclcurl.n.md000066400000000000000000003034721522613063100165770ustar00rootroot00000000000000--- title: TclCurl section: n date: 15 May 2026 source: TclCurl 8.0.3 volume: TclCurl Easy Interface --- # NAME TclCurl - Transfer data to and from URLs using FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS, and GOPHER. # SYNOPSIS ```tcl curl::init curl::transfer ?options? curl::version curl::escape url curl::unescape url curl::curlConfig option curl::versioninfo option curl::easystrerror errorCode ``` ```tcl curlHandle configure ?options? curlHandle perform curlHandle getinfo curlinfo_option curlHandle cleanup curlHandle reset curlHandle duphandle curlHandle pause curlHandle resume ``` # DESCRIPTION The TclCurl extension gives Tcl programmers access to the libcurl library written by **Daniel Stenberg**. With TclCurl, you can download from URLs, upload to them, and perform many other network transfer operations. For more information, see . # curl::init This procedure must be called first. It returns a `curlHandle`, which you use to invoke TclCurl procedures. Calling `init` initializes TclCurl, and each call to `init` MUST have a corresponding call to `cleanup` when the operation is complete. You should perform all sequential file transfers using the same `curlHandle`. This allows TclCurl to reuse persistent connections when possible. **RETURN VALUE** The `curlHandle` to use. # curlHandle configure ?OPTIONS? **configure** is used to set the options for a transfer. Most operations in TclCurl have default behavior, and you can change that behavior by setting the appropriate options as documented. Each option is specified as the *option* followed by a parameter. **Notes:** The options set with this procedure apply to subsequent data transfers performed when you invoke `perform`. The options are not reset between transfers (except where noted), so if you want subsequent transfers with different options, you must change them between the transfers. You can optionally reset all options back to the internal default with **curlHandle reset**. `curlHandle` is the value returned by the `curl::init` call. **OPTIONS** # BEHAVIOUR OPTIONS **-verbose** : Set this option to 1 to make the library display detailed information about its operations. This option is useful when debugging libcurl and protocol-related problems. You will rarely want to enable this in production, but it is often helpful when debugging or reporting problems. Another useful debugging option is **-debugproc** **-header** : Set this option to 1 to include headers in the body output. This is relevant only for protocols that actually send headers before the data, such as HTTP. **-noprogress** : Set this option to 1 to disable the progress meter completely. It also prevents *progressproc* from being called. **-nosignal** : Set this option to 1 to make TclCurl avoid functions that install signal handlers or cause signals to be sent to the process. This option exists mainly so that multi-threaded Unix applications can still use timeout options without risking signal-related side effects. If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while name resolution is in progress. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which allows proper timeouts for name resolution without signals. Setting *nosignal* to 1 makes libcurl stop asking the system to ignore SIGPIPE signals. Such signals may otherwise be sent by the system when data is written to a socket that has been closed by the peer. libcurl tries to avoid triggering SIGPIPE, but some operating systems provide no reliable way to prevent it, and even on those that do, some corner cases remain. In addition, using *ntlm_Wb* authentication may cause a SIGCHLD signal to be raised. **-wildcard** : Set this option to 1 to transfer multiple files that match a file name pattern. The pattern can be specified as part of the **-url** option, using an fnmatch-like pattern (shell pattern matching) in the last part of the URL, that is, the file name. By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function with the **-fnmatchproc** option. At present, this feature is supported only for FTP downloads. A brief introduction of its syntax follows: - * - ASTERISK `ftp://example.com/some/path/***.txt**` (for all `.txt` files from the root directory) - ? - QUESTION MARK The question mark matches any single character. `ftp://example.com/some/path/**photo?.jpeg**` - [ - BRACKET EXPRESSION The left bracket opens a bracket expression. The question mark and asterisk have no special meaning in a bracket expression. Each bracket expression ends by the right bracket and matches exactly one character. Some examples follow: **[a-zA-Z0-9]** or **[f-gF-G]** - character interval **[abc]** - character enumeration **[^abc]** or **[!abc]** - negation **[[:***name***:]]** class expression. Supported classes are **alnum**,**lower**, **space**, **alpha**, **digit**, **print**, **upper**, **blank**, **graph**, **xdigit**. **[][-!^]** - special case - matches only '-', ']', '[', '!' or '^'. These characters have no special purpose. **[\\[\\]\\\\]** - escape syntax. Matches '[', ']' or '\\'. Using the rules above, a file name pattern can be constructed: `ftp://example.com/some/path/**[a-z[:upper:]\\\\].jpeg**` # CALLBACK OPTIONS **-writeproc** : Sets a Tcl procedure that TclCurl invokes whenever received data is available to be handled. The callback procedure must have a single argument. When the procedure is invoked, that argument refers to the contents of a data buffer managed by libcurl. NOTE: The amount of data passed on each invocation is not fixed. The callback may be invoked with an empty buffer, or with a buffer containing a large amount of data. **-file** : File in which the transferred data will be saved. **-readproc** : Sets a Tcl procedure that TclCurl calls whenever it needs to read data to send to the peer. The procedure must take one parameter, which contains the maximum number of bytes to read. It should return the actual number of bytes read, or `0` if you want to stop the transfer. If you stop the current transfer by returning `0` prematurely, for example after indicating that you would upload *N* bytes but uploading fewer than *N*, the server may appear to hang while waiting for the remaining data. When doing TFTP uploads, you must return exactly the amount of data requested by the callback. Otherwise, the server may treat it as the final packet and end the transfer. **-infile** : File from which the data will be transferred. **-progressproc** : Name of the Tcl procedure that TclCurl invokes at regular intervals during an operation, roughly once per second or more often, whether or not data is currently being transferred. Unknown or unused argument values passed to the callback are set to zero. For example, if you only download data, the upload size remains `0`. The procedure must have the following prototype: **proc ProgressCallback {dltotal dlnow ultotal ulnow}** For this option to work, you must set the **-noprogress** option to `0`. Setting this option to the empty string restores the original progress function. If you transfer data with the multi interface, this procedure will not be called during periods of idleness unless you call the appropriate procedure that performs transfers. You can pause and resume a transfer from within this procedure using the **pause** and **resume** commands. **-writeheader** : Pass the file name to which the header part of the received data will be written. Headers are written to this file one by one, and only complete lines are written. This makes header parsing straightforward. See also the **-headervar** option to get the headers into an array. **-debugproc** : Name of the procedure that receives the debug data produced by the **-verbose** option. The callback procedure must have two arguments: **debugProc {infoType data}** The **infoType** argument identifies the kind of debug information: `0` text, `1` incoming header, `2` outgoing header, `3` incoming data, `4` outgoing data, `5` incoming SSL data, and `6` outgoing SSL data. The **data** argument contains the corresponding data buffer. **-chunkbgnproc** : Name of the procedure that is called before a file is transferred by FTP. The callback procedure must have one argument: **ChunkBgnProc {remains}** The *remains* argument is the number of files left to be transferred or skipped. This callback makes sense only when using the **-wildcard** option. **-chunkbgnvar** : Name of the variable in the global scope that will contain the data for the file about to be transferred. If you do not use this option, `::fileData` is used. The available data is: `filename`, `filetype` (`file`, `directory`, `symlink`, `device block`, `device char`, `named pipe`, `socket`, `door`, or `error` if it could not be identified), `time`, `perm`, `uid`, `gid`, `size`, `hardlinks`, and `flags`. **-chunkendproc** : Name of the procedure that is called after a file has been transferred or skipped by FTP. The callback procedure takes no arguments: **ChunkEndProc {}** It should return `0` if everything is fine and `1` if an error occurred. **-fnmatchProc** : Name of the procedure that is called instead of the internal wildcard matching function. The callback procedure must have two arguments: **FnMatchProc {pattern string}** The *pattern* argument contains the pattern to be matched. The *string* argument contains the candidate string. The procedure must return `0` if the string matches the pattern and `1` otherwise. # ERROR OPTIONS **-errorbuffer** : Pass the name of a variable in which TclCurl may store human-readable error messages. This can provide more information than the command return code alone. **-stderr** : Pass a file name. TclCurl uses this stream instead of `stderr` when reporting errors. **-failonerror** : Set this option to 1 to make the transfer fail if the returned HTTP status code is 400 or greater. By default, TclCurl returns the page normally and does not treat such status codes as transfer errors. This behavior is not fail-safe, and in some cases non-successful response codes may still pass through, especially when authentication is involved, as with status codes 401 and 407. Some header data may be transferred before this condition is detected. For example, a `100-continue` response may be received for a POST or PUT request before a subsequent `401` or `407` response is returned. # NETWORK OPTIONS **-url** : The URL to use for the transfer. If the URL does not include a protocol part, such as `http://` or `ftp://`, TclCurl attempts to guess the protocol from the host name. If the protocol specified in the URL is not supported, TclCurl returns the **unsupported protocol** error when you call **perform**. Use **curl::versioninfo** for detailed information about the supported protocols. Starting with version 7.22.0, the fragment part of the URI is no longer sent as part of the path, unlike earlier versions. **NOTE**: This is the only option that must be set before **perform** is called. **-protocols** : Pass a lowercase list of protocols to limit which protocols TclCurl may use for the transfer. This allows a TclCurl build that supports a wide range of protocols to be restricted for specific transfers to a subset of them. Accepted protocols are `http`, `https`, `ftp`, `ftps`, `scp`, `sftp`, `telnet`, `ldap`, `ldaps`, `dict`, `file`, `tftp`, `imap`, `imaps`, `pop`, `pop3`, `smtp`, `smtps`, `gopher`, and `all`. **-redirprotocols** : Pass a lowercase list of accepted protocols to limit which protocols TclCurl may use when following a redirect with **-followlocation** enabled. This allows specific transfers to be restricted to a subset of protocols for redirections. By default, TclCurl allows all protocols except `FILE` and `SCP`. This differs from versions before 7.19.4, which would follow redirects to all supported protocols unconditionally. **-proxy** : If you need to use an HTTP proxy, set the proxy string with this option. To specify a port number in the string, append `:[port]` to the end of the host name. The proxy string may be prefixed with `[protocol]://`, although such a prefix is ignored unless noted otherwise below. When you configure an HTTP proxy, TclCurl transparently converts operations to HTTP even if you specify an FTP URL or another protocol. This may affect which library features are available. For example, **quote** and similar FTP-specific features do not work unless you tunnel through the HTTP proxy. Such tunneling is enabled with **-proxytunnel**. TclCurl respects the environment variables `http_proxy`, `ftp_proxy`, `all_proxy`, and others of the same kind, if they are set. Using this option overrides any such environment variables. Setting the proxy string to `""` explicitly disables proxy use, even if a corresponding environment variable is set. The proxy host string can be specified in the same way as the proxy environment variables, including a protocol prefix such as `http://` and embedded user name and password information. Since 7.22.0, the proxy string may include a `protocol://` prefix to specify alternative proxy protocols. Use `socks4://`, `socks4a://`, `socks5://`, or `socks5h://` to request a specific SOCKS version. The last form enables SOCKS5 and asks the proxy to perform name resolution. If no protocol is specified, and for `http://` and all other prefixes, the proxy is treated as an HTTP proxy. **-proxyport** : Use this option to set the proxy port unless it is already specified in the proxy string passed with **-proxy**. If not specified, TclCurl uses port `1080` by default. **-proxytype** : Pass the proxy type. Available values are `http`, `http1.0`, `socks4`, `socks4a`, `socks5`, and `socks5h`. The default is `http`. If you set it to *http1.0*, it will only affect how libcurl speaks to a proxy when CONNECT is used. The HTTP version used for ordinary HTTP requests is instead controlled by *httpversion*. **-noproxy** : Pass a string containing a comma-separated list of hosts that should not use a proxy, if one is specified. The only wildcard is a single `*` character, which matches all hosts and effectively disables the proxy. Each name in this list is matched either as a domain containing the host name, or as the host name itself. For example, `local.com` matches `local.com`, `local.com:80`, and `www.local.com`, but not `www.notlocal.com`. **-httpproxytunnel** : Set this option to 1 to tunnel all non-HTTP operations through the given HTTP proxy. Using a proxy and tunneling through a proxy are different behaviors. This option should be enabled only when that distinction is required. **-socks5gssapiservice** : Pass the service name. The default service name for a SOCKS5 server is `rcmd/server-fqdn`. This option allows you to change it. **-socks5gssapinec** : Pass `1` to enable this option or `0` to disable it. As part of the GSSAPI negotiation, a protection mode is negotiated. RFC 1961 specifies in sections 4.3 and 4.4 that this exchange should be protected, but the NEC reference implementation does not do so. When enabled, this option allows the protection mode negotiation to be exchanged unprotected. **-interface** : Pass the interface name to use as the outgoing network interface. The name may be an interface name, an IP address, or a host name. **-localport** : Sets the local port number of the socket used for the connection. This can be used together with **-interface**, and it is recommended to use **-localportrange** as well when this option is set. Valid port numbers are `1` through `65535`. **-localportrange** : Number of attempts TclCurl should make to find a working local port number. It starts with the port specified by **-localport** and increments it by one for each retry. Setting this value to `1` or less makes TclCurl try only one port number. Because port numbers are a limited resource and may already be in use, setting this value too low may cause unnecessary connection setup failures. **-dnscachetimeout** : Pass the timeout in seconds. Name resolution results are kept in memory for this number of seconds. Set this option to `0` to disable caching completely, or to `-1` to keep cached entries indefinitely. By default, TclCurl caches this information for `60` seconds. The name resolution functions in various libc implementations do not re-read name server information unless explicitly told to do so, for example by calling *res_init(3)*. As a result, TclCurl may continue to use older server information even after DHCP has updated it, which may appear to be a DNS cache issue. **-dnsuseglobalcache** : If this option is set to `1`, TclCurl uses a global DNS cache that survives the creation and deletion of curl handles. This is not thread-safe because it relies on a global variable. *This option was deprecated in libcurl v7.11.1 and is disabled by default in the TclCurl build. See `README.md` for instructions on how to re-enable it.* **WARNING:** This option is obsolete. Use the share interface instead. See *tclcurl_share*. **-buffersize** : Pass the preferred size for the TclCurl receive buffer. A smaller buffer may cause the write callback to be invoked more often with smaller chunks. This value is treated as a request, not as a guarantee. **-port** : Pass the remote port number to connect to instead of the port specified in the URL or the default port for the protocol in use. **-tcpnodelay** : Pass a number to specify whether the `TCP_NODELAY` option should be set or cleared (`1` = set, `0` = clear). This option is cleared by default. It has no effect after the connection has been established. Setting this option will disable TCP's Nagle algorithm. The purpose of this algorithm is to try to minimize the number of small packets on the network (where "small packets" means TCP segments less than the Maximum Segment Size (MSS) for the network). Maximizing the amount of data sent per TCP segment is good because it amortizes the overhead of the send. However, in some cases (most notably telnet or rlogin) small segments may need to be sent without delay. This is less efficient than sending larger amounts of data at a time, and can contribute to congestion on the network if overdone. **-addressscope** : Pass a number specifying the `scope_id` value to use when connecting to IPv6 link-local or site-local addresses. # NAMES AND PASSWORDS OPTIONS **-netrc** : Set this option to make TclCurl scan your **~/.netrc** file for the user name and password of the remote site you are about to access. TclCurl does not verify that the file has the correct properties set, as the standard Unix `ftp` client does. Only machine name, user name, and password are taken into account; `init` macros and similar entries are not supported. Accepted values: `optional` : Use of **~/.netrc** is optional, and information in the URL takes precedence. The file is searched using the host and user name, to find the password only, or using the host name alone, to find the first user name and password for that machine, depending on which information is not specified in the URL. Undefined values for this option have the same effect. `ignored` : TclCurl ignores the file and uses only the information in the URL. This is the default. `required` : TclCurl requires use of the file, ignores the information in the URL, and searches the file using the host name only. **-netrcfile** : Pass a string containing the full path name of the file to use as the `.netrc` file. For this option to work, you must set **-netrc** to **required**. If this option is omitted and **-netrc** is set, TclCurl attempts to find a `.netrc` file in the current user's home directory. **-userpwd** : Pass a string in the form `[username]:[password]` to use for the connection. Use **-httpauth** to select the authentication method. When using NTLM, you can specify a domain by prepending it to the user name and separating the domain and name with a forward slash (`/`) or backward slash (`\\`), for example `domain/user:password` or `domain\\user:password`. Some HTTP servers on Windows also support this form for Basic authentication. When using HTTP and **-followlocation**, TclCurl might perform several requests to possibly different hosts. TclCurl will only send this user and password information to hosts using the initial host name (unless **-unrestrictedauth** is set), so if TclCurl follows locations to other hosts it will not send the user and password to those. This is enforced to prevent accidental information leakage. **-proxyuserpwd** : Pass a string in the form `[username]:[password]` to use for the connection to the HTTP proxy. **-username** : Pass a string containing the user name to use for the transfer. It sets the user name used in protocol authentication. This option should not be used together with the older **-userpwd** option. To specify the password to use together with the user name, use the **-password** option. **-password** : Pass a string containing the password to use for the transfer. This option should be used together with **-username**. **-proxyusername** : Pass a string containing the user name to use for the transfer while connecting to the proxy. This option is used in the same way as **-proxyuserpwd**, except that it allows the user name to contain a colon, as in `sip:user@example.com`. **-proxyusername** is an alternative way to set the user name while connecting to the proxy. It should not be used together with **-proxyuserpwd**. **-proxypassword** : Pass a string containing the password to use for the transfer while connecting to the proxy. This option is intended to be used together with **-proxyusername**. **-httpauth** : Set this option to the authentication method to use. Accepted values are: `basic` : HTTP Basic authentication. This is the default choice and the only method in widespread use that is supported almost everywhere. It sends the user name and password over the network in plain text. `digest` : HTTP Digest authentication. Over public networks, this is generally more secure than Basic authentication. `digestie` : HTTP Digest authentication with an Internet Explorer-specific variant. TclCurl uses a compatibility behavior known to have been used by Internet Explorer before version 7 and still required by some servers. `gssnegotiate` : HTTP GSS-Negotiate authentication. This method, also known simply as `Negotiate`, was designed by Microsoft and is used in Microsoft web applications. It is primarily intended to support Kerberos 5 authentication, but it may also be used with other authentication methods. `ntlm` : HTTP NTLM authentication. This is a proprietary protocol developed and used by Microsoft. It uses a challenge-response mechanism and hashing, similar to Digest, to avoid sending the password in clear text. `ntlmwb` : NTLM delegated to the winbind helper. Authentication is performed by a separate binary application that is executed when needed. The name of that application is specified when libcurl is built, but it is typically `/usr/bin/ntlm_auth`. Note that libcurl will fork when necessary to run the winbind application and kill it when complete, calling waitpid() to await its exit when done. On POSIX operating systems, killing the process will cause a SIGCHLD signal to be raised (regardless of whether **-nosignal** is set). This behavior is subject to change in future versions of libcurl. `any` : TclCurl automatically selects the method it considers the most secure. `anysafe` : TclCurl may use any method except Basic and automatically selects the one it considers the most secure. **-tlsauthtype** : Selects the authentication method to use for TLS authentication. Accepted values: `tlsauthsrp` : Uses TLS-SRP authentication. Secure Remote Password authentication for TLS is defined in RFC 5054 and provides mutual authentication if both sides share a secret. To use this value, you must also set **-tlsauthusername** and **-tlsauthpassword**. libcurl must be built with GnuTLS or with OpenSSL support for TLS-SRP for this to work. **-tlsauthusername** : Pass a string containing the user name to use for the TLS authentication method specified with **-tlsauthtype**. This option requires **-tlsauthpassword** to be set as well. **-tlsauthpassword** : Pass a string containing the password to use for the TLS authentication method specified with **-tlsauthtype**. This option requires **-tlsauthusername** to be set as well. **-proxyauth** : Use this option to tell TclCurl which authentication method to use for proxy authentication. For some methods, this causes an extra network round trip. Set the actual user name and password with **-proxyuserpwd**. The methods are those listed above for the **httpauth** option. As of this writing, only Basic and NTLM work. # HTTP OPTIONS **-autoreferer** : Set this option to `1` to enable automatic updates of the `Referer:` header when TclCurl follows a `Location:` redirect. **-encoding** : Sets the contents of the `Accept-Encoding:` header sent in an HTTP request, and enables decoding of a response when a `Content-Encoding:` header is received. Accepted values: `identity` : Requests no encoding. `deflate` : Requests compression using the zlib algorithm. `gzip` : Requests gzip compression. `all` : Sends an `Accept-Encoding:` header containing all supported encodings. This is a request, not a requirement; the server may or may not honor it. This option must be set or any unsolicited encoding used by the server is ignored. See `lib/README.encoding` in the libcurl documentation for details. **-transferencoding** : Adds a request for compressed `Transfer-Encoding` in the outgoing HTTP request. If the server supports this and chooses to use it, the response may use a compressed `Transfer-Encoding`, which TclCurl then decompresses automatically when receiving the data. `Transfer-Encoding` differs from the `Content-Encoding` requested with **-encoding** in that `Transfer-Encoding` applies strictly to the transfer and therefore must be decoded before the data reaches the client. Traditionally, `Transfer-Encoding` has been used less widely and is less consistently supported by HTTP clients and servers. **-followlocation** : Set this option to `1` to make TclCurl follow any `Location:` header sent by the server as part of an HTTP response. TclCurl resends the request to the new location and continues to follow further `Location:` headers until no more are returned. Use **-maxredirs** to limit the number of redirects TclCurl follows. Since 7.19.4, TclCurl can also restrict which protocols it follows automatically. The accepted protocols are set with **-redirprotocols**. By default, the `FILE` protocol is excluded. **-unrestrictedauth** : Set this option to `1` to allow TclCurl to continue sending authentication credentials when following redirects, even if the host name changes. This option is meaningful only when **-followlocation** is enabled. **-maxredirs** : Sets the redirection limit. After that many redirects have been followed, the next redirect causes an error. This option is meaningful only when **-followlocation** is enabled. Set the limit to `0` to refuse all redirects. Set it to `-1` for an unlimited number of redirects, which is the default. -postredir : Controls how TclCurl acts on redirects after POST requests that receive a `301`, `302`, or `303` response. Accepted values are `301`, `302`, `303`, and `all`. The values `301`, `302`, and `303` make TclCurl preserve the POST request method for the corresponding redirect status code. The value `all` enables all three behaviors. The non-RFC behavior is common in web browsers, so TclCurl performs this conversion by default to maintain consistency. However, a server may require a POST to remain a POST after such a redirection. This option is meaningful only when **-followlocation** is enabled. The legacy alias **-post301** is accepted for compatibility and uses the same values. **-put** : Set this option to `1` to make TclCurl upload a file using HTTP `PUT`. The file to upload must be specified with **-infile** and **-infilesize**. This option is deprecated as of version 0.12.1. Use **-upload**. This option does not limit how much data TclCurl will actually send, as that is controlled entirely by what the read callback returns. **-post** : Set this option to `1` to make TclCurl perform a regular HTTP `POST` request using the `application/x-www-form-urlencoded` format commonly used by HTML forms. Use **-postfields** to specify the data to post and **-postfieldsize** to specify its size. Use the **-postfields** option to specify what data to post and **-postfieldsize** to set the data size. Optionally, you can also provide `POST` data using **-readproc**. You can override the default `POST` `Content-Type:` header by setting your own with **-httpheader**. Using `POST` with HTTP 1.1 implies the use of an `Expect: 100-continue` header. You can disable this header with **-httpheader** as usual. If you use `POST` with an HTTP 1.1 server, you can send data without knowing the size in advance by using chunked encoding. Enable this by adding a header such as `Transfer-Encoding: chunked` with **-httpheader**. With HTTP 1.0, or without chunked transfer encoding, you must specify the size in the request. Setting **-post** to `1` also sets **-nobody** to `0`. **NOTE:** If you have issued a `POST` request and later want to make a `HEAD` or `GET` request instead, you must explicitly select the new request type with **-nobody**, **-httpget**, or a similar option. **-postfields** : Pass a string containing the complete data to send in an HTTP `POST` request. You must ensure that the data is formatted exactly as you want the server to receive it. TclCurl does not convert or encode it for you. Most web servers assume this data is URL-encoded. This is the normal `application/x-www-form-urlencoded` form, which is the most commonly used one by HTML forms. If you want to do a zero-byte POST, you need to set **-postfieldsize** explicitly to zero, because setting **-postfields** to `NULL` or `""` effectively disables sending the specified string. TclCurl then assumes that the `POST` data is supplied through the read callback. Using `POST` with HTTP 1.1 implies the use of an `Expect: 100-continue` header. You can disable this header with **-httpheader** as usual. **NOTE:** To make `multipart/form-data` posts, see **-httppost**. **-postfieldsize** : Use this option to post data without letting TclCurl call `strlen()` to determine the data size. This is also required if you want to post fully binary data, which would otherwise likely fail. If this size is set to zero, the library uses `strlen()` to determine the data size. **-httppost** : Makes TclCurl perform an HTTP `multipart/form-data` `POST` request. The data to send is described through a Tcl list. **This is the only case where the data is reset after a transfer.** Each part consists of at least a **NAME** and a **CONTENTS** part. If the part is used for file upload, it may also contain **CONTENT-TYPE** and **FILENAME** information. The list must contain a **'name'** tag followed by the section name. The section value can then be described with **'value'**, followed by a string containing the data to post, **'file'**, followed by the name of the file to post, or **'contenttype'**, followed by the content type (`text/plain`, `image/jpg`, and so on). You can also supply an alternate file name with **'filename'**. This is useful if the server checks whether the provided file name is valid, or if you want to include the full path of the file being posted. You can also post the contents of a variable as if it were a file by using **'bufferName'** and **'buffer'**, or use **'filecontent'** followed by a file name to read that file and use its contents as data. To specify additional headers for a form section, use **'contentheader'** followed by a list of headers. See `httpPost.tcl` and `httpBufferPost.tcl` for examples. Return values: `1` : If the memory allocation fails. `2` : If one option is given twice for one form. `3` : If an empty string was given. `4` : If an unknown option was used. `5` : If some form information is incomplete or invalid. `6` : If an illegal option is used in an array. `7` : If TclCurl has no HTTP support. **-referer** : Pass a string to set the `Referer:` header in the HTTP request sent to the remote server. The `Referer:` header identifies the resource from which the target URI was obtained. Servers may use it for logging, analytics, backlink generation, caching decisions, or request-flow checks. This option is useful when a scripted client must reproduce the request context normally sent by a web browser, or when a server expects a specific referring URI. The header value should normally be a URI identifying the referring resource. Fragments and userinfo components are not part of a valid `Referer:` field value. The field name `Referer` is a historical misspelling of `referrer`, but the misspelled form is the standardized HTTP header name. Because this header may reveal navigation context or sensitive URI data, it should be set with care. It should not be relied upon as a secure means of authentication or access control. You can also set this header through **-httpheader**. **-useragent** : Pass a string to set the `User-Agent:` header in the HTTP request sent to the remote server. You can also set custom headers with **-httpheader**. **-httpheader** : Pass a list of HTTP headers to send in the request. If you add a header that TclCurl would otherwise generate internally, your header is used instead. If you add a header with no value, such as `Accept:`, the internal header is disabled. This option can therefore be used to add, replace, or remove internal headers. This option is useful when the request must include headers not exposed by dedicated TclCurl options, or when you need exact control over the final HTTP request. Common uses include setting custom authentication-related headers, API-specific headers, cache-control directives, or overriding headers such as `Content-Type:` or `Accept:`. The headers in the list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. If you include CRLF yourself, the server will likely ignore part of the headers you specified. The first line of a request, containing the method, usually `GET` or `POST`, is not a header and cannot be replaced with this option. Only the lines following the request line are headers. Adding the method line to this list causes an invalid header to be sent. **NOTE:** The most commonly replaced headers have dedicated shortcut options: **-cookie**, **-useragent**, and **-referer**. **-http200aliases** : Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers return a custom response line. For example, IceCast servers may return `ICY 200 OK`. If you include such a string in the list, it is treated as a valid HTTP status line such as `HTTP/1.0 200 OK`. **NOTE:** The alias itself is not parsed for a version string. Before version 7.16.3, TclCurl used the value set by **-httpversion**, but since 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matches. **-cookie** : Pass a string to set a cookie in the HTTP request. The string should use the format `[NAME]=[CONTENTS];`, where `NAME` is the cookie name and `CONTENTS` is the cookie value. If you need to set multiple cookies, you must set them all in a single option value by concatenating them into one string, for example `name1=content1; name2=content2;`. This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are performed because of authentication, redirects, or similar causes, they all receive this cookie header. If this option is used multiple times, only the last value is kept. **-cookiefile** : Pass the name of a file containing cookie data. The cookie data may be in Netscape cookie file format or in regular HTTP-style headers written to a file. If the file is empty or does not exist, this option still enables cookies for the handle, causing TclCurl to parse received cookies and use matching cookies in later requests. If you use this option multiple times, each use adds another file to read. **-cookiejar** : Pass a file name to which TclCurl writes all internally known cookies when **curlHandle cleanup** is called. If no cookies are known, no file is created. Specify `-` to write the cookies to standard output. Using this option also enables cookies for the session, so matching cookies are sent on later requests, including those caused by redirects. TclCurl cannot report an error if writing the cookie jar fails. If **-verbose** is enabled, a warning is displayed, but that is the only visible feedback in this case. **-cookiesession** : Set this option to `1` to mark the current run as a new cookie session. This makes TclCurl ignore session cookies loaded from a previous session. By default, TclCurl stores and loads all cookies, including session cookies. Session cookies are cookies without an expiry date and are meant to exist only for the current session. **-cookielist** : Pass a string containing a cookie. The cookie may be in Netscape/Mozilla format or in regular HTTP-style header form, such as `Set-Cookie: ...`. If the cookie engine is not enabled, it is enabled automatically. Special values are `ALL`, which erases all known cookies, and `FLUSH`, which writes all known cookies to the file specified by **-cookiejar**. **-httpget** : Set this option to `1` to force the HTTP request method back to `GET`. This is useful if `POST`, `PUT`, or a custom request has previously been used with the same handle. Setting **-httpget** to `1` also sets **-nobody** to `0`. **-httpversion** : Selects the HTTP version to use. This option should be used only when it is necessary to override the default behavior because of server-side requirements. Accepted values: `none` : Lets TclCurl use the HTTP version it considers appropriate. `1.0` : Enforce HTTP 1.0 requests. `1.1` : Enforce HTTP 1.1 requests. `2.0` : Enforce HTTP version 2 requests. `2TLS` : Enforce version 2 requests for HTTPS, version 1.1 for HTTP. `2_PRIOR_KNOWLEDGE` : Enforce HTTP 2 requests without performing an HTTP/1.1 `Upgrade` first. **-ignorecontentlength** : Ignores the `Content-Length` header. This is useful for Apache 1.x and similar servers, which may report an incorrect content length for files larger than 2 gigabytes. If this option is used, TclCurl cannot report progress accurately and stops the download only when the server closes the connection. **-httpcontentdecoding** : Set this option to `0` to disable content decoding, or to `1` to enable it. TclCurl does not enable content decoding by default; for that, you must also use **-encoding**. **-httptransferencoding** : Set this option to `0` to disable transfer decoding, or to `1` to enable it. The default is `1`. TclCurl performs chunked transfer decoding by default unless this option is disabled. # SMTP OPTIONS **-mailfrom** : Pass a string specifying the sender address to use in the SMTP envelope. This option controls the envelope sender used at the SMTP protocol level. It does not set or modify the `From:` header field in the message body. **-mailrcpt** : Pass a list of recipient addresses to use in the SMTP envelope. This option controls the envelope recipients used at the SMTP protocol level. It does not set or modify message header fields such as `To:`, `Cc:`, or `Bcc:`. In SMTP, recipients are specified with angle brackets (`<>`). If a recipient value does not begin with an angle bracket, TclCurl assumes that it is a plain email address and adds the angle brackets automatically. # TFTP OPTION **-tftpblksize** : Specifies the block size to use for TFTP data transmission. According to RFC 2348, valid values range from `8` to `65464` bytes. If this option is not specified, the default block size is `512` bytes. The requested block size is used only if the remote server supports it. If the server does not return an option acknowledgment, or if it returns an acknowledgment without a block size value, the default of `512` bytes is used. # FTP OPTIONS **-ftpport** : Pass a string identifying the address to use for the FTP `PORT` instruction. The `PORT` instruction tells the remote server to connect to the specified client address. The string may be a plain IP address, a host name, a network interface name on Unix, or simply `-` to let the library use the system's default IP address. By default, FTP transfers are passive, so `PORT` is not used. The address can be followed by `:` and a port number, optionally followed by `-` and a port range. If the port specified is `0`, the operating system chooses a free port. If a range is provided and no port in that range is available, libcurl reports `CURLE_FTP_PORT_FAILED` for the handle. Invalid port or port-range settings are ignored. IPv6 addresses followed by a port or port range must be enclosed in brackets. IPv6 addresses without a port or port range may also be enclosed in brackets. Examples: `eth0:0` `192.168.1.2:32000-33000` `curl.se:32123` `[::1]:1234-4567` To disable `PORT` and return to passive mode, set this option to the empty string. **-quote** : Pass a list of FTP or SFTP commands to send to the server before the FTP transfer request. These commands are sent before any other FTP commands, including `CWD`. If you do not want to transfer any files, set **-nobody** to `1` and **-header** to `0`. Prefix a command with an asterisk (`*`) to make TclCurl continue even if that command fails. By default, a failure stops the transfer. To disable this option, set it to the empty string. The commands must be raw FTP commands. For example, to create a directory you must send `mkd Test`, not `mkdir Test`. Valid SFTP commands are `chgrp`, `chmod`, `chown`, `ln`, `mkdir`, `pwd`, `rename`, `rm`, `rmdir`, and `symlink`. **-postquote** : Pass a list of FTP commands to send to the server after the FTP transfer request. If you do not want to transfer any files, set **-nobody** to `1` and **-header** to `0`. **-prequote** : Pass a list of FTP or SFTP commands to send to the server after the transfer type has been set. **-dirlistonly** : Set this option to `1` to list only file names in a directory instead of requesting a full directory listing with file sizes, dates, and similar information. This option works with both FTP and SFTP URLs. For FTP, this causes an `NLST` command to be sent. Some FTP servers return only files in response to `NLST`, and may omit subdirectories and symbolic links. Setting this option to `1` also implies a directory listing even if the URL does not end with a slash, which would otherwise be required. Do not use this option together with **-wildcardmatch**, as it effectively disables that feature. **-append** : Set this option to `1` to append to the remote file instead of overwriting it. This is useful only when uploading to an FTP site. **-ftpuseeprt** : Set this option to `1` to make TclCurl use the `EPRT` and `LPRT` commands for active FTP transfers, which are enabled with **-ftpport**. When this option is enabled, TclCurl first attempts `EPRT`, then `LPRT`, and only then falls back to `PORT`. If this option is set to `0`, only `PORT` is used. **-ftpuseepsv** : Set this option to `1` to make TclCurl use the `EPSV` command for passive FTP transfers. This is the default behavior. When enabled, TclCurl first attempts `EPSV` before using `PASV`. If this option is set to `0`, TclCurl uses only `PASV`. **-ftpusepret** : Set this option to `1` to make TclCurl send a `PRET` command before `PASV` or `EPSV`. Some FTP servers, especially `drftpd`, require this non-standard command for directory listings and uploads or downloads in passive mode. This option has no effect for active FTP transfers. **-ftpcreatemissingdirs** : Controls whether TclCurl should attempt to create a remote directory when the transfer requires that directory to exist, but a `CWD` command shows that it does not yet exist or cannot yet be entered. This setting also applies to SFTP connections. TclCurl attempts to create the remote directory if it cannot obtain a handle to the target location. Creation fails if a file with the same name already exists, or if permissions do not allow directory creation. Accepted values: `1` : After a failed `CWD`, TclCurl attempts to create the missing remote directory and then continues with the transfer. `2` : After a failed `CWD`, TclCurl attempts to create the missing remote directory. If the subsequent `MKD` command fails, TclCurl retries the `CWD` command before giving up. This is useful when multiple simultaneous connections target the same server and another connection may have created the directory in the meantime. **-ftpresponsetimeout** : Sets a timeout, in seconds, for how long the server may take to return a response to an FTP command before the session is considered hung. While TclCurl is waiting for such a response, this value overrides **-timeout**. If both options are used, **-ftpresponsetimeout** should normally be set to a value smaller than **-timeout**. **-ftpalternativetouser** : Pass a string to use for authentication if the usual FTP `USER user` and `PASS password` negotiation fails. This is known to be required in some cases when connecting to Tumbleweed Secure Transport FTPS servers that use client-certificate authentication. **-ftpskippasvip** : Set this option to `1` to make TclCurl ignore the IP address suggested by the server in its `227` response to TclCurl's `PASV` command when opening the data connection. TclCurl instead reuses the same IP address already in use for the control connection, while still using the port number from the `227` response. This option has no effect if `PORT`, `EPRT`, or `EPSV` is used instead of `PASV`. **-ftpsslauth** : Selects how TclCurl issues `AUTH TLS` or `AUTH SSL` when FTP over SSL is enabled with **-ftpssl**. This option may be needed for servers such as BSDFTPD-SSL, which do not handle `AUTH SSL` correctly and require `AUTH TLS` instead. Accepted values: `default` : Lets TclCurl choose. `ssl` : Tries `AUTH SSL` first, and tries `AUTH TLS` only if that fails. `tls` : Tries `AUTH TLS` first, and tries `AUTH SSL` only if that fails. **-ftpsslccc** : Controls use of CCC (Clear Command Channel). CCC shuts down the SSL/TLS layer after authentication, so the remainder of the control channel is unencrypted. This can allow NAT routers to inspect the FTP control channel. Accepted values are: `none` : Do not attempt to use CCC. `passive` : Do not initiate the shutdown. Wait for the server to do so, and do not send a reply. `active` : Initiate the shutdown and wait for a reply. **-ftpaccount** : Pass a string containing account data, or `""` to disable it. If an FTP server requests account data after the user name and password have been provided, TclCurl sends this value with the `ACCT` command. **-ftpfilemethod** : Selects how TclCurl navigates FTP paths. Accepted values are: `multicwd` : The default. TclCurl performs one `CWD` operation for each path component in the URL. For deep hierarchies this may require many commands. This is the method described by RFC 1738. `nocwd` : TclCurl does not perform `CWD` at all. Instead it sends commands such as `SIZE`, `RETR`, and `STOR` with the full path. `singlecwd` : TclCurl performs one `CWD` to the full target directory and then operates on the file normally. This is somewhat more standards compliant than `nocwd`, without the full overhead of `multicwd`. # PROTOCOL OPTIONS **-transfertext** : Set this option to `1` to use ASCII mode for FTP transfers instead of the default binary transfer mode. On Win32 systems, this does not set `stdout` to binary mode. This option can be useful when transferring text data between systems that treat characters such as newlines differently. **NOTE:** TclCurl does not perform full ASCII conversion during ASCII FTP transfers. It simply sets the transfer mode to ASCII and performs a normal transfer. **-proxytransfermode** : Set this option to `1` to make TclCurl set the transfer mode, binary or ASCII, for FTP transfers performed through an HTTP proxy by appending `;type=a` or `;type=i` to the URL. If this option is omitted or set to `0`, **-transfertext** has no effect for FTP transfers performed through an HTTP proxy. Not all proxies support this feature. **-crlf** : Set this option to `1` to make TclCurl convert Unix newlines to CRLF newlines during transfers. Set it to `0` to disable this behavior. **-range** : Pass a string specifying the requested range. The format is `X-Y`, where either `X` or `Y` may be omitted. HTTP transfers also support multiple ranges separated by commas, as in `X-Y,N-M`. When multiple ranges are requested over HTTP, the server returns the response document in pieces using standard MIME separation rules. Range requests are supported only for HTTP, FTP, and FILE transfers. **-resumefrom** : Pass the offset, in bytes, at which the transfer should start. Set this option to `0` to start the transfer from the beginning, which disables resume behavior. For FTP, set this option to `-1` to start from the end of the target file, which is useful when continuing an interrupted upload. For FTP uploads, the resume position specifies where in the local source file TclCurl should resume reading. The data read from that point is then appended to the remote target file. **-customrequest** : Pass a string containing the request method to use instead of the default method, such as `GET` or `HEAD`, when making an HTTP request. This is useful for methods such as `DELETE` and other less common HTTP requests. Use this option only when the server is known to support the specified method. TclCurl still behaves internally according to the type of request it would otherwise have used. As a result, changing the request method with this option can produce inconsistent behavior if the corresponding request type is not selected through the usual dedicated option. For example, to make a proper `HEAD` request, use **-nobody**. To make a proper `POST` request, use **-post** or **-postfields**. **-filetime** : Set this option to `1` to make TclCurl attempt to obtain the modification time of the remote document during the transfer. This requires the remote server either to send the time directly or to support a command for querying it. After the transfer, the `filetime` value can be retrieved with the `getinfo` procedure. For FTP transfers, this typically means that the server must support a command for querying the remote file modification time, such as `MDTM`. If the server does not provide this information, the transfer can still succeed, but the retrieved `filetime` value remains unknown. **-nobody** : Set this option to `1` to omit the body from the output. This is relevant only for protocols that distinguish between a header part and a body part. For HTTP and HTTPS, this causes TclCurl to issue a `HEAD` request. To change the request back to `GET`, use **-httpget**. To switch to `POST`, use **-post** or a related option. **-infilesize** : Use this option when uploading a file to specify the expected size of the input file. This option is mandatory for uploads performed with SCP. **-upload** : Set this option to `1` to prepare for an upload. The **-infile** and **-infilesize** options are also relevant for uploads. If the protocol is HTTP, uploading means using the PUT request unless you tell TclCurl otherwise. Using PUT with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with **-httpheader** as usual. If you use PUT to a HTTP 1.1 server, you can upload data without knowing the size before starting the transfer if you use chunked encoding. You enable this by adding a header like "Transfer-Encoding: chunked" with **-httpheader**. With HTTP 1.0 or without chunked transfer, you must specify the size. -maxfilesize : This allows you to specify the maximum size (in bytes) of a file to download. If the file requested is larger than this value, the transfer will not start and error 'filesize exceeded' (63) will be returned. NOTE: The file size is not always known prior to download, and for such files this option has no effect even if the file transfer ends up being larger than this given limit. This concerns both FTP and HTTP transfers. -timecondition : Defines how the **timevalue** value is treated. Accepted values are `ifmodsince` and `ifunmodsince`. This feature applies to HTTP, FTP, and FILE. -timevalue : This should be the time in seconds since 1 jan 1970, and the time will be used in a condition as specified with **timecondition**. # CONNECTION OPTIONS **-timeout** : Pass the maximum time, in seconds, that a TclCurl transfer operation may take. Name resolution alone may take a noticeable amount of time, so setting this value too low can abort otherwise normal operations. This option may cause libcurl to use `SIGALRM` to interrupt blocking system calls. On Unix-like systems, signals may therefore be used unless **-nosignal** is enabled. **-timeoutms** : Like **-timeout**, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity. **-lowspeedlimit** : Pass the speed, in bytes per second, below which the transfer rate must remain during **-lowspeedtime** seconds before TclCurl considers the transfer too slow and aborts it. **-lowspeedtime** : Pass the number of seconds during which the transfer speed must stay below **-lowspeedlimit** before TclCurl considers the transfer too slow and aborts it. **-maxsendspeed** : Pass a speed in bytes per second. If an upload exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed. **-maxrecvspeed** : Pass a speed in bytes per second. If a download exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed. **-maxconnects** : Sets the size of the persistent connection cache for protocols that support persistent connections. This value is the maximum number of simultaneous connections TclCurl may cache in the easy handle. The default is `5`. When the maximum is reached, TclCurl closes the oldest cached connection to prevent the number of open connections from increasing further. **NOTE:** If transfers have already been performed with this easy handle, reducing **-maxconnects** may cause existing open connections to be closed earlier than expected. If this easy handle is added to a multi handle, this setting is ignored. In that case, configure the corresponding **maxconnects** option on the multi handle instead. **-connecttimeout** : Pass the maximum time, in seconds, that the connection phase may take. This limits only the time required to establish the connection. Once the connection has been established, this option no longer applies. Set it to `0` to disable the connection timeout. On Unix-like systems, signals may be used unless **-nosignal** is enabled. **-connecttimeoutms** : Like **-connecttimeout**, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity. **-ipresolve** : Selects which IP address families may be used when resolving host names. This option is relevant only when a host name resolves to more than one IP version. Accepted values are: `whatever` : The default. Resolves addresses using all IP versions supported by the system. `v4` : Resolves only IPv4 addresses. `v6` : Resolves only IPv6 addresses. **-resolve** : Pass a list of host name resolution entries to use for requests made with this handle. Each entry must use the format `HOST:PORT:ADDRESS`, where `HOST` is the name TclCurl tries to resolve, `PORT` is the destination service port, and `ADDRESS` is the numeric IP address to use. If libcurl supports IPv6, `ADDRESS` may be either an IPv4 or an IPv6 address. This option effectively pre-populates the DNS cache with entries for a given `HOST:PORT` pair, so redirects and other requests to the same `HOST:PORT` use the supplied `ADDRESS`. To remove an entry from the DNS cache, include a string in the form `-HOST:PORT`. The host name must be prefixed with a dash, and both the host name and port must exactly match an entry added earlier. **-usessl** : Selects the desired level of SSL or TLS use for the transfer. This option is relevant for protocols such as FTP, SMTP, POP3, and IMAP. You can also use `ftps://` URLs to enable SSL/TLS explicitly for both the control connection and the data connection. Accepted values: `nope` : Do not attempt to use SSL. `try` : Attempt to use SSL, but continue even if it cannot be negotiated. `control` : Use SSL for the control connection, or fail with `use ssl failed` (`64`). `all` : Use SSL for all communication, or fail with `use ssl failed` (`64`). # SSL AND SECURITY OPTIONS **-sslcert** : Pass a string containing the file name of the certificate to use. The default format is `PEM`, and it can be changed with **-sslcerttype**. When libcurl is built against NSS, this value is the nickname of the certificate to use for authentication. To use a file in the current directory in that case, prefix it with `./` to avoid confusion with a nickname. **-sslcerttype** : Pass a string specifying the format of the certificate given with **-sslcert**. Accepted values are: `PEM` : PEM format. `DER` : DER format. **-sslkey** : Pass a string containing the file name of the private key to use. The default format is `PEM`, and it can be changed with **-sslkeytype**. **-sslkeytype** : Pass a string specifying the format of the private key given with **-sslkey**. Accepted values are: `PEM` : PEM format. `DER` : DER format. `ENG` : Uses a crypto engine. In this case **-sslkey** is interpreted as an identifier passed to the engine, and **-sslengine** must also be set. **NOTE:** The `DER` private-key format may not work with some OpenSSL versions because of upstream limitations. **-keypasswd** : Pass a string containing the passphrase required to use the private key specified with **-sslkey** or **-sshprivatekeyfile**. A passphrase is not needed to load a certificate itself, but it may be needed to load the corresponding private key. This option was formerly known as **-sslkeypasswd** and **-sslcertpasswd**. **-sslengine** : Pass a string containing the identifier of the crypto engine to use for private-key operations. **NOTE:** If the crypto engine cannot be loaded, TclCurl returns an error. **-sslenginedefault** : Set this option to `1` to make the selected crypto engine the default for asymmetric cryptographic operations. **NOTE:** If the crypto engine cannot be made the default, TclCurl returns an error. **-sslversion** : Selects the SSL or TLS protocol version to use. Accepted values are: `default` : Uses the default behavior. TclCurl attempts to negotiate an appropriate protocol version with the remote server. `tlsv1` : Requires TLSv1 or later. `sslv2` : Requires SSLv2. `sslv3` : Requires SSLv3. `tlsv1_0` : Requires TLSv1.0 or later. `tlsv1_1` : Requires TLSv1.1 or later. `tlsv1_2` : Requires TLSv1.2 or later. `tlsv1_3` : Requires TLSv1.3 or later. `maxdefault` : Uses the maximum TLS version supported by libcurl or by the SSL backend's default configuration. `maxtlsv1_0` : Sets the maximum supported TLS version to TLSv1.0. `maxtlsv1_1` : Sets the maximum supported TLS version to TLSv1.1. `maxtlsv1_2` : Sets the maximum supported TLS version to TLSv1.2. `maxtlsv1_3` : Sets the maximum supported TLS version to TLSv1.3. **-sslverifypeer** : Controls whether TclCurl verifies the authenticity of the peer certificate. Set this option to `1` to enable verification or to `0` to disable it. The default is `1`. During the SSL or TLS handshake, the server sends a certificate declaring its identity. TclCurl verifies that certificate against a chain of trust rooted in one or more certification authority (CA) certificates. TclCurl uses the default CA bundle provided by libcurl, but you can specify alternate certificates with **-cainfo** or **-capath**. If **-sslverifypeer** is nonzero and verification fails, the connection fails. If this option is `0`, peer-certificate verification is skipped. Certificate verification alone does not confirm that the peer is the specific host you intended to contact. Use **-sslverifyhost** to control host-name verification. **-cainfo** : Pass the name of a file containing one or more CA certificates used to verify the peer certificate. This option is meaningful primarily together with **-sslverifypeer**. If peer verification is disabled, **-cainfo** does not need to name an accessible file. By default, this option is set to the system path of libcurl's CA bundle, as determined when libcurl was built. When libcurl is built against NSS, this value refers to the directory containing the NSS certificate database. **-issuercert** : Pass the name of a file containing a CA certificate in PEM format. If this option is set, an additional check is performed to verify that the peer certificate was issued by the CA certificate provided here. This is useful in multi-level PKI environments where the peer certificate must be constrained to a specific branch of the certificate hierarchy. This option is meaningful only when used together with **-sslverifypeer**. Otherwise, failure of this additional check is not treated as a connection failure. **-capath** : Pass the name of a directory containing multiple CA certificates to use when verifying the peer certificate. When libcurl is built against OpenSSL, this directory must be prepared with the `openssl c_rehash` utility. This option is meaningful primarily together with **-sslverifypeer**. If peer verification is disabled, **-capath** does not need to name an accessible directory. This option is OpenSSL-specific and has no effect when libcurl is built against GnuTLS. NSS-based libcurl provides it only for backward compatibility. On Windows, this option may not work because of OpenSSL limitations. **-crlfile** : Pass the name of a file containing one or more certificate revocation lists in PEM format to use during certificate validation. When libcurl is built against NSS or GnuTLS, there is no supported way to influence revocation checking with this option. When libcurl is built with OpenSSL support, both `X509_V_FLAG_CRL_CHECK` and `X509_V_FLAG_CRL_CHECK_ALL` are enabled if a CRL file is provided, so CRL checking is applied throughout the certificate chain. This option is meaningful only when used together with **-sslverifypeer**. If the CRL file cannot be loaded, the SSL exchange fails with the specific error code `CURLE_SSL_CRL_BADFILE`. A certificate-verification failure caused by revocation information in the CRL does not produce that specific error code. **-sslverifyhost** : Controls whether TclCurl verifies that the server certificate matches the host name you intended to contact. During the SSL or TLS handshake, the server sends a certificate declaring its identity. When **-sslverifyhost** is set to `2`, the certificate must identify the intended server or the connection fails. TclCurl considers the server to match when the Common Name field or a Subject Alternative Name field in the certificate matches the host name in the URL. When this option is set to `1`, the certificate must contain a Common Name field, but the specific name is not checked. This setting is generally not useful. When this option is set to `0`, the connection succeeds regardless of the names contained in the certificate. The default value is `2`. This option verifies the host identity claimed by the certificate. To verify that the certificate itself is trusted, use **-sslverifypeer**. If libcurl is built against NSS and **-sslverifypeer** is `0`, **-sslverifyhost** is ignored. **-certinfo** : Set this option to `1` to enable collection of certificate-chain information. When enabled, TclCurl, if built against OpenSSL, extracts certificate details from the chain used in the SSL connection. That information can be retrieved after the transfer with the **getinfo** command and its `certinfo` option. **-randomfile** : Pass a file name. TclCurl uses this file as a source of randomness for the SSL random engine. *This option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See `README.md` for instructions on how to re-enable it.* **-egdsocket** : Pass the path name of an Entropy Gathering Daemon socket. TclCurl uses it as a source of randomness for the SSL random engine. *This option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See `README.md` for instructions on how to re-enable it.* **-sslcipherlist** : Pass a string containing the cipher list to use for the SSL or TLS connection. The list consists of one or more cipher strings separated normally by colons, although commas or spaces are also accepted. The characters `!`, `-`, and `+` may also be used as operators. With OpenSSL and GnuTLS, valid examples include `RC4-SHA`, `SHA1+DES`, `TLSv1`, and `DEFAULT`. The default list is usually defined by the SSL backend at build time. With NSS, valid examples include `rsa_rc4_128_md5` and `rsa_aes_128_sha`. NSS does not support incremental add or remove semantics for ciphers. If this option is used, all known ciphers are disabled and only the ciphers listed here are enabled. For details about cipher-list syntax, see: For NSS-specific cipher-list details, see: **-sslsessionidcache** : Set this option to `0` to disable TclCurl's use of SSL session-ID caching, or to `1` to enable it. The default is `1`. In normal circumstances, reusing SSL session IDs is harmless and may improve performance. However, some broken SSL implementations may require this option to be disabled. **-krblevel** : Selects the Kerberos security level for FTP and thereby also enables Kerberos awareness. Accepted values are `clear`, `safe`, `confidential`, and `private`. If the string does not match one of these values, `private` is used. Set the string to `NULL` to disable Kerberos 4. Set it to `""` to disable Kerberos support for FTP. **-gssapidelegation** : Selects the GSSAPI credential delegation mode. Accepted values are: `flag` : Allows unconditional delegation. `policyflag` : Delegates only if the `OK-AS-DELEGATE` flag is set in the service ticket, provided that this feature is supported by the GSSAPI implementation and that `GSS_C_DELEG_POLICY_FLAG` was available at compile time. Delegation is disabled by default since 7.21.7. # SSH OPTIONS **-sshauthtypes** : Selects the allowed SSH authentication types. Accepted values are: `publickey` : Use public-key authentication. `password` : Use password authentication. `host` : Use host-based authentication. `keyboard` : Use keyboard-interactive authentication. `any` : Let TclCurl select an authentication method automatically. **-sshhostpublickeymd5** : Pass a string containing 32 hexadecimal digits. The string must be the 128-bit MD5 checksum of the remote host public key. TclCurl rejects the connection unless the checksum matches. This option applies only to SCP and SFTP transfers. **-sshpublickeyfile** : Pass the file name of the public key to use. If this option is not used, TclCurl defaults to `$HOME/.ssh/id_dsa.pub` when the `HOME` environment variable is set, and to `id_dsa.pub` in the current directory otherwise. **-sshprivatekeyfile** : Pass the file name of the private key to use. If this option is not used, TclCurl defaults to `$HOME/.ssh/id_dsa` when the `HOME` environment variable is set, and to `id_dsa` in the current directory otherwise. If the private key is passphrase-protected, use **-keypasswd** to specify the passphrase. **-sshknownhosts** : Pass a string containing the file name of the `known_hosts` file to use. The file must use the OpenSSH `known_hosts` format supported by libssh2. If this option is set, TclCurl accepts connections only to hosts that are present in that file with a matching public key. Use **-sshkeyproc** to override the default behavior for host and key matching. **-sshkeyproc** : Pass the name of a callback procedure that TclCurl invokes after `known_hosts` matching has been performed, so that the application can decide how the connection should proceed. The callback is invoked only if **-sshknownhosts** is also set. The callback receives a list with three elements: 1. A list containing the key type from the `known_hosts` file and the key itself. 2. A list containing the key type presented by the remote host and the key itself. 3. A value describing TclCurl's matching result. Possible key-type values are `rsa`, `rsa1`, `dss`, and `unknown`. Possible match-result values are `match`, `mismatch`, `missing`, and `error`. Return values: `0` : Accept the host and key. TclCurl appends the host and key to the `known_hosts` file before continuing with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. Updating the file is done by replacing it with a new copy, so the file permissions must allow that. `1` : Accept the host and key, and continue with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. `2` : Reject the host and key. TclCurl closes the connection. `3` : Reject the host and key, but keep the SSH connection alive. This can be useful if the application needs to inspect the host or key state and then retry without incurring the full setup cost again. Any other return value causes TclCurl to close the connection. # OTHER OPTIONS **-headervar** : Name of the Tcl array variable in which TclCurl stores the headers returned by the server. **-bodyvar** : Name of the Tcl variable in which TclCurl stores the requested file contents. The stored data may be either text or binary data. **-canceltransvarname** : Name of a Tcl variable used together with **-progressproc**. If the progress callback sets this variable to `1`, the transfer is canceled. **-command** : Executes the given command after the transfer has completed. This option works only with blocking transfers and therefore has limited practical use. **-share** : Pass a share handle. The share handle must have been created previously by calling **curl::shareinit**. Setting this option causes the easy handle to use data from the shared handle instead of keeping its own separate copy. See *tclcurl_share* for details. **-newfileperms** : Pass a numeric value specifying the permissions assigned to newly created files on the remote server. The default value is `0644`, but any valid value may be used. This option applies only to `sftp://`, `scp://`, and `file://` transfers. **-newdirectoryperms** : Pass a numeric value specifying the permissions assigned to newly created directories on the remote server. The default value is `0755`, but any valid value may be used. This option applies only to `sftp://`, `scp://`, and `file://` transfers. # TELNET OPTIONS -telnetoptions : Pass a list with variables to pass to the telnet negotiations. The variables should be in the format . TclCurl supports the options 'TTYPE', 'XDISPLOC' and 'NEW_ENV'. See the TELNET standard for details. # NOT SUPPORTED Some of the options libcurl offers are not supported, I don't think them worth supporting in TclCurl but if you need one of them don't forget to complain: **CURLOPT_FRESH_CONNECT, CURLOPT_FORBID_REUSE, CURLOPT_PRIVATE,** **CURLOPT_SSL_CTX_FUNCTION, CURLOPT_SSL_CTX_DATA, CURLOPT_SSL_CTX_FUNCTION and** **CURLOPT_CONNECT_ONLY, CURLOPT_OPENSOCKETFUNCTION, CURLOPT_OPENSOCKETDATA.** # curlHandle perform This procedure is called after the **init** and all the **configure** calls are made, and will perform the transfer as described in the options. It must be called with the same *curlHandle* **curl::init** call returned. You can do any amount of calls to perform while using the same handle. If you intend to transfer more than one file, you are even encouraged to do so. TclCurl will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources. Just note that you will have to use configure between the invokes to set options for the following perform. You must never call this procedure simultaneously from two places using the same handle. Let it return first before invoking it another time. If you want parallel transfers, you must use several curl handles. RETURN VALUE : `0` if all went well, non-zero if it didn't. In case of error, if the errorbuffer was set with configure there will be a readable error message. The error codes are: **1** : Unsupported protocol. This build of TclCurl has no support for this protocol. **2** : Very early initialization code failed. This is likely to be and internal error or a resource problem where something fundamental couldn't get done at init time. **3** : URL malformat. The syntax was not correct. **4** : A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision. This means that a feature or option was not enabled or explicitly disabled when libcurl was built and in order to get it to function you have to get a rebuilt libcurl. **5** : Couldn't resolve proxy. The given proxy host could not be resolved. **6** : Couldn't resolve host. The given remote host was not resolved. **7** : Failed to connect to host or proxy. **8** : FTP weird server reply. The server sent data TclCurl couldn't parse. The given remote server is probably not an OK FTP server. **9** : We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory. **11** : FTP weird PASS reply. TclCurl couldn't parse the reply sent to the PASS request. **13** : FTP weird PASV reply, TclCurl couldn't parse the reply sent to the PASV or EPSV request. **14** : FTP weird 227 format. TclCurl couldn't parse the 227-line the server sent. **15** : FTP can't get host. Couldn't resolve the host IP we got in the 227-line. **17** : FTP couldn't set type. Couldn't change transfer method to either binary or ascii. **18** : Partial file. Only a part of the file was transferred, this happens when the server first reports an expected transfer size and then delivers data that doesn't match the given size. **19** : FTP couldn't RETR file, we either got a weird reply to a 'RETR' command or a zero byte transfer. **21** : Quote error. A custom 'QUOTE' returned error code 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command. **22** : HTTP returned error. This return code only appears if **-failonerror** is used and the HTTP server returns an error code that is 400 or higher. **23** : Write error. TclCurl couldn't write data to a local filesystem or an error was returned from a write callback. **25** : Failed upload failed. For FTP, the server typcially denied the STOR command. The error buffer usually contains the server's explanation to this. **26** : Read error. There was a problem reading from a local file or an error was returned from the read callback. **27** : Out of memory. A memory allocation request failed. This should never happen unless something weird is going on in your computer. **28** : Operation timeout. The specified time-out period was reached according to the conditions. **30** : The FTP PORT command failed, not all FTP servers support the PORT command, try doing a transfer using PASV instead!. **31** : FTP couldn't use REST. This command is used for resumed FTP transfers. **33** : Range error. The server doesn't support or accept range requests. **34** : HTTP post error. Internal post-request generation error. **35** : SSL connect error. The SSL handshaking failed, the error buffer may have a clue to the reason, could be certificates, passwords, ... **36** : The download could not be resumed because the specified offset was out of the file boundary. **37** : A file given with FILE:// couldn't be read. Did you checked the permissions? **38** : LDAP cannot bind. LDAP bind operation failed. **39** : LDAP search failed. **41** : A required zlib function was not found. **42** : Aborted by callback. An application told TclCurl to abort the operation. **43** : Internal error. A function was called with a bad parameter. **45** : Interface error. A specified outgoing interface could not be used. **47** : Too many redirects. When following redirects, TclCurl hit the maximum amount, set your limit with --maxredirs **48** : An option passed to TclCurl is not recognized/known. Refer to the appropriate documentation. This is most likely a problem in the program that uses TclCurl. The error buffer might contain more specific information about which exact option it concerns. **49** : A telnet option string was illegally formatted. **51** : The remote peer's SSL certificate or SSH md5 fingerprint wasn't ok **52** : The server didn't reply anything, which here is considered an error. **53** : The specified crypto engine wasn't found. **54** : Failed setting the selected SSL crypto engine as default! **55** : Failed sending network data. **56** : Failure with receiving network data. **58** : Problem with the local client certificate. **59** : Couldn't use specified SSL cipher. **60** : Peer certificate cannot be authenticated with known CA certificates. **61** : Unrecognized transfer encoding. **62** : Invalid LDAP URL. **63** : Maximum file size exceeded. **64** : SSL use failed. **65** : Sending the data requires a rewind that failed, since TclCurl should take care of it for you, it means you found a bug. **66** : Failed to initialise ssl engine. **67** : Failed to login, user password or similar was not accepted. **68** : File not found on TFTP server. **69** : There is a permission problem with the TFTP request. **70** : The remote server has run out of space. **71** : Illegal TFTP operation. **72** : Unknown transfer ID. **73** : TFTP file already exists and will not be overwritten. **74** : No such user in the TFTP server and good behaving TFTP servers should never return this. **75** : Character conversion failed. **77** : Problem with reading the SSL CA cert (path? access rights?). **78** : Remote file not found **79** : Error from the SSH layer **80** : Failed to shut down the SSL connection **82** : Failed to load CRL file **83** : Issuer check failed **84** : The FTP server does not understand the PRET command at all or does not support the given argument. Be careful when using **-customrequest**, a custom LIST command will be sent with PRET CMD before PASV as well. **85** : Mismatch of RTSP CSeq numbers. **86** : Mismatch of RTSP Session Identifiers. **87** : Unable to parse FTP file list (during FTP wildcard downloading). **88** : Chunk callback reported error. # curlHandle getinfo OPTION Request internal information from the curl session with this procedure. This procedure is intended to get used *AFTER* a performed transfer, and can be relied upon only if the **perform** returns 0. Use this function AFTER a performed transfer if you want to get transfer-oriented data. The following information can be extracted: effectiveurl : Returns the last used effective URL. responsecode : Returns the last received HTTP or FTP code. This will be zero if no server response code has been received. Note that a proxy's CONNECT response should be read with **httpconnectcode** and not this. httpconnectcode : Returns the last received proxy response code to a CONNECT request. filetime : Returns the remote time of the retrieved document (in number of seconds since 1 jan 1970 in the GMT/UTC time zone). If you get -1, it can be because of many reasons (unknown, the server hides it or the server doesn't support the command that tells document time etc) and the time of the document is unknown. In order for this to work you have to set the **-filetime** option before the transfer. namelookuptime : Returns the time, in seconds, it took from the start until the name resolving was completed. connecttime : Returns the time, in seconds, it took from the start until the connect to the remote host (or proxy) was completed. appconnecttime : Returns the time, in seconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed. This time is most often very near to the PRETRANSFER time, except for cases such as HTTP pippelining where the pretransfer time can be delayed due to waits in line for the pipeline and more. pretransfertime : Returns the time, in seconds, it took from the start until the file transfer is just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved. starttransfertime : Returns the time, in seconds, it took from the start until the first byte is just about to be transferred. This includes the **pretransfertime**, and also the time the server needs to calculate the result. totaltime : Returns the total transaction time, in seconds, for the previous transfer, including name resolving, TCP connect etc. redirecturl : Returns the URL a redirect would take you to if you enable **followlocation**. This can come very handy if you think using the built-in libcurl redirect logic isn't good enough for you but you would still prefer to avoid implementing all the magic of figuring out the new URL. redirecttime : Returns the total time, in seconds, it took for all redirection steps including name lookup, connect, pretransfer and transfer before the final transaction was started, it returns the complete execution time for multiple redirections, so it returns zero if no redirections were needed. redirectcount : Returns the total number of redirections that were actually followed. numconnects : Returns how many new connections TclCurl had to create to achieve the previous transfer (only the successful connects are counted). Combined with **redirectcount** you are able to know how many times TclCurl successfully reused existing connection(s) or not. See the Connection Options of **setopt** to see how TclCurl tries to make persistent connections to save time. primaryip : Returns the IP address of the most recent connection done with this handle. This string may be IPv6 if that's enabled. primaryport : Returns the destination port of the most recent connection done with this handle. localip : Returns the local (source) IP address of the most recent connection done with this handle. This string may be IPv6 if that's enabled. localport : Returns the local (source) port of the most recent connection done with this handle. sizeupload : Returns the total amount of bytes that were uploaded. sizedownload : Returns the total amount of bytes that were downloaded. The amount is only for the latest transfer and will be reset again for each new transfer. speeddownload : Returns the average download speed, measured in bytes/second, for the complete download. speedupload : Returns the average upload speed, measured in bytes/second, for the complete upload. headersize : Returns the total size in bytes of all the headers received. requestsize : Returns the total size of the issued requests. This is so far only for HTTP requests. Note that this may be more than one request if followLocation is true. sslverifyresult : Returns the result of the certification verification that was requested (using the -sslverifypeer option to configure). sslengines : Returns a **list** of the OpenSSL crypto-engines supported. Note that engines are normally implemented in separate dynamic libraries. Hence not all the returned engines may be available at run-time. contentlengthdownload : Returns the content-length of the download. This is the value read from the **Content-Length:** field. If the size isn't known, it returns -1. contentlengthupload : Returns the specified size of the upload. contenttype : Returns the content-type of the downloaded object. This is the value read from the Content-Type: field. If you get an empty string, it means the server didn't send a valid Content-Type header or that the protocol used doesn't support this. httpauthavail : Returns a list with the authentication method(s) available. proxyauthavail : Returns a list with the authentication method(s) available for your proxy athentication. oserrno : Returns the errno value from a connect failure. This value is only set on failure, it is no reset after a successful operation. cookielist : Returns a list of all cookies TclCurl knows (expired ones, too). If there are no cookies (cookies for the handle have not been enabled or simply none have been received) the list will be empty. ftpentrypath : Returns a string holding the path of the entry path. That is the initial path TclCurl ended up in when logging on to the remote FTP server. Returns an empty string if something is wrong. certinfo : Returns list with information about the certificate chain, assuming you had the **-certinfo** option enabled when the previous request was done. The list first item reports how many certs it found and then you can extract info for each of those certs by following the list. The info chain is provided in a series of data in the format "name:content" where the content is for the specific named data. NOTE: this option is only available in libcurl built with OpenSSL support. conditionunmet : Returns the number 1 if the condition provided in the previous request didn't match (see *timecondition*), you will get a zero if the condition instead was met. # curlHandle cleanup This procedure must be the last one to call for a curl session. It is the opposite of the curl::init procedure and must be called with the same curlhandle as input as the curl::init call returned. This will effectively close all connections TclCurl has used and possibly has kept open until now. Don't call this procedure if you intend to transfer more files. # curlHandle reset Re-initializes all options previously set on a specified handle to the default values. This puts back the handle to the same state as it was in when it was just created with curl::init. It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares. # curlHandle duphandle This procedure will return a new curl handle, a duplicate, using all the options previously set in the input curl handle. Both handles can subsequently be used independently and they must both be freed with **cleanup**. The new handle will not inherit any state information, connections, SSL sessions or cookies. RETURN VALUE : A new curl handle or an error message if the copy fails. # curlHandle pause You can use this command from within a progress callback procedure to pause the transfer. # curlHandle resume Resumes a transfer paused with **curlhandle pause** # curl::transfer In case you do not want to use persistent connections you can use this command, it takes the same arguments as the *curlHandle* **configure** and will init, configure, perform and cleanup a connection for you. You can also get the *getinfo* information by using *-infooption variable* pairs, after the transfer *variable* will contain the value that would have been returned by *$curlHandle getinfo option*. RETURN VALUE : The same error code **perform** would return. # curl::version Returns a string with the version number of tclcurl, libcurl and some of its important components (like OpenSSL version). RETURN VALUE : The string with the version info. # curl::escape URL This procedure will convert the given input string to an URL encoded string and return that. All input characters that are not a-z, A-Z or 0-9 will be converted to their "URL escaped" version (%NN where NN is a two-digit hexadecimal number) RETURN VALUE : The converted string. # curl::unescape URL This procedure will convert the given URL encoded input string to a "plain string" and return that. All input characters that are URL encoded (%XX where XX is a two-digit hexadecimal number) will be converted to their plain text versions. RETURN VALUE : The string unencoded. # curl::curlConfig OPTION Returns some information about how you have **cURL** installed. -prefix : Returns the directory root where you installed **cURL**. -feature : Returns a list containing particular main features the installed **libcurl** was built with. The list may include SSL, KRB4 or IPv6, do not assume any particular order. -vernum : Outputs version information about the installed libcurl, in numerical mode. This outputs the version number, in hexadecimal, with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e... # curl::versioninfo OPTION Returns information about various run-time features in TclCurl. Applications should use this information to judge if things are possible to do or not, instead of using compile-time checks, as dynamic/DLL libraries can be changed independent of applications. -version : Returns the version of libcurl we are using. -versionnum : Returns the version of libcurl we are using in hexadecimal with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e... Note that the initial zero might be omitted. -host : Returns a string with the host information as discovered by a configure script or set by the build environment. -features : Returns a list with the features compiled into libcurl, the possible elements are: ASYNCHDNS : Libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface. CONV : Libcurl was built with support for character conversions. DEBUG : Libcurl was built with extra debug capabilities built-in. This is mainly of interest for libcurl hackers. GSSNEGOTIATE : Supports HTTP GSS-Negotiate. IDN : Supports IDNA, domain names with international letters. IPV6 : Supports IPv6. KERBEROS4 : Supports kerberos4 (when using FTP). LARGEFILE : Libcurl was built with support for large files. LIBZ : Supports HTTP deflate using libz. NTML : Supports HTTP NTLM SPNEGO : Libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478) SSL : Supports SSL (HTTPS/FTPS) SSPI : Libcurl was built with support for SSPI. This is only available on Windows and makes libcurl use Windows-provided functions for NTLM authentication. It also allows libcurl to use the current user and the current user's password without the app having to pass them on. TLSAUTH_SRP : Libcurl was built with support for TLS-SRP. **NTLM_WB** Libcurl was built with support for NTLM delegation to a winbind helper. Do not assume any particular order. -sslversion : Returns a string with the OpenSSL version used, like OpenSSL/0.9.6b. -sslversionnum : Returns the numerical OpenSSL version value as defined by the OpenSSL project. If libcurl has no SSL support, this is 0. -libzversion : Returns a string, there is no numerical version, for example: 1.1.3. -protocols : Lists what particular protocols the installed TclCurl was built to support. At the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE, TELNET, LDAP, DICT. Do not assume any particular order. The protocols will be listed using uppercase. There may be none, one or several protocols in the list. # curl::easystrerror errorCode This procedure returns a string describing the error code passed in the argument. # EXAMPLES The examples in this section assume you are running from the root of the TclCurl source tree. To start the local HTTP test server used in the examples, run: ```sh tclsh testservers/testserver.tcl ``` By default, this starts an HTTP server on `http://127.0.0.1:8990/`. The path `http://127.0.0.1:8990/tclcurl-man` returns the HTML version of this manual page from `doc/tclcurl.html`, which makes it a convenient target for a basic `GET` example. # BASIC HTTP GET The file `examples/http_get.tcl` contains a minimal HTTP `GET` example. It performs a simple request, stores the response body in a Tcl variable, and prints both the HTTP response code and the size of the returned document. If the request succeeds, `rc` is `0`, `responsecode` is `200`, and `body` contains the HTML document returned by the server. # AUTHORS Andres Garcia Garcia Massimo Manghi # SEE ALSO curl, The art of HTTP scripting (at , RFC 2396, tclcurl-ng-8.0.3/doc/tclcurl.n.md.in000066400000000000000000003035061522613063100172020ustar00rootroot00000000000000--- title: TclCurl section: n date: 15 May 2026 source: TclCurl @PACKAGE_VERSION@ volume: TclCurl Easy Interface --- # NAME TclCurl - Transfer data to and from URLs using FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS, and GOPHER. # SYNOPSIS ```tcl curl::init curl::transfer ?options? curl::version curl::escape url curl::unescape url curl::curlConfig option curl::versioninfo option curl::easystrerror errorCode ``` ```tcl curlHandle configure ?options? curlHandle perform curlHandle getinfo curlinfo_option curlHandle cleanup curlHandle reset curlHandle duphandle curlHandle pause curlHandle resume ``` # DESCRIPTION The TclCurl extension gives Tcl programmers access to the libcurl library written by **Daniel Stenberg**. With TclCurl, you can download from URLs, upload to them, and perform many other network transfer operations. For more information, see . # curl::init This procedure must be called first. It returns a `curlHandle`, which you use to invoke TclCurl procedures. Calling `init` initializes TclCurl, and each call to `init` MUST have a corresponding call to `cleanup` when the operation is complete. You should perform all sequential file transfers using the same `curlHandle`. This allows TclCurl to reuse persistent connections when possible. **RETURN VALUE** The `curlHandle` to use. # curlHandle configure ?OPTIONS? **configure** is used to set the options for a transfer. Most operations in TclCurl have default behavior, and you can change that behavior by setting the appropriate options as documented. Each option is specified as the *option* followed by a parameter. **Notes:** The options set with this procedure apply to subsequent data transfers performed when you invoke `perform`. The options are not reset between transfers (except where noted), so if you want subsequent transfers with different options, you must change them between the transfers. You can optionally reset all options back to the internal default with **curlHandle reset**. `curlHandle` is the value returned by the `curl::init` call. **OPTIONS** # BEHAVIOUR OPTIONS **-verbose** : Set this option to 1 to make the library display detailed information about its operations. This option is useful when debugging libcurl and protocol-related problems. You will rarely want to enable this in production, but it is often helpful when debugging or reporting problems. Another useful debugging option is **-debugproc** **-header** : Set this option to 1 to include headers in the body output. This is relevant only for protocols that actually send headers before the data, such as HTTP. **-noprogress** : Set this option to 1 to disable the progress meter completely. It also prevents *progressproc* from being called. **-nosignal** : Set this option to 1 to make TclCurl avoid functions that install signal handlers or cause signals to be sent to the process. This option exists mainly so that multi-threaded Unix applications can still use timeout options without risking signal-related side effects. If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while name resolution is in progress. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which allows proper timeouts for name resolution without signals. Setting *nosignal* to 1 makes libcurl stop asking the system to ignore SIGPIPE signals. Such signals may otherwise be sent by the system when data is written to a socket that has been closed by the peer. libcurl tries to avoid triggering SIGPIPE, but some operating systems provide no reliable way to prevent it, and even on those that do, some corner cases remain. In addition, using *ntlm_Wb* authentication may cause a SIGCHLD signal to be raised. **-wildcard** : Set this option to 1 to transfer multiple files that match a file name pattern. The pattern can be specified as part of the **-url** option, using an fnmatch-like pattern (shell pattern matching) in the last part of the URL, that is, the file name. By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function with the **-fnmatchproc** option. At present, this feature is supported only for FTP downloads. A brief introduction of its syntax follows: - * - ASTERISK `ftp://example.com/some/path/***.txt**` (for all `.txt` files from the root directory) - ? - QUESTION MARK The question mark matches any single character. `ftp://example.com/some/path/**photo?.jpeg**` - [ - BRACKET EXPRESSION The left bracket opens a bracket expression. The question mark and asterisk have no special meaning in a bracket expression. Each bracket expression ends by the right bracket and matches exactly one character. Some examples follow: **[a-zA-Z0-9]** or **[f-gF-G]** - character interval **[abc]** - character enumeration **[^abc]** or **[!abc]** - negation **[[:***name***:]]** class expression. Supported classes are **alnum**,**lower**, **space**, **alpha**, **digit**, **print**, **upper**, **blank**, **graph**, **xdigit**. **[][-!^]** - special case - matches only '-', ']', '[', '!' or '^'. These characters have no special purpose. **[\\[\\]\\\\]** - escape syntax. Matches '[', ']' or '\\'. Using the rules above, a file name pattern can be constructed: `ftp://example.com/some/path/**[a-z[:upper:]\\\\].jpeg**` # CALLBACK OPTIONS **-writeproc** : Sets a Tcl procedure that TclCurl invokes whenever received data is available to be handled. The callback procedure must have a single argument. When the procedure is invoked, that argument refers to the contents of a data buffer managed by libcurl. NOTE: The amount of data passed on each invocation is not fixed. The callback may be invoked with an empty buffer, or with a buffer containing a large amount of data. **-file** : File in which the transferred data will be saved. **-readproc** : Sets a Tcl procedure that TclCurl calls whenever it needs to read data to send to the peer. The procedure must take one parameter, which contains the maximum number of bytes to read. It should return the actual number of bytes read, or `0` if you want to stop the transfer. If you stop the current transfer by returning `0` prematurely, for example after indicating that you would upload *N* bytes but uploading fewer than *N*, the server may appear to hang while waiting for the remaining data. When doing TFTP uploads, you must return exactly the amount of data requested by the callback. Otherwise, the server may treat it as the final packet and end the transfer. **-infile** : File from which the data will be transferred. **-progressproc** : Name of the Tcl procedure that TclCurl invokes at regular intervals during an operation, roughly once per second or more often, whether or not data is currently being transferred. Unknown or unused argument values passed to the callback are set to zero. For example, if you only download data, the upload size remains `0`. The procedure must have the following prototype: **proc ProgressCallback {dltotal dlnow ultotal ulnow}** For this option to work, you must set the **-noprogress** option to `0`. Setting this option to the empty string restores the original progress function. If you transfer data with the multi interface, this procedure will not be called during periods of idleness unless you call the appropriate procedure that performs transfers. You can pause and resume a transfer from within this procedure using the **pause** and **resume** commands. **-writeheader** : Pass the file name to which the header part of the received data will be written. Headers are written to this file one by one, and only complete lines are written. This makes header parsing straightforward. See also the **-headervar** option to get the headers into an array. **-debugproc** : Name of the procedure that receives the debug data produced by the **-verbose** option. The callback procedure must have two arguments: **debugProc {infoType data}** The **infoType** argument identifies the kind of debug information: `0` text, `1` incoming header, `2` outgoing header, `3` incoming data, `4` outgoing data, `5` incoming SSL data, and `6` outgoing SSL data. The **data** argument contains the corresponding data buffer. **-chunkbgnproc** : Name of the procedure that is called before a file is transferred by FTP. The callback procedure must have one argument: **ChunkBgnProc {remains}** The *remains* argument is the number of files left to be transferred or skipped. This callback makes sense only when using the **-wildcard** option. **-chunkbgnvar** : Name of the variable in the global scope that will contain the data for the file about to be transferred. If you do not use this option, `::fileData` is used. The available data is: `filename`, `filetype` (`file`, `directory`, `symlink`, `device block`, `device char`, `named pipe`, `socket`, `door`, or `error` if it could not be identified), `time`, `perm`, `uid`, `gid`, `size`, `hardlinks`, and `flags`. **-chunkendproc** : Name of the procedure that is called after a file has been transferred or skipped by FTP. The callback procedure takes no arguments: **ChunkEndProc {}** It should return `0` if everything is fine and `1` if an error occurred. **-fnmatchProc** : Name of the procedure that is called instead of the internal wildcard matching function. The callback procedure must have two arguments: **FnMatchProc {pattern string}** The *pattern* argument contains the pattern to be matched. The *string* argument contains the candidate string. The procedure must return `0` if the string matches the pattern and `1` otherwise. # ERROR OPTIONS **-errorbuffer** : Pass the name of a variable in which TclCurl may store human-readable error messages. This can provide more information than the command return code alone. **-stderr** : Pass a file name. TclCurl uses this stream instead of `stderr` when reporting errors. **-failonerror** : Set this option to 1 to make the transfer fail if the returned HTTP status code is 400 or greater. By default, TclCurl returns the page normally and does not treat such status codes as transfer errors. This behavior is not fail-safe, and in some cases non-successful response codes may still pass through, especially when authentication is involved, as with status codes 401 and 407. Some header data may be transferred before this condition is detected. For example, a `100-continue` response may be received for a POST or PUT request before a subsequent `401` or `407` response is returned. # NETWORK OPTIONS **-url** : The URL to use for the transfer. If the URL does not include a protocol part, such as `http://` or `ftp://`, TclCurl attempts to guess the protocol from the host name. If the protocol specified in the URL is not supported, TclCurl returns the **unsupported protocol** error when you call **perform**. Use **curl::versioninfo** for detailed information about the supported protocols. Starting with version 7.22.0, the fragment part of the URI is no longer sent as part of the path, unlike earlier versions. **NOTE**: This is the only option that must be set before **perform** is called. **-protocols** : Pass a lowercase list of protocols to limit which protocols TclCurl may use for the transfer. This allows a TclCurl build that supports a wide range of protocols to be restricted for specific transfers to a subset of them. Accepted protocols are `http`, `https`, `ftp`, `ftps`, `scp`, `sftp`, `telnet`, `ldap`, `ldaps`, `dict`, `file`, `tftp`, `imap`, `imaps`, `pop`, `pop3`, `smtp`, `smtps`, `gopher`, and `all`. **-redirprotocols** : Pass a lowercase list of accepted protocols to limit which protocols TclCurl may use when following a redirect with **-followlocation** enabled. This allows specific transfers to be restricted to a subset of protocols for redirections. By default, TclCurl allows all protocols except `FILE` and `SCP`. This differs from versions before 7.19.4, which would follow redirects to all supported protocols unconditionally. **-proxy** : If you need to use an HTTP proxy, set the proxy string with this option. To specify a port number in the string, append `:[port]` to the end of the host name. The proxy string may be prefixed with `[protocol]://`, although such a prefix is ignored unless noted otherwise below. When you configure an HTTP proxy, TclCurl transparently converts operations to HTTP even if you specify an FTP URL or another protocol. This may affect which library features are available. For example, **quote** and similar FTP-specific features do not work unless you tunnel through the HTTP proxy. Such tunneling is enabled with **-proxytunnel**. TclCurl respects the environment variables `http_proxy`, `ftp_proxy`, `all_proxy`, and others of the same kind, if they are set. Using this option overrides any such environment variables. Setting the proxy string to `""` explicitly disables proxy use, even if a corresponding environment variable is set. The proxy host string can be specified in the same way as the proxy environment variables, including a protocol prefix such as `http://` and embedded user name and password information. Since 7.22.0, the proxy string may include a `protocol://` prefix to specify alternative proxy protocols. Use `socks4://`, `socks4a://`, `socks5://`, or `socks5h://` to request a specific SOCKS version. The last form enables SOCKS5 and asks the proxy to perform name resolution. If no protocol is specified, and for `http://` and all other prefixes, the proxy is treated as an HTTP proxy. **-proxyport** : Use this option to set the proxy port unless it is already specified in the proxy string passed with **-proxy**. If not specified, TclCurl uses port `1080` by default. **-proxytype** : Pass the proxy type. Available values are `http`, `http1.0`, `socks4`, `socks4a`, `socks5`, and `socks5h`. The default is `http`. If you set it to *http1.0*, it will only affect how libcurl speaks to a proxy when CONNECT is used. The HTTP version used for ordinary HTTP requests is instead controlled by *httpversion*. **-noproxy** : Pass a string containing a comma-separated list of hosts that should not use a proxy, if one is specified. The only wildcard is a single `*` character, which matches all hosts and effectively disables the proxy. Each name in this list is matched either as a domain containing the host name, or as the host name itself. For example, `local.com` matches `local.com`, `local.com:80`, and `www.local.com`, but not `www.notlocal.com`. **-httpproxytunnel** : Set this option to 1 to tunnel all non-HTTP operations through the given HTTP proxy. Using a proxy and tunneling through a proxy are different behaviors. This option should be enabled only when that distinction is required. **-socks5gssapiservice** : Pass the service name. The default service name for a SOCKS5 server is `rcmd/server-fqdn`. This option allows you to change it. **-socks5gssapinec** : Pass `1` to enable this option or `0` to disable it. As part of the GSSAPI negotiation, a protection mode is negotiated. RFC 1961 specifies in sections 4.3 and 4.4 that this exchange should be protected, but the NEC reference implementation does not do so. When enabled, this option allows the protection mode negotiation to be exchanged unprotected. **-interface** : Pass the interface name to use as the outgoing network interface. The name may be an interface name, an IP address, or a host name. **-localport** : Sets the local port number of the socket used for the connection. This can be used together with **-interface**, and it is recommended to use **-localportrange** as well when this option is set. Valid port numbers are `1` through `65535`. **-localportrange** : Number of attempts TclCurl should make to find a working local port number. It starts with the port specified by **-localport** and increments it by one for each retry. Setting this value to `1` or less makes TclCurl try only one port number. Because port numbers are a limited resource and may already be in use, setting this value too low may cause unnecessary connection setup failures. **-dnscachetimeout** : Pass the timeout in seconds. Name resolution results are kept in memory for this number of seconds. Set this option to `0` to disable caching completely, or to `-1` to keep cached entries indefinitely. By default, TclCurl caches this information for `60` seconds. The name resolution functions in various libc implementations do not re-read name server information unless explicitly told to do so, for example by calling *res_init(3)*. As a result, TclCurl may continue to use older server information even after DHCP has updated it, which may appear to be a DNS cache issue. **-dnsuseglobalcache** : If this option is set to `1`, TclCurl uses a global DNS cache that survives the creation and deletion of curl handles. This is not thread-safe because it relies on a global variable. *This option was deprecated in libcurl v7.11.1 and is disabled by default in the TclCurl build. See `README.md` for instructions on how to re-enable it.* **WARNING:** This option is obsolete. Use the share interface instead. See *tclcurl_share*. **-buffersize** : Pass the preferred size for the TclCurl receive buffer. A smaller buffer may cause the write callback to be invoked more often with smaller chunks. This value is treated as a request, not as a guarantee. **-port** : Pass the remote port number to connect to instead of the port specified in the URL or the default port for the protocol in use. **-tcpnodelay** : Pass a number to specify whether the `TCP_NODELAY` option should be set or cleared (`1` = set, `0` = clear). This option is cleared by default. It has no effect after the connection has been established. Setting this option will disable TCP's Nagle algorithm. The purpose of this algorithm is to try to minimize the number of small packets on the network (where "small packets" means TCP segments less than the Maximum Segment Size (MSS) for the network). Maximizing the amount of data sent per TCP segment is good because it amortizes the overhead of the send. However, in some cases (most notably telnet or rlogin) small segments may need to be sent without delay. This is less efficient than sending larger amounts of data at a time, and can contribute to congestion on the network if overdone. **-addressscope** : Pass a number specifying the `scope_id` value to use when connecting to IPv6 link-local or site-local addresses. # NAMES AND PASSWORDS OPTIONS **-netrc** : Set this option to make TclCurl scan your **~/.netrc** file for the user name and password of the remote site you are about to access. TclCurl does not verify that the file has the correct properties set, as the standard Unix `ftp` client does. Only machine name, user name, and password are taken into account; `init` macros and similar entries are not supported. Accepted values: `optional` : Use of **~/.netrc** is optional, and information in the URL takes precedence. The file is searched using the host and user name, to find the password only, or using the host name alone, to find the first user name and password for that machine, depending on which information is not specified in the URL. Undefined values for this option have the same effect. `ignored` : TclCurl ignores the file and uses only the information in the URL. This is the default. `required` : TclCurl requires use of the file, ignores the information in the URL, and searches the file using the host name only. **-netrcfile** : Pass a string containing the full path name of the file to use as the `.netrc` file. For this option to work, you must set **-netrc** to **required**. If this option is omitted and **-netrc** is set, TclCurl attempts to find a `.netrc` file in the current user's home directory. **-userpwd** : Pass a string in the form `[username]:[password]` to use for the connection. Use **-httpauth** to select the authentication method. When using NTLM, you can specify a domain by prepending it to the user name and separating the domain and name with a forward slash (`/`) or backward slash (`\\`), for example `domain/user:password` or `domain\\user:password`. Some HTTP servers on Windows also support this form for Basic authentication. When using HTTP and **-followlocation**, TclCurl might perform several requests to possibly different hosts. TclCurl will only send this user and password information to hosts using the initial host name (unless **-unrestrictedauth** is set), so if TclCurl follows locations to other hosts it will not send the user and password to those. This is enforced to prevent accidental information leakage. **-proxyuserpwd** : Pass a string in the form `[username]:[password]` to use for the connection to the HTTP proxy. **-username** : Pass a string containing the user name to use for the transfer. It sets the user name used in protocol authentication. This option should not be used together with the older **-userpwd** option. To specify the password to use together with the user name, use the **-password** option. **-password** : Pass a string containing the password to use for the transfer. This option should be used together with **-username**. **-proxyusername** : Pass a string containing the user name to use for the transfer while connecting to the proxy. This option is used in the same way as **-proxyuserpwd**, except that it allows the user name to contain a colon, as in `sip:user@example.com`. **-proxyusername** is an alternative way to set the user name while connecting to the proxy. It should not be used together with **-proxyuserpwd**. **-proxypassword** : Pass a string containing the password to use for the transfer while connecting to the proxy. This option is intended to be used together with **-proxyusername**. **-httpauth** : Set this option to the authentication method to use. Accepted values are: `basic` : HTTP Basic authentication. This is the default choice and the only method in widespread use that is supported almost everywhere. It sends the user name and password over the network in plain text. `digest` : HTTP Digest authentication. Over public networks, this is generally more secure than Basic authentication. `digestie` : HTTP Digest authentication with an Internet Explorer-specific variant. TclCurl uses a compatibility behavior known to have been used by Internet Explorer before version 7 and still required by some servers. `gssnegotiate` : HTTP GSS-Negotiate authentication. This method, also known simply as `Negotiate`, was designed by Microsoft and is used in Microsoft web applications. It is primarily intended to support Kerberos 5 authentication, but it may also be used with other authentication methods. `ntlm` : HTTP NTLM authentication. This is a proprietary protocol developed and used by Microsoft. It uses a challenge-response mechanism and hashing, similar to Digest, to avoid sending the password in clear text. `ntlmwb` : NTLM delegated to the winbind helper. Authentication is performed by a separate binary application that is executed when needed. The name of that application is specified when libcurl is built, but it is typically `/usr/bin/ntlm_auth`. Note that libcurl will fork when necessary to run the winbind application and kill it when complete, calling waitpid() to await its exit when done. On POSIX operating systems, killing the process will cause a SIGCHLD signal to be raised (regardless of whether **-nosignal** is set). This behavior is subject to change in future versions of libcurl. `any` : TclCurl automatically selects the method it considers the most secure. `anysafe` : TclCurl may use any method except Basic and automatically selects the one it considers the most secure. **-tlsauthtype** : Selects the authentication method to use for TLS authentication. Accepted values: `tlsauthsrp` : Uses TLS-SRP authentication. Secure Remote Password authentication for TLS is defined in RFC 5054 and provides mutual authentication if both sides share a secret. To use this value, you must also set **-tlsauthusername** and **-tlsauthpassword**. libcurl must be built with GnuTLS or with OpenSSL support for TLS-SRP for this to work. **-tlsauthusername** : Pass a string containing the user name to use for the TLS authentication method specified with **-tlsauthtype**. This option requires **-tlsauthpassword** to be set as well. **-tlsauthpassword** : Pass a string containing the password to use for the TLS authentication method specified with **-tlsauthtype**. This option requires **-tlsauthusername** to be set as well. **-proxyauth** : Use this option to tell TclCurl which authentication method to use for proxy authentication. For some methods, this causes an extra network round trip. Set the actual user name and password with **-proxyuserpwd**. The methods are those listed above for the **httpauth** option. As of this writing, only Basic and NTLM work. # HTTP OPTIONS **-autoreferer** : Set this option to `1` to enable automatic updates of the `Referer:` header when TclCurl follows a `Location:` redirect. **-encoding** : Sets the contents of the `Accept-Encoding:` header sent in an HTTP request, and enables decoding of a response when a `Content-Encoding:` header is received. Accepted values: `identity` : Requests no encoding. `deflate` : Requests compression using the zlib algorithm. `gzip` : Requests gzip compression. `all` : Sends an `Accept-Encoding:` header containing all supported encodings. This is a request, not a requirement; the server may or may not honor it. This option must be set or any unsolicited encoding used by the server is ignored. See `lib/README.encoding` in the libcurl documentation for details. **-transferencoding** : Adds a request for compressed `Transfer-Encoding` in the outgoing HTTP request. If the server supports this and chooses to use it, the response may use a compressed `Transfer-Encoding`, which TclCurl then decompresses automatically when receiving the data. `Transfer-Encoding` differs from the `Content-Encoding` requested with **-encoding** in that `Transfer-Encoding` applies strictly to the transfer and therefore must be decoded before the data reaches the client. Traditionally, `Transfer-Encoding` has been used less widely and is less consistently supported by HTTP clients and servers. **-followlocation** : Set this option to `1` to make TclCurl follow any `Location:` header sent by the server as part of an HTTP response. TclCurl resends the request to the new location and continues to follow further `Location:` headers until no more are returned. Use **-maxredirs** to limit the number of redirects TclCurl follows. Since 7.19.4, TclCurl can also restrict which protocols it follows automatically. The accepted protocols are set with **-redirprotocols**. By default, the `FILE` protocol is excluded. **-unrestrictedauth** : Set this option to `1` to allow TclCurl to continue sending authentication credentials when following redirects, even if the host name changes. This option is meaningful only when **-followlocation** is enabled. **-maxredirs** : Sets the redirection limit. After that many redirects have been followed, the next redirect causes an error. This option is meaningful only when **-followlocation** is enabled. Set the limit to `0` to refuse all redirects. Set it to `-1` for an unlimited number of redirects, which is the default. -postredir : Controls how TclCurl acts on redirects after POST requests that receive a `301`, `302`, or `303` response. Accepted values are `301`, `302`, `303`, and `all`. The values `301`, `302`, and `303` make TclCurl preserve the POST request method for the corresponding redirect status code. The value `all` enables all three behaviors. The non-RFC behavior is common in web browsers, so TclCurl performs this conversion by default to maintain consistency. However, a server may require a POST to remain a POST after such a redirection. This option is meaningful only when **-followlocation** is enabled. The legacy alias **-post301** is accepted for compatibility and uses the same values. **-put** : Set this option to `1` to make TclCurl upload a file using HTTP `PUT`. The file to upload must be specified with **-infile** and **-infilesize**. This option is deprecated as of version 0.12.1. Use **-upload**. This option does not limit how much data TclCurl will actually send, as that is controlled entirely by what the read callback returns. **-post** : Set this option to `1` to make TclCurl perform a regular HTTP `POST` request using the `application/x-www-form-urlencoded` format commonly used by HTML forms. Use **-postfields** to specify the data to post and **-postfieldsize** to specify its size. Use the **-postfields** option to specify what data to post and **-postfieldsize** to set the data size. Optionally, you can also provide `POST` data using **-readproc**. You can override the default `POST` `Content-Type:` header by setting your own with **-httpheader**. Using `POST` with HTTP 1.1 implies the use of an `Expect: 100-continue` header. You can disable this header with **-httpheader** as usual. If you use `POST` with an HTTP 1.1 server, you can send data without knowing the size in advance by using chunked encoding. Enable this by adding a header such as `Transfer-Encoding: chunked` with **-httpheader**. With HTTP 1.0, or without chunked transfer encoding, you must specify the size in the request. Setting **-post** to `1` also sets **-nobody** to `0`. **NOTE:** If you have issued a `POST` request and later want to make a `HEAD` or `GET` request instead, you must explicitly select the new request type with **-nobody**, **-httpget**, or a similar option. **-postfields** : Pass a string containing the complete data to send in an HTTP `POST` request. You must ensure that the data is formatted exactly as you want the server to receive it. TclCurl does not convert or encode it for you. Most web servers assume this data is URL-encoded. This is the normal `application/x-www-form-urlencoded` form, which is the most commonly used one by HTML forms. If you want to do a zero-byte POST, you need to set **-postfieldsize** explicitly to zero, because setting **-postfields** to `NULL` or `""` effectively disables sending the specified string. TclCurl then assumes that the `POST` data is supplied through the read callback. Using `POST` with HTTP 1.1 implies the use of an `Expect: 100-continue` header. You can disable this header with **-httpheader** as usual. **NOTE:** To make `multipart/form-data` posts, see **-httppost**. **-postfieldsize** : Use this option to post data without letting TclCurl call `strlen()` to determine the data size. This is also required if you want to post fully binary data, which would otherwise likely fail. If this size is set to zero, the library uses `strlen()` to determine the data size. **-httppost** : Makes TclCurl perform an HTTP `multipart/form-data` `POST` request. The data to send is described through a Tcl list. **This is the only case where the data is reset after a transfer.** Each part consists of at least a **NAME** and a **CONTENTS** part. If the part is used for file upload, it may also contain **CONTENT-TYPE** and **FILENAME** information. The list must contain a **'name'** tag followed by the section name. The section value can then be described with **'value'**, followed by a string containing the data to post, **'file'**, followed by the name of the file to post, or **'contenttype'**, followed by the content type (`text/plain`, `image/jpg`, and so on). You can also supply an alternate file name with **'filename'**. This is useful if the server checks whether the provided file name is valid, or if you want to include the full path of the file being posted. You can also post the contents of a variable as if it were a file by using **'bufferName'** and **'buffer'**, or use **'filecontent'** followed by a file name to read that file and use its contents as data. To specify additional headers for a form section, use **'contentheader'** followed by a list of headers. See `httpPost.tcl` and `httpBufferPost.tcl` for examples. Return values: `1` : If the memory allocation fails. `2` : If one option is given twice for one form. `3` : If an empty string was given. `4` : If an unknown option was used. `5` : If some form information is incomplete or invalid. `6` : If an illegal option is used in an array. `7` : If TclCurl has no HTTP support. **-referer** : Pass a string to set the `Referer:` header in the HTTP request sent to the remote server. The `Referer:` header identifies the resource from which the target URI was obtained. Servers may use it for logging, analytics, backlink generation, caching decisions, or request-flow checks. This option is useful when a scripted client must reproduce the request context normally sent by a web browser, or when a server expects a specific referring URI. The header value should normally be a URI identifying the referring resource. Fragments and userinfo components are not part of a valid `Referer:` field value. The field name `Referer` is a historical misspelling of `referrer`, but the misspelled form is the standardized HTTP header name. Because this header may reveal navigation context or sensitive URI data, it should be set with care. It should not be relied upon as a secure means of authentication or access control. You can also set this header through **-httpheader**. **-useragent** : Pass a string to set the `User-Agent:` header in the HTTP request sent to the remote server. You can also set custom headers with **-httpheader**. **-httpheader** : Pass a list of HTTP headers to send in the request. If you add a header that TclCurl would otherwise generate internally, your header is used instead. If you add a header with no value, such as `Accept:`, the internal header is disabled. This option can therefore be used to add, replace, or remove internal headers. This option is useful when the request must include headers not exposed by dedicated TclCurl options, or when you need exact control over the final HTTP request. Common uses include setting custom authentication-related headers, API-specific headers, cache-control directives, or overriding headers such as `Content-Type:` or `Accept:`. The headers in the list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. If you include CRLF yourself, the server will likely ignore part of the headers you specified. The first line of a request, containing the method, usually `GET` or `POST`, is not a header and cannot be replaced with this option. Only the lines following the request line are headers. Adding the method line to this list causes an invalid header to be sent. **NOTE:** The most commonly replaced headers have dedicated shortcut options: **-cookie**, **-useragent**, and **-referer**. **-http200aliases** : Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers return a custom response line. For example, IceCast servers may return `ICY 200 OK`. If you include such a string in the list, it is treated as a valid HTTP status line such as `HTTP/1.0 200 OK`. **NOTE:** The alias itself is not parsed for a version string. Before version 7.16.3, TclCurl used the value set by **-httpversion**, but since 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matches. **-cookie** : Pass a string to set a cookie in the HTTP request. The string should use the format `[NAME]=[CONTENTS];`, where `NAME` is the cookie name and `CONTENTS` is the cookie value. If you need to set multiple cookies, you must set them all in a single option value by concatenating them into one string, for example `name1=content1; name2=content2;`. This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are performed because of authentication, redirects, or similar causes, they all receive this cookie header. If this option is used multiple times, only the last value is kept. **-cookiefile** : Pass the name of a file containing cookie data. The cookie data may be in Netscape cookie file format or in regular HTTP-style headers written to a file. If the file is empty or does not exist, this option still enables cookies for the handle, causing TclCurl to parse received cookies and use matching cookies in later requests. If you use this option multiple times, each use adds another file to read. **-cookiejar** : Pass a file name to which TclCurl writes all internally known cookies when **curlHandle cleanup** is called. If no cookies are known, no file is created. Specify `-` to write the cookies to standard output. Using this option also enables cookies for the session, so matching cookies are sent on later requests, including those caused by redirects. TclCurl cannot report an error if writing the cookie jar fails. If **-verbose** is enabled, a warning is displayed, but that is the only visible feedback in this case. **-cookiesession** : Set this option to `1` to mark the current run as a new cookie session. This makes TclCurl ignore session cookies loaded from a previous session. By default, TclCurl stores and loads all cookies, including session cookies. Session cookies are cookies without an expiry date and are meant to exist only for the current session. **-cookielist** : Pass a string containing a cookie. The cookie may be in Netscape/Mozilla format or in regular HTTP-style header form, such as `Set-Cookie: ...`. If the cookie engine is not enabled, it is enabled automatically. Special values are `ALL`, which erases all known cookies, and `FLUSH`, which writes all known cookies to the file specified by **-cookiejar**. **-httpget** : Set this option to `1` to force the HTTP request method back to `GET`. This is useful if `POST`, `PUT`, or a custom request has previously been used with the same handle. Setting **-httpget** to `1` also sets **-nobody** to `0`. **-httpversion** : Selects the HTTP version to use. This option should be used only when it is necessary to override the default behavior because of server-side requirements. Accepted values: `none` : Lets TclCurl use the HTTP version it considers appropriate. `1.0` : Enforce HTTP 1.0 requests. `1.1` : Enforce HTTP 1.1 requests. `2.0` : Enforce HTTP version 2 requests. `2TLS` : Enforce version 2 requests for HTTPS, version 1.1 for HTTP. `2_PRIOR_KNOWLEDGE` : Enforce HTTP 2 requests without performing an HTTP/1.1 `Upgrade` first. **-ignorecontentlength** : Ignores the `Content-Length` header. This is useful for Apache 1.x and similar servers, which may report an incorrect content length for files larger than 2 gigabytes. If this option is used, TclCurl cannot report progress accurately and stops the download only when the server closes the connection. **-httpcontentdecoding** : Set this option to `0` to disable content decoding, or to `1` to enable it. TclCurl does not enable content decoding by default; for that, you must also use **-encoding**. **-httptransferencoding** : Set this option to `0` to disable transfer decoding, or to `1` to enable it. The default is `1`. TclCurl performs chunked transfer decoding by default unless this option is disabled. # SMTP OPTIONS **-mailfrom** : Pass a string specifying the sender address to use in the SMTP envelope. This option controls the envelope sender used at the SMTP protocol level. It does not set or modify the `From:` header field in the message body. **-mailrcpt** : Pass a list of recipient addresses to use in the SMTP envelope. This option controls the envelope recipients used at the SMTP protocol level. It does not set or modify message header fields such as `To:`, `Cc:`, or `Bcc:`. In SMTP, recipients are specified with angle brackets (`<>`). If a recipient value does not begin with an angle bracket, TclCurl assumes that it is a plain email address and adds the angle brackets automatically. # TFTP OPTION **-tftpblksize** : Specifies the block size to use for TFTP data transmission. According to RFC 2348, valid values range from `8` to `65464` bytes. If this option is not specified, the default block size is `512` bytes. The requested block size is used only if the remote server supports it. If the server does not return an option acknowledgment, or if it returns an acknowledgment without a block size value, the default of `512` bytes is used. # FTP OPTIONS **-ftpport** : Pass a string identifying the address to use for the FTP `PORT` instruction. The `PORT` instruction tells the remote server to connect to the specified client address. The string may be a plain IP address, a host name, a network interface name on Unix, or simply `-` to let the library use the system's default IP address. By default, FTP transfers are passive, so `PORT` is not used. The address can be followed by `:` and a port number, optionally followed by `-` and a port range. If the port specified is `0`, the operating system chooses a free port. If a range is provided and no port in that range is available, libcurl reports `CURLE_FTP_PORT_FAILED` for the handle. Invalid port or port-range settings are ignored. IPv6 addresses followed by a port or port range must be enclosed in brackets. IPv6 addresses without a port or port range may also be enclosed in brackets. Examples: `eth0:0` `192.168.1.2:32000-33000` `curl.se:32123` `[::1]:1234-4567` To disable `PORT` and return to passive mode, set this option to the empty string. **-quote** : Pass a list of FTP or SFTP commands to send to the server before the FTP transfer request. These commands are sent before any other FTP commands, including `CWD`. If you do not want to transfer any files, set **-nobody** to `1` and **-header** to `0`. Prefix a command with an asterisk (`*`) to make TclCurl continue even if that command fails. By default, a failure stops the transfer. To disable this option, set it to the empty string. The commands must be raw FTP commands. For example, to create a directory you must send `mkd Test`, not `mkdir Test`. Valid SFTP commands are `chgrp`, `chmod`, `chown`, `ln`, `mkdir`, `pwd`, `rename`, `rm`, `rmdir`, and `symlink`. **-postquote** : Pass a list of FTP commands to send to the server after the FTP transfer request. If you do not want to transfer any files, set **-nobody** to `1` and **-header** to `0`. **-prequote** : Pass a list of FTP or SFTP commands to send to the server after the transfer type has been set. **-dirlistonly** : Set this option to `1` to list only file names in a directory instead of requesting a full directory listing with file sizes, dates, and similar information. This option works with both FTP and SFTP URLs. For FTP, this causes an `NLST` command to be sent. Some FTP servers return only files in response to `NLST`, and may omit subdirectories and symbolic links. Setting this option to `1` also implies a directory listing even if the URL does not end with a slash, which would otherwise be required. Do not use this option together with **-wildcardmatch**, as it effectively disables that feature. **-append** : Set this option to `1` to append to the remote file instead of overwriting it. This is useful only when uploading to an FTP site. **-ftpuseeprt** : Set this option to `1` to make TclCurl use the `EPRT` and `LPRT` commands for active FTP transfers, which are enabled with **-ftpport**. When this option is enabled, TclCurl first attempts `EPRT`, then `LPRT`, and only then falls back to `PORT`. If this option is set to `0`, only `PORT` is used. **-ftpuseepsv** : Set this option to `1` to make TclCurl use the `EPSV` command for passive FTP transfers. This is the default behavior. When enabled, TclCurl first attempts `EPSV` before using `PASV`. If this option is set to `0`, TclCurl uses only `PASV`. **-ftpusepret** : Set this option to `1` to make TclCurl send a `PRET` command before `PASV` or `EPSV`. Some FTP servers, especially `drftpd`, require this non-standard command for directory listings and uploads or downloads in passive mode. This option has no effect for active FTP transfers. **-ftpcreatemissingdirs** : Controls whether TclCurl should attempt to create a remote directory when the transfer requires that directory to exist, but a `CWD` command shows that it does not yet exist or cannot yet be entered. This setting also applies to SFTP connections. TclCurl attempts to create the remote directory if it cannot obtain a handle to the target location. Creation fails if a file with the same name already exists, or if permissions do not allow directory creation. Accepted values: `1` : After a failed `CWD`, TclCurl attempts to create the missing remote directory and then continues with the transfer. `2` : After a failed `CWD`, TclCurl attempts to create the missing remote directory. If the subsequent `MKD` command fails, TclCurl retries the `CWD` command before giving up. This is useful when multiple simultaneous connections target the same server and another connection may have created the directory in the meantime. **-ftpresponsetimeout** : Sets a timeout, in seconds, for how long the server may take to return a response to an FTP command before the session is considered hung. While TclCurl is waiting for such a response, this value overrides **-timeout**. If both options are used, **-ftpresponsetimeout** should normally be set to a value smaller than **-timeout**. **-ftpalternativetouser** : Pass a string to use for authentication if the usual FTP `USER user` and `PASS password` negotiation fails. This is known to be required in some cases when connecting to Tumbleweed Secure Transport FTPS servers that use client-certificate authentication. **-ftpskippasvip** : Set this option to `1` to make TclCurl ignore the IP address suggested by the server in its `227` response to TclCurl's `PASV` command when opening the data connection. TclCurl instead reuses the same IP address already in use for the control connection, while still using the port number from the `227` response. This option has no effect if `PORT`, `EPRT`, or `EPSV` is used instead of `PASV`. **-ftpsslauth** : Selects how TclCurl issues `AUTH TLS` or `AUTH SSL` when FTP over SSL is enabled with **-ftpssl**. This option may be needed for servers such as BSDFTPD-SSL, which do not handle `AUTH SSL` correctly and require `AUTH TLS` instead. Accepted values: `default` : Lets TclCurl choose. `ssl` : Tries `AUTH SSL` first, and tries `AUTH TLS` only if that fails. `tls` : Tries `AUTH TLS` first, and tries `AUTH SSL` only if that fails. **-ftpsslccc** : Controls use of CCC (Clear Command Channel). CCC shuts down the SSL/TLS layer after authentication, so the remainder of the control channel is unencrypted. This can allow NAT routers to inspect the FTP control channel. Accepted values are: `none` : Do not attempt to use CCC. `passive` : Do not initiate the shutdown. Wait for the server to do so, and do not send a reply. `active` : Initiate the shutdown and wait for a reply. **-ftpaccount** : Pass a string containing account data, or `""` to disable it. If an FTP server requests account data after the user name and password have been provided, TclCurl sends this value with the `ACCT` command. **-ftpfilemethod** : Selects how TclCurl navigates FTP paths. Accepted values are: `multicwd` : The default. TclCurl performs one `CWD` operation for each path component in the URL. For deep hierarchies this may require many commands. This is the method described by RFC 1738. `nocwd` : TclCurl does not perform `CWD` at all. Instead it sends commands such as `SIZE`, `RETR`, and `STOR` with the full path. `singlecwd` : TclCurl performs one `CWD` to the full target directory and then operates on the file normally. This is somewhat more standards compliant than `nocwd`, without the full overhead of `multicwd`. # PROTOCOL OPTIONS **-transfertext** : Set this option to `1` to use ASCII mode for FTP transfers instead of the default binary transfer mode. On Win32 systems, this does not set `stdout` to binary mode. This option can be useful when transferring text data between systems that treat characters such as newlines differently. **NOTE:** TclCurl does not perform full ASCII conversion during ASCII FTP transfers. It simply sets the transfer mode to ASCII and performs a normal transfer. **-proxytransfermode** : Set this option to `1` to make TclCurl set the transfer mode, binary or ASCII, for FTP transfers performed through an HTTP proxy by appending `;type=a` or `;type=i` to the URL. If this option is omitted or set to `0`, **-transfertext** has no effect for FTP transfers performed through an HTTP proxy. Not all proxies support this feature. **-crlf** : Set this option to `1` to make TclCurl convert Unix newlines to CRLF newlines during transfers. Set it to `0` to disable this behavior. **-range** : Pass a string specifying the requested range. The format is `X-Y`, where either `X` or `Y` may be omitted. HTTP transfers also support multiple ranges separated by commas, as in `X-Y,N-M`. When multiple ranges are requested over HTTP, the server returns the response document in pieces using standard MIME separation rules. Range requests are supported only for HTTP, FTP, and FILE transfers. **-resumefrom** : Pass the offset, in bytes, at which the transfer should start. Set this option to `0` to start the transfer from the beginning, which disables resume behavior. For FTP, set this option to `-1` to start from the end of the target file, which is useful when continuing an interrupted upload. For FTP uploads, the resume position specifies where in the local source file TclCurl should resume reading. The data read from that point is then appended to the remote target file. **-customrequest** : Pass a string containing the request method to use instead of the default method, such as `GET` or `HEAD`, when making an HTTP request. This is useful for methods such as `DELETE` and other less common HTTP requests. Use this option only when the server is known to support the specified method. TclCurl still behaves internally according to the type of request it would otherwise have used. As a result, changing the request method with this option can produce inconsistent behavior if the corresponding request type is not selected through the usual dedicated option. For example, to make a proper `HEAD` request, use **-nobody**. To make a proper `POST` request, use **-post** or **-postfields**. **-filetime** : Set this option to `1` to make TclCurl attempt to obtain the modification time of the remote document during the transfer. This requires the remote server either to send the time directly or to support a command for querying it. After the transfer, the `filetime` value can be retrieved with the `getinfo` procedure. For FTP transfers, this typically means that the server must support a command for querying the remote file modification time, such as `MDTM`. If the server does not provide this information, the transfer can still succeed, but the retrieved `filetime` value remains unknown. **-nobody** : Set this option to `1` to omit the body from the output. This is relevant only for protocols that distinguish between a header part and a body part. For HTTP and HTTPS, this causes TclCurl to issue a `HEAD` request. To change the request back to `GET`, use **-httpget**. To switch to `POST`, use **-post** or a related option. **-infilesize** : Use this option when uploading a file to specify the expected size of the input file. This option is mandatory for uploads performed with SCP. **-upload** : Set this option to `1` to prepare for an upload. The **-infile** and **-infilesize** options are also relevant for uploads. If the protocol is HTTP, uploading means using the PUT request unless you tell TclCurl otherwise. Using PUT with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with **-httpheader** as usual. If you use PUT to a HTTP 1.1 server, you can upload data without knowing the size before starting the transfer if you use chunked encoding. You enable this by adding a header like "Transfer-Encoding: chunked" with **-httpheader**. With HTTP 1.0 or without chunked transfer, you must specify the size. -maxfilesize : This allows you to specify the maximum size (in bytes) of a file to download. If the file requested is larger than this value, the transfer will not start and error 'filesize exceeded' (63) will be returned. NOTE: The file size is not always known prior to download, and for such files this option has no effect even if the file transfer ends up being larger than this given limit. This concerns both FTP and HTTP transfers. -timecondition : Defines how the **timevalue** value is treated. Accepted values are `ifmodsince` and `ifunmodsince`. This feature applies to HTTP, FTP, and FILE. -timevalue : This should be the time in seconds since 1 jan 1970, and the time will be used in a condition as specified with **timecondition**. # CONNECTION OPTIONS **-timeout** : Pass the maximum time, in seconds, that a TclCurl transfer operation may take. Name resolution alone may take a noticeable amount of time, so setting this value too low can abort otherwise normal operations. This option may cause libcurl to use `SIGALRM` to interrupt blocking system calls. On Unix-like systems, signals may therefore be used unless **-nosignal** is enabled. **-timeoutms** : Like **-timeout**, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity. **-lowspeedlimit** : Pass the speed, in bytes per second, below which the transfer rate must remain during **-lowspeedtime** seconds before TclCurl considers the transfer too slow and aborts it. **-lowspeedtime** : Pass the number of seconds during which the transfer speed must stay below **-lowspeedlimit** before TclCurl considers the transfer too slow and aborts it. **-maxsendspeed** : Pass a speed in bytes per second. If an upload exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed. **-maxrecvspeed** : Pass a speed in bytes per second. If a download exceeds this average speed during the transfer, TclCurl pauses the transfer as needed to keep the average rate less than or equal to the specified value. The default is unlimited speed. **-maxconnects** : Sets the size of the persistent connection cache for protocols that support persistent connections. This value is the maximum number of simultaneous connections TclCurl may cache in the easy handle. The default is `5`. When the maximum is reached, TclCurl closes the oldest cached connection to prevent the number of open connections from increasing further. **NOTE:** If transfers have already been performed with this easy handle, reducing **-maxconnects** may cause existing open connections to be closed earlier than expected. If this easy handle is added to a multi handle, this setting is ignored. In that case, configure the corresponding **maxconnects** option on the multi handle instead. **-connecttimeout** : Pass the maximum time, in seconds, that the connection phase may take. This limits only the time required to establish the connection. Once the connection has been established, this option no longer applies. Set it to `0` to disable the connection timeout. On Unix-like systems, signals may be used unless **-nosignal** is enabled. **-connecttimeoutms** : Like **-connecttimeout**, but takes a value in milliseconds. If libcurl is built to use the standard system name resolver, name resolution still uses full-second timeout granularity. **-ipresolve** : Selects which IP address families may be used when resolving host names. This option is relevant only when a host name resolves to more than one IP version. Accepted values are: `whatever` : The default. Resolves addresses using all IP versions supported by the system. `v4` : Resolves only IPv4 addresses. `v6` : Resolves only IPv6 addresses. **-resolve** : Pass a list of host name resolution entries to use for requests made with this handle. Each entry must use the format `HOST:PORT:ADDRESS`, where `HOST` is the name TclCurl tries to resolve, `PORT` is the destination service port, and `ADDRESS` is the numeric IP address to use. If libcurl supports IPv6, `ADDRESS` may be either an IPv4 or an IPv6 address. This option effectively pre-populates the DNS cache with entries for a given `HOST:PORT` pair, so redirects and other requests to the same `HOST:PORT` use the supplied `ADDRESS`. To remove an entry from the DNS cache, include a string in the form `-HOST:PORT`. The host name must be prefixed with a dash, and both the host name and port must exactly match an entry added earlier. **-usessl** : Selects the desired level of SSL or TLS use for the transfer. This option is relevant for protocols such as FTP, SMTP, POP3, and IMAP. You can also use `ftps://` URLs to enable SSL/TLS explicitly for both the control connection and the data connection. Accepted values: `nope` : Do not attempt to use SSL. `try` : Attempt to use SSL, but continue even if it cannot be negotiated. `control` : Use SSL for the control connection, or fail with `use ssl failed` (`64`). `all` : Use SSL for all communication, or fail with `use ssl failed` (`64`). # SSL AND SECURITY OPTIONS **-sslcert** : Pass a string containing the file name of the certificate to use. The default format is `PEM`, and it can be changed with **-sslcerttype**. When libcurl is built against NSS, this value is the nickname of the certificate to use for authentication. To use a file in the current directory in that case, prefix it with `./` to avoid confusion with a nickname. **-sslcerttype** : Pass a string specifying the format of the certificate given with **-sslcert**. Accepted values are: `PEM` : PEM format. `DER` : DER format. **-sslkey** : Pass a string containing the file name of the private key to use. The default format is `PEM`, and it can be changed with **-sslkeytype**. **-sslkeytype** : Pass a string specifying the format of the private key given with **-sslkey**. Accepted values are: `PEM` : PEM format. `DER` : DER format. `ENG` : Uses a crypto engine. In this case **-sslkey** is interpreted as an identifier passed to the engine, and **-sslengine** must also be set. **NOTE:** The `DER` private-key format may not work with some OpenSSL versions because of upstream limitations. **-keypasswd** : Pass a string containing the passphrase required to use the private key specified with **-sslkey** or **-sshprivatekeyfile**. A passphrase is not needed to load a certificate itself, but it may be needed to load the corresponding private key. This option was formerly known as **-sslkeypasswd** and **-sslcertpasswd**. **-sslengine** : Pass a string containing the identifier of the crypto engine to use for private-key operations. **NOTE:** If the crypto engine cannot be loaded, TclCurl returns an error. **-sslenginedefault** : Set this option to `1` to make the selected crypto engine the default for asymmetric cryptographic operations. **NOTE:** If the crypto engine cannot be made the default, TclCurl returns an error. **-sslversion** : Selects the SSL or TLS protocol version to use. Accepted values are: `default` : Uses the default behavior. TclCurl attempts to negotiate an appropriate protocol version with the remote server. `tlsv1` : Requires TLSv1 or later. `sslv2` : Requires SSLv2. `sslv3` : Requires SSLv3. `tlsv1_0` : Requires TLSv1.0 or later. `tlsv1_1` : Requires TLSv1.1 or later. `tlsv1_2` : Requires TLSv1.2 or later. `tlsv1_3` : Requires TLSv1.3 or later. `maxdefault` : Uses the maximum TLS version supported by libcurl or by the SSL backend's default configuration. `maxtlsv1_0` : Sets the maximum supported TLS version to TLSv1.0. `maxtlsv1_1` : Sets the maximum supported TLS version to TLSv1.1. `maxtlsv1_2` : Sets the maximum supported TLS version to TLSv1.2. `maxtlsv1_3` : Sets the maximum supported TLS version to TLSv1.3. **-sslverifypeer** : Controls whether TclCurl verifies the authenticity of the peer certificate. Set this option to `1` to enable verification or to `0` to disable it. The default is `1`. During the SSL or TLS handshake, the server sends a certificate declaring its identity. TclCurl verifies that certificate against a chain of trust rooted in one or more certification authority (CA) certificates. TclCurl uses the default CA bundle provided by libcurl, but you can specify alternate certificates with **-cainfo** or **-capath**. If **-sslverifypeer** is nonzero and verification fails, the connection fails. If this option is `0`, peer-certificate verification is skipped. Certificate verification alone does not confirm that the peer is the specific host you intended to contact. Use **-sslverifyhost** to control host-name verification. **-cainfo** : Pass the name of a file containing one or more CA certificates used to verify the peer certificate. This option is meaningful primarily together with **-sslverifypeer**. If peer verification is disabled, **-cainfo** does not need to name an accessible file. By default, this option is set to the system path of libcurl's CA bundle, as determined when libcurl was built. When libcurl is built against NSS, this value refers to the directory containing the NSS certificate database. **-issuercert** : Pass the name of a file containing a CA certificate in PEM format. If this option is set, an additional check is performed to verify that the peer certificate was issued by the CA certificate provided here. This is useful in multi-level PKI environments where the peer certificate must be constrained to a specific branch of the certificate hierarchy. This option is meaningful only when used together with **-sslverifypeer**. Otherwise, failure of this additional check is not treated as a connection failure. **-capath** : Pass the name of a directory containing multiple CA certificates to use when verifying the peer certificate. When libcurl is built against OpenSSL, this directory must be prepared with the `openssl c_rehash` utility. This option is meaningful primarily together with **-sslverifypeer**. If peer verification is disabled, **-capath** does not need to name an accessible directory. This option is OpenSSL-specific and has no effect when libcurl is built against GnuTLS. NSS-based libcurl provides it only for backward compatibility. On Windows, this option may not work because of OpenSSL limitations. **-crlfile** : Pass the name of a file containing one or more certificate revocation lists in PEM format to use during certificate validation. When libcurl is built against NSS or GnuTLS, there is no supported way to influence revocation checking with this option. When libcurl is built with OpenSSL support, both `X509_V_FLAG_CRL_CHECK` and `X509_V_FLAG_CRL_CHECK_ALL` are enabled if a CRL file is provided, so CRL checking is applied throughout the certificate chain. This option is meaningful only when used together with **-sslverifypeer**. If the CRL file cannot be loaded, the SSL exchange fails with the specific error code `CURLE_SSL_CRL_BADFILE`. A certificate-verification failure caused by revocation information in the CRL does not produce that specific error code. **-sslverifyhost** : Controls whether TclCurl verifies that the server certificate matches the host name you intended to contact. During the SSL or TLS handshake, the server sends a certificate declaring its identity. When **-sslverifyhost** is set to `2`, the certificate must identify the intended server or the connection fails. TclCurl considers the server to match when the Common Name field or a Subject Alternative Name field in the certificate matches the host name in the URL. When this option is set to `1`, the certificate must contain a Common Name field, but the specific name is not checked. This setting is generally not useful. When this option is set to `0`, the connection succeeds regardless of the names contained in the certificate. The default value is `2`. This option verifies the host identity claimed by the certificate. To verify that the certificate itself is trusted, use **-sslverifypeer**. If libcurl is built against NSS and **-sslverifypeer** is `0`, **-sslverifyhost** is ignored. **-certinfo** : Set this option to `1` to enable collection of certificate-chain information. When enabled, TclCurl, if built against OpenSSL, extracts certificate details from the chain used in the SSL connection. That information can be retrieved after the transfer with the **getinfo** command and its `certinfo` option. **-randomfile** : Pass a file name. TclCurl uses this file as a source of randomness for the SSL random engine. *This option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See `README.md` for instructions on how to re-enable it.* **-egdsocket** : Pass the path name of an Entropy Gathering Daemon socket. TclCurl uses it as a source of randomness for the SSL random engine. *This option was deprecated in libcurl v7.84 and is disabled by default in the TclCurl build. See `README.md` for instructions on how to re-enable it.* **-sslcipherlist** : Pass a string containing the cipher list to use for the SSL or TLS connection. The list consists of one or more cipher strings separated normally by colons, although commas or spaces are also accepted. The characters `!`, `-`, and `+` may also be used as operators. With OpenSSL and GnuTLS, valid examples include `RC4-SHA`, `SHA1+DES`, `TLSv1`, and `DEFAULT`. The default list is usually defined by the SSL backend at build time. With NSS, valid examples include `rsa_rc4_128_md5` and `rsa_aes_128_sha`. NSS does not support incremental add or remove semantics for ciphers. If this option is used, all known ciphers are disabled and only the ciphers listed here are enabled. For details about cipher-list syntax, see: For NSS-specific cipher-list details, see: **-sslsessionidcache** : Set this option to `0` to disable TclCurl's use of SSL session-ID caching, or to `1` to enable it. The default is `1`. In normal circumstances, reusing SSL session IDs is harmless and may improve performance. However, some broken SSL implementations may require this option to be disabled. **-krblevel** : Selects the Kerberos security level for FTP and thereby also enables Kerberos awareness. Accepted values are `clear`, `safe`, `confidential`, and `private`. If the string does not match one of these values, `private` is used. Set the string to `NULL` to disable Kerberos 4. Set it to `""` to disable Kerberos support for FTP. **-gssapidelegation** : Selects the GSSAPI credential delegation mode. Accepted values are: `flag` : Allows unconditional delegation. `policyflag` : Delegates only if the `OK-AS-DELEGATE` flag is set in the service ticket, provided that this feature is supported by the GSSAPI implementation and that `GSS_C_DELEG_POLICY_FLAG` was available at compile time. Delegation is disabled by default since 7.21.7. # SSH OPTIONS **-sshauthtypes** : Selects the allowed SSH authentication types. Accepted values are: `publickey` : Use public-key authentication. `password` : Use password authentication. `host` : Use host-based authentication. `keyboard` : Use keyboard-interactive authentication. `any` : Let TclCurl select an authentication method automatically. **-sshhostpublickeymd5** : Pass a string containing 32 hexadecimal digits. The string must be the 128-bit MD5 checksum of the remote host public key. TclCurl rejects the connection unless the checksum matches. This option applies only to SCP and SFTP transfers. **-sshpublickeyfile** : Pass the file name of the public key to use. If this option is not used, TclCurl defaults to `$HOME/.ssh/id_dsa.pub` when the `HOME` environment variable is set, and to `id_dsa.pub` in the current directory otherwise. **-sshprivatekeyfile** : Pass the file name of the private key to use. If this option is not used, TclCurl defaults to `$HOME/.ssh/id_dsa` when the `HOME` environment variable is set, and to `id_dsa` in the current directory otherwise. If the private key is passphrase-protected, use **-keypasswd** to specify the passphrase. **-sshknownhosts** : Pass a string containing the file name of the `known_hosts` file to use. The file must use the OpenSSH `known_hosts` format supported by libssh2. If this option is set, TclCurl accepts connections only to hosts that are present in that file with a matching public key. Use **-sshkeyproc** to override the default behavior for host and key matching. **-sshkeyproc** : Pass the name of a callback procedure that TclCurl invokes after `known_hosts` matching has been performed, so that the application can decide how the connection should proceed. The callback is invoked only if **-sshknownhosts** is also set. The callback receives a list with three elements: 1. A list containing the key type from the `known_hosts` file and the key itself. 2. A list containing the key type presented by the remote host and the key itself. 3. A value describing TclCurl's matching result. Possible key-type values are `rsa`, `rsa1`, `dss`, and `unknown`. Possible match-result values are `match`, `mismatch`, `missing`, and `error`. Return values: `0` : Accept the host and key. TclCurl appends the host and key to the `known_hosts` file before continuing with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. Updating the file is done by replacing it with a new copy, so the file permissions must allow that. `1` : Accept the host and key, and continue with the connection. If the host and key are not already present in the in-memory known-hosts pool, TclCurl also adds them there. `2` : Reject the host and key. TclCurl closes the connection. `3` : Reject the host and key, but keep the SSH connection alive. This can be useful if the application needs to inspect the host or key state and then retry without incurring the full setup cost again. Any other return value causes TclCurl to close the connection. # OTHER OPTIONS **-headervar** : Name of the Tcl array variable in which TclCurl stores the headers returned by the server. **-bodyvar** : Name of the Tcl variable in which TclCurl stores the requested file contents. The stored data may be either text or binary data. **-canceltransvarname** : Name of a Tcl variable used together with **-progressproc**. If the progress callback sets this variable to `1`, the transfer is canceled. **-command** : Executes the given command after the transfer has completed. This option works only with blocking transfers and therefore has limited practical use. **-share** : Pass a share handle. The share handle must have been created previously by calling **curl::shareinit**. Setting this option causes the easy handle to use data from the shared handle instead of keeping its own separate copy. See *tclcurl_share* for details. **-newfileperms** : Pass a numeric value specifying the permissions assigned to newly created files on the remote server. The default value is `0644`, but any valid value may be used. This option applies only to `sftp://`, `scp://`, and `file://` transfers. **-newdirectoryperms** : Pass a numeric value specifying the permissions assigned to newly created directories on the remote server. The default value is `0755`, but any valid value may be used. This option applies only to `sftp://`, `scp://`, and `file://` transfers. # TELNET OPTIONS -telnetoptions : Pass a list with variables to pass to the telnet negotiations. The variables should be in the format . TclCurl supports the options 'TTYPE', 'XDISPLOC' and 'NEW_ENV'. See the TELNET standard for details. # NOT SUPPORTED Some of the options libcurl offers are not supported, I don't think them worth supporting in TclCurl but if you need one of them don't forget to complain: **CURLOPT_FRESH_CONNECT, CURLOPT_FORBID_REUSE, CURLOPT_PRIVATE,** **CURLOPT_SSL_CTX_FUNCTION, CURLOPT_SSL_CTX_DATA, CURLOPT_SSL_CTX_FUNCTION and** **CURLOPT_CONNECT_ONLY, CURLOPT_OPENSOCKETFUNCTION, CURLOPT_OPENSOCKETDATA.** # curlHandle perform This procedure is called after the **init** and all the **configure** calls are made, and will perform the transfer as described in the options. It must be called with the same *curlHandle* **curl::init** call returned. You can do any amount of calls to perform while using the same handle. If you intend to transfer more than one file, you are even encouraged to do so. TclCurl will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources. Just note that you will have to use configure between the invokes to set options for the following perform. You must never call this procedure simultaneously from two places using the same handle. Let it return first before invoking it another time. If you want parallel transfers, you must use several curl handles. RETURN VALUE : `0` if all went well, non-zero if it didn't. In case of error, if the errorbuffer was set with configure there will be a readable error message. The error codes are: **1** : Unsupported protocol. This build of TclCurl has no support for this protocol. **2** : Very early initialization code failed. This is likely to be and internal error or a resource problem where something fundamental couldn't get done at init time. **3** : URL malformat. The syntax was not correct. **4** : A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision. This means that a feature or option was not enabled or explicitly disabled when libcurl was built and in order to get it to function you have to get a rebuilt libcurl. **5** : Couldn't resolve proxy. The given proxy host could not be resolved. **6** : Couldn't resolve host. The given remote host was not resolved. **7** : Failed to connect to host or proxy. **8** : FTP weird server reply. The server sent data TclCurl couldn't parse. The given remote server is probably not an OK FTP server. **9** : We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory. **11** : FTP weird PASS reply. TclCurl couldn't parse the reply sent to the PASS request. **13** : FTP weird PASV reply, TclCurl couldn't parse the reply sent to the PASV or EPSV request. **14** : FTP weird 227 format. TclCurl couldn't parse the 227-line the server sent. **15** : FTP can't get host. Couldn't resolve the host IP we got in the 227-line. **17** : FTP couldn't set type. Couldn't change transfer method to either binary or ascii. **18** : Partial file. Only a part of the file was transferred, this happens when the server first reports an expected transfer size and then delivers data that doesn't match the given size. **19** : FTP couldn't RETR file, we either got a weird reply to a 'RETR' command or a zero byte transfer. **21** : Quote error. A custom 'QUOTE' returned error code 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command. **22** : HTTP returned error. This return code only appears if **-failonerror** is used and the HTTP server returns an error code that is 400 or higher. **23** : Write error. TclCurl couldn't write data to a local filesystem or an error was returned from a write callback. **25** : Failed upload failed. For FTP, the server typcially denied the STOR command. The error buffer usually contains the server's explanation to this. **26** : Read error. There was a problem reading from a local file or an error was returned from the read callback. **27** : Out of memory. A memory allocation request failed. This should never happen unless something weird is going on in your computer. **28** : Operation timeout. The specified time-out period was reached according to the conditions. **30** : The FTP PORT command failed, not all FTP servers support the PORT command, try doing a transfer using PASV instead!. **31** : FTP couldn't use REST. This command is used for resumed FTP transfers. **33** : Range error. The server doesn't support or accept range requests. **34** : HTTP post error. Internal post-request generation error. **35** : SSL connect error. The SSL handshaking failed, the error buffer may have a clue to the reason, could be certificates, passwords, ... **36** : The download could not be resumed because the specified offset was out of the file boundary. **37** : A file given with FILE:// couldn't be read. Did you checked the permissions? **38** : LDAP cannot bind. LDAP bind operation failed. **39** : LDAP search failed. **41** : A required zlib function was not found. **42** : Aborted by callback. An application told TclCurl to abort the operation. **43** : Internal error. A function was called with a bad parameter. **45** : Interface error. A specified outgoing interface could not be used. **47** : Too many redirects. When following redirects, TclCurl hit the maximum amount, set your limit with --maxredirs **48** : An option passed to TclCurl is not recognized/known. Refer to the appropriate documentation. This is most likely a problem in the program that uses TclCurl. The error buffer might contain more specific information about which exact option it concerns. **49** : A telnet option string was illegally formatted. **51** : The remote peer's SSL certificate or SSH md5 fingerprint wasn't ok **52** : The server didn't reply anything, which here is considered an error. **53** : The specified crypto engine wasn't found. **54** : Failed setting the selected SSL crypto engine as default! **55** : Failed sending network data. **56** : Failure with receiving network data. **58** : Problem with the local client certificate. **59** : Couldn't use specified SSL cipher. **60** : Peer certificate cannot be authenticated with known CA certificates. **61** : Unrecognized transfer encoding. **62** : Invalid LDAP URL. **63** : Maximum file size exceeded. **64** : SSL use failed. **65** : Sending the data requires a rewind that failed, since TclCurl should take care of it for you, it means you found a bug. **66** : Failed to initialise ssl engine. **67** : Failed to login, user password or similar was not accepted. **68** : File not found on TFTP server. **69** : There is a permission problem with the TFTP request. **70** : The remote server has run out of space. **71** : Illegal TFTP operation. **72** : Unknown transfer ID. **73** : TFTP file already exists and will not be overwritten. **74** : No such user in the TFTP server and good behaving TFTP servers should never return this. **75** : Character conversion failed. **77** : Problem with reading the SSL CA cert (path? access rights?). **78** : Remote file not found **79** : Error from the SSH layer **80** : Failed to shut down the SSL connection **82** : Failed to load CRL file **83** : Issuer check failed **84** : The FTP server does not understand the PRET command at all or does not support the given argument. Be careful when using **-customrequest**, a custom LIST command will be sent with PRET CMD before PASV as well. **85** : Mismatch of RTSP CSeq numbers. **86** : Mismatch of RTSP Session Identifiers. **87** : Unable to parse FTP file list (during FTP wildcard downloading). **88** : Chunk callback reported error. # curlHandle getinfo OPTION Request internal information from the curl session with this procedure. This procedure is intended to get used *AFTER* a performed transfer, and can be relied upon only if the **perform** returns 0. Use this function AFTER a performed transfer if you want to get transfer-oriented data. The following information can be extracted: effectiveurl : Returns the last used effective URL. responsecode : Returns the last received HTTP or FTP code. This will be zero if no server response code has been received. Note that a proxy's CONNECT response should be read with **httpconnectcode** and not this. httpconnectcode : Returns the last received proxy response code to a CONNECT request. filetime : Returns the remote time of the retrieved document (in number of seconds since 1 jan 1970 in the GMT/UTC time zone). If you get -1, it can be because of many reasons (unknown, the server hides it or the server doesn't support the command that tells document time etc) and the time of the document is unknown. In order for this to work you have to set the **-filetime** option before the transfer. namelookuptime : Returns the time, in seconds, it took from the start until the name resolving was completed. connecttime : Returns the time, in seconds, it took from the start until the connect to the remote host (or proxy) was completed. appconnecttime : Returns the time, in seconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed. This time is most often very near to the PRETRANSFER time, except for cases such as HTTP pippelining where the pretransfer time can be delayed due to waits in line for the pipeline and more. pretransfertime : Returns the time, in seconds, it took from the start until the file transfer is just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved. starttransfertime : Returns the time, in seconds, it took from the start until the first byte is just about to be transferred. This includes the **pretransfertime**, and also the time the server needs to calculate the result. totaltime : Returns the total transaction time, in seconds, for the previous transfer, including name resolving, TCP connect etc. redirecturl : Returns the URL a redirect would take you to if you enable **followlocation**. This can come very handy if you think using the built-in libcurl redirect logic isn't good enough for you but you would still prefer to avoid implementing all the magic of figuring out the new URL. redirecttime : Returns the total time, in seconds, it took for all redirection steps including name lookup, connect, pretransfer and transfer before the final transaction was started, it returns the complete execution time for multiple redirections, so it returns zero if no redirections were needed. redirectcount : Returns the total number of redirections that were actually followed. numconnects : Returns how many new connections TclCurl had to create to achieve the previous transfer (only the successful connects are counted). Combined with **redirectcount** you are able to know how many times TclCurl successfully reused existing connection(s) or not. See the Connection Options of **setopt** to see how TclCurl tries to make persistent connections to save time. primaryip : Returns the IP address of the most recent connection done with this handle. This string may be IPv6 if that's enabled. primaryport : Returns the destination port of the most recent connection done with this handle. localip : Returns the local (source) IP address of the most recent connection done with this handle. This string may be IPv6 if that's enabled. localport : Returns the local (source) port of the most recent connection done with this handle. sizeupload : Returns the total amount of bytes that were uploaded. sizedownload : Returns the total amount of bytes that were downloaded. The amount is only for the latest transfer and will be reset again for each new transfer. speeddownload : Returns the average download speed, measured in bytes/second, for the complete download. speedupload : Returns the average upload speed, measured in bytes/second, for the complete upload. headersize : Returns the total size in bytes of all the headers received. requestsize : Returns the total size of the issued requests. This is so far only for HTTP requests. Note that this may be more than one request if followLocation is true. sslverifyresult : Returns the result of the certification verification that was requested (using the -sslverifypeer option to configure). sslengines : Returns a **list** of the OpenSSL crypto-engines supported. Note that engines are normally implemented in separate dynamic libraries. Hence not all the returned engines may be available at run-time. contentlengthdownload : Returns the content-length of the download. This is the value read from the **Content-Length:** field. If the size isn't known, it returns -1. contentlengthupload : Returns the specified size of the upload. contenttype : Returns the content-type of the downloaded object. This is the value read from the Content-Type: field. If you get an empty string, it means the server didn't send a valid Content-Type header or that the protocol used doesn't support this. httpauthavail : Returns a list with the authentication method(s) available. proxyauthavail : Returns a list with the authentication method(s) available for your proxy athentication. oserrno : Returns the errno value from a connect failure. This value is only set on failure, it is no reset after a successful operation. cookielist : Returns a list of all cookies TclCurl knows (expired ones, too). If there are no cookies (cookies for the handle have not been enabled or simply none have been received) the list will be empty. ftpentrypath : Returns a string holding the path of the entry path. That is the initial path TclCurl ended up in when logging on to the remote FTP server. Returns an empty string if something is wrong. certinfo : Returns list with information about the certificate chain, assuming you had the **-certinfo** option enabled when the previous request was done. The list first item reports how many certs it found and then you can extract info for each of those certs by following the list. The info chain is provided in a series of data in the format "name:content" where the content is for the specific named data. NOTE: this option is only available in libcurl built with OpenSSL support. conditionunmet : Returns the number 1 if the condition provided in the previous request didn't match (see *timecondition*), you will get a zero if the condition instead was met. # curlHandle cleanup This procedure must be the last one to call for a curl session. It is the opposite of the curl::init procedure and must be called with the same curlhandle as input as the curl::init call returned. This will effectively close all connections TclCurl has used and possibly has kept open until now. Don't call this procedure if you intend to transfer more files. # curlHandle reset Re-initializes all options previously set on a specified handle to the default values. This puts back the handle to the same state as it was in when it was just created with curl::init. It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares. # curlHandle duphandle This procedure will return a new curl handle, a duplicate, using all the options previously set in the input curl handle. Both handles can subsequently be used independently and they must both be freed with **cleanup**. The new handle will not inherit any state information, connections, SSL sessions or cookies. RETURN VALUE : A new curl handle or an error message if the copy fails. # curlHandle pause You can use this command from within a progress callback procedure to pause the transfer. # curlHandle resume Resumes a transfer paused with **curlhandle pause** # curl::transfer In case you do not want to use persistent connections you can use this command, it takes the same arguments as the *curlHandle* **configure** and will init, configure, perform and cleanup a connection for you. You can also get the *getinfo* information by using *-infooption variable* pairs, after the transfer *variable* will contain the value that would have been returned by *$curlHandle getinfo option*. RETURN VALUE : The same error code **perform** would return. # curl::version Returns a string with the version number of tclcurl, libcurl and some of its important components (like OpenSSL version). RETURN VALUE : The string with the version info. # curl::escape URL This procedure will convert the given input string to an URL encoded string and return that. All input characters that are not a-z, A-Z or 0-9 will be converted to their "URL escaped" version (%NN where NN is a two-digit hexadecimal number) RETURN VALUE : The converted string. # curl::unescape URL This procedure will convert the given URL encoded input string to a "plain string" and return that. All input characters that are URL encoded (%XX where XX is a two-digit hexadecimal number) will be converted to their plain text versions. RETURN VALUE : The string unencoded. # curl::curlConfig OPTION Returns some information about how you have **cURL** installed. -prefix : Returns the directory root where you installed **cURL**. -feature : Returns a list containing particular main features the installed **libcurl** was built with. The list may include SSL, KRB4 or IPv6, do not assume any particular order. -vernum : Outputs version information about the installed libcurl, in numerical mode. This outputs the version number, in hexadecimal, with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e... # curl::versioninfo OPTION Returns information about various run-time features in TclCurl. Applications should use this information to judge if things are possible to do or not, instead of using compile-time checks, as dynamic/DLL libraries can be changed independent of applications. -version : Returns the version of libcurl we are using. -versionnum : Returns the version of libcurl we are using in hexadecimal with 8 bits for each part; major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl 12.13.14 would appear as 0c0d0e... Note that the initial zero might be omitted. -host : Returns a string with the host information as discovered by a configure script or set by the build environment. -features : Returns a list with the features compiled into libcurl, the possible elements are: ASYNCHDNS : Libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface. CONV : Libcurl was built with support for character conversions. DEBUG : Libcurl was built with extra debug capabilities built-in. This is mainly of interest for libcurl hackers. GSSNEGOTIATE : Supports HTTP GSS-Negotiate. IDN : Supports IDNA, domain names with international letters. IPV6 : Supports IPv6. KERBEROS4 : Supports kerberos4 (when using FTP). LARGEFILE : Libcurl was built with support for large files. LIBZ : Supports HTTP deflate using libz. NTML : Supports HTTP NTLM SPNEGO : Libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478) SSL : Supports SSL (HTTPS/FTPS) SSPI : Libcurl was built with support for SSPI. This is only available on Windows and makes libcurl use Windows-provided functions for NTLM authentication. It also allows libcurl to use the current user and the current user's password without the app having to pass them on. TLSAUTH_SRP : Libcurl was built with support for TLS-SRP. **NTLM_WB** Libcurl was built with support for NTLM delegation to a winbind helper. Do not assume any particular order. -sslversion : Returns a string with the OpenSSL version used, like OpenSSL/0.9.6b. -sslversionnum : Returns the numerical OpenSSL version value as defined by the OpenSSL project. If libcurl has no SSL support, this is 0. -libzversion : Returns a string, there is no numerical version, for example: 1.1.3. -protocols : Lists what particular protocols the installed TclCurl was built to support. At the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE, TELNET, LDAP, DICT. Do not assume any particular order. The protocols will be listed using uppercase. There may be none, one or several protocols in the list. # curl::easystrerror errorCode This procedure returns a string describing the error code passed in the argument. # EXAMPLES The examples in this section assume you are running from the root of the TclCurl source tree. To start the local HTTP test server used in the examples, run: ```sh tclsh testservers/testserver.tcl ``` By default, this starts an HTTP server on `http://127.0.0.1:8990/`. The path `http://127.0.0.1:8990/tclcurl-man` returns the HTML version of this manual page from `doc/tclcurl.html`, which makes it a convenient target for a basic `GET` example. # BASIC HTTP GET The file `examples/http_get.tcl` contains a minimal HTTP `GET` example. It performs a simple request, stores the response body in a Tcl variable, and prints both the HTTP response code and the size of the returned document. If the request succeeds, `rc` is `0`, `responsecode` is `200`, and `body` contains the HTML document returned by the server. # AUTHORS Andres Garcia Garcia Massimo Manghi # SEE ALSO curl, The art of HTTP scripting (at , RFC 2396, tclcurl-ng-8.0.3/doc/tclcurl_multi.html000066400000000000000000000223101522613063100201060ustar00rootroot00000000000000 TclCurl Multi Interface

NAME

TclCurl - Perform multiple simultaneous URL transfers with the TclCurl multi interface.

SYNOPSIS

curl::multiinit
curl::multistrerror errorCode
multiHandle addhandle
multiHandle removehandle
multiHandle configure
multiHandle perform
multiHandle active
multiHandle getinfo
multiHandle cleanup
multiHandle auto ?-command command?

DESCRIPTION

TclCurl’s multi interface provides capabilities that are distinct from those of the easy interface. In particular, it is designed to:

  • Provide a “pull” interface, in which the application decides when and how data transfers are driven.
  • Support multiple simultaneous transfers within the same thread.
  • Allow Tk applications to remain responsive while transfers are in progress.

BLOCKING

Some operations still use blocking code even when the multi interface is used. You should be aware of the following current limitations:

  • Name resolution on non-Windows systems unless c-ares is used.
  • GnuTLS SSL connections.
  • Active FTP connections.
  • HTTP proxy CONNECT operations.
  • SOCKS proxy handshakes.
  • file:// transfers.
  • TELNET transfers.

curl::multiinit

This procedure must be called first. It returns a multiHandle, which you use to invoke the TclCurl multi-interface procedures. Each call to multiinit MUST have a corresponding call to cleanup when the operation is complete.

RETURN VALUE

The multiHandle to use.

multiHandle addhandle ?easyHandle?

Each individual transfer is represented by an easy handle. You must create the easy handle, configure it with the appropriate options, and then add it to the multi stack with the addhandle command.

If the easy handle is not configured to use a shared or global DNS cache, it will use the DNS cache shared by all easy handles associated with the same multi handle.

After an easy handle has been added to a multi stack, you must not call perform on that easy handle directly.

multiHandle is the value returned by the curl::multiinit call.

RETURN VALUE

Possible return values are:

-1
The handle was added to the multi stack. Call perform soon.
0
The handle was added successfully.
1
Invalid multi handle.
2
Invalid easy handle. This may mean that it is not an easy handle, or that it is already in use by this or by another multi handle.
3
Out of memory.
4
You found a bug in TclCurl.

multiHandle removehandle ?easyHandle?

When a transfer is complete, or when you want to stop a transfer before it is complete, you can use the removehandle command. Once removed from the multi handle, the easy handle can again be used with other easy-interface operations.

Note that when a transfer completes, the easy handle remains associated with the multi stack. You must remove it explicitly before cleaning it up or reconfiguring it and adding it again to the multi handle for another transfer.

RETURN VALUE

Possible return values are:

0
The handle was removed successfully.
1
Invalid multi handle.
2
Invalid easy handle.
3
Out of memory.
4
You found a bug in TclCurl.

multiHandle configure

So far the only options are:

-pipelining

Pass 1 to enable this option or 0 to disable it. When enabled, TclCurl will attempt to use HTTP pipelining where possible for transfers associated with this multi handle.

In practice, if you add a second request that can reuse an existing connection, that request may be sent on the same connection instead of being executed in parallel on a separate one.

-maxconnects

Pass a number which will be used as the maximum amount of simultaneously open connections that TclCurl may cache. The default is 10. TclCurl may enlarge the cache so that it can hold up to four times the number of easy handles added to the multi handle.

By setting this option, you can prevent the cache size from growing beyond the limit set by you. When the cache is full, curl closes the oldest one in the cache to prevent the number of open connections from increasing.

This option applies only to multi handles. When using the easy interface, use the easy handle’s own maxconnects option instead.

multiHandle perform

Adding easy handles to the multi stack does not start any transfer. One of the main purposes of the multi interface is to let the application drive the transfers explicitly. You do this by invoking perform.

When perform is called, TclCurl advances the transfers for the easy handles in the multi stack that are currently ready for I/O. As data is sent or received, TclCurl may invoke the callbacks configured on the individual easy handles, such as read, write, progress, header, or debug callbacks, according to the state of each transfer. Depending on the state of the transfers, this may involve all handles, some of them, or none.

If, after a call to perform, the number of running handles has changed from the previous call, or is lower than the number of easy handles added to the multi handle, one or more transfers are no longer running. In that case, you can call getinfo to obtain information about each completed transfer. If an added handle fails very quickly, it may never be counted as running.

RETURN VALUE

If everything goes well, this command returns the number of running handles, or 0 if all transfers are complete. In case of error, it returns the error code.

This command reports only errors related to the multi stack as a whole. Individual transfers may still have failed even when perform itself returns successfully.

multiHandle active

Use the active command to determine whether any of the easy handles are currently ready to transfer data before invoking perform. It returns the number of transfers that are currently active.

RETURN VALUE

The number of active transfers, or -1 in case of error.

multiHandle getinfo

This procedure returns a small amount of information about transfers in the multi stack. For more detailed information, use the getinfo command on the individual easy handles.

RETURN VALUE

A list with the following elements:

  • the easyHandle to which the information applies
  • the state of the transfer, 1 if it is complete
  • the transfer exit code, 0 if no error occurred
  • the number of messages still in the info queue

If there are no messages in the queue, this command returns {"" 0 0 0}.

multiHandle cleanup

This procedure must be the last one called for a multi stack. It is the counterpart of curl::multiinit and must be called with the same multiHandle that curl::multiinit returned.

multiHandle auto ?-command command?

With this command, Tcl’s event loop takes care of periodically invoking perform for you. Before using it, you must already have added at least one easy handle to the multi handle.

The -command option lets you specify a command to invoke after all easy handles have finished their transfers. In practice, you should use this command to perform the necessary cleanup of the handles. Otherwise, the transferred files may not be complete.

This support is still experimental and may change without warning.

You can find a couple of examples at tests/multi.

curl::multistrerror errorCode

This procedure returns a string describing the error code passed in the argument.

SEE ALSO

TclCurl, curl

tclcurl-ng-8.0.3/doc/tclcurl_multi.n000066400000000000000000000204411522613063100174020ustar00rootroot00000000000000.\" -*- mode: troff; coding: utf-8 -*- .TH "TclCurl Multi Interface" "n" "19-05-2026" "TclCurl 8.0.3" "TclCurl Easy Interface" .SH NAME .LP TclCurl - Perform multiple simultaneous URL transfers with the TclCurl multi interface. .SH SYNOPSIS .LP .EX curl::multiinit curl::multistrerror errorCode .EE .LP .EX multiHandle addhandle multiHandle removehandle multiHandle configure multiHandle perform multiHandle active multiHandle getinfo multiHandle cleanup multiHandle auto ?-command command? .EE .SH DESCRIPTION .LP TclCurl\(cqs multi interface provides capabilities that are distinct from those of the easy interface. In particular, it is designed to: .IP "\(bu" 3 Provide a \(lqpull\(rq interface, in which the application decides when and how data transfers are driven. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 Support multiple simultaneous transfers within the same thread. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 Allow Tk applications to remain responsive while transfers are in progress. .SH BLOCKING .LP Some operations still use blocking code even when the multi interface is used. You should be aware of the following current limitations: .IP "\(bu" 3 Name resolution on non-Windows systems unless c-ares is used. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 GnuTLS SSL connections. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 Active FTP connections. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 HTTP proxy CONNECT operations. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 SOCKS proxy handshakes. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 \f(CRfile://\fR transfers. .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 TELNET transfers. .SH curl::multiinit .LP This procedure must be called first. It returns a \f(CRmultiHandle\fR, which you use to invoke the TclCurl multi-interface procedures. Each call to \f(CRmultiinit\fR MUST have a corresponding call to \f(CRcleanup\fR when the operation is complete. .PP \fBRETURN VALUE\fR .PP The \f(CRmultiHandle\fR to use. .SH multiHandle addhandle ?easyHandle? .LP Each individual transfer is represented by an easy handle. You must create the easy handle, configure it with the appropriate options, and then add it to the multi stack with the \f(CRaddhandle\fR command. .PP If the easy handle is not configured to use a shared or global DNS cache, it will use the DNS cache shared by all easy handles associated with the same multi handle. .PP After an easy handle has been added to a multi stack, you must not call \f(CRperform\fR on that easy handle directly. .PP \f(CRmultiHandle\fR is the value returned by the \f(CRcurl::multiinit\fR call. .PP \fBRETURN VALUE\fR .PP Possible return values are: .TP 3 \f(CR-1\fR The handle was added to the multi stack. Call \f(CRperform\fR soon. .TP 3 \f(CR0\fR The handle was added successfully. .TP 3 \f(CR1\fR Invalid multi handle. .TP 3 \f(CR2\fR Invalid easy handle. This may mean that it is not an easy handle, or that it is already in use by this or by another multi handle. .TP 3 \f(CR3\fR Out of memory. .TP 3 \f(CR4\fR You found a bug in TclCurl. .SH multiHandle removehandle ?easyHandle? .LP When a transfer is complete, or when you want to stop a transfer before it is complete, you can use the \f(CRremovehandle\fR command. Once removed from the multi handle, the easy handle can again be used with other easy-interface operations. .PP Note that when a transfer completes, the easy handle remains associated with the multi stack. You must remove it explicitly before cleaning it up or reconfiguring it and adding it again to the multi handle for another transfer. .PP \fBRETURN VALUE\fR .PP Possible return values are: .TP 3 \f(CR0\fR The handle was removed successfully. .TP 3 \f(CR1\fR Invalid multi handle. .TP 3 \f(CR2\fR Invalid easy handle. .TP 3 \f(CR3\fR Out of memory. .TP 3 \f(CR4\fR You found a bug in TclCurl. .SH multiHandle configure .LP So far the only options are: .TP 3 \fB-pipelining\fR Pass \f(CR1\fR to enable this option or \f(CR0\fR to disable it. When enabled, TclCurl will attempt to use HTTP pipelining where possible for transfers associated with this multi handle. .IP In practice, if you add a second request that can reuse an existing connection, that request may be sent on the same connection instead of being executed in parallel on a separate one. .TP 3 \fB-maxconnects\fR Pass a number which will be used as the maximum amount of simultaneously open connections that TclCurl may cache. The default is \f(CR10\fR. TclCurl may enlarge the cache so that it can hold up to four times the number of easy handles added to the multi handle. .IP By setting this option, you can prevent the cache size from growing beyond the limit set by you. When the cache is full, curl closes the oldest one in the cache to prevent the number of open connections from increasing. .IP This option applies only to multi handles. When using the easy interface, use the easy handle\(cqs own \f(CRmaxconnects\fR option instead. .SH multiHandle perform .LP Adding easy handles to the multi stack does not start any transfer. One of the main purposes of the multi interface is to let the application drive the transfers explicitly. You do this by invoking \f(CRperform\fR. .PP When \f(CRperform\fR is called, TclCurl advances the transfers for the easy handles in the multi stack that are currently ready for I/O. As data is sent or received, TclCurl may invoke the callbacks configured on the individual easy handles, such as read, write, progress, header, or debug callbacks, according to the state of each transfer. Depending on the state of the transfers, this may involve all handles, some of them, or none. .PP If, after a call to \f(CRperform\fR, the number of running handles has changed from the previous call, or is lower than the number of easy handles added to the multi handle, one or more transfers are no longer running. In that case, you can call \f(CRgetinfo\fR to obtain information about each completed transfer. If an added handle fails very quickly, it may never be counted as running. .PP \fBRETURN VALUE\fR .PP If everything goes well, this command returns the number of running handles, or \f(CR0\fR if all transfers are complete. In case of error, it returns the error code. .PP This command reports only errors related to the multi stack as a whole. Individual transfers may still have failed even when \f(CRperform\fR itself returns successfully. .SH multiHandle active .LP Use the \f(CRactive\fR command to determine whether any of the easy handles are currently ready to transfer data before invoking \f(CRperform\fR. It returns the number of transfers that are currently active. .PP \fBRETURN VALUE\fR .PP The number of active transfers, or \f(CR-1\fR in case of error. .SH multiHandle getinfo .LP This procedure returns a small amount of information about transfers in the multi stack. For more detailed information, use the \f(CRgetinfo\fR command on the individual easy handles. .PP \fBRETURN VALUE\fR .PP A list with the following elements: .IP "\(bu" 3 the \f(CReasyHandle\fR to which the information applies .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 the state of the transfer, \f(CR1\fR if it is complete .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 the transfer exit code, \f(CR0\fR if no error occurred .if n \ .sp -1 .if t \ .sp -0.25v .IP "\(bu" 3 the number of messages still in the info queue .LP If there are no messages in the queue, this command returns \f(CR{\(dq\(dq 0 0 0}\fR. .SH multiHandle cleanup .LP This procedure must be the last one called for a multi stack. It is the counterpart of \f(CRcurl::multiinit\fR and must be called with the same \f(CRmultiHandle\fR that \f(CRcurl::multiinit\fR returned. .SH multiHandle auto ?-command command? .LP With this command, Tcl\(cqs event loop takes care of periodically invoking \f(CRperform\fR for you. Before using it, you must already have added at least one easy handle to the multi handle. .PP The \f(CR-command\fR option lets you specify a command to invoke after all easy handles have finished their transfers. In practice, you should use this command to perform the necessary cleanup of the handles. Otherwise, the transferred files may not be complete. .PP This support is still experimental and may change without warning. .PP You can find a couple of examples at \f(CRtests/multi\fR. .SH curl::multistrerror errorCode .LP This procedure returns a string describing the error code passed in the argument. .SH SEE ALSO .LP TclCurl, curl tclcurl-ng-8.0.3/doc/tclcurl_multi.n.md000066400000000000000000000165721522613063100200130ustar00rootroot00000000000000--- title: TclCurl Multi Interface section: n date: 19-05-2026 source: TclCurl 8.0.3 volume: TclCurl Easy Interface --- # NAME TclCurl - Perform multiple simultaneous URL transfers with the TclCurl multi interface. # SYNOPSIS ```tcl curl::multiinit curl::multistrerror errorCode ``` ```tcl multiHandle addhandle multiHandle removehandle multiHandle configure multiHandle perform multiHandle active multiHandle getinfo multiHandle cleanup multiHandle auto ?-command command? ``` # DESCRIPTION TclCurl's multi interface provides capabilities that are distinct from those of the easy interface. In particular, it is designed to: - Provide a "pull" interface, in which the application decides when and how data transfers are driven. - Support multiple simultaneous transfers within the same thread. - Allow Tk applications to remain responsive while transfers are in progress. # BLOCKING Some operations still use blocking code even when the multi interface is used. You should be aware of the following current limitations: - Name resolution on non-Windows systems unless c-ares is used. - GnuTLS SSL connections. - Active FTP connections. - HTTP proxy CONNECT operations. - SOCKS proxy handshakes. - `file://` transfers. - TELNET transfers. # curl::multiinit This procedure must be called first. It returns a `multiHandle`, which you use to invoke the TclCurl multi-interface procedures. Each call to `multiinit` MUST have a corresponding call to `cleanup` when the operation is complete. **RETURN VALUE** The `multiHandle` to use. # multiHandle addhandle ?easyHandle? Each individual transfer is represented by an easy handle. You must create the easy handle, configure it with the appropriate options, and then add it to the multi stack with the `addhandle` command. If the easy handle is not configured to use a shared or global DNS cache, it will use the DNS cache shared by all easy handles associated with the same multi handle. After an easy handle has been added to a multi stack, you must not call `perform` on that easy handle directly. `multiHandle` is the value returned by the `curl::multiinit` call. **RETURN VALUE** Possible return values are: `-1` : The handle was added to the multi stack. Call `perform` soon. `0` : The handle was added successfully. `1` : Invalid multi handle. `2` : Invalid easy handle. This may mean that it is not an easy handle, or that it is already in use by this or by another multi handle. `3` : Out of memory. `4` : You found a bug in TclCurl. # multiHandle removehandle ?easyHandle? When a transfer is complete, or when you want to stop a transfer before it is complete, you can use the `removehandle` command. Once removed from the multi handle, the easy handle can again be used with other easy-interface operations. Note that when a transfer completes, the easy handle remains associated with the multi stack. You must remove it explicitly before cleaning it up or reconfiguring it and adding it again to the multi handle for another transfer. **RETURN VALUE** Possible return values are: `0` : The handle was removed successfully. `1` : Invalid multi handle. `2` : Invalid easy handle. `3` : Out of memory. `4` : You found a bug in TclCurl. # multiHandle configure So far the only options are: **-pipelining** : Pass `1` to enable this option or `0` to disable it. When enabled, TclCurl will attempt to use HTTP pipelining where possible for transfers associated with this multi handle. In practice, if you add a second request that can reuse an existing connection, that request may be sent on the same connection instead of being executed in parallel on a separate one. **-maxconnects** : Pass a number which will be used as the maximum amount of simultaneously open connections that TclCurl may cache. The default is `10`. TclCurl may enlarge the cache so that it can hold up to four times the number of easy handles added to the multi handle. By setting this option, you can prevent the cache size from growing beyond the limit set by you. When the cache is full, curl closes the oldest one in the cache to prevent the number of open connections from increasing. This option applies only to multi handles. When using the easy interface, use the easy handle's own `maxconnects` option instead. # multiHandle perform Adding easy handles to the multi stack does not start any transfer. One of the main purposes of the multi interface is to let the application drive the transfers explicitly. You do this by invoking `perform`. When `perform` is called, TclCurl advances the transfers for the easy handles in the multi stack that are currently ready for I/O. As data is sent or received, TclCurl may invoke the callbacks configured on the individual easy handles, such as read, write, progress, header, or debug callbacks, according to the state of each transfer. Depending on the state of the transfers, this may involve all handles, some of them, or none. If, after a call to `perform`, the number of running handles has changed from the previous call, or is lower than the number of easy handles added to the multi handle, one or more transfers are no longer running. In that case, you can call `getinfo` to obtain information about each completed transfer. If an added handle fails very quickly, it may never be counted as running. **RETURN VALUE** If everything goes well, this command returns the number of running handles, or `0` if all transfers are complete. In case of error, it returns the error code. This command reports only errors related to the multi stack as a whole. Individual transfers may still have failed even when `perform` itself returns successfully. # multiHandle active Use the `active` command to determine whether any of the easy handles are currently ready to transfer data before invoking `perform`. It returns the number of transfers that are currently active. **RETURN VALUE** The number of active transfers, or `-1` in case of error. # multiHandle getinfo This procedure returns a small amount of information about transfers in the multi stack. For more detailed information, use the `getinfo` command on the individual easy handles. **RETURN VALUE** A list with the following elements: - the `easyHandle` to which the information applies - the state of the transfer, `1` if it is complete - the transfer exit code, `0` if no error occurred - the number of messages still in the info queue If there are no messages in the queue, this command returns `{"" 0 0 0}`. # multiHandle cleanup This procedure must be the last one called for a multi stack. It is the counterpart of `curl::multiinit` and must be called with the same `multiHandle` that `curl::multiinit` returned. # multiHandle auto ?-command command? With this command, Tcl's event loop takes care of periodically invoking `perform` for you. Before using it, you must already have added at least one easy handle to the multi handle. The `-command` option lets you specify a command to invoke after all easy handles have finished their transfers. In practice, you should use this command to perform the necessary cleanup of the handles. Otherwise, the transferred files may not be complete. This support is still experimental and may change without warning. You can find a couple of examples at `tests/multi`. # curl::multistrerror errorCode This procedure returns a string describing the error code passed in the argument. # SEE ALSO TclCurl, curl tclcurl-ng-8.0.3/doc/tclcurl_multi.n.md.in000066400000000000000000000166061522613063100204160ustar00rootroot00000000000000--- title: TclCurl Multi Interface section: n date: 19-05-2026 source: TclCurl @PACKAGE_VERSION@ volume: TclCurl Easy Interface --- # NAME TclCurl - Perform multiple simultaneous URL transfers with the TclCurl multi interface. # SYNOPSIS ```tcl curl::multiinit curl::multistrerror errorCode ``` ```tcl multiHandle addhandle multiHandle removehandle multiHandle configure multiHandle perform multiHandle active multiHandle getinfo multiHandle cleanup multiHandle auto ?-command command? ``` # DESCRIPTION TclCurl's multi interface provides capabilities that are distinct from those of the easy interface. In particular, it is designed to: - Provide a "pull" interface, in which the application decides when and how data transfers are driven. - Support multiple simultaneous transfers within the same thread. - Allow Tk applications to remain responsive while transfers are in progress. # BLOCKING Some operations still use blocking code even when the multi interface is used. You should be aware of the following current limitations: - Name resolution on non-Windows systems unless c-ares is used. - GnuTLS SSL connections. - Active FTP connections. - HTTP proxy CONNECT operations. - SOCKS proxy handshakes. - `file://` transfers. - TELNET transfers. # curl::multiinit This procedure must be called first. It returns a `multiHandle`, which you use to invoke the TclCurl multi-interface procedures. Each call to `multiinit` MUST have a corresponding call to `cleanup` when the operation is complete. **RETURN VALUE** The `multiHandle` to use. # multiHandle addhandle ?easyHandle? Each individual transfer is represented by an easy handle. You must create the easy handle, configure it with the appropriate options, and then add it to the multi stack with the `addhandle` command. If the easy handle is not configured to use a shared or global DNS cache, it will use the DNS cache shared by all easy handles associated with the same multi handle. After an easy handle has been added to a multi stack, you must not call `perform` on that easy handle directly. `multiHandle` is the value returned by the `curl::multiinit` call. **RETURN VALUE** Possible return values are: `-1` : The handle was added to the multi stack. Call `perform` soon. `0` : The handle was added successfully. `1` : Invalid multi handle. `2` : Invalid easy handle. This may mean that it is not an easy handle, or that it is already in use by this or by another multi handle. `3` : Out of memory. `4` : You found a bug in TclCurl. # multiHandle removehandle ?easyHandle? When a transfer is complete, or when you want to stop a transfer before it is complete, you can use the `removehandle` command. Once removed from the multi handle, the easy handle can again be used with other easy-interface operations. Note that when a transfer completes, the easy handle remains associated with the multi stack. You must remove it explicitly before cleaning it up or reconfiguring it and adding it again to the multi handle for another transfer. **RETURN VALUE** Possible return values are: `0` : The handle was removed successfully. `1` : Invalid multi handle. `2` : Invalid easy handle. `3` : Out of memory. `4` : You found a bug in TclCurl. # multiHandle configure So far the only options are: **-pipelining** : Pass `1` to enable this option or `0` to disable it. When enabled, TclCurl will attempt to use HTTP pipelining where possible for transfers associated with this multi handle. In practice, if you add a second request that can reuse an existing connection, that request may be sent on the same connection instead of being executed in parallel on a separate one. **-maxconnects** : Pass a number which will be used as the maximum amount of simultaneously open connections that TclCurl may cache. The default is `10`. TclCurl may enlarge the cache so that it can hold up to four times the number of easy handles added to the multi handle. By setting this option, you can prevent the cache size from growing beyond the limit set by you. When the cache is full, curl closes the oldest one in the cache to prevent the number of open connections from increasing. This option applies only to multi handles. When using the easy interface, use the easy handle's own `maxconnects` option instead. # multiHandle perform Adding easy handles to the multi stack does not start any transfer. One of the main purposes of the multi interface is to let the application drive the transfers explicitly. You do this by invoking `perform`. When `perform` is called, TclCurl advances the transfers for the easy handles in the multi stack that are currently ready for I/O. As data is sent or received, TclCurl may invoke the callbacks configured on the individual easy handles, such as read, write, progress, header, or debug callbacks, according to the state of each transfer. Depending on the state of the transfers, this may involve all handles, some of them, or none. If, after a call to `perform`, the number of running handles has changed from the previous call, or is lower than the number of easy handles added to the multi handle, one or more transfers are no longer running. In that case, you can call `getinfo` to obtain information about each completed transfer. If an added handle fails very quickly, it may never be counted as running. **RETURN VALUE** If everything goes well, this command returns the number of running handles, or `0` if all transfers are complete. In case of error, it returns the error code. This command reports only errors related to the multi stack as a whole. Individual transfers may still have failed even when `perform` itself returns successfully. # multiHandle active Use the `active` command to determine whether any of the easy handles are currently ready to transfer data before invoking `perform`. It returns the number of transfers that are currently active. **RETURN VALUE** The number of active transfers, or `-1` in case of error. # multiHandle getinfo This procedure returns a small amount of information about transfers in the multi stack. For more detailed information, use the `getinfo` command on the individual easy handles. **RETURN VALUE** A list with the following elements: - the `easyHandle` to which the information applies - the state of the transfer, `1` if it is complete - the transfer exit code, `0` if no error occurred - the number of messages still in the info queue If there are no messages in the queue, this command returns `{"" 0 0 0}`. # multiHandle cleanup This procedure must be the last one called for a multi stack. It is the counterpart of `curl::multiinit` and must be called with the same `multiHandle` that `curl::multiinit` returned. # multiHandle auto ?-command command? With this command, Tcl's event loop takes care of periodically invoking `perform` for you. Before using it, you must already have added at least one easy handle to the multi handle. The `-command` option lets you specify a command to invoke after all easy handles have finished their transfers. In practice, you should use this command to perform the necessary cleanup of the handles. Otherwise, the transferred files may not be complete. This support is still experimental and may change without warning. You can find a couple of examples at `tests/multi`. # curl::multistrerror errorCode This procedure returns a string describing the error code passed in the argument. # SEE ALSO TclCurl, curl tclcurl-ng-8.0.3/doc/tclcurl_share.html000066400000000000000000000046011522613063100200610ustar00rootroot00000000000000 TclCurl Share

NAME

TclCurl - Share selected data between multiple easy handles.

SYNOPSIS

curl::shareinit
curl::sharestrerror errorCode
shareHandle share ?data?
shareHandle unshare ?data?
shareHandle cleanup

DESCRIPTION

The share API allows two or more easy handles to share selected kinds of data. At present, TclCurl supports sharing cookie data and DNS cache data.

curl::shareinit

This procedure must be called first. It returns a shareHandle, which you use to share data between easy handles through the -share option of the configure command. Each call to shareinit MUST have a corresponding call to cleanup when the operation is complete.

RETURN VALUE

The shareHandle to use.

shareHandle share ?data?

This parameter specifies the kind of data to be shared. It may be set to one of the values described below:

cookies

Cookie data is shared between the easy handles associated with this shared object.

dns

Cached DNS entries are shared between the easy handles associated with this shared object.

Note that when you use the multi interface, all easy handles added to the same multi handle share DNS cache by default, without requiring this setting.

shareHandle unshare ?data?

This command does the opposite of share. The specified data type will no longer be shared. Valid values are the same as for share.

shareHandle cleanup

Deletes a shared object. After this command has been called, the share handle can no longer be used.

curl::sharestrerror errorCode

This procedure returns a string describing the error code passed in the argument.

SEE ALSO

curl, TclCurl

tclcurl-ng-8.0.3/doc/tclcurl_share.n000066400000000000000000000035171522613063100173570ustar00rootroot00000000000000.\" -*- mode: troff; coding: utf-8 -*- .TH "TclCurl Share" "n" "19-05-2026" "TclCurl 8.0.3" "TclCurl Easy Interface" .SH NAME .LP TclCurl - Share selected data between multiple easy handles. .SH SYNOPSIS .LP .EX curl::shareinit curl::sharestrerror errorCode .EE .LP .EX shareHandle share ?data? shareHandle unshare ?data? shareHandle cleanup .EE .SH DESCRIPTION .LP The share API allows two or more easy handles to share selected kinds of data. At present, TclCurl supports sharing cookie data and DNS cache data. .SH curl::shareinit .LP This procedure must be called first. It returns a \f(CRshareHandle\fR, which you use to share data between easy handles through the \f(CR-share\fR option of the \f(CRconfigure\fR command. Each call to \f(CRshareinit\fR MUST have a corresponding call to \f(CRcleanup\fR when the operation is complete. .PP \fBRETURN VALUE\fR .PP The \f(CRshareHandle\fR to use. .SH shareHandle share ?data? .LP This parameter specifies the kind of data to be shared. It may be set to one of the values described below: .TP 3 \f(CRcookies\fR Cookie data is shared between the easy handles associated with this shared object. .TP 3 \f(CRdns\fR Cached DNS entries are shared between the easy handles associated with this shared object. .IP Note that when you use the multi interface, all easy handles added to the same multi handle share DNS cache by default, without requiring this setting. .SH shareHandle unshare ?data? .LP This command does the opposite of \f(CRshare\fR. The specified data type will no longer be shared. Valid values are the same as for \f(CRshare\fR. .SH shareHandle cleanup .LP Deletes a shared object. After this command has been called, the share handle can no longer be used. .SH curl::sharestrerror errorCode .LP This procedure returns a string describing the error code passed in the argument. .SH SEE ALSO .LP curl, TclCurl tclcurl-ng-8.0.3/doc/tclcurl_share.n.md000066400000000000000000000033621522613063100177540ustar00rootroot00000000000000--- title: TclCurl Share section: n date: 19-05-2026 source: TclCurl 8.0.3 volume: TclCurl Easy Interface --- # NAME TclCurl - Share selected data between multiple easy handles. # SYNOPSIS ```tcl curl::shareinit curl::sharestrerror errorCode ``` ```tcl shareHandle share ?data? shareHandle unshare ?data? shareHandle cleanup ``` # DESCRIPTION The share API allows two or more easy handles to share selected kinds of data. At present, TclCurl supports sharing cookie data and DNS cache data. # curl::shareinit This procedure must be called first. It returns a `shareHandle`, which you use to share data between easy handles through the `-share` option of the `configure` command. Each call to `shareinit` MUST have a corresponding call to `cleanup` when the operation is complete. **RETURN VALUE** The `shareHandle` to use. # shareHandle share ?data? This parameter specifies the kind of data to be shared. It may be set to one of the values described below: `cookies` : Cookie data is shared between the easy handles associated with this shared object. `dns` : Cached DNS entries are shared between the easy handles associated with this shared object. Note that when you use the multi interface, all easy handles added to the same multi handle share DNS cache by default, without requiring this setting. # shareHandle unshare ?data? This command does the opposite of `share`. The specified data type will no longer be shared. Valid values are the same as for `share`. # shareHandle cleanup Deletes a shared object. After this command has been called, the share handle can no longer be used. # curl::sharestrerror errorCode This procedure returns a string describing the error code passed in the argument. # SEE ALSO curl, TclCurl tclcurl-ng-8.0.3/doc/tclcurl_share.n.md.in000066400000000000000000000033761522613063100203660ustar00rootroot00000000000000--- title: TclCurl Share section: n date: 19-05-2026 source: TclCurl @PACKAGE_VERSION@ volume: TclCurl Easy Interface --- # NAME TclCurl - Share selected data between multiple easy handles. # SYNOPSIS ```tcl curl::shareinit curl::sharestrerror errorCode ``` ```tcl shareHandle share ?data? shareHandle unshare ?data? shareHandle cleanup ``` # DESCRIPTION The share API allows two or more easy handles to share selected kinds of data. At present, TclCurl supports sharing cookie data and DNS cache data. # curl::shareinit This procedure must be called first. It returns a `shareHandle`, which you use to share data between easy handles through the `-share` option of the `configure` command. Each call to `shareinit` MUST have a corresponding call to `cleanup` when the operation is complete. **RETURN VALUE** The `shareHandle` to use. # shareHandle share ?data? This parameter specifies the kind of data to be shared. It may be set to one of the values described below: `cookies` : Cookie data is shared between the easy handles associated with this shared object. `dns` : Cached DNS entries are shared between the easy handles associated with this shared object. Note that when you use the multi interface, all easy handles added to the same multi handle share DNS cache by default, without requiring this setting. # shareHandle unshare ?data? This command does the opposite of `share`. The specified data type will no longer be shared. Valid values are the same as for `share`. # shareHandle cleanup Deletes a shared object. After this command has been called, the share handle can no longer be used. # curl::sharestrerror errorCode This procedure returns a string describing the error code passed in the argument. # SEE ALSO curl, TclCurl tclcurl-ng-8.0.3/examples/000077500000000000000000000000001522613063100154115ustar00rootroot00000000000000tclcurl-ng-8.0.3/examples/README.md000066400000000000000000000051031522613063100166670ustar00rootroot00000000000000# Examples This directory contains runnable TclCurl examples extracted from the manual page and aligned with the local test infrastructure used by the project. # Starting the Local HTTP Server Some examples use the HTTP server implemented for the test suite. To start it, run the following command from the root of the TclCurl source tree: ```sh tclsh testservers/testserver.tcl ``` To exercise the static-file fallback, you can point the server at a custom document root: ```sh tclsh testservers/testserver.tcl --docroot /tmp/tclcurl ``` By default, the server removes that document root when it shuts down. Pass `--keepdocroot` if you want to inspect or reuse its contents after shutdown. By default, this starts several local services, including an HTTP server on: ```text http://127.0.0.1:8990/ ``` The HTTP example in this directory uses the path: ```text http://127.0.0.1:8990/tclcurl-man ``` That path is provided by `testservers/http_server.tcl` and returns the HTML version of the TclCurl manual from `doc/tclcurl.html`. # Running the Basic HTTP GET Example After the test server is running, open a second terminal in the root of the source tree and run: ```sh tclsh examples/http_get.tcl ``` The script performs a basic HTTP `GET` request, stores the returned document in a Tcl variable, and prints: - the TclCurl return code from `perform` - the HTTP response code - the number of downloaded bytes If the request succeeds, the TclCurl return code is `0`, the HTTP response code is `200`, and the downloaded body contains the HTML manual page served by the local test server. # Running the URL-Encoded GET Example The file `examples/http_urlencoded.tcl` shows how to build a query string for an HTTP `GET` request using `curl::escape` to encode form-style values safely. Run it from the root of the source tree with: ```sh tclsh examples/http_urlencoded.tcl ``` This script sends a request to the local test path: ```text http://127.0.0.1:8990/request-inspect ``` The server responds with an inspection report that includes the HTTP method, the request path, and the full request target, including the encoded query string. This makes it easy to verify that the parameters were encoded and sent as intended. # Notes - The examples assume that TclCurl is available to `package require TclCurl`. - The commands above should be run from the repository root so that the test server can find the expected project files. - If you start the server with a custom `--docroot`, keep `TCLCURL_TEST_DOC_ROOT` aligned with it when running server-backed tests that create or fetch static fixtures. tclcurl-ng-8.0.3/examples/http_get.tcl000066400000000000000000000006221522613063100177330ustar00rootroot00000000000000#!/usr/bin/env tclsh package require TclCurl set body {} set curlHandle [curl::init] $curlHandle configure \ -url http://127.0.0.1:8990/tclcurl-man \ -bodyvar body \ -noprogress 1 set rc [$curlHandle perform] set httpCode [$curlHandle getinfo responsecode] puts "perform rc: $rc" puts "HTTP response code: $httpCode" puts "Downloaded bytes: [string length $body]" $curlHandle cleanup tclcurl-ng-8.0.3/examples/http_urlencoded.tcl000066400000000000000000000011421522613063100212760ustar00rootroot00000000000000#!/usr/bin/env tclsh package require TclCurl set firstName [curl::escape "Massimo"] set lastName [curl::escape "Manghi"] set city [curl::escape "Parma Italy"] set query "firstName=$firstName&lastName=$lastName&city=$city" set url "http://127.0.0.1:8990/request-inspect?$query" set body {} set curlHandle [curl::init] $curlHandle configure \ -url $url \ -bodyvar body \ -noprogress 1 set rc [$curlHandle perform] set httpCode [$curlHandle getinfo responsecode] puts "perform rc: $rc" puts "HTTP response code: $httpCode" puts "Server inspection output:" puts $body $curlHandle cleanup tclcurl-ng-8.0.3/generic/000077500000000000000000000000001522613063100152075ustar00rootroot00000000000000tclcurl-ng-8.0.3/generic/curl_getinfo.c000066400000000000000000000342201522613063100200340ustar00rootroot00000000000000/* * curl_getinfo.c -- Functions related to the 'curl_easy_getinfo' function in libcurl. * * Implementation of the TclCurl extension that creates the curl namespace * so that Tcl interpreters can access libcurl. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. */ #include #include #include #define TCLCURL_GETINFO_LIST(X) \ X(TCLCURL_INFO_EFFECTIVEURL, "effectiveurl") \ X(TCLCURL_INFO_HTTPCODE, "httpcode") \ X(TCLCURL_INFO_RESPONSECODE, "responsecode") \ X(TCLCURL_INFO_FILETIME, "filetime") \ X(TCLCURL_INFO_TOTALTIME, "totaltime") \ X(TCLCURL_INFO_NAMELOOKUPTIME, "namelookuptime") \ X(TCLCURL_INFO_CONNECTTIME, "connecttime") \ X(TCLCURL_INFO_PRETRANSFERTIME, "pretransfertime") \ X(TCLCURL_INFO_SIZEUPLOAD, "sizeupload") \ X(TCLCURL_INFO_SIZEDOWNLOAD, "sizedownload") \ X(TCLCURL_INFO_SPEEDDOWNLOAD, "speeddownload") \ X(TCLCURL_INFO_SPEEDUPLOAD, "speedupload") \ X(TCLCURL_INFO_HEADERSIZE, "headersize") \ X(TCLCURL_INFO_REQUESTSIZE, "requestsize") \ X(TCLCURL_INFO_SSLVERIFYRESULT, "sslverifyresult") \ X(TCLCURL_INFO_CONTENTLENGTHDOWNLOAD, "contentlengthdownload") \ X(TCLCURL_INFO_CONTENTLENGTHUPLOAD, "contentlengthupload") \ X(TCLCURL_INFO_STARTTRANSFERTIME, "starttransfertime") \ X(TCLCURL_INFO_CONTENTTYPE, "contenttype") \ X(TCLCURL_INFO_REDIRECTTIME, "redirecttime") \ X(TCLCURL_INFO_REDIRECTCOUNT, "redirectcount") \ X(TCLCURL_INFO_HTTPAUTHAVAIL, "httpauthavail") \ X(TCLCURL_INFO_PROXYAUTHAVAIL, "proxyauthavail") \ X(TCLCURL_INFO_OSERRNO, "oserrno") \ X(TCLCURL_INFO_NUMCONNECTS, "numconnects") \ X(TCLCURL_INFO_SSLENGINES, "sslengines") \ X(TCLCURL_INFO_HTTPCONNECTCODE, "httpconnectcode") \ X(TCLCURL_INFO_COOKIELIST, "cookielist") \ X(TCLCURL_INFO_FTPENTRYPATH, "ftpentrypath") \ X(TCLCURL_INFO_REDIRECTURL, "redirecturl") \ X(TCLCURL_INFO_PRIMARYIP, "primaryip") \ X(TCLCURL_INFO_APPCONNECTTIME, "appconnecttime") \ X(TCLCURL_INFO_CERTINFO, "certinfo") \ X(TCLCURL_INFO_CONDITIONUNMET, "conditionunmet") \ X(TCLCURL_INFO_PRIMARYPORT, "primaryport") \ X(TCLCURL_INFO_LOCALIP, "localip") \ X(TCLCURL_INFO_LOCALPORT, "localport") typedef enum { #define TCLCURL_GETINFO_ENUM_ENTRY(name, label) name, TCLCURL_GETINFO_LIST(TCLCURL_GETINFO_ENUM_ENTRY) #undef TCLCURL_GETINFO_ENUM_ENTRY TCLCURL_INFO_COUNT } TclCurlGetInfoId; static const char *const getInfoTable[TCLCURL_INFO_COUNT + 1] = { #define TCLCURL_GETINFO_TABLE_ENTRY(name, label) label, TCLCURL_GETINFO_LIST(TCLCURL_GETINFO_TABLE_ENTRY) #undef TCLCURL_GETINFO_TABLE_ENTRY NULL }; /*---------------------------------------------------------------------- * * curlGetInfo -- * * Invokes the 'curl_easy_getinfo' function in libcurl. * * Parameters: * * Results: * 0 if all went well. * The CURLcode for the error. * *---------------------------------------------------------------------*/ static Tcl_Obj* curlGetInfo(Tcl_Interp *interp,CURL *curlHandle,int tableIndex) { char* charPtr; long longNumber; double doubleNumber; struct curl_slist* slistPtr; struct curl_slist* slistHead; struct curl_certinfo* certinfoPtr=NULL; int i; Tcl_Obj* resultObjPtr = NULL; switch(tableIndex) { case TCLCURL_INFO_EFFECTIVEURL: if (!curl_easy_getinfo(curlHandle,CURLINFO_EFFECTIVE_URL,&charPtr)) { resultObjPtr = Tcl_NewStringObj(charPtr,-1); } break; case TCLCURL_INFO_HTTPCODE: case TCLCURL_INFO_RESPONSECODE: if (!curl_easy_getinfo(curlHandle,CURLINFO_RESPONSE_CODE,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_FILETIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_FILETIME,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_TOTALTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_TOTAL_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_NAMELOOKUPTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_NAMELOOKUP_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_CONNECTTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_CONNECT_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_PRETRANSFERTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_PRETRANSFER_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_SIZEUPLOAD: { curl_off_t longCurlInt; if (!curl_easy_getinfo(curlHandle,CURLINFO_SIZE_UPLOAD_T,&longCurlInt)) { resultObjPtr = Tcl_NewWideIntObj((Tcl_WideInt)longCurlInt); } break; } case TCLCURL_INFO_SIZEDOWNLOAD: { curl_off_t longCurlInt; if (!curl_easy_getinfo(curlHandle,CURLINFO_SIZE_DOWNLOAD_T,&longCurlInt)) { resultObjPtr = Tcl_NewWideIntObj((Tcl_WideInt)longCurlInt); } break; } case TCLCURL_INFO_SPEEDDOWNLOAD: { curl_off_t longCurlInt; if (!curl_easy_getinfo(curlHandle,CURLINFO_SPEED_DOWNLOAD_T,&longCurlInt)) { resultObjPtr = Tcl_NewWideIntObj((Tcl_WideInt)longCurlInt); } break; } case TCLCURL_INFO_SPEEDUPLOAD: { curl_off_t longCurlInt; if (!curl_easy_getinfo(curlHandle,CURLINFO_SPEED_UPLOAD_T,&longCurlInt)) { resultObjPtr = Tcl_NewWideIntObj((Tcl_WideInt)longCurlInt); } break; } case TCLCURL_INFO_HEADERSIZE: if (!curl_easy_getinfo(curlHandle,CURLINFO_HEADER_SIZE,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_REQUESTSIZE: if (!curl_easy_getinfo(curlHandle,CURLINFO_REQUEST_SIZE,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_SSLVERIFYRESULT: if (!curl_easy_getinfo(curlHandle,CURLINFO_SSL_VERIFYRESULT,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_CONTENTLENGTHDOWNLOAD: { curl_off_t longCurlInt; if (!curl_easy_getinfo(curlHandle,CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,&longCurlInt)) { resultObjPtr = Tcl_NewWideIntObj((Tcl_WideInt)longCurlInt); } break; } case TCLCURL_INFO_CONTENTLENGTHUPLOAD: { curl_off_t longCurlInt; if (!curl_easy_getinfo(curlHandle,CURLINFO_CONTENT_LENGTH_UPLOAD_T,&longCurlInt)) { resultObjPtr = Tcl_NewWideIntObj((Tcl_WideInt)longCurlInt); } break; } case TCLCURL_INFO_STARTTRANSFERTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_STARTTRANSFER_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_CONTENTTYPE: if (!curl_easy_getinfo(curlHandle,CURLINFO_CONTENT_TYPE,&charPtr)) { resultObjPtr = Tcl_NewStringObj(charPtr,-1); } break; case TCLCURL_INFO_REDIRECTTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_REDIRECT_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_REDIRECTCOUNT: if (!curl_easy_getinfo(curlHandle,CURLINFO_REDIRECT_COUNT,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_HTTPAUTHAVAIL: case TCLCURL_INFO_PROXYAUTHAVAIL: if (tableIndex == TCLCURL_INFO_HTTPAUTHAVAIL) { if (!curl_easy_getinfo(curlHandle,CURLINFO_HTTPAUTH_AVAIL,&longNumber)) { resultObjPtr = Tcl_NewListObj(0,(Tcl_Obj **)NULL); } } else { if (!curl_easy_getinfo(curlHandle,CURLINFO_PROXYAUTH_AVAIL,&longNumber)) { resultObjPtr = Tcl_NewListObj(0,(Tcl_Obj **)NULL); } } if (resultObjPtr != NULL) { if (longNumber&CURLAUTH_BASIC) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj("basic",-1)); } if (longNumber&CURLAUTH_DIGEST) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj("digest",-1)); } if (longNumber&CURLAUTH_GSSNEGOTIATE) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj("gssnegotiate",-1)); } if (longNumber&CURLAUTH_NTLM) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj("NTLM",-1)); } } break; case TCLCURL_INFO_OSERRNO: if (!curl_easy_getinfo(curlHandle,CURLINFO_OS_ERRNO,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_NUMCONNECTS: if (!curl_easy_getinfo(curlHandle,CURLINFO_NUM_CONNECTS,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_SSLENGINES: if (!curl_easy_getinfo(curlHandle,CURLINFO_SSL_ENGINES,&slistPtr)) { resultObjPtr = Tcl_NewListObj(0,(Tcl_Obj **)NULL); slistHead = slistPtr; while (slistPtr != NULL) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj(slistPtr->data,-1)); slistPtr = slistPtr->next; } curl_slist_free_all(slistHead); } break; case TCLCURL_INFO_HTTPCONNECTCODE: if (!curl_easy_getinfo(curlHandle,CURLINFO_HTTP_CONNECTCODE,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_COOKIELIST: if (!curl_easy_getinfo(curlHandle,CURLINFO_COOKIELIST,&slistPtr)) { resultObjPtr = Tcl_NewListObj(0,(Tcl_Obj **)NULL); slistHead = slistPtr; while (slistPtr!=NULL) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj(slistPtr->data,-1)); slistPtr = slistPtr->next; } curl_slist_free_all(slistHead); } break; case TCLCURL_INFO_FTPENTRYPATH: if (!curl_easy_getinfo(curlHandle,CURLINFO_FTP_ENTRY_PATH,&charPtr)) { resultObjPtr = Tcl_NewStringObj(charPtr,-1); } break; case TCLCURL_INFO_REDIRECTURL: if (!curl_easy_getinfo(curlHandle,CURLINFO_REDIRECT_URL,&charPtr)) { resultObjPtr = Tcl_NewStringObj(charPtr,-1); } break; case TCLCURL_INFO_PRIMARYIP: if (!curl_easy_getinfo(curlHandle,CURLINFO_PRIMARY_IP,&charPtr)) { resultObjPtr = Tcl_NewStringObj(charPtr,-1); } break; case TCLCURL_INFO_APPCONNECTTIME: if (!curl_easy_getinfo(curlHandle,CURLINFO_APPCONNECT_TIME,&doubleNumber)) { resultObjPtr = Tcl_NewDoubleObj(doubleNumber); } break; case TCLCURL_INFO_CERTINFO: if (!curl_easy_getinfo(curlHandle,CURLINFO_CERTINFO,&certinfoPtr)) { resultObjPtr = Tcl_NewListObj(0,(Tcl_Obj **)NULL); Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewIntObj(certinfoPtr->num_of_certs)); for (i=0; i < certinfoPtr->num_of_certs; i++) { for (slistPtr = certinfoPtr->certinfo[i]; slistPtr; slistPtr=slistPtr->next) { Tcl_ListObjAppendElement(interp,resultObjPtr,Tcl_NewStringObj(slistPtr->data,-1)); } } } break; case TCLCURL_INFO_CONDITIONUNMET: if (!curl_easy_getinfo(curlHandle,CURLINFO_CONDITION_UNMET,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_PRIMARYPORT: if (!curl_easy_getinfo(curlHandle,CURLINFO_PRIMARY_PORT,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; case TCLCURL_INFO_LOCALIP: if (!curl_easy_getinfo(curlHandle,CURLINFO_LOCAL_IP,&charPtr)) { resultObjPtr = Tcl_NewStringObj(charPtr,-1); } break; case TCLCURL_INFO_LOCALPORT: if (!curl_easy_getinfo(curlHandle,CURLINFO_LOCAL_PORT,&longNumber)) { resultObjPtr = Tcl_NewLongObj(longNumber); } break; } return resultObjPtr; } int TclCurl_GetInfo (Tcl_Interp* interp,Tcl_Obj* get_info_arg,CURL* curlHandle,Tcl_Obj** result_p) { int tableIndex; Tcl_Obj* resultObj; if (Tcl_GetIndexFromObj(interp,get_info_arg,getInfoTable, "getinfo option",TCL_EXACT,&tableIndex) == TCL_ERROR) { return 1; } resultObj = curlGetInfo(interp,curlHandle,tableIndex); if (resultObj == NULL) { return 1; } *result_p = resultObj; return 0; } tclcurl-ng-8.0.3/generic/curl_mime.c000066400000000000000000000375241522613063100173420ustar00rootroot00000000000000/* * curl_mime.c -- * * mime formatted multipart form data management. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. * */ #include "tclcurl.h" #include "curl_mime.h" #include "curl_setopts.h" enum curlFormIndices { NAME_HTTP_OPT, CONTENTS_HTTP_OPT, FILE_HTTP_OPT, CONTENTTYPE_HTTP_OPT, CONTENTHEADER_HTTP_OPT, FILENAME_HTTP_OPT, BUFFERNAME_HTTP_OPT, BUFFER_HTTP_OPT, FILECONTENT_HTTP_OPT }; const static char *curlFormTable[] = { "name", "contents", "file", "contenttype", "contentheader", "filename", "bufferName", "buffer", "filecontent", (char *)NULL }; /*---------------------------------------------------------------------- * * TclCurl_SetPostData -- * * In case there is going to be a post transfer, this function sets the * data that is going to be posted. * * Parameters: * interp: Tcl interpreter we are using. * curlData: A pointer to the struct with the transfer data. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ int TclCurl_SetPostData(Tcl_Interp *interp,struct curlObjData *curlDataPtr) { Tcl_Obj *errorMsgObjPtr; if (curlDataPtr->postFields != NULL) { if (curlDataPtr->postFieldSize >= 0) { if (curl_easy_setopt(curlDataPtr->curl,CURLOPT_POSTFIELDSIZE_LARGE, curlDataPtr->postFieldSize)) { errorMsgObjPtr = Tcl_NewStringObj("Error setting POST field size",-1); Tcl_SetObjResult(interp,errorMsgObjPtr); return TCL_ERROR; } } if (curl_easy_setopt(curlDataPtr->curl,CURLOPT_COPYPOSTFIELDS, curlDataPtr->postFields)) { errorMsgObjPtr = Tcl_NewStringObj("Error setting the data to post",-1); Tcl_SetObjResult(interp,errorMsgObjPtr); return TCL_ERROR; } } #ifdef CURL_PRE_7_56_DEPR if (curlDataPtr->postListFirst != NULL) { if (curl_easy_setopt(curlDataPtr->curl,CURLOPT_MIMEPOST,curlDataPtr->postListFirst)) { curl_formfree(curlDataPtr->postListFirst); errorMsgObjPtr = Tcl_NewStringObj("Error setting the data to post",-1); Tcl_SetObjResult(interp,errorMsgObjPtr); return TCL_ERROR; } } #else if (curlDataPtr->mime != NULL) { if (curl_easy_setopt(curlDataPtr->curl,CURLOPT_MIMEPOST,curlDataPtr->mime)) { curl_mime_free(curlDataPtr->mime); curlDataPtr->mime = NULL; errorMsgObjPtr = Tcl_NewStringObj("Error setting the data to post",-1); Tcl_SetObjResult(interp,errorMsgObjPtr); return TCL_ERROR; } } #endif return TCL_OK; } /*---------------------------------------------------------------------- * * TclCurl_ResetPostData -- * * After performing a transfer, this function is invoked to erease the * posr data. * * Parameter: * curlData: A pointer to the struct with the transfer data. *---------------------------------------------------------------------- */ #ifdef CURL_PRE_7_56_DEPR void TclCurl_ResetPostData(struct curlObjData *curlDataPtr) { struct formArrayStruct *tmpPtr; Tcl_Free(curlDataPtr->postFields); curlDataPtr->postFields = NULL; curlDataPtr->postFieldSize = -1; curl_easy_setopt(curlDataPtr->curl,CURLOPT_COPYPOSTFIELDS,NULL); curl_easy_setopt(curlDataPtr->curl,CURLOPT_POSTFIELDSIZE_LARGE,(curl_off_t)-1); if (curlDataPtr->postListFirst) { curl_formfree(curlDataPtr->postListFirst); curlDataPtr->postListFirst = NULL; curlDataPtr->postListLast = NULL; curl_easy_setopt(curlDataPtr->curl,CURLOPT_MIMEPOST,NULL); while (curlDataPtr->formArray != NULL) { if (curlDataPtr->formArray->formHeaderList != NULL) { curl_slist_free_all(curlDataPtr->formArray->formHeaderList); curlDataPtr->formArray->formHeaderList = NULL; } curlResetFormArray(curlDataPtr->formArray->formArray); tmpPtr=curlDataPtr->formArray->next; Tcl_Free((char *)curlDataPtr->formArray); curlDataPtr->formArray=tmpPtr; } } } /*---------------------------------------------------------------------- * * TclCurl_ResetFormArray -- * * Cleans the contents of the formArray, it is done after a transfer or * if 'curl_formadd' returns an error. * * Parameter: * formArray: A pointer to the array to clean up. *---------------------------------------------------------------------- */ static void TclCurl_ResetFormArray(struct curl_forms *formArray) { int i; for (i=0;formArray[i].option!=CURLFORM_END;i++) { switch (formArray[i].option) { case CURLFORM_COPYNAME: case CURLFORM_COPYCONTENTS: case CURLFORM_FILE: case CURLFORM_CONTENTTYPE: case CURLFORM_FILENAME: case CURLFORM_FILECONTENT: case CURLFORM_BUFFER: case CURLFORM_BUFFERPTR: Tcl_Free((char *)(formArray[i].value)); break; default: break; } } Tcl_Free((char *)formArray); } #else void TclCurl_ResetPostData(struct curlObjData *curlDataPtr) { Tcl_Free(curlDataPtr->postFields); curlDataPtr->postFields = NULL; curlDataPtr->postFieldSize = -1; curl_easy_setopt(curlDataPtr->curl,CURLOPT_COPYPOSTFIELDS,NULL); curl_easy_setopt(curlDataPtr->curl,CURLOPT_POSTFIELDSIZE_LARGE,(curl_off_t)-1); if (curlDataPtr->mime != NULL) { curl_mime_free(curlDataPtr->mime); curlDataPtr->mime = NULL; } curl_easy_setopt(curlDataPtr->curl,CURLOPT_MIMEPOST,NULL); } #endif /*---------------------------------------------------------------------- * * TclCurl_HandleHttpPost -- * * Performs the heavyweght job of building the HTTP post request data * * Parameter: * formArray: A pointer to the array to clean up. *---------------------------------------------------------------------- */ #ifndef CURL_PRE_7_56_DEPR int TclCurl_HandleHttpPost(TclCurlOptsArgs *coa) { curl_mimepart* part; Tcl_Size post_data_numel; Tcl_Obj** httpPostData; int curlTableIndex; int arg_p = 0; if (Tcl_ListObjGetElements(coa->interp,coa->objv,&post_data_numel,&httpPostData) == TCL_ERROR) { return TCL_ERROR; } if (coa->curlData->mime == NULL) { coa->curlData->mime = curl_mime_init(coa->curlData->curl); if (coa->curlData->mime == NULL) { curlErrorSetOpt(coa->interp,configTable,coa->curlOptsIndex,"Could not initialize MIME data"); return TCL_ERROR; } } part = curl_mime_addpart(coa->curlData->mime); if (part == NULL) { curlErrorSetOpt(coa->interp,configTable,coa->curlOptsIndex,"Could not append MIME part"); return TCL_ERROR; } while (arg_p < post_data_numel) { if (Tcl_GetIndexFromObj(coa->interp,httpPostData[arg_p],curlFormTable, "CURLFORM option",TCL_EXACT,&curlTableIndex) == TCL_ERROR) { /* TODO: add meaningful error information */ return TCL_ERROR; } switch (curlTableIndex) { case NAME_HTTP_OPT: { Tcl_Size data_l; curl_mime_name(part,Tcl_GetStringFromObj(httpPostData[++arg_p],&data_l)); break; } case CONTENTS_HTTP_OPT: { Tcl_Size buffer_l; const char* tmpStr; size_t buffer_size; tmpStr = Tcl_GetStringFromObj(httpPostData[++arg_p],&buffer_l); if (TclCurl_TclSize2SizeT(buffer_l,&buffer_size) == 0) { curlErrorSetOpt(coa->interp,configTable,coa->curlOptsIndex,"Inconsistent buffer size"); return TCL_ERROR; } curl_mime_data(part,tmpStr,buffer_size); break; } case FILE_HTTP_OPT: { Tcl_Size data_l; curl_mime_filedata(part,Tcl_GetStringFromObj(httpPostData[++arg_p],&data_l)); break; } case CONTENTTYPE_HTTP_OPT: { Tcl_Size data_l; curl_mime_type(part,Tcl_GetStringFromObj(httpPostData[++arg_p],&data_l)); break; } case CONTENTHEADER_HTTP_OPT: { struct curl_slist* curl_content_headers_l = NULL; if(SetoptsList(coa->interp,&curl_content_headers_l,httpPostData[++arg_p])) { curlErrorSetOpt(coa->interp,configTable,coa->curlOptsIndex,"Header list invalid"); return TCL_ERROR; } curl_mime_headers(part,curl_content_headers_l,1); break; } case BUFFERNAME_HTTP_OPT: case FILENAME_HTTP_OPT: { Tcl_Size data_l; curl_mime_filename(part,Tcl_GetStringFromObj(httpPostData[++arg_p],&data_l)); break; } case BUFFER_HTTP_OPT: { Tcl_Size tcl_buffer_l; size_t buffer_size; const char* tmpStr; tmpStr = (const char *) Tcl_GetByteArrayFromObj(httpPostData[++arg_p],&tcl_buffer_l); if (TclCurl_TclSize2SizeT(tcl_buffer_l,&buffer_size) == 0) { curlErrorSetOpt(coa->interp,configTable,coa->curlOptsIndex,"Inconsistent buffer size"); return TCL_ERROR; } curl_mime_data(part,tmpStr,buffer_size); break; } case FILECONTENT_HTTP_OPT: { Tcl_Size data_l; curl_mime_filedata(part,Tcl_GetStringFromObj(httpPostData[++arg_p],&data_l)); break; } } arg_p++; } return TCL_OK; } #else int TclCurl_HandleHttpPost(TclCurlOptsArgs *args) { Tcl_Obj* resultObjPtr; Tcl_Size i,j; Tcl_Size post_data_numel; Tcl_Obj** httpPostData; int curlTableIndex; int formaddError,formArrayIndex; struct formArrayStruct* newFormArray; struct curl_forms* formArray; Tcl_Size curlformBufferSize; size_t contentslen; unsigned char* tmpUStr; char* tmpStr = NULL; if (Tcl_ListObjGetElements(args->interp,args->objv,&post_data_numel,&httpPostData) == TCL_ERROR) { return TCL_ERROR; } formaddError = 0; newFormArray = (struct formArrayStruct *)Tcl_Alloc(sizeof(struct formArrayStruct)); formArray = (struct curl_forms *)Tcl_Alloc(post_data_numel*(sizeof(struct curl_forms))); formArrayIndex = 0; newFormArray->next=args->curlData->formArray; newFormArray->formArray=formArray; newFormArray->formHeaderList=NULL; for (i=0,j=0;iinterp,httpPostData[i],curlFormTable, "CURLFORM option",TCL_EXACT,&curlTableIndex) == TCL_ERROR) { formaddError=1; break; } switch (curlTableIndex) { case NAME_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_COPYNAME; formArray[formArrayIndex].value = curlstrdup(Tcl_GetString(httpPostData[i+1])); break; case CONTENTS_HTTP_OPT: { tmpStr=Tcl_GetStringFromObj(httpPostData[i+1],&curlformBufferSize); formArray[formArrayIndex].option = CURLFORM_COPYCONTENTS; formArray[formArrayIndex].value = Tcl_Alloc((curlformBufferSize > 0) ? curlformBufferSize : 1); if (curlformBufferSize > 0) { size_t buffer_size; if (TclCurl_TclSize2SizeT(curlformBufferSize,&buffer_size) == 0) { curlErrorSetOpt(args->interp,configTable,args->tableIndex,"Inconsistent buffer size"); return TCL_ERROR; } memcpy((char *)formArray[formArrayIndex].value,tmpStr,buffer_size); } else { memset((char *)formArray[formArrayIndex].value,0,1); } formArrayIndex++; formArray[formArrayIndex].option = CURLFORM_CONTENTSLENGTH; contentslen=curlformBufferSize++; formArray[formArrayIndex].value = (char *)contentslen; break; } case FILE_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_FILE; formArray[formArrayIndex].value = curlstrdup(Tcl_GetString(httpPostData[i+1])); break; case CONTENTTYPE_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_CONTENTTYPE; formArray[formArrayIndex].value = curlstrdup(Tcl_GetString(httpPostData[i+1])); break; case CONTENTHEADER_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_CONTENTHEADER; if(SetoptsList(args->interp,&newFormArray->formHeaderList,httpPostData[i+1])) { curlErrorSetOpt(args->interp,configTable,args->tableIndex,"Header list invalid"); formaddError=1; return TCL_ERROR; } formArray[formArrayIndex].value = (char *)newFormArray->formHeaderList; break; case FILENAME_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_FILENAME; formArray[formArrayIndex].value = curlstrdup(Tcl_GetString(httpPostData[i+1])); break; case BUFFERNAME_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_BUFFER; formArray[formArrayIndex].value = curlstrdup(Tcl_GetString(httpPostData[i+1])); break; case BUFFER_HTTP_OPT: tmpUStr=Tcl_GetByteArrayFromObj(httpPostData[i+1],&curlformBufferSize); formArray[formArrayIndex].option = CURLFORM_BUFFERPTR; formArray[formArrayIndex].value = (char *) memcpy(Tcl_Alloc(curlformBufferSize), tmpUStr, curlformBufferSize); formArrayIndex++; formArray[formArrayIndex].option = CURLFORM_BUFFERLENGTH; contentslen=curlformBufferSize; formArray[formArrayIndex].value = (char *)contentslen; break; case FILECONTENT_HTTP_OPT: formArray[formArrayIndex].option = CURLFORM_FILECONTENT; formArray[formArrayIndex].value = curlstrdup(Tcl_GetString(httpPostData[i+1])); break; } formArrayIndex++; } formArray[formArrayIndex].option=CURLFORM_END; args->curlData->formArray=newFormArray; if (formaddError == 0) { formaddError=curl_formadd(&(args->curlData->postListFirst), &(args->curlData->postListLast), CURLFORM_ARRAY, formArray, CURLFORM_END); } if (formaddError != CURL_FORMADD_OK) { TclCurl_ResetFormArray(formArray); args->curlData->formArray=newFormArray->next; Tcl_Free((char *)newFormArray); resultObjPtr=Tcl_ObjPrintf("%d",formaddError); Tcl_SetObjResult(args->interp,resultObjPtr); Tcl_Free(tmpStr); return TCL_ERROR; } return TCL_OK; } #endif tclcurl-ng-8.0.3/generic/curl_mime.h000066400000000000000000000016761522613063100173460ustar00rootroot00000000000000/* * curl_mime.h -- * * mime formatted multipart form data management. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. * */ #ifndef __curl_mime_h__ #define __curl_mime_h__ typedef struct TclCurlOptionDef TclCurlOptionDef; typedef struct TclCurlOptsArgs TclCurlOptsArgs; int TclCurl_SetPostData(Tcl_Interp *interp,struct curlObjData *curlDataPtr); void TclCurl_ResetPostData(struct curlObjData *curlDataPtr); /* void TclCurl_ResetFormArray(struct curl_forms *formArray); */ /* Internal helper used by the setopts handler table. */ int TclCurl_HandleHttpPost(TclCurlOptsArgs *args); #endif tclcurl-ng-8.0.3/generic/curl_setopts.c000066400000000000000000001451321522613063100201070ustar00rootroot00000000000000/* * curl_setopts.c -- * * Central CLI option management. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. * * Portions of this file were drafted or revised with AI assistance * under the direction and review of Massimo Manghi. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclcurl.h" #include "curl_setopts.h" #ifndef TCL_UNUSED #define TCL_UNUSED(x) (void)(x) #endif /* * The optionTable array is built straight from the X-macro * table data defined in curl_setopts.h */ const static char *optionTable[] = { #define TCLCURLOPT_OPTION_ENTRY(option, optname, configname, handler, curlopt, message) optname, TCLCURL_OPTION_LIST(TCLCURLOPT_OPTION_ENTRY) #undef TCLCURLOPT_OPTION_ENTRY (char *)NULL }; const static char *gssapidelegation[] = { "flag", "policyflag", (char *) NULL }; const static char *tlsauth[] = { "none", "srp", (char *)NULL }; const static char *postredir[] = { "301", "302", "all", (char *)NULL }; const static char *sshauthtypes[] = { "publickey", "password", "host", "keyboard", "any", (char *)NULL }; const static char *ftpfilemethod[] = { "default", "multicwd", "nocwd", "singlecwd", (char *)NULL }; const static char *sslversion[] = { "default", "tlsv1", "sslv2", "sslv3", "tlsv1_0", "tlsv1_1", "tlsv1_2", "tlsv1_3", "maxdefault", "maxtlsv1_0", "maxtlsv1_1", "maxtlsv1_2", "maxtlsv1_3", (char *)NULL }; const static char *ftpsslauth[] = { "default", "ssl", "tls", (char *)NULL }; const static char *ipresolve[] = { "whatever", "v4", "v6", (char *)NULL }; const static char *httpAuthMethods[] = { "basic", "digest", "digestie", "gssnegotiate", "ntlm", "any", "anysafe", "ntlmwb", (char *)NULL }; const static char *proxyTypeTable[] = { "http", "http1.0", "socks4", "socks4a", "socks5", "socks5h", (char *)NULL }; const static char *encodingTable[] = { "identity", "deflated", "all", (char *)NULL }; const static char *netrcTable[] = { "optional", "ignored", "required", (char *)NULL }; CONST static char *httpVersionTable[] = { "none", /* CURL_HTTP_VERSION_NONE */ "1.0", /* CURL_HTTP_VERSION_1_0 */ "1.1", /* CURL_HTTP_VERSION_1_1 */ "2.0", /* CURL_HTTP_VERSION_2_0 */ "2TLS", /* CURL_HTTP_VERSION_2TLS */ "2_PRIOR_KNOWLEDGE", /* CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE */ (char *)NULL }; const static char *timeCond[] = { "ifmodsince", "ifunmodsince", (char *)NULL }; /* *---------------------------------------------------------------------- * * curlSetOptsTransfer -- * * This procedure is invoked when the user invokes the 'setopt' * command, it is used to set the 'curl' options * * Parameter: * interp: Pointer to the interpreter we are using. * curlHandle: the curl handle for which the option is set. * objc and objv: The usual in Tcl. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ int curlSetOptsTransfer(Tcl_Interp *interp,struct curlObjData *curlData,int objc,Tcl_Obj *const objv[]) { int optionTableIndex; if (Tcl_GetIndexFromObj(interp,objv[2],optionTable,"option",TCL_EXACT,&optionTableIndex)==TCL_ERROR) { return TCL_ERROR; } return TclCurl_SetOpts(interp,curlData,objv[3],optionTableIndex); } /* *---------------------------------------------------------------------- * * curlConfigTransfer -- * * This procedure is invoked by the user command 'configure', it reads * the options passed by the user to configure a transfer, and passes * then, one by one to 'curlSetOpts'. * * Parameter: * interp: Pointer to the interpreter we are using. * curlHandle: the curl handle for which the option is set. * objc and objv: The usual in Tcl. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ int curlConfigTransfer(Tcl_Interp *interp, struct curlObjData *curlData, int objc, Tcl_Obj *const objv[]) { int configOptionIndex; int i,j; Tcl_Obj *resultPtr; for(i=2,j=3;icurl; shandleName=Tcl_GetString(tclObj); if (Tcl_GetCommandInfo(interp,shandleName,infoPtr) == 0) { Tcl_Free((char *)infoPtr); return 1; } shandleDataPtr=(struct shcurlObjData *)(infoPtr->objClientData); if (curl_easy_setopt(curlHandle,opt,shandleDataPtr->shandle)) { Tcl_Free((char *)infoPtr); curlErrorSetOpt(interp,configTable,configOptionIndex,shandleName); return 1; } Tcl_Free((char *)infoPtr); if (curlData->shareToken != shandleDataPtr->token) { curlDetachShareHandle(curlData); curlData->shareToken = shandleDataPtr->token; curlData->nextSharedHandle = shandleDataPtr->users; shandleDataPtr->users = curlData; } return 0; } /* *---------------------------------------------------------------------- * * TclCurl option dispatch -- * * These procedures take care of setting the transfer options. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ #define TCLCURL_OPT_HANDLER(handler) handler(TclCurlOptsArgs *args); static int TCLCURL_OPT_HANDLER(TclCurl_HandleSetoptChar) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSetoptInt) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSetoptLong) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSetoptCurlOffT) static int TCLCURL_OPT_HANDLER(TclCurl_HandlePostFields) static int TCLCURL_OPT_HANDLER(TclCurl_HandlePostFieldSize) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSetoptSHandle) static int TCLCURL_OPT_HANDLER(TclCurl_HandleOutFile) static int TCLCURL_OPT_HANDLER(TclCurl_HandleReadData) static int TCLCURL_OPT_HANDLER(TclCurl_HandleNetrc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleTransferText) static int TCLCURL_OPT_HANDLER(TclCurl_HandleMute) static int TCLCURL_OPT_HANDLER(TclCurl_HandleErrorBuffer) static int TCLCURL_OPT_HANDLER(TclCurl_HandleHttpHeaderList) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSslVersion) static int TCLCURL_OPT_HANDLER(TclCurl_HandleQuoteList) static int TCLCURL_OPT_HANDLER(TclCurl_HandlePostQuoteList) static int TCLCURL_OPT_HANDLER(TclCurl_HandleWriteHeader) static int TCLCURL_OPT_HANDLER(TclCurl_HandleTimeCondition) static int TCLCURL_OPT_HANDLER(TclCurl_HandleStderrFile) static int TCLCURL_OPT_HANDLER(TclCurl_HandleHeaderVar) static int TCLCURL_OPT_HANDLER(TclCurl_HandleBodyVar) static int TCLCURL_OPT_HANDLER(TclCurl_HandleProgressProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleCancelTransVarName) static int TCLCURL_OPT_HANDLER(TclCurl_HandleWriteProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleReadProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleHttpVersion) static int TCLCURL_OPT_HANDLER(TclCurl_HandlePrequoteList) static int TCLCURL_OPT_HANDLER(TclCurl_HandleDebugProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleEncoding) static int TCLCURL_OPT_HANDLER(TclCurl_HandleProxyType) static int TCLCURL_OPT_HANDLER(TclCurl_HandleHttp200Aliases) static int TCLCURL_OPT_HANDLER(TclCurl_HandleCommand) static int TCLCURL_OPT_HANDLER(TclCurl_HandleHttpAuth) static int TCLCURL_OPT_HANDLER(TclCurl_HandleProxyAuth) static int TCLCURL_OPT_HANDLER(TclCurl_HandleIpResolve) static int TCLCURL_OPT_HANDLER(TclCurl_HandleFtpSsl) static int TCLCURL_OPT_HANDLER(TclCurl_HandleObsolete) static int TCLCURL_OPT_HANDLER(TclCurl_HandleFtpSslAuth) static int TCLCURL_OPT_HANDLER(TclCurl_HandleFtpFileMethod) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSshAuthTypes) static int TCLCURL_OPT_HANDLER(TclCurl_HandlePostRedir) static int TCLCURL_OPT_HANDLER(TclCurl_HandleProtocolMask) static int TCLCURL_OPT_HANDLER(TclCurl_HandleFtpSslCcc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleSshKeyFunction) static int TCLCURL_OPT_HANDLER(TclCurl_HandleMailRcpt) static int TCLCURL_OPT_HANDLER(TclCurl_HandleChunkBgnProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleChunkBgnVar) static int TCLCURL_OPT_HANDLER(TclCurl_HandleChunkEndProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleFnmatchProc) static int TCLCURL_OPT_HANDLER(TclCurl_HandleResolveList) static int TCLCURL_OPT_HANDLER(TclCurl_HandleTlsAuthType) static int TCLCURL_OPT_HANDLER(TclCurl_HandleGssApiDelegation) static int TCLCURL_OPT_HANDLER(TclCurl_HandleTelnetOptions) static int TCLCURL_OPT_HANDLER(TclCurl_HandleCainfoBlob) int TCLCURL_OPT_HANDLER(TclCurl_HandleHttpPost) #undef TCLCURL_OPT_HANDLER static const TclCurlOptionDef curlOptionDefs[] = { #define TCLCURLOPT_DEF_ENTRY(option, optname, configname, handler, curlopt, message) \ [option] = { optname, configname, handler, curlopt, message }, TCLCURL_OPTION_LIST(TCLCURLOPT_DEF_ENTRY) #undef TCLCURLOPT_DEF_ENTRY }; /* *---------------------------------------------------------------------- * * TclCurl_SetOpts -- * * This procedure takes care of setting the transfer options. * * Parameter: * interp: Pointer to the interpreter we are using. * curlHandle: the curl handle for which the option is set. * objv: A pointer to the object where the data to set is stored. * curlOptsIndex: The index of the option in the TclCurl option table. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ int TclCurl_SetOpts(Tcl_Interp *interp, struct curlObjData *curlData, Tcl_Obj *const objv, int curlOptsIndex) { if (curlOptsIndex < 0 || curlOptsIndex >= TCLCURLOPT_COUNT) { return TCL_ERROR; } TclCurlOptsArgs args = { .interp = interp, .curlData = curlData, .objv = objv, .curlOptsIndex = curlOptsIndex, .def = &curlOptionDefs[curlOptsIndex] }; return curlOptionDefs[curlOptsIndex].handler(&args); } static int TclCurl_HandleSetoptChar(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptChar(args->interp, curlHandle, args->def->curlOpt, args->curlOptsIndex, args->objv)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleSetoptInt(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptInt(args->interp, curlHandle, args->def->curlOpt, args->curlOptsIndex, args->objv)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleSetoptLong(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptLong(args->interp,curlHandle,args->def->curlOpt,args->curlOptsIndex,args->objv)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleSetoptCurlOffT(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptCurlOffT(args->interp,curlHandle,args->def->curlOpt,args->curlOptsIndex,args->objv)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandlePostFields(TclCurlOptsArgs *args) { Tcl_Free(args->curlData->postFields); args->curlData->postFields = curlstrdup(Tcl_GetString(args->objv)); return TCL_OK; } static int TclCurl_HandlePostFieldSize(TclCurlOptsArgs *args) { Tcl_WideInt wideNumber; if (Tcl_GetWideIntFromObj(args->interp,args->objv,&wideNumber)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,Tcl_GetString(args->objv)); return TCL_ERROR; } args->curlData->postFieldSize = (curl_off_t) wideNumber; return TCL_OK; } static int TclCurl_HandleSetoptSHandle(TclCurlOptsArgs *args) { if (SetoptSHandle(args->interp, args->curlData, args->def->curlOpt, args->curlOptsIndex, args->objv)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleOutFile(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Free(args->curlData->outFile); args->curlData->outFile=curlstrdup(Tcl_GetString(args->objv)); if (args->curlData->outFlag) { if (args->curlData->outHandle!=NULL) { fclose(args->curlData->outHandle); args->curlData->outHandle=NULL; } } if ((strcmp(args->curlData->outFile,""))&&(strcmp(args->curlData->outFile,"stdout"))) { args->curlData->outFlag=1; } else { args->curlData->outFlag=0; curl_easy_setopt(curlHandle,CURLOPT_WRITEDATA,stdout); args->curlData->outFile=NULL; } curl_easy_setopt(curlHandle,CURLOPT_WRITEFUNCTION,NULL); return TCL_OK; } static int TclCurl_HandleReadData(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Free(args->curlData->inFile); args->curlData->inFile=curlstrdup(Tcl_GetString(args->objv)); if (args->curlData->inFlag) { if (args->curlData->inHandle!=NULL) { fclose(args->curlData->inHandle); args->curlData->inHandle=NULL; } } if ((strcmp(args->curlData->inFile,""))&&(strcmp(args->curlData->inFile,"stdin"))) { args->curlData->inFlag=1; } else { curl_easy_setopt(curlHandle,CURLOPT_READDATA,stdin); args->curlData->inFlag=0; args->curlData->inFile=NULL; } curl_easy_setopt(curlHandle,CURLOPT_READFUNCTION,NULL); return TCL_OK; } static int TclCurl_HandleNetrc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; int netrcIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, netrcTable, "netrc option",TCL_EXACT,&netrcIndex)==TCL_ERROR) { return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_NETRC,netrcIndex)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,netrcTable[netrcIndex]); return 1; } return TCL_OK; } static int TclCurl_HandleTransferText(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptInt(args->interp, curlHandle, args->def->curlOpt, args->curlOptsIndex, args->objv)) { return TCL_ERROR; } Tcl_GetIntFromObj(args->interp,args->objv,&args->curlData->transferText); return TCL_OK; } static int TclCurl_HandleMute(TclCurlOptsArgs *args) { TCL_UNUSED(args); return TCL_OK; } static int TclCurl_HandleErrorBuffer(TclCurlOptsArgs *args) { if (TclCurl_ErrorBuffer(args->interp,args->curlData,args->objv) == TCL_ERROR) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleHttpHeaderList(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if(SetoptsList(args->interp,&args->curlData->headerList,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"Header list invalid"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_HTTPHEADER,args->curlData->headerList)) { curl_slist_free_all(args->curlData->headerList); args->curlData->headerList=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleSslVersion(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int sslVersionIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, sslversion, "sslversion ",TCL_EXACT,&sslVersionIndex)==TCL_ERROR) { return TCL_ERROR; } switch(sslVersionIndex) { case 0: longNumber=CURL_SSLVERSION_DEFAULT; break; case 1: longNumber=CURL_SSLVERSION_TLSv1; break; case 2: longNumber=CURL_SSLVERSION_SSLv2; break; case 3: longNumber=CURL_SSLVERSION_SSLv3; break; case 4: longNumber=CURL_SSLVERSION_TLSv1_0; break; case 5: longNumber=CURL_SSLVERSION_TLSv1_1; break; case 6: longNumber=CURL_SSLVERSION_TLSv1_2; break; case 7: longNumber=CURL_SSLVERSION_TLSv1_3; break; case 8: longNumber=CURL_SSLVERSION_MAX_DEFAULT; break; case 9: longNumber=CURL_SSLVERSION_MAX_TLSv1_0; break; case 10: longNumber=CURL_SSLVERSION_MAX_TLSv1_1; break; case 11: longNumber=CURL_SSLVERSION_MAX_TLSv1_2; break; case 12: longNumber=CURL_SSLVERSION_MAX_TLSv1_3; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_SSLVERSION, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleQuoteList(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if(SetoptsList(args->interp,&args->curlData->quote,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"quote list invalid"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_QUOTE,args->curlData->quote)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"quote list invalid"); curl_slist_free_all(args->curlData->quote); args->curlData->quote=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandlePostQuoteList(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if(SetoptsList(args->interp,&args->curlData->postquote,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"postquote invalid"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_POSTQUOTE,args->curlData->postquote)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"postquote invalid"); curl_slist_free_all(args->curlData->postquote); args->curlData->postquote=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleWriteHeader(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Free(args->curlData->headerFile); args->curlData->headerFile=curlstrdup(Tcl_GetString(args->objv)); if (args->curlData->headerFlag) { if (args->curlData->headerHandle!=NULL) { fclose(args->curlData->headerHandle); args->curlData->headerHandle=NULL; } curl_easy_setopt(curlHandle,CURLOPT_HEADERDATA,NULL); } if ((strcmp(args->curlData->headerFile,""))&&(strcmp(args->curlData->headerFile,"stdout")) &&(strcmp(args->curlData->headerFile,"stderr"))) { args->curlData->headerFlag=1; } else { if ((strcmp(args->curlData->headerFile,"stdout"))) { curl_easy_setopt(curlHandle,CURLOPT_HEADERDATA,stderr); } else { curl_easy_setopt(curlHandle,CURLOPT_HEADERDATA,stdout); } args->curlData->headerFlag=0; args->curlData->headerFile=NULL; } return TCL_OK; } static int TclCurl_HandleTimeCondition(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; long longNumber=0; int timeConditionIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, timeCond, "time cond option",TCL_EXACT, &timeConditionIndex)==TCL_ERROR) { return TCL_ERROR; } if (timeConditionIndex==0) { longNumber=CURL_TIMECOND_IFMODSINCE; } else { longNumber=CURL_TIMECOND_IFUNMODSINCE; } if (curl_easy_setopt(curlHandle,CURLOPT_TIMECONDITION,longNumber)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleStderrFile(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Free(args->curlData->stderrFile); args->curlData->stderrFile=curlstrdup(Tcl_GetString(args->objv)); if ((strcmp(args->curlData->stderrFile,""))&&(strcmp(args->curlData->stderrFile,"stdout")) &&(strcmp(args->curlData->stderrFile,"stderr"))) { args->curlData->stderrFlag=1; } else { args->curlData->stderrFlag=0; if (strcmp(args->curlData->stderrFile,"stdout")) { curl_easy_setopt(curlHandle,CURLOPT_STDERR,stderr); } else { curl_easy_setopt(curlHandle,CURLOPT_STDERR,stdout); } args->curlData->stderrFile=NULL; } return TCL_OK; } static int TclCurl_HandleHeaderVar(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (args->curlData->headerFlag) { if (args->curlData->headerHandle!=NULL) { fclose(args->curlData->headerHandle); args->curlData->headerHandle=NULL; } curl_easy_setopt(curlHandle,CURLOPT_HEADERDATA,NULL); args->curlData->headerFlag=0; } if (curl_easy_setopt(curlHandle,CURLOPT_HEADERFUNCTION, curlHeaderReader)) { return TCL_ERROR; } Tcl_Free(args->curlData->headerVar); args->curlData->headerVar=curlstrdup(Tcl_GetString(args->objv)); if (curl_easy_setopt(curlHandle,CURLOPT_HEADERDATA, (FILE *)args->curlData)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleBodyVar(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Free(args->curlData->bodyVarName); args->curlData->bodyVarName=curlstrdup(Tcl_GetString(args->objv)); if (args->curlData->outFlag) { if (args->curlData->outHandle!=NULL) { fclose(args->curlData->outHandle); args->curlData->outHandle=NULL; } curl_easy_setopt(curlHandle,CURLOPT_WRITEDATA,NULL); } args->curlData->outFlag=0; if (curl_easy_setopt(curlHandle,CURLOPT_WRITEFUNCTION, curlBodyReader)) { return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_WRITEDATA,args->curlData)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleProgressProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Free(args->curlData->progressProc); args->curlData->progressProc=curlstrdup(Tcl_GetString(args->objv)); if (strcmp(args->curlData->progressProc,"")) { if (curl_easy_setopt(curlHandle,CURLOPT_XFERINFOFUNCTION, curlProgressCallback)) { return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_XFERINFODATA, args->curlData)) { return TCL_ERROR; } } else { if (curl_easy_setopt(curlHandle,CURLOPT_XFERINFOFUNCTION,NULL)) { return TCL_ERROR; } } return TCL_OK; } static int TclCurl_HandleCancelTransVarName(TclCurlOptsArgs *args) { if (args->curlData->cancelTransVarName) { Tcl_UnlinkVar(args->interp,args->curlData->cancelTransVarName); Tcl_Free(args->curlData->cancelTransVarName); } args->curlData->cancelTransVarName=curlstrdup(Tcl_GetString(args->objv)); Tcl_LinkVar(args->interp,args->curlData->cancelTransVarName, (char *)&(args->curlData->cancelTrans),TCL_LINK_INT); return TCL_OK; } static int TclCurl_HandleWriteProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; args->curlData->writeProc=curlstrdup(Tcl_GetString(args->objv)); if (args->curlData->outFlag) { if (args->curlData->outHandle!=NULL) { fclose(args->curlData->outHandle); args->curlData->outHandle=NULL; } curl_easy_setopt(curlHandle,CURLOPT_WRITEDATA,NULL); } args->curlData->outFlag=0; if (curl_easy_setopt(curlHandle,CURLOPT_WRITEFUNCTION, curlWriteProcInvoke)) { curl_easy_setopt(curlHandle,CURLOPT_WRITEFUNCTION,NULL); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_WRITEDATA,args->curlData)) { curl_easy_setopt(curlHandle,CURLOPT_WRITEFUNCTION,NULL); return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleReadProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; args->curlData->readProc=curlstrdup(Tcl_GetString(args->objv)); if (args->curlData->inFlag) { if (args->curlData->inHandle!=NULL) { fclose(args->curlData->inHandle); args->curlData->inHandle=NULL; } curl_easy_setopt(curlHandle,CURLOPT_READDATA,NULL); } args->curlData->inFlag=0; if (strcmp(args->curlData->readProc,"")) { if (curl_easy_setopt(curlHandle,CURLOPT_READFUNCTION, curlReadProcInvoke)) { return TCL_ERROR; } } else { curl_easy_setopt(curlHandle,CURLOPT_READFUNCTION,NULL); return TCL_OK; } if (curl_easy_setopt(curlHandle,CURLOPT_READDATA,args->curlData)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleHttpVersion(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; char* tmpStr = NULL; int httpVersionIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, httpVersionTable, "http version",TCL_EXACT,&httpVersionIndex)==TCL_ERROR) { return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_HTTP_VERSION, httpVersionIndex)) { tmpStr=curlstrdup(Tcl_GetString(args->objv)); curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,tmpStr); Tcl_Free(tmpStr); return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandlePrequoteList(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if(SetoptsList(args->interp,&args->curlData->prequote,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"prequote invalid"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_PREQUOTE,args->curlData->prequote)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"prequote invalid"); curl_slist_free_all(args->curlData->prequote); args->curlData->prequote=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleDebugProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; args->curlData->debugProc=curlstrdup(Tcl_GetString(args->objv)); if (curl_easy_setopt(curlHandle,CURLOPT_DEBUGFUNCTION, curlDebugProcInvoke)) { return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_DEBUGDATA,args->curlData)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleEncoding(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; int encodingTableIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, encodingTable, "encoding",TCL_EXACT,&encodingTableIndex)==TCL_ERROR) { return TCL_ERROR; } if (encodingTableIndex==2) { if (curl_easy_setopt(curlHandle,CURLOPT_ACCEPT_ENCODING,"")) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"all"); return 1; } } else { if (SetoptChar(args->interp,curlHandle,CURLOPT_ACCEPT_ENCODING,args->curlOptsIndex,args->objv)) { return TCL_ERROR; } } return TCL_OK; } static int TclCurl_HandleProxyType(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; int proxyTypeIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, proxyTypeTable, "proxy type",TCL_EXACT,&proxyTypeIndex)==TCL_ERROR) { return TCL_ERROR; } switch(proxyTypeIndex) { case 0: curl_easy_setopt(curlHandle,CURLOPT_PROXYTYPE, CURLPROXY_HTTP); break; case 1: curl_easy_setopt(curlHandle,CURLOPT_PROXYTYPE, CURLPROXY_HTTP_1_0); break; case 2: curl_easy_setopt(curlHandle,CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); break; case 3: curl_easy_setopt(curlHandle,CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A); break; case 4: curl_easy_setopt(curlHandle,CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); break; case 5: curl_easy_setopt(curlHandle,CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); break; } return TCL_OK; } static int TclCurl_HandleHttp200Aliases(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if(SetoptsList(args->interp,&args->curlData->http200aliases,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"http200aliases invalid"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_HTTP200ALIASES,args->curlData->http200aliases)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"http200aliases invalid"); curl_slist_free_all(args->curlData->http200aliases); args->curlData->http200aliases=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleCommand(TclCurlOptsArgs *args) { Tcl_Free(args->curlData->command); args->curlData->command=curlstrdup(Tcl_GetString(args->objv)); return TCL_OK; } static int TclCurl_HandleHttpAuth(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int httpAuthMethodIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, httpAuthMethods, "authentication method",TCL_EXACT,&httpAuthMethodIndex)==TCL_ERROR) { return TCL_ERROR; } args->curlData->anyAuthFlag=0; switch(httpAuthMethodIndex) { case 0: longNumber=CURLAUTH_BASIC; break; case 1: longNumber=CURLAUTH_DIGEST; break; case 2: longNumber=CURLAUTH_DIGEST_IE; break; case 3: longNumber=CURLAUTH_GSSNEGOTIATE; break; case 4: longNumber=CURLAUTH_NTLM; break; case 5: longNumber=CURLAUTH_ANY; args->curlData->anyAuthFlag=1; break; case 6: longNumber=CURLAUTH_ANYSAFE; break; case 7: longNumber=CURLAUTH_NTLM_WB; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_HTTPAUTH ,args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleProxyAuth(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int proxyAuthMethodIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, httpAuthMethods, "authentication method",TCL_EXACT,&proxyAuthMethodIndex)==TCL_ERROR) { return TCL_ERROR; } switch(proxyAuthMethodIndex) { case 0: longNumber=CURLAUTH_BASIC; break; case 1: longNumber=CURLAUTH_DIGEST; break; case 2: longNumber=CURLAUTH_GSSNEGOTIATE; break; case 3: longNumber=CURLAUTH_NTLM; break; case 5: longNumber=CURLAUTH_ANYSAFE; break; case 4: default: longNumber=CURLAUTH_ANY; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_PROXYAUTH ,args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleIpResolve(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int ipResolveIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, ipresolve, "ip version",TCL_EXACT,&ipResolveIndex)==TCL_ERROR) { return TCL_ERROR; } switch(ipResolveIndex) { case 0: longNumber=CURL_IPRESOLVE_WHATEVER; break; case 1: longNumber=CURL_IPRESOLVE_V4; break; case 2: longNumber=CURL_IPRESOLVE_V6; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_IPRESOLVE, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleFtpSsl(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber = TclCurl_FTPSSLMethod(args->interp,args->objv); if (longNumber == -1) { return TCL_ERROR; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_USE_SSL, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleObsolete(TclCurlOptsArgs *args) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex, args->def->errorMessage ? args->def->errorMessage : "option is obsolete"); return TCL_ERROR; } static int TclCurl_HandleFtpSslAuth(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int ftpSslAuthIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, ftpsslauth, "ftpsslauth method ",TCL_EXACT,&ftpSslAuthIndex) == TCL_ERROR) { return TCL_ERROR; } switch(ftpSslAuthIndex) { case 0: longNumber=CURLFTPAUTH_DEFAULT; break; case 1: longNumber=CURLFTPAUTH_SSL; break; case 2: longNumber=CURLFTPAUTH_TLS; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_FTPSSLAUTH, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleFtpFileMethod(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int ftpFileMethodIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, ftpfilemethod, "ftp file method ",TCL_EXACT,&ftpFileMethodIndex)==TCL_ERROR) { return TCL_ERROR; } switch(ftpFileMethodIndex) { case 0: case 1: longNumber = 1; break; case 2: longNumber = 2; break; case 3: longNumber = 3; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_FTP_FILEMETHOD, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleSshAuthTypes(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int sshAuthTypeIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, sshauthtypes, "ssh auth type ",TCL_EXACT,&sshAuthTypeIndex)==TCL_ERROR) { return TCL_ERROR; } switch(sshAuthTypeIndex) { case 0: longNumber = CURLSSH_AUTH_PUBLICKEY; break; case 1: longNumber = CURLSSH_AUTH_PASSWORD; break; case 2: longNumber = CURLSSH_AUTH_HOST; break; case 3: longNumber = CURLSSH_AUTH_KEYBOARD; break; case 4: longNumber = CURLSSH_AUTH_ANY; break; case 5: longNumber = CURLSSH_AUTH_NONE; break; case 6: longNumber = CURLSSH_AUTH_AGENT; break; case 7: longNumber = CURLSSH_AUTH_DEFAULT; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_SSH_AUTH_TYPES, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandlePostRedir(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int postRedirIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, postredir, "Postredir option ",TCL_EXACT,&postRedirIndex)==TCL_ERROR) { return TCL_ERROR; } switch(postRedirIndex) { case 0: longNumber=CURL_REDIR_POST_301; break; case 1: longNumber=CURL_REDIR_POST_302; break; case 2: longNumber=CURL_REDIR_POST_303; break; case 3: longNumber=CURL_REDIR_POST_ALL; break; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_POSTREDIR,args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleProtocolMask(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj **protocols; Tcl_Size protocols_c; Tcl_Obj *tmpObjPtr; if (Tcl_ListObjGetElements(args->interp,args->objv,&protocols_c,&protocols) == TCL_ERROR) { return TCL_ERROR; } tmpObjPtr = TclCurl_JoinList(protocols,protocols_c,","); Tcl_IncrRefCount(tmpObjPtr); curl_easy_setopt(curlHandle,CURLOPT_PROTOCOLS_STR,Tcl_GetString(tmpObjPtr)); Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleFtpSslCcc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber = TclCurl_FTPClearCommandChannelOpt(args->interp,args->objv); if (longNumber < 0) { return TCL_ERROR; } tmpObjPtr = Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_FTP_SSL_CCC,args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleSshKeyFunction(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (curl_easy_setopt(curlHandle,CURLOPT_SSH_KEYFUNCTION,curlsshkeycallback)) { return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_SSH_KEYDATA,args->curlData)) { return TCL_ERROR; } args->curlData->sshkeycallProc=curlstrdup(Tcl_GetString(args->objv)); return TCL_OK; } static int TclCurl_HandleMailRcpt(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptsList(args->interp,&args->curlData->mailrcpt,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"mailrcpt invalid"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_MAIL_RCPT,args->curlData->mailrcpt)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"mailrcpt invalid"); curl_slist_free_all(args->curlData->mailrcpt); args->curlData->mailrcpt=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleChunkBgnProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; args->curlData->chunkBgnProc=curlstrdup(Tcl_GetString(args->objv)); if (strcmp(args->curlData->chunkBgnProc,"")) { if (curl_easy_setopt(curlHandle,CURLOPT_CHUNK_BGN_FUNCTION, curlChunkBgnProcInvoke)) { return TCL_ERROR; } } else { curl_easy_setopt(curlHandle,CURLOPT_CHUNK_BGN_FUNCTION,NULL); return TCL_OK; } if (curl_easy_setopt(curlHandle,CURLOPT_CHUNK_DATA,args->curlData)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleChunkBgnVar(TclCurlOptsArgs *args) { args->curlData->chunkBgnVar=curlstrdup(Tcl_GetString(args->objv)); if (!strcmp(args->curlData->chunkBgnVar,"")) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"invalid var name"); return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleChunkEndProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; args->curlData->chunkEndProc=curlstrdup(Tcl_GetString(args->objv)); if (strcmp(args->curlData->chunkEndProc,"")) { if (curl_easy_setopt(curlHandle,CURLOPT_CHUNK_END_FUNCTION, curlChunkEndProcInvoke)) { return TCL_ERROR; } } else { curl_easy_setopt(curlHandle,CURLOPT_CHUNK_END_FUNCTION,NULL); return TCL_OK; } return TCL_OK; } static int TclCurl_HandleFnmatchProc(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; args->curlData->fnmatchProc=curlstrdup(Tcl_GetString(args->objv)); if (strcmp(args->curlData->fnmatchProc,"")) { if (curl_easy_setopt(curlHandle,CURLOPT_FNMATCH_FUNCTION, curlfnmatchProcInvoke)) { return TCL_ERROR; } } else { curl_easy_setopt(curlHandle,CURLOPT_FNMATCH_FUNCTION,NULL); return TCL_OK; } if (curl_easy_setopt(curlHandle,CURLOPT_FNMATCH_DATA,args->curlData)) { return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleResolveList(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptsList(args->interp,&args->curlData->resolve,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"invalid list"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_RESOLVE,args->curlData->resolve)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"resolve list invalid"); curl_slist_free_all(args->curlData->resolve); args->curlData->resolve=NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleTlsAuthType(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int tlsAuthTypeIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, tlsauth, "TSL auth option ",TCL_EXACT,&tlsAuthTypeIndex)==TCL_ERROR) { return TCL_ERROR; } switch(tlsAuthTypeIndex) { case 0: longNumber=CURL_TLSAUTH_NONE; break; case 1: longNumber=CURL_TLSAUTH_SRP; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_TLSAUTH_TYPE, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleGssApiDelegation(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; Tcl_Obj *tmpObjPtr; long longNumber=0; int gssApiDelegationIndex; if (Tcl_GetIndexFromObj(args->interp, args->objv, gssapidelegation, "GSS API delegation option ",TCL_EXACT,&gssApiDelegationIndex)==TCL_ERROR) { return TCL_ERROR; } switch(gssApiDelegationIndex) { case 0: longNumber=CURLGSSAPI_DELEGATION_FLAG; break; case 1: longNumber=CURLGSSAPI_DELEGATION_POLICY_FLAG; } tmpObjPtr=Tcl_NewLongObj(longNumber); Tcl_IncrRefCount(tmpObjPtr); if (SetoptLong(args->interp,curlHandle,CURLOPT_GSSAPI_DELEGATION, args->curlOptsIndex,tmpObjPtr)) { Tcl_DecrRefCount(tmpObjPtr); return TCL_ERROR; } Tcl_DecrRefCount(tmpObjPtr); return TCL_OK; } static int TclCurl_HandleTelnetOptions(TclCurlOptsArgs *args) { CURL *curlHandle = args->curlData->curl; if (SetoptsList(args->interp,&args->curlData->telnetoptions,args->objv)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"invalid list"); return TCL_ERROR; } if (curl_easy_setopt(curlHandle,CURLOPT_TELNETOPTIONS,args->curlData->telnetoptions)) { curlErrorSetOpt(args->interp,configTable,args->curlOptsIndex,"telnetoptions list invalid"); curl_slist_free_all(args->curlData->telnetoptions); args->curlData->telnetoptions = NULL; return TCL_ERROR; } return TCL_OK; } static int TclCurl_HandleCainfoBlob(TclCurlOptsArgs *args) { #if CURL_AT_LEAST_VERSION(7, 77, 0) if (SetoptBlob(args->interp,args->curlData->curl,CURLOPT_CAINFO_BLOB, args->curlOptsIndex,args->objv)) { return TCL_ERROR; } return TCL_OK; #else return TCL_ERROR; #endif } tclcurl-ng-8.0.3/generic/curl_setopts.h000066400000000000000000000551431522613063100201160ustar00rootroot00000000000000/* * curl_setopts.h -- * * Definition and central X-macro based table of symbols and functions for * the CLI option management. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. * * Portions of this file were drafted or revised with AI assistance * under the direction and review of Massimo Manghi. */ #ifndef __curl_setopts_h__ #define __curl_setopts_h__ #include "curl_mime.h" #ifdef CURL_PRE_7_84_DEPR #define TCLCURL_OPTION_LIST_PRE_7_84_DEPR(entry) entry #else #define TCLCURL_OPTION_LIST_PRE_7_84_DEPR(entry) \ #endif #ifdef CURL_PRE_7_11_1_DEPR #define TCLCURL_OPTION_LIST_PRE_7_11_1_DEPR(entry) entry #else #define TCLCURL_OPTION_LIST_PRE_7_11_1_DEPR(entry) \ #endif #ifdef CURL_PRE_8_17_0_DEPR #define TCLCURL_OPTION_LIST_PRE_8_17_0_DEPR(entry) entry #else #define TCLCURL_OPTION_LIST_PRE_8_17_0_DEPR(entry) \ #endif #define TCLCURL_OPTION_LIST(X) \ X(TCLCURLOPT_URL,"CURLOPT_URL","-url",TclCurl_HandleSetoptChar,CURLOPT_URL,NULL) \ X(TCLCURLOPT_FILE,"CURLOPT_FILE","-file",TclCurl_HandleOutFile,0,NULL) \ X(TCLCURLOPT_READDATA,"CURLOPT_READDATA","-infile",TclCurl_HandleReadData,0,NULL) \ X(TCLCURLOPT_USERAGENT,"CURLOPT_USERAGENT","-useragent",TclCurl_HandleSetoptChar,CURLOPT_USERAGENT,NULL) \ X(TCLCURLOPT_REFERER,"CURLOPT_REFERER","-referer",TclCurl_HandleSetoptChar,CURLOPT_REFERER,NULL) \ X(TCLCURLOPT_VERBOSE,"CURLOPT_VERBOSE","-verbose",TclCurl_HandleSetoptInt,CURLOPT_VERBOSE,NULL) \ X(TCLCURLOPT_HEADER,"CURLOPT_HEADER","-header",TclCurl_HandleSetoptInt,CURLOPT_HEADER,NULL) \ X(TCLCURLOPT_NOBODY,"CURLOPT_NOBODY","-nobody",TclCurl_HandleSetoptInt,CURLOPT_NOBODY,NULL) \ X(TCLCURLOPT_PROXY,"CURLOPT_PROXY","-proxy",TclCurl_HandleSetoptChar,CURLOPT_PROXY,NULL) \ X(TCLCURLOPT_PROXYPORT,"CURLOPT_PROXYPORT","-proxyport",TclCurl_HandleSetoptLong,CURLOPT_PROXYPORT,NULL) \ X(TCLCURLOPT_HTTPPROXYTUNNEL,"CURLOPT_HTTPPROXYTUNNEL","-httpproxytunnel",TclCurl_HandleSetoptInt,CURLOPT_HTTPPROXYTUNNEL,NULL) \ X(TCLCURLOPT_FAILONERROR,"CURLOPT_FAILONERROR","-failonerror",TclCurl_HandleSetoptInt,CURLOPT_FAILONERROR,NULL) \ X(TCLCURLOPT_TIMEOUT,"CURLOPT_TIMEOUT","-timeout",TclCurl_HandleSetoptLong,CURLOPT_TIMEOUT,NULL) \ X(TCLCURLOPT_LOW_SPEED_LIMIT,"CURLOPT_LOW_SPEED_LIMIT","-lowspeedlimit",TclCurl_HandleSetoptLong,CURLOPT_LOW_SPEED_LIMIT,NULL) \ X(TCLCURLOPT_LOW_SPEED_TIME,"CURLOPT_LOW_SPEED_TIME","-lowspeedtime",TclCurl_HandleSetoptLong,CURLOPT_LOW_SPEED_TIME,NULL) \ X(TCLCURLOPT_RESUME_FROM,"CURLOPT_RESUME_FROM","-resumefrom",TclCurl_HandleSetoptLong,CURLOPT_RESUME_FROM,NULL) \ X(TCLCURLOPT_INFILESIZE,"CURLOPT_INFILESIZE","-infilesize",TclCurl_HandleSetoptLong,CURLOPT_INFILESIZE,NULL) \ X(TCLCURLOPT_UPLOAD,"CURLOPT_UPLOAD","-upload",TclCurl_HandleSetoptInt,CURLOPT_UPLOAD,NULL) \ X(TCLCURLOPT_FTPLISTONLY,"CURLOPT_FTPLISTONLY","-ftplistonly",TclCurl_HandleSetoptInt,CURLOPT_DIRLISTONLY,NULL) \ X(TCLCURLOPT_FTPAPPEND,"CURLOPT_FTPAPPEND","-ftpappend",TclCurl_HandleSetoptInt,CURLOPT_APPEND,NULL) \ X(TCLCURLOPT_NETRC,"CURLOPT_NETRC","-netrc",TclCurl_HandleNetrc,0,NULL) \ X(TCLCURLOPT_FOLLOWLOCATION,"CURLOPT_FOLLOWLOCATION","-followlocation",TclCurl_HandleSetoptInt,CURLOPT_FOLLOWLOCATION,NULL) \ X(TCLCURLOPT_TRANSFERTEXT,"CURLOPT_TRANSFERTEXT","-transfertext",TclCurl_HandleTransferText,CURLOPT_TRANSFERTEXT,NULL) \ X(TCLCURLOPT_PUT,"CURLOPT_PUT","-put",TclCurl_HandleSetoptInt,CURLOPT_UPLOAD,NULL) \ X(TCLCURLOPT_MUTE,"CURLOPT_MUTE","-mute",TclCurl_HandleMute,0,NULL) \ X(TCLCURLOPT_USERPWD,"CURLOPT_USERPWD","-userpwd",TclCurl_HandleSetoptChar,CURLOPT_USERPWD,NULL) \ X(TCLCURLOPT_PROXYUSERPWD, "CURLOPT_PROXYUSERPWD","-proxyuserpwd", TclCurl_HandleSetoptChar, CURLOPT_PROXYUSERPWD, NULL) \ X(TCLCURLOPT_RANGE,"CURLOPT_RANGE","-range",TclCurl_HandleSetoptChar,CURLOPT_RANGE,NULL) \ X(TCLCURLOPT_ERRORBUFFER,"CURLOPT_ERRORBUFFER","-errorbuffer",TclCurl_HandleErrorBuffer,0,NULL) \ X(TCLCURLOPT_HTTPGET,"CURLOPT_HTTPGET","-httpget",TclCurl_HandleSetoptLong,CURLOPT_HTTPGET,NULL) \ X(TCLCURLOPT_POST,"CURLOPT_POST","-post",TclCurl_HandleSetoptInt,CURLOPT_POST,NULL) \ X(TCLCURLOPT_POSTFIELDS,"CURLOPT_POSTFIELDS","-postfields",TclCurl_HandlePostFields,0,NULL) \ X(TCLCURLOPT_POSTFIELDSIZE_LARGE,"CURLOPT_POSTFIELDSIZE_LARGE","-postfieldsize",TclCurl_HandlePostFieldSize,0,NULL) \ X(TCLCURLOPT_FTPPORT,"CURLOPT_FTPPORT","-ftpport",TclCurl_HandleSetoptChar,CURLOPT_FTPPORT,NULL) \ X(TCLCURLOPT_COOKIE,"CURLOPT_COOKIE","-cookie",TclCurl_HandleSetoptChar,CURLOPT_COOKIE,NULL) \ X(TCLCURLOPT_COOKIEFILE,"CURLOPT_COOKIEFILE","-cookiefile",TclCurl_HandleSetoptChar,CURLOPT_COOKIEFILE,NULL) \ X(TCLCURLOPT_HTTPHEADER,"CURLOPT_HTTPHEADER","-httpheader",TclCurl_HandleHttpHeaderList,0,NULL) \ X(TCLCURLOPT_HTTPPOST,"CURLOPT_HTTPPOST","-httppost",TclCurl_HandleHttpPost,0,NULL) \ X(TCLCURLOPT_SSLCERT,"CURLOPT_SSLCERT","-sslcert",TclCurl_HandleSetoptChar,CURLOPT_SSLCERT,NULL) \ X(TCLCURLOPT_SSLCERTPASSWD, "CURLOPT_SSLCERTPASSWD","-sslcertpasswd",TclCurl_HandleSetoptChar,CURLOPT_SSLCERTPASSWD,NULL) \ X(TCLCURLOPT_SSLVERSION, "CURLOPT_SSLVERSION", "-sslversion", TclCurl_HandleSslVersion,0,NULL) \ X(TCLCURLOPT_CRLF,"CURLOPT_CRLF","-crlf",TclCurl_HandleSetoptInt,CURLOPT_CRLF,NULL) \ X(TCLCURLOPT_QUOTE,"CURLOPT_QUOTE","-quote",TclCurl_HandleQuoteList,0,NULL) \ X(TCLCURLOPT_POSTQUOTE,"CURLOPT_POSTQUOTE","-postquote",TclCurl_HandlePostQuoteList,0,NULL) \ X(TCLCURLOPT_WRITEHEADER,"CURLOPT_WRITEHEADER","-writeheader",TclCurl_HandleWriteHeader,0,NULL) \ X(TCLCURLOPT_TIMECONDITION,"CURLOPT_TIMECONDITION","-timecondition",TclCurl_HandleTimeCondition,0,NULL) \ X(TCLCURLOPT_TIMEVALUE,"CURLOPT_TIMEVALUE","-timevalue",TclCurl_HandleSetoptLong,CURLOPT_TIMEVALUE,NULL) \ X(TCLCURLOPT_CUSTOMREQUEST,"CURLOPT_CUSTOMREQUEST","-customrequest",TclCurl_HandleSetoptChar,CURLOPT_CUSTOMREQUEST,NULL) \ X(TCLCURLOPT_STDERR,"CURLOPT_STDERR","-stderr",TclCurl_HandleStderrFile,0,NULL) \ X(TCLCURLOPT_INTERFACE,"CURLOPT_INTERFACE","-interface",TclCurl_HandleSetoptChar,CURLOPT_INTERFACE,NULL) \ TCLCURL_OPTION_LIST_PRE_8_17_0_DEPR(X(TCLCURLOPT_KRB4LEVEL,"CURLOPT_KRB4LEVEL","-krb4level",TclCurl_HandleSetoptChar,CURLOPT_KRBLEVEL,NULL)) \ X(TCLCURLOPT_SSL_VERIFYPEER,"CURLOPT_SSL_VERIFYPEER","-sslverifypeer",TclCurl_HandleSetoptLong,CURLOPT_SSL_VERIFYPEER,NULL) \ X(TCLCURLOPT_CAINFO,"CURLOPT_CAINFO","-cainfo",TclCurl_HandleSetoptChar,CURLOPT_CAINFO,NULL) \ X(TCLCURLOPT_FILETIME,"CURLOPT_FILETIME","-filetime",TclCurl_HandleSetoptLong,CURLOPT_FILETIME,NULL) \ X(TCLCURLOPT_MAXREDIRS,"CURLOPT_MAXREDIRS","-maxredirs",TclCurl_HandleSetoptLong,CURLOPT_MAXREDIRS,NULL) \ X(TCLCURLOPT_MAXCONNECTS,"CURLOPT_MAXCONNECTS","-maxconnects",TclCurl_HandleSetoptLong,CURLOPT_MAXCONNECTS,NULL) \ X(TCLCURLOPT_CLOSEPOLICY,"CURLOPT_CLOSEPOLICY","-closepolicy",TclCurl_HandleObsolete,0,"option is obsolete") \ TCLCURL_OPTION_LIST_PRE_7_84_DEPR(X(TCLCURLOPT_RANDOM_FILE,"CURLOPT_RANDOM_FILE","-randomfile",TclCurl_HandleSetoptChar,CURLOPT_RANDOM_FILE,NULL)) \ TCLCURL_OPTION_LIST_PRE_7_84_DEPR(X(TCLCURLOPT_EGDSOCKET,"CURLOPT_EGDSOCKET","-egdsocket",TclCurl_HandleSetoptChar,CURLOPT_EGDSOCKET,NULL)) \ X(TCLCURLOPT_CONNECTTIMEOUT,"CURLOPT_CONNECTTIMEOUT","-connecttimeout",TclCurl_HandleSetoptLong,CURLOPT_CONNECTTIMEOUT,NULL) \ X(TCLCURLOPT_NOPROGRESS,"CURLOPT_NOPROGRESS","-noprogress",TclCurl_HandleSetoptLong,CURLOPT_NOPROGRESS,NULL) \ X(TCLCURLOPT_HEADERVAR,"CURLOPT_HEADERVAR","-headervar",TclCurl_HandleHeaderVar,0,NULL) \ X(TCLCURLOPT_BODYVAR,"CURLOPT_BODYVAR","-bodyvar",TclCurl_HandleBodyVar,0,NULL) \ X(TCLCURLOPT_PROGRESSPROC,"CURLOPT_PROGRESSPROC","-progressproc",TclCurl_HandleProgressProc,0,NULL) \ X(TCLCURLOPT_CANCELTRANSVARNAME,"CURLOPT_CANCELTRANSVARNAME","-canceltransvarname",TclCurl_HandleCancelTransVarName,0,NULL) \ X(TCLCURLOPT_WRITEPROC,"CURLOPT_WRITEPROC","-writeproc",TclCurl_HandleWriteProc,0,NULL) \ X(TCLCURLOPT_READPROC,"CURLOPT_READPROC","-readproc",TclCurl_HandleReadProc,0,NULL) \ X(TCLCURLOPT_SSL_VERIFYHOST,"CURLOPT_SSL_VERIFYHOST","-sslverifyhost",TclCurl_HandleSetoptLong,CURLOPT_SSL_VERIFYHOST,NULL) \ X(TCLCURLOPT_COOKIEJAR,"CURLOPT_COOKIEJAR","-cookiejar",TclCurl_HandleSetoptChar, CURLOPT_COOKIEJAR, NULL) \ X(TCLCURLOPT_SSL_CIPHER_LIST, "CURLOPT_SSL_CIPHER_LIST","-sslcipherlist",TclCurl_HandleSetoptChar,CURLOPT_SSL_CIPHER_LIST,NULL) \ X(TCLCURLOPT_HTTP_VERSION, "CURLOPT_HTTP_VERSION", "-httpversion", TclCurl_HandleHttpVersion, CURLOPT_HTTP_VERSION, NULL) \ X(TCLCURLOPT_FTP_USE_EPSV, "CURLOPT_FTP_USE_EPSV", "-ftpuseepsv", TclCurl_HandleSetoptLong, CURLOPT_FTP_USE_EPSV, NULL) \ X(TCLCURLOPT_SSLCERTTYPE, "CURLOPT_SSLCERTTYPE", "-sslcerttype", TclCurl_HandleSetoptChar, CURLOPT_SSLCERTTYPE, NULL) \ X(TCLCURLOPT_SSLKEY, "CURLOPT_SSLKEY", "-sslkey", TclCurl_HandleSetoptChar, CURLOPT_SSLKEY, NULL) \ X(TCLCURLOPT_SSLKEYTYPE, "CURLOPT_SSLKEYTYPE", "-sslkeytype", TclCurl_HandleSetoptChar, CURLOPT_SSLKEYTYPE, NULL) \ X(TCLCURLOPT_SSLKEYPASSWD, "CURLOPT_SSLKEYPASSWD", "-sslkeypasswd", TclCurl_HandleSetoptChar, CURLOPT_KEYPASSWD, NULL) \ X(TCLCURLOPT_SSL_ENGINE, "CURLOPT_SSL_ENGINE", "-sslengine", TclCurl_HandleSetoptChar, CURLOPT_SSLENGINE, NULL) \ X(TCLCURLOPT_SSL_ENGINEDEFAULT, "CURLOPT_SSL_ENGINEDEFAULT", "-sslenginedefault", TclCurl_HandleSetoptLong, CURLOPT_SSLENGINE_DEFAULT, NULL) \ X(TCLCURLOPT_PREQUOTE, "CURLOPT_PREQUOTE", "-prequote", TclCurl_HandlePrequoteList, 0, NULL) \ X(TCLCURLOPT_DEBUGPROC, "CURLOPT_DEBUGPROC", "-debugproc", TclCurl_HandleDebugProc, 0, NULL) \ X(TCLCURLOPT_DNS_CACHE_TIMEOUT, "CURLOPT_DNS_CACHE_TIMEOUT", "-dnscachetimeout", TclCurl_HandleSetoptLong, CURLOPT_DNS_CACHE_TIMEOUT, NULL) \ TCLCURL_OPTION_LIST_PRE_7_11_1_DEPR(X(TCLCURLOPT_DNS_USE_GLOBAL_CACHE,"CURLOPT_DNS_USE_GLOBAL_CACHE","-dnsuseglobalcache",TclCurl_HandleSetoptLong,CURLOPT_DNS_USE_GLOBAL_CACHE,NULL)) \ X(TCLCURLOPT_COOKIESESSION, "CURLOPT_COOKIESESSION", "-cookiesession", TclCurl_HandleSetoptLong, CURLOPT_COOKIESESSION, NULL) \ X(TCLCURLOPT_CAPATH, "CURLOPT_CAPATH", "-capath", TclCurl_HandleSetoptChar, CURLOPT_CAPATH, NULL) \ X(TCLCURLOPT_BUFFERSIZE, "CURLOPT_BUFFERSIZE", "-buffersize", TclCurl_HandleSetoptLong, CURLOPT_BUFFERSIZE, NULL) \ X(TCLCURLOPT_NOSIGNAL, "CURLOPT_NOSIGNAL", "-nosignal", TclCurl_HandleSetoptLong, CURLOPT_NOSIGNAL, NULL) \ X(TCLCURLOPT_ENCODING, "CURLOPT_ENCODING", "-encoding", TclCurl_HandleEncoding, CURLOPT_ACCEPT_ENCODING, NULL) \ X(TCLCURLOPT_PROXYTYPE, "CURLOPT_PROXYTYPE", "-proxytype", TclCurl_HandleProxyType, 0, NULL) \ X(TCLCURLOPT_HTTP200ALIASES, "CURLOPT_HTTP200ALIASES", "-http200aliases", TclCurl_HandleHttp200Aliases, 0, NULL) \ X(TCLCURLOPT_UNRESTRICTED_AUTH, "CURLOPT_UNRESTRICTED_AUTH", "-unrestrictedauth", TclCurl_HandleSetoptInt, CURLOPT_UNRESTRICTED_AUTH, NULL) \ X(TCLCURLOPT_FTP_USE_EPRT, "CURLOPT_FTP_USE_EPRT", "-ftpuseeprt", TclCurl_HandleSetoptLong, CURLOPT_FTP_USE_EPRT, NULL) \ X(TCLCURLOPT_NOSUCHOPTION, "CURLOPT_NOSUCHOPTION", "-command", TclCurl_HandleCommand, 0, NULL) \ X(TCLCURLOPT_HTTPAUTH, "CURLOPT_HTTPAUTH", "-httpauth", TclCurl_HandleHttpAuth, 0, NULL) \ X(TCLCURLOPT_FTP_CREATE_MISSING_DIRS,"CURLOPT_FTP_CREATE_MISSING_DIRS","-ftpcreatemissingdirs",TclCurl_HandleSetoptLong,CURLOPT_FTP_CREATE_MISSING_DIRS, NULL) \ X(TCLCURLOPT_PROXYAUTH, "CURLOPT_PROXYAUTH", "-proxyauth", TclCurl_HandleProxyAuth, 0, NULL) \ X(TCLCURLOPT_FTP_RESPONSE_TIMEOUT,"CURLOPT_FTP_RESPONSE_TIMEOUT","-ftpresponsetimeout",TclCurl_HandleSetoptLong,CURLOPT_FTP_RESPONSE_TIMEOUT,NULL) \ X(TCLCURLOPT_IPRESOLVE, "CURLOPT_IPRESOLVE", "-ipresolve", TclCurl_HandleIpResolve, 0, NULL) \ X(TCLCURLOPT_MAXFILESIZE, "CURLOPT_MAXFILESIZE", "-maxfilesize", TclCurl_HandleSetoptLong, CURLOPT_MAXFILESIZE, NULL) \ X(TCLCURLOPT_NETRC_FILE, "CURLOPT_NETRC_FILE", "-netrcfile", TclCurl_HandleSetoptChar, CURLOPT_NETRC_FILE, NULL) \ X(TCLCURLOPT_FTP_SSL, "CURLOPT_FTP_SSL", "-ftpssl", TclCurl_HandleFtpSsl, CURLOPT_USE_SSL, NULL) \ X(TCLCURLOPT_SHARE, "CURLOPT_SHARE", "-share", TclCurl_HandleSetoptSHandle, CURLOPT_SHARE, NULL) \ X(TCLCURLOPT_PORT, "CURLOPT_PORT", "-port", TclCurl_HandleSetoptLong, CURLOPT_PORT, NULL) \ X(TCLCURLOPT_TCP_NODELAY, "CURLOPT_TCP_NODELAY", "-tcpnodelay",TclCurl_HandleSetoptLong,CURLOPT_TCP_NODELAY, NULL) \ X(TCLCURLOPT_AUTOREFERER, "CURLOPT_AUTOREFERER", "-autoreferer",TclCurl_HandleSetoptLong,CURLOPT_AUTOREFERER, NULL) \ X(TCLCURLOPT_SOURCE_HOST, "CURLOPT_SOURCE_HOST", "-sourcehost", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_SOURCE_USERPWD, "CURLOPT_SOURCE_USERPWD", "-sourceuserpwd", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_SOURCE_PATH, "CURLOPT_SOURCE_PATH", "-sourcepath", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_SOURCE_PORT, "CURLOPT_SOURCE_PORT", "-sourceport", TclCurl_HandleObsolete, 0, "option is obsolete, check '-ftpport'") \ X(TCLCURLOPT_PASV_HOST, "CURLOPT_PASV_HOST", "-pasvhost", TclCurl_HandleObsolete, 0, "option is obsolete, check '-ftpport'") \ X(TCLCURLOPT_SOURCE_PREQUOTE, "CURLOPT_SOURCE_PREQUOTE", "-sourceprequote", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_SOURCE_POSTQUOTE, "CURLOPT_SOURCE_POSTQUOTE", "-sourcepostquote", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_FTPSSLAUTH, "CURLOPT_FTPSSLAUTH", "-ftpsslauth", TclCurl_HandleFtpSslAuth, 0, NULL) \ X(TCLCURLOPT_SOURCE_URL, "CURLOPT_SOURCE_URL", "-sourceurl", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_SOURCE_QUOTE, "CURLOPT_SOURCE_QUOTE", "-sourcequote", TclCurl_HandleObsolete, 0, "option is obsolete") \ X(TCLCURLOPT_FTP_ACCOUNT, "CURLOPT_FTP_ACCOUNT", "-ftpaccount", TclCurl_HandleSetoptChar, CURLOPT_FTP_ACCOUNT, NULL) \ X(TCLCURLOPT_IGNORE_CONTENT_LENGTH,"CURLOPT_IGNORE_CONTENT_LENGTH","-ignorecontentlength",TclCurl_HandleSetoptLong,CURLOPT_IGNORE_CONTENT_LENGTH,NULL) \ X(TCLCURLOPT_COOKIELIST,"CURLOPT_COOKIELIST","-cookielist",TclCurl_HandleSetoptChar,CURLOPT_COOKIELIST,NULL) \ X(TCLCURLOPT_FTP_SKIP_PASV_IP,"CURLOPT_FTP_SKIP_PASV_IP","-ftpskippasvip",TclCurl_HandleSetoptLong,CURLOPT_FTP_SKIP_PASV_IP,NULL) \ X(TCLCURLOPT_FTP_FILEMETHOD,"CURLOPT_FTP_FILEMETHOD","-ftpfilemethod",TclCurl_HandleFtpFileMethod,0,NULL) \ X(TCLCURLOPT_LOCALPORT,"CURLOPT_LOCALPORT","-localport",TclCurl_HandleSetoptLong,CURLOPT_LOCALPORT,NULL) \ X(TCLCURLOPT_LOCALPORTRANGE,"CURLOPT_LOCALPORTRANGE","-localportrange",TclCurl_HandleSetoptLong,CURLOPT_LOCALPORTRANGE, NULL) \ X(TCLCURLOPT_MAX_SEND_SPEED_LARGE, "CURLOPT_MAX_SEND_SPEED_LARGE", "-maxsendspeed", TclCurl_HandleSetoptCurlOffT, CURLOPT_MAX_SEND_SPEED_LARGE, NULL) \ X(TCLCURLOPT_MAX_RECV_SPEED_LARGE, "CURLOPT_MAX_RECV_SPEED_LARGE", "-maxrecvspeed", TclCurl_HandleSetoptCurlOffT, CURLOPT_MAX_RECV_SPEED_LARGE, NULL) \ X(TCLCURLOPT_FTP_ALTERNATIVE_TO_USER, "CURLOPT_FTP_ALTERNATIVE_TO_USER", "-ftpalternativetouser", TclCurl_HandleSetoptChar, CURLOPT_FTP_ALTERNATIVE_TO_USER, NULL) \ X(TCLCURLOPT_SSL_SESSIONID_CACHE,"CURLOPT_SSL_SESSIONID_CACHE","-sslsessionidcache",TclCurl_HandleSetoptLong,CURLOPT_SSL_SESSIONID_CACHE,NULL) \ X(TCLCURLOPT_SSH_AUTH_TYPES,"CURLOPT_SSH_AUTH_TYPES","-sshauthtypes",TclCurl_HandleSshAuthTypes,0,NULL) \ X(TCLCURLOPT_SSH_PUBLIC_KEYFILE, "CURLOPT_SSH_PUBLIC_KEYFILE", "-sshpublickeyfile", TclCurl_HandleSetoptChar, CURLOPT_SSH_PUBLIC_KEYFILE, NULL) \ X(TCLCURLOPT_SSH_PRIVATE_KEYFILE, "CURLOPT_SSH_PRIVATE_KEYFILE", "-sshprivatekeyfile", TclCurl_HandleSetoptChar, CURLOPT_SSH_PRIVATE_KEYFILE, NULL) \ X(TCLCURLOPT_TIMEOUT_MS, "CURLOPT_TIMEOUT_MS", "-timeoutms", TclCurl_HandleSetoptLong, CURLOPT_TIMEOUT_MS, NULL) \ X(TCLCURLOPT_CONNECTTIMEOUT_MS, "CURLOPT_CONNECTTIMEOUT_MS", "-connecttimeoutms", TclCurl_HandleSetoptLong, CURLOPT_CONNECTTIMEOUT_MS, NULL) \ X(TCLCURLOPT_HTTP_CONTENT_DECODING, "CURLOPT_HTTP_CONTENT_DECODING", "-contentdecoding", TclCurl_HandleSetoptLong, CURLOPT_HTTP_CONTENT_DECODING, NULL) \ X(TCLCURLOPT_HTTP_TRANSFER_DECODING, "CURLOPT_HTTP_TRANSFER_DECODING", "-transferdecoding", TclCurl_HandleSetoptLong, CURLOPT_HTTP_TRANSFER_DECODING, NULL) \ TCLCURL_OPTION_LIST_PRE_8_17_0_DEPR(X(TCLCURLOPT_KRBLEVEL, "CURLOPT_KRBLEVEL", "-krblevel", TclCurl_HandleSetoptChar, CURLOPT_KRBLEVEL, NULL)) \ X(TCLCURLOPT_NEW_FILE_PERMS, "CURLOPT_NEW_FILE_PERMS", "-newfileperms", TclCurl_HandleSetoptLong, CURLOPT_NEW_FILE_PERMS, NULL) \ X(TCLCURLOPT_NEW_DIRECTORY_PERMS, "CURLOPT_NEW_DIRECTORY_PERMS", "-newdirectoryperms", TclCurl_HandleSetoptLong, CURLOPT_NEW_DIRECTORY_PERMS, NULL) \ X(TCLCURLOPT_KEYPASSWD, "CURLOPT_KEYPASSWD", "-keypasswd", TclCurl_HandleSetoptChar, CURLOPT_KEYPASSWD, NULL) \ X(TCLCURLOPT_APPEND, "CURLOPT_APPEND", "-append", TclCurl_HandleSetoptInt, CURLOPT_APPEND, NULL) \ X(TCLCURLOPT_DIRLISTONLY, "CURLOPT_DIRLISTONLY", "-dirlistonly", TclCurl_HandleSetoptInt, CURLOPT_DIRLISTONLY, NULL) \ X(TCLCURLOPT_USE_SSL, "CURLOPT_USE_SSL", "-usessl", TclCurl_HandleFtpSsl, CURLOPT_USE_SSL, NULL) \ X(TCLCURLOPT_POST301, "CURLOPT_POST301", "-post301", TclCurl_HandlePostRedir, 0, NULL) \ X(TCLCURLOPT_SSH_HOST_PUBLIC_KEY_MD5,"CURLOPT_SSH_HOST_PUBLIC_KEY_MD5","-sshhostpublickeymd5",TclCurl_HandleSetoptChar,CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,NULL) \ X(TCLCURLOPT_PROXY_TRANSFER_MODE, "CURLOPT_PROXY_TRANSFER_MODE", "-proxytransfermode", TclCurl_HandleSetoptLong, CURLOPT_PROXY_TRANSFER_MODE, NULL) \ X(TCLCURLOPT_CRLFILE, "CURLOPT_CRLFILE", "-crlfile", TclCurl_HandleSetoptChar, CURLOPT_CRLFILE, NULL) \ X(TCLCURLOPT_ISSUERCERT, "CURLOPT_ISSUERCERT", "-issuercert", TclCurl_HandleSetoptChar, CURLOPT_ISSUERCERT, NULL) \ X(TCLCURLOPT_ADDRESS_SCOPE, "CURLOPT_ADDRESS_SCOPE", "-addressscope", TclCurl_HandleSetoptLong, CURLOPT_ADDRESS_SCOPE, NULL) \ X(TCLCURLOPT_CERTINFO, "CURLOPT_CERTINFO", "-certinfo", TclCurl_HandleSetoptLong, CURLOPT_CERTINFO, NULL) \ X(TCLCURLOPT_POSTREDIR, "CURLOPT_POSTREDIR", "-postredir", TclCurl_HandlePostRedir, 0, NULL) \ X(TCLCURLOPT_USERNAME, "CURLOPT_USERNAME", "-username", TclCurl_HandleSetoptChar, CURLOPT_USERNAME, NULL) \ X(TCLCURLOPT_PASSWORD, "CURLOPT_PASSWORD", "-password", TclCurl_HandleSetoptChar, CURLOPT_PASSWORD, NULL) \ X(TCLCURLOPT_PROXYUSERNAME, "CURLOPT_PROXYUSERNAME", "-proxyuser", TclCurl_HandleSetoptChar, CURLOPT_PROXYUSERNAME, NULL) \ X(TCLCURLOPT_PROXYPASSWORD, "CURLOPT_PROXYPASSWORD", "-proxypassword", TclCurl_HandleSetoptChar, CURLOPT_PROXYPASSWORD, NULL) \ X(TCLCURLOPT_TFTP_BLKSIZE, "CURLOPT_TFTP_BLKSIZE", "-tftpblksize", TclCurl_HandleSetoptLong, CURLOPT_TFTP_BLKSIZE, NULL) \ X(TCLCURLOPT_PROXY_SERVICE_NAME, "CURLOPT_PROXY_SERVICE_NAME", "-socks5gssapiservice", TclCurl_HandleSetoptChar, CURLOPT_PROXY_SERVICE_NAME, NULL) \ X(TCLCURLOPT_SOCKS5_GSSAPI_NEC, "CURLOPT_SOCKS5_GSSAPI_NEC", "-socks5gssapinec", TclCurl_HandleSetoptLong, CURLOPT_SOCKS5_GSSAPI_NEC, NULL) \ X(TCLCURLOPT_PROTOCOLS_STR, "CURLOPT_PROTOCOLS_STR", "-protocols", TclCurl_HandleProtocolMask, CURLOPT_PROTOCOLS_STR, NULL) \ X(TCLCURLOPT_REDIR_PROTOCOLS_STR, "CURLOPT_REDIR_PROTOCOLS_STR", "-redirprotocols", TclCurl_HandleProtocolMask, CURLOPT_REDIR_PROTOCOLS_STR, NULL) \ X(TCLCURLOPT_FTP_SSL_CCC, "CURLOPT_FTP_SSL_CCC", "-ftpsslccc", TclCurl_HandleFtpSslCcc, 0, NULL) \ X(TCLCURLOPT_SSH_KNOWNHOSTS, "CURLOPT_SSH_KNOWNHOSTS", "-sshknownhosts", TclCurl_HandleSetoptChar, CURLOPT_SSH_KNOWNHOSTS, NULL) \ X(TCLCURLOPT_SSH_KEYFUNCTION, "CURLOPT_SSH_KEYFUNCTION", "-sshkeyproc", TclCurl_HandleSshKeyFunction, 0, NULL) \ X(TCLCURLOPT_MAIL_FROM, "CURLOPT_MAIL_FROM", "-mailfrom", TclCurl_HandleSetoptChar, CURLOPT_MAIL_FROM, NULL) \ X(TCLCURLOPT_MAIL_RCPT, "CURLOPT_MAIL_RCPT", "-mailrcpt", TclCurl_HandleMailRcpt, 0, NULL) \ X(TCLCURLOPT_FTP_USE_PRET, "CURLOPT_FTP_USE_PRET", "-ftpusepret", TclCurl_HandleSetoptLong, CURLOPT_FTP_USE_PRET, NULL) \ X(TCLCURLOPT_WILDCARDMATCH, "CURLOPT_WILDCARDMATCH", "-wildcardmatch", TclCurl_HandleSetoptLong, CURLOPT_WILDCARDMATCH, NULL) \ X(TCLCURLOPT_CHUNK_BGN_PROC, "CURLOPT_CHUNK_BGN_PROC", "-chunkbgnproc", TclCurl_HandleChunkBgnProc, 0, NULL) \ X(TCLCURLOPT_CHUNK_BGN_VAR, "CURLOPT_CHUNK_BGN_VAR", "-chunkbgnvar", TclCurl_HandleChunkBgnVar, 0, NULL) \ X(TCLCURLOPT_CHUNK_END_PROC, "CURLOPT_CHUNK_END_PROC", "-chunkendproc", TclCurl_HandleChunkEndProc, 0, NULL) \ X(TCLCURLOPT_FNMATCH_PROC, "CURLOPT_FNMATCH_PROC", "-fnmatchproc", TclCurl_HandleFnmatchProc, 0, NULL) \ X(TCLCURLOPT_RESOLVE, "CURLOPT_RESOLVE", "-resolve", TclCurl_HandleResolveList, 0, NULL) \ X(TCLCURLOPT_TLSAUTH_USERNAME, "CURLOPT_TLSAUTH_USERNAME", "-tlsauthusername", TclCurl_HandleSetoptChar, CURLOPT_TLSAUTH_USERNAME, NULL) \ X(TCLCURLOPT_TLSAUTH_PASSWORD, "CURLOPT_TLSAUTH_PASSWORD", "-tlsauthpassword", TclCurl_HandleSetoptChar, CURLOPT_TLSAUTH_PASSWORD, NULL) \ X(TCLCURLOPT_TLSAUTH_TYPE, "CURLOPT_TLSAUTH_TYPE", "-tlsauthtype", TclCurl_HandleTlsAuthType, 0, NULL) \ X(TCLCURLOPT_TRANSFER_ENCODING, "CURLOPT_TRANSFER_ENCODING", "-transferencoding", TclCurl_HandleSetoptLong, CURLOPT_TRANSFER_ENCODING, NULL) \ X(TCLCURLOPT_GSSAPI_DELEGATION, "CURLOPT_GSSAPI_DELEGATION", "-gssapidelegation", TclCurl_HandleGssApiDelegation, 0, NULL) \ X(TCLCURLOPT_NOPROXY, "CURLOPT_NOPROXY", "-noproxy", TclCurl_HandleSetoptChar, CURLOPT_NOPROXY, NULL) \ X(TCLCURLOPT_TELNETOPTIONS, "CURLOPT_TELNETOPTIONS", "-telnetoptions", TclCurl_HandleTelnetOptions, 0, NULL) \ X(TCLCURLOPT_CAINFO_BLOB,"CURLOPT_CAINFO_BLOB","-cainfoblob",TclCurl_HandleCainfoBlob,0,NULL) enum curlOptionsIndices { #define TCLCURLOPT_ENUM_ENTRY(option, optname, configname, handler, curlopt, message) option, TCLCURL_OPTION_LIST(TCLCURLOPT_ENUM_ENTRY) #undef TCLCURLOPT_ENUM_ENTRY TCLCURLOPT_COUNT }; const static char *configTable[] = { #define TCLCURLOPT_CONFIG_ENTRY(option, optname, configname, handler, curlopt, message) configname, TCLCURL_OPTION_LIST(TCLCURLOPT_CONFIG_ENTRY) #undef TCLCURLOPT_CONFIG_ENTRY (char *) NULL }; typedef struct TclCurlOptionDef TclCurlOptionDef; typedef struct TclCurlOptsArgs TclCurlOptsArgs; struct TclCurlOptsArgs { Tcl_Interp* interp; struct curlObjData* curlData; Tcl_Obj *const objv; int curlOptsIndex; const TclCurlOptionDef* def; }; typedef int (*TclCurlOptionHandler)(TclCurlOptsArgs *args); struct TclCurlOptionDef { const char *optionName; const char *configName; TclCurlOptionHandler handler; CURLoption curlOpt; const char *errorMessage; }; #endif tclcurl-ng-8.0.3/generic/curl_utils.c000066400000000000000000000210541522613063100175420ustar00rootroot00000000000000/* * tclcurl_utils.c */ #include #include #include #include #include #include #include "tclcurl.h" #include "tclcompat.h" enum ProtocolNamesIndices { TCLCURL_PROTO_HTTP, TCLCURL_PROTO_HTTPS, TCLCURL_PROTO_FTP, TCLCURL_PROTO_FTPS, TCLCURL_PROTO_SCP, TCLCURL_PROTO_SFTP, TCLCURL_PROTO_TELNET, TCLCURL_PROTO_LDAP, TCLCURL_PROTO_LDAPS, TCLCURL_PROTO_DICT, TCLCURL_PROTO_FILE, TCLCURL_PROTO_TFTP, TCLCURL_PROTO_IMAP, TCLCURL_PROTO_IMAPS, TCLCURL_PROTO_POP3, TCLCURL_PROTO_POP3S, TCLCURL_PROTO_SMTP, TCLCURL_PROTO_SMTPS, TCLCURL_PROTO_RTSP, TCLCURL_PROTO_RTMP, TCLCURL_PROTO_RTMPT, TCLCURL_PROTO_RTMPE, TCLCURL_PROTO_RTMPTE, TCLCURL_PROTO_RTMPS, TCLCURL_PROTO_RTMPTS, TCLCURL_PROTO_GOPHER, TCLCURL_PROTO_ALL }; const static char *protocolNames[] = { "http", "https", "ftp", "ftps", "scp", "sftp", "telnet", "ldap", "ldaps", "dict", "file", "tftp", "imap", "imaps", "pop3", "pop3s", "smtp", "smtps", "rtsp", "rtmp", "rtmpt", "rtmpe", "rtmpte", "rtmps", "rtmpts", "gopher", "all", (char*)NULL }; unsigned long int TclCurl_BuildProtocolMask(Tcl_Interp* interp, Tcl_Obj** protocols,Tcl_Size protocols_c) { unsigned long int protocolMask; int curlTableIndex; Tcl_Size i; for (i = 0,protocolMask = 0; i < protocols_c; i++) { if (Tcl_GetIndexFromObj(interp,protocols[i],protocolNames, "protocol",TCL_EXACT,&curlTableIndex)==TCL_ERROR) { return TCL_ERROR; } switch(curlTableIndex) { case TCLCURL_PROTO_HTTP: /* http 1 */ protocolMask|=CURLPROTO_HTTP; break; case TCLCURL_PROTO_HTTPS: /* https 2 */ protocolMask|=CURLPROTO_HTTPS; break; case TCLCURL_PROTO_FTP: /* ftp 4 */ protocolMask|=CURLPROTO_FTP; break; case TCLCURL_PROTO_FTPS: /* ftps 8 */ protocolMask|=CURLPROTO_FTPS; break; case TCLCURL_PROTO_SCP: /* scp 16 */ protocolMask|=CURLPROTO_SCP; break; case TCLCURL_PROTO_SFTP: /* sftp 32 */ protocolMask|=CURLPROTO_SFTP; break; case TCLCURL_PROTO_TELNET: /* telnet 64 */ protocolMask|=CURLPROTO_TELNET; break; case TCLCURL_PROTO_LDAP: /* ldap 128 */ protocolMask|=CURLPROTO_LDAP; break; case TCLCURL_PROTO_LDAPS: /* ldaps 256 */ protocolMask|=CURLPROTO_LDAPS; break; case TCLCURL_PROTO_DICT: /* dict 512 */ protocolMask|=CURLPROTO_DICT; break; case TCLCURL_PROTO_FILE: /* file 1024 */ protocolMask|=CURLPROTO_FILE; break; case TCLCURL_PROTO_TFTP: /* tftp 2048 */ protocolMask|=CURLPROTO_TFTP; break; case TCLCURL_PROTO_IMAP: /* imap 4096 */ protocolMask|=CURLPROTO_IMAP; break; case TCLCURL_PROTO_IMAPS: /* imaps */ protocolMask|=CURLPROTO_IMAPS; break; case TCLCURL_PROTO_POP3: /* pop3 */ protocolMask|=CURLPROTO_POP3; break; case TCLCURL_PROTO_POP3S: /* pop3s */ protocolMask|=CURLPROTO_POP3S; break; case TCLCURL_PROTO_SMTP: /* smtp */ protocolMask|=CURLPROTO_SMTP; break; case TCLCURL_PROTO_SMTPS: /* smtps */ protocolMask|=CURLPROTO_SMTPS; break; case TCLCURL_PROTO_RTSP: /* rtsp */ protocolMask|=CURLPROTO_RTSP; break; case TCLCURL_PROTO_RTMP: /* rtmp */ protocolMask|=CURLPROTO_RTMP; break; case TCLCURL_PROTO_RTMPT: /* rtmpt */ protocolMask|=CURLPROTO_RTMPT; break; case TCLCURL_PROTO_RTMPE: /* rtmpe */ protocolMask|=CURLPROTO_RTMPE; break; case TCLCURL_PROTO_RTMPTE: /* rtmpte */ protocolMask|=CURLPROTO_RTMPTE; break; case TCLCURL_PROTO_RTMPS: /* rtmps */ protocolMask|=CURLPROTO_RTMPS; break; case TCLCURL_PROTO_RTMPTS: /* rtmpts */ protocolMask|=CURLPROTO_RTMPTS; break; case TCLCURL_PROTO_GOPHER: /* gopher */ protocolMask|=CURLPROTO_GOPHER; break; case TCLCURL_PROTO_ALL: /* all FFFF */ protocolMask|=CURLPROTO_ALL; } } return protocolMask; } int TclCurl_ErrorBuffer(Tcl_Interp *interp, struct curlObjData* curlData,Tcl_Obj *const tcl_o) { int exitCode; const char *startPtr; const char *endPtr; char *tmpStr = NULL; Tcl_RegExp regExp; CURL *curlHandle=curlData->curl; tmpStr = curlstrdup(Tcl_GetString(tcl_o)); regExp = Tcl_RegExpCompile(interp,"(.*)(?:\\()(.*)(?:\\))"); exitCode = Tcl_RegExpExec(interp,regExp,tmpStr,tmpStr); switch (exitCode) { case -1: Tcl_Free((char *)tmpStr); return TCL_ERROR; case 0: if (*tmpStr!=0) { curlData->errorBufferName=curlstrdup(tmpStr); } else { curlData->errorBuffer=NULL; } curlData->errorBufferKey=NULL; break; case 1: { int charLength; Tcl_RegExpRange(regExp,1,&startPtr,&endPtr); charLength = endPtr-startPtr; curlData->errorBufferName = Tcl_Alloc(charLength+1); strncpy(curlData->errorBufferName,startPtr,charLength); curlData->errorBufferName[charLength] = 0; Tcl_RegExpRange(regExp,2,&startPtr,&endPtr); charLength = endPtr-startPtr; curlData->errorBufferKey = Tcl_Alloc(charLength+1); strncpy(curlData->errorBufferKey,startPtr,charLength); curlData->errorBufferKey[charLength] = 0; break; } } Tcl_Free((char *)tmpStr); if (curlData->errorBufferName!=NULL) { curlData->errorBuffer=Tcl_Alloc(CURL_ERROR_SIZE); if (curl_easy_setopt(curlHandle,CURLOPT_ERRORBUFFER, curlData->errorBuffer)) { Tcl_Free((char *)curlData->errorBuffer); curlData->errorBuffer=NULL; return TCL_ERROR; } } else { Tcl_Free(curlData->errorBuffer); } return TCL_OK; } /* * Implementation of a very elementary function to strip spaces * from string arguments * */ char* TclCurl_StripSpaces (char* str) { char* start = str; char* end = start + strlen(str) - 1; size_t len = strlen(str); char** sstarts = (char **) calloc(len,sizeof(char *)); int segment = 0; int s; bool space_strand = true; char* p = start; while (isspace(*p)) { p++; } while (p != end) { if (isspace(*p)) { *p = 0; space_strand = true; } else { if (space_strand) { sstarts[segment++] = p; } space_strand = false; } p++; } p = start; for (s = 0; s < segment; s++) { char* s_p; size_t s_len; s_p = sstarts[s]; s_len = strlen(sstarts[s]); memmove(p,s_p,s_len); p += s_len; *p = 0; } free(sstarts); return start; } /* * C level reimplementation of Tcl command 'join' * */ Tcl_Obj* TclCurl_JoinList (Tcl_Obj** objList,Tcl_Size obj_cnt,const char* join_c) { Tcl_Obj* joined_string = Tcl_NewObj(); Tcl_Obj* join_obj = Tcl_NewStringObj(join_c,-1); int i; Tcl_IncrRefCount(join_obj); for (i = 0; i < obj_cnt; i++) { if (i > 0) { Tcl_AppendObjToObj(joined_string,join_obj); } Tcl_AppendObjToObj(joined_string,objList[i]); } Tcl_DecrRefCount(join_obj); return joined_string; } tclcurl-ng-8.0.3/generic/ftp.c000066400000000000000000000024711522613063100161500ustar00rootroot00000000000000/* * */ #include #include #include "tclcompat.h" const static char *ftpsslccc[] = { "none", "passive", "active", (char *)NULL }; const static char *ftpssl[] = { "nope", "try", "control", "all", (char *)NULL }; long TclCurl_FTPClearCommandChannelOpt(Tcl_Interp* interp,Tcl_Obj* opt_o) { int intNumber; if (Tcl_GetIndexFromObj(interp, opt_o, ftpsslccc, "Clear Command Channel option ", TCL_EXACT, &intNumber) == TCL_ERROR) { return -1; } switch(intNumber) { case 0: return CURLFTPSSL_CCC_NONE; case 1: return CURLFTPSSL_CCC_PASSIVE; case 2: return CURLFTPSSL_CCC_ACTIVE; } /* It's not supposed to ever get here */ return -1; } long TclCurl_FTPSSLMethod(Tcl_Interp* interp,Tcl_Obj* ssl_method_o) { int intNumber; if (Tcl_GetIndexFromObj(interp, ssl_method_o, ftpssl, "ftps method ",TCL_EXACT,&intNumber)==TCL_ERROR) { return -1; } switch(intNumber) { case 0: return CURLUSESSL_NONE; case 1: return CURLUSESSL_TRY; case 2: return CURLUSESSL_CONTROL; case 3: return CURLUSESSL_ALL; } /* It's not supposed to ever get here */ return -1; } tclcurl-ng-8.0.3/generic/multi.c000066400000000000000000000725211522613063100165140ustar00rootroot00000000000000/* * multi.c -- * * Implementation of the part of the TclCurl extension that deals with libcurl's * 'multi' interface. * * Copyright (c)2002-2011 Andres Garcia Garcia. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include "multi.h" #include "curl_mime.h" #ifndef _WIN32 #include #endif typedef int (*TclCurlMultiCommandProc)(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); typedef int (*TclCurlMultiConfigProc)(Tcl_Interp *interp, CURLM *curlMultiHandle, CURLMoption opt, int tableIndex, Tcl_Obj *tclObj); struct TclCurlMultiConfigDispatch { CURLMoption option; TclCurlMultiConfigProc proc; }; static int TclCurl_MultiDispatchAddHandle(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchRemoveHandle(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchPerform(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchCleanup(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchGetInfo(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchActive(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchAuto(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static int TclCurl_MultiDispatchConfigure(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]); static const TclCurlMultiCommandProc multiCommandDispatch[TCLCURL_MULTI_CMD_COUNT] = { #define TCLCURL_MULTI_COMMAND_DISPATCH_ENTRY(name, label, proc) [name] = proc, TCLCURL_MULTI_COMMAND_LIST(TCLCURL_MULTI_COMMAND_DISPATCH_ENTRY) #undef TCLCURL_MULTI_COMMAND_DISPATCH_ENTRY }; static const struct TclCurlMultiConfigDispatch multiConfigDispatch[TCLCURL_MULTI_CONFIG_COUNT] = { #define TCLCURL_MULTI_CONFIG_DISPATCH_ENTRY(name, label, opt, proc) [name] = { opt, proc }, TCLCURL_MULTI_CONFIG_LIST(TCLCURL_MULTI_CONFIG_DISPATCH_ENTRY) #undef TCLCURL_MULTI_CONFIG_DISPATCH_ENTRY }; /* *---------------------------------------------------------------------- * * Tclcurl_MultiInit -- * * This procedure initializes the 'multi' part of the package * * Results: * A standard Tcl result. * *---------------------------------------------------------------------- */ int Tclcurl_MultiInit (Tcl_Interp *interp) { Tcl_CreateObjCommand (interp,"::curl::multiinit",curlInitMultiObjCmd, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlCreateMultiObjCmd -- * * Looks for the first free handle (mcurl1, mcurl2,...) and creates a * Tcl command for it. * * Results: * A string with the name of the handle, don't forget to free it. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ char * curlCreateMultiObjCmd (Tcl_Interp *interp,struct curlMultiObjData *curlMultiData) { char *handleName; int i; Tcl_CmdInfo info; Tcl_Command cmdToken; /* We try with mcurl1, if it already exists with mcurl2, ... */ handleName=(char *)Tcl_Alloc(10); for (i=1;;i++) { sprintf(handleName,"mcurl%d",i); if (!Tcl_GetCommandInfo(interp,handleName,&info)) { cmdToken=Tcl_CreateObjCommand(interp,handleName,curlMultiObjCmd, (ClientData)curlMultiData, (Tcl_CmdDeleteProc *)curlMultiDeleteCmd); break; } } curlMultiData->token=cmdToken; return handleName; } /* *---------------------------------------------------------------------- * * curlInitMultiObjCmd -- * * This procedure is invoked to process the "curl::multiInit" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlInitMultiObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { Tcl_Obj *result; struct curlMultiObjData *curlMultiData; char *multiHandleName; curlMultiData=(struct curlMultiObjData *)Tcl_Alloc(sizeof(struct curlMultiObjData)); if (curlMultiData==NULL) { result=Tcl_NewStringObj("Couldn't allocate memory",-1); Tcl_SetObjResult(interp,result); return TCL_ERROR; } memset(curlMultiData, 0, sizeof(struct curlMultiObjData)); curlMultiData->interp=interp; curlMultiData->mcurl=curl_multi_init(); if (curlMultiData->mcurl==NULL) { result=Tcl_NewStringObj("Couldn't open curl multi handle",-1); Tcl_SetObjResult(interp,result); return TCL_ERROR; } multiHandleName=curlCreateMultiObjCmd(interp,curlMultiData); result=Tcl_NewStringObj(multiHandleName,-1); Tcl_SetObjResult(interp,result); Tcl_Free(multiHandleName); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlMultiObjCmd -- * * This procedure is invoked to process the "multi curl" commands. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlMultiObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { struct curlMultiObjData *curlMultiData=(struct curlMultiObjData *)clientData; int tableIndex; if (objc<2) { Tcl_WrongNumArgs(interp,1,objv,"option arg ?arg?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], multiCommandTable, "option", TCL_EXACT,&tableIndex)==TCL_ERROR) { return TCL_ERROR; } return multiCommandDispatch[tableIndex](interp,curlMultiData,objc,objv); } static int TclCurl_MultiDispatchAddHandle(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { CURLMcode errorCode; errorCode=curlAddMultiHandle(interp,curlMultiData->mcurl,objv[2]); return curlReturnCURLMcode(interp,errorCode); } static int TclCurl_MultiDispatchRemoveHandle(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { CURLMcode errorCode; errorCode=curlRemoveMultiHandle(interp,curlMultiData->mcurl,objv[2]); return curlReturnCURLMcode(interp,errorCode); } static int TclCurl_MultiDispatchPerform(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { return curlMultiPerform(interp,curlMultiData->mcurl); } static int TclCurl_MultiDispatchCleanup(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { Tcl_DeleteCommandFromToken(interp,curlMultiData->token); return TCL_OK; } static int TclCurl_MultiDispatchGetInfo(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { curlMultiGetInfo(interp,curlMultiData->mcurl); return TCL_OK; } static int TclCurl_MultiDispatchActive(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { curlMultiActiveTransfers(interp,curlMultiData); return TCL_OK; } static int TclCurl_MultiDispatchAuto(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { curlMultiAutoTransfer(interp,curlMultiData,objc,objv); return TCL_OK; } static int TclCurl_MultiDispatchConfigure(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc, Tcl_Obj *const objv[]) { curlMultiConfigTransfer(interp,curlMultiData,objc,objv); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlAddMultiHandle -- * * Adds an 'easy' curl handle to the stack of a 'multi' handle. * * Parameter: * interp: Pointer to the interpreter we are using. * curlMultiHandle: The handle into which we will add the easy one. * objvPtr: The Tcl object with the name of the easy handle. * * Results: * '0' all went well. * 'non-zero' in case of error. *---------------------------------------------------------------------- */ CURLMcode curlAddMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandlePtr ,Tcl_Obj *objvPtr) { struct curlObjData *curlDataPtr; CURLMcode errorCode; curlDataPtr=curlGetEasyHandle(interp,objvPtr); if (curlOpenFiles(interp,curlDataPtr)) { return TCL_ERROR; } if (TclCurl_SetPostData(interp,curlDataPtr)) { return TCL_ERROR; } errorCode=curl_multi_add_handle(curlMultiHandlePtr,curlDataPtr->curl); curlEasyHandleListAdd(curlMultiHandlePtr,curlDataPtr->curl ,Tcl_GetString(objvPtr)); return errorCode; } /* *---------------------------------------------------------------------- * * curlRemoveMultiHandle -- * * Removes an 'easy' curl handle to the stack of a 'multi' handle. * * Parameter: * interp: Pointer to the interpreter we are using. * curlMultiHandle: The handle into which we will add the easy one. * objvPtr: The Tcl object with the name of the easy handle. * * Results: * '0' all went well. * 'non-zero' in case of error. *---------------------------------------------------------------------- */ CURLMcode curlRemoveMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandle ,Tcl_Obj *objvPtr) { struct curlObjData *curlDataPtr; CURLMcode errorCode; curlDataPtr=curlGetEasyHandle(interp,objvPtr); errorCode=curl_multi_remove_handle(curlMultiHandle,curlDataPtr->curl); curlEasyHandleListRemove(curlMultiHandle,curlDataPtr->curl); curlCloseFiles(curlDataPtr); TclCurl_ResetPostData(curlDataPtr); if (curlDataPtr->bodyVarName) { curlSetBodyVarName(interp,curlDataPtr); } return errorCode; } /* *---------------------------------------------------------------------- * * curlMultiPerform -- * * Invokes the 'curl_multi_perform' function to update the current * transfers. * * Parameter: * interp: Pointer to the interpreter we are using. * curlMultiHandle: The handle of the transfer to update. * objvPtr: The Tcl object with the name of the easy handle. * * Results: Usual Tcl result. *---------------------------------------------------------------------- */ int curlMultiPerform(Tcl_Interp *interp,CURLM *curlMultiHandlePtr) { CURLMcode errorCode; int runningTransfers; for (errorCode=-1;errorCode<0;) { errorCode=curl_multi_perform(curlMultiHandlePtr,&runningTransfers); } if (errorCode==0) { curlReturnCURLMcode(interp,runningTransfers); return TCL_OK; } curlReturnCURLMcode(interp,errorCode); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * curlMultiDeleteCmd -- * * This procedure is invoked when curl multi handle is deleted. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Cleans the curl handle and frees the memory. * *---------------------------------------------------------------------- */ int curlMultiDeleteCmd(ClientData clientData) { struct curlMultiObjData *curlMultiData=(struct curlMultiObjData *)clientData; CURLM *curlMultiHandle=curlMultiData->mcurl; CURLMcode errorCode; Tcl_Interp *interp=curlMultiData->interp; struct easyHandleList *listPtr1,*listPtr2; listPtr1=curlMultiData->handleListFirst; while (listPtr1!=NULL) { listPtr2=listPtr1->next; Tcl_Free(listPtr1->name); Tcl_Free((char *)listPtr1); listPtr1=listPtr2; } errorCode=curl_multi_cleanup(curlMultiHandle); curlMultiFreeSpace(curlMultiData); return curlReturnCURLMcode(interp,errorCode); } /* *---------------------------------------------------------------------- * * curlGetMultiInfo -- * Invokes the curl_multi_info_read function in libcurl to get * some info about the transfer, like if they are done and * things like that. * * Parameter: * interp: The Tcl interpreter we are using, mainly to report errors. * curlMultiHandlePtr: Pointer to the multi handle of the transfer. * * Results: * Standard Tcl codes. The Tcl command will return a list with the * name of the Tcl command and other info. *---------------------------------------------------------------------- */ int curlMultiGetInfo(Tcl_Interp *interp,CURLM *curlMultiHandlePtr) { struct CURLMsg *multiInfo; int msgLeft; Tcl_Obj *resultPtr; multiInfo=curl_multi_info_read(curlMultiHandlePtr, &msgLeft); resultPtr=Tcl_NewListObj(0,(Tcl_Obj **)NULL); if (multiInfo==NULL) { Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewStringObj("",-1)); Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(0)); Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(0)); Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(0)); } else { Tcl_ListObjAppendElement(interp,resultPtr, Tcl_NewStringObj(curlGetEasyName(curlMultiHandlePtr,multiInfo->easy_handle),-1)); Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(multiInfo->msg)); Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(multiInfo->data.result)); Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(msgLeft)); } Tcl_SetObjResult(interp,resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlMultiActiveTransfers -- * This function is used to know whether an connection is ready to * transfer data. This code has been copied almost verbatim from * libcurl's examples. * * Parameter: * multiHandlePtr: Pointer to the multi handle of the transfer. * * Results: * *---------------------------------------------------------------------- */ int curlMultiGetActiveTransfers( struct curlMultiObjData *curlMultiData) { struct timeval timeout; int selectCode; int maxfd; FD_ZERO(&(curlMultiData->fdread)); FD_ZERO(&(curlMultiData->fdwrite)); FD_ZERO(&(curlMultiData->fdexcep)); /* set a suitable timeout to play around with */ timeout.tv_sec = 1; timeout.tv_usec = 0; /* get file descriptors from the transfers */ curl_multi_fdset(curlMultiData->mcurl, &(curlMultiData->fdread), &(curlMultiData->fdwrite), &(curlMultiData->fdexcep), &maxfd); selectCode = select(maxfd+1, &(curlMultiData->fdread) , &(curlMultiData->fdwrite), &(curlMultiData->fdexcep) , &timeout); return selectCode; } /* *---------------------------------------------------------------------- * * curlMultiActiveTransfers -- * Implements the Tcl 'active', it queries the multi handle to know * if any of the connections are ready to transfer data. * * Parameter: * interp: The Tcl interpreter we are using, mainly to report errors. * curlMultiHandlePtr: Pointer to the multi handle of the transfer. * * Results: * Standard Tcl codes. The Tcl command will return the number of * transfers. *---------------------------------------------------------------------- */ int curlMultiActiveTransfers(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData) { int selectCode; Tcl_Obj *resultPtr; selectCode = curlMultiGetActiveTransfers(curlMultiData); if (selectCode==-1) { return TCL_ERROR; } resultPtr=Tcl_NewIntObj(selectCode); Tcl_SetObjResult(interp,resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlGetEasyHandle -- * * Given the name of an easy curl handle (curl1,...), in a Tcl object * this function will return the pointer the 'internal' libcurl handle. * * Parameter: * The Tcl object with the name. * * Results: * The pointer to the libcurl handle *---------------------------------------------------------------------- */ struct curlObjData * curlGetEasyHandle(Tcl_Interp *interp,Tcl_Obj *nameObjPtr) { char *handleName; Tcl_CmdInfo *infoPtr=(Tcl_CmdInfo *)Tcl_Alloc(sizeof(Tcl_CmdInfo)); struct curlObjData *curlDataPtr; handleName=Tcl_GetString(nameObjPtr); if (0==Tcl_GetCommandInfo(interp,handleName,infoPtr)) { return NULL; } curlDataPtr=(struct curlObjData *)(infoPtr->objClientData); Tcl_Free((char *)infoPtr); return curlDataPtr; } /* *---------------------------------------------------------------------- * * curlMultiFreeSpace -- * * Frees the space taken by a curlMultiObjData struct. * * Parameter: * interp: Pointer to the interpreter we are using. * curlMultiHandle: the curl handle for which the option is set. * objc and objv: The usual in Tcl. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ void curlMultiFreeSpace(struct curlMultiObjData *curlMultiData) { curl_multi_cleanup(curlMultiData->mcurl); Tcl_Free(curlMultiData->postCommand); Tcl_Free((char *)curlMultiData); } /* *---------------------------------------------------------------------- * * curlEasyHandleListAdd * Adds an easy handle to the list of handles in a multiHandle. * * Parameter: * multiDataPtr: Pointer to the struct of the multi handle. * easyHandle: The easy handle to add to the list. * * Results: *---------------------------------------------------------------------- */ void curlEasyHandleListAdd(struct curlMultiObjData *multiDataPtr,CURL *easyHandlePtr,char *name) { struct easyHandleList *easyHandleListPtr; easyHandleListPtr=(struct easyHandleList *)Tcl_Alloc(sizeof(struct easyHandleList)); easyHandleListPtr->curl =easyHandlePtr; easyHandleListPtr->name =curlstrdup(name); easyHandleListPtr->next=NULL; if (multiDataPtr->handleListLast==NULL) { multiDataPtr->handleListFirst=easyHandleListPtr; multiDataPtr->handleListLast =easyHandleListPtr; } else { multiDataPtr->handleListLast->next=easyHandleListPtr; multiDataPtr->handleListLast=easyHandleListPtr; } } /* *---------------------------------------------------------------------- * * curlEasyHandleListRemove * When we remove an easy handle from the multiHandle, this function * will remove said handle from the linked list. * * Parameter: * multiDataPtr: Pointer to the struct of the multi handle. * easyHandle: The easy handle to add to the list. * * Results: *---------------------------------------------------------------------- */ void curlEasyHandleListRemove(struct curlMultiObjData *multiDataPtr,CURL *easyHandle) { struct easyHandleList *listPtr1,*listPtr2; listPtr1=NULL; listPtr2=multiDataPtr->handleListFirst; while(listPtr2!=NULL) { if (listPtr2->curl==easyHandle) { if (listPtr1==NULL) { multiDataPtr->handleListFirst=listPtr2->next; } else { listPtr1->next=listPtr2->next; } if (listPtr2==multiDataPtr->handleListLast) { multiDataPtr->handleListLast=listPtr1; } Tcl_Free(listPtr2->name); Tcl_Free((char *)listPtr2); break; } listPtr1=listPtr2; listPtr2=listPtr2->next; } } /* *---------------------------------------------------------------------- * * curlGetEasyName * * Given the pointer to an easy handle, this function will return * the name of the Tcl command. * * Parameter: * multiDataPtr: Multi handle we are using. * easyHandle: The easy handle whose Tcl command we want to know. * * Results: * A string with the name of the command. *---------------------------------------------------------------------- */ char * curlGetEasyName(struct curlMultiObjData *multiDataPtr,CURL *easyHandle) { struct easyHandleList *listPtr; listPtr=multiDataPtr->handleListFirst; while(listPtr!=NULL) { if (listPtr->curl==easyHandle) { return listPtr->name; } listPtr=listPtr->next; } return NULL; } /* *---------------------------------------------------------------------- * * curlReturnCURLMcode * * When one of the command wants to return a CURLMcode, it calls * this function. * * Parameter: * interp: Pointer to the interpreter we are using. * errorCode: the value to be returned. * * Results: * A standard Tcl result. *---------------------------------------------------------------------- */ int curlReturnCURLMcode (Tcl_Interp *interp,CURLMcode errorCode) { Tcl_Obj *resultPtr; resultPtr=Tcl_NewIntObj(errorCode); Tcl_SetObjResult(interp,resultPtr); if (errorCode>0) { return TCL_ERROR; } return TCL_OK; } /*---------------------------------------------------------------------- * * curlMultiAutoTransfer -- * * Creates the event source that will take care of downloading using * the multi interface driven by Tcl's event loop. * * Parameters: * The usual Tcl command parameters. * * Results: * Standard Tcl return code. *---------------------------------------------------------------------- */ int curlMultiAutoTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc,Tcl_Obj *const objv[]) { if (objc==4) { Tcl_Free(curlMultiData->postCommand); curlMultiData->postCommand=curlstrdup(Tcl_GetString(objv[3])); } Tcl_CreateEventSource((Tcl_EventSetupProc *)curlEventSetup, (Tcl_EventCheckProc *)curlEventCheck, (ClientData *)curlMultiData); /* We have to call perform once to boot the transfer, otherwise it seems nothing works *shrug* */ while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curlMultiData->mcurl,&(curlMultiData->runningTransfers))) { } return TCL_OK; } /*---------------------------------------------------------------------- * * curlMultiConfigTrasnfer -- * This procedure is invoked by the user command 'configure', it reads * the options passed by the user to configure a multi handle. * * Parameters: * The usual Tcl command parameters. * * Results: * Standard Tcl return code. *---------------------------------------------------------------------- */ int curlMultiConfigTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc,Tcl_Obj *const objv[]) { int tableIndex; int i,j; Tcl_Obj *resultPtr; char errorMsg[500]; for(i=2,j=3;imcurl, multiConfigDispatch[tableIndex].option,tableIndex,objv)) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * SetMultiOptLong -- * * Set the curl options that require a long * * Parameter: * interp: The interpreter we are working with. * curlMultiHandle: and the multi curl handle * opt: the option to set * tclObj: The Tcl with the value for the option. * * Results: * 0 if all went well. * 1 in case of error. *---------------------------------------------------------------------- */ int SetMultiOptLong(Tcl_Interp *interp,CURLM *curlMultiHandle,CURLMoption opt, int tableIndex,Tcl_Obj *tclObj) { long longNumber; char *parPtr; if (Tcl_GetLongFromObj(interp,tclObj,&longNumber)) { parPtr=curlstrdup(Tcl_GetString(tclObj)); curlErrorSetOpt(interp,multiConfigTable,tableIndex,parPtr); Tcl_Free(parPtr); return 1; } if (curl_multi_setopt(curlMultiHandle,opt,longNumber)) { parPtr=curlstrdup(Tcl_GetString(tclObj)); curlErrorSetOpt(interp,multiConfigTable,tableIndex,parPtr); Tcl_Free(parPtr); return 1; } return 0; } /*---------------------------------------------------------------------- * * curlEventSetup -- * * This function is invoked by Tcl just after curlMultiAutoTransfer and * then every time just before curlEventCheck, I only use to set the * maximun time without checking for events * * NOTE: I hate having a fixed value, I will have to look into it. * * Parameters: * They are passed automagically by Tcl, but I don't use them. *---------------------------------------------------------------------- */ void curlEventSetup(ClientData clientData, int flags) { Tcl_Time time = {0 , 0}; Tcl_SetMaxBlockTime(&time); } /*---------------------------------------------------------------------- * * curlEventCheck -- * * Invoked automagically by Tcl from time to time, we check if there * are any active transfer, if so we put an event in the queue so that * 'curl_multi_perfom' will be eventually called, if not we delete * the event source. * * Parameters: * They are passed automagically by Tcl. *---------------------------------------------------------------------- */ void curlEventCheck(ClientData clientData, int flags) { struct curlMultiObjData *curlMultiData = (struct curlMultiObjData *)clientData; struct curlEvent *curlEventPtr; int selectCode; selectCode = curlMultiGetActiveTransfers(curlMultiData); if (curlMultiData->runningTransfers == 0) { Tcl_DeleteEventSource((Tcl_EventSetupProc *)curlEventSetup, (Tcl_EventCheckProc *)curlEventCheck, (ClientData *)curlMultiData); } else { if (selectCode >= 0) { curlEventPtr=(struct curlEvent *)Tcl_Alloc(sizeof(struct curlEvent)); curlEventPtr->proc=curlEventProc; curlEventPtr->curlMultiData=curlMultiData; Tcl_QueueEvent((Tcl_Event *)curlEventPtr, TCL_QUEUE_TAIL); } } } /*---------------------------------------------------------------------- * * curlEventProc -- * * Finally Tcl event loop decides it is time to transfer something. * * Parameters: * They are passed automagically by Tcl. *---------------------------------------------------------------------- */ int curlEventProc(Tcl_Event *evPtr,int flags) { struct curlMultiObjData *curlMultiData; //CURLMcode errorCode; Tcl_Obj *tclCommandObjPtr; char tclCommand[300]; curlMultiData = (struct curlMultiObjData *)((struct curlEvent *)evPtr)->curlMultiData; //errorCode=curl_multi_perform(curlMultiData->mcurl,&curlMultiData->runningTransfers); curl_multi_perform(curlMultiData->mcurl,&curlMultiData->runningTransfers); if (curlMultiData->runningTransfers==0) { if (curlMultiData->postCommand!=NULL) { snprintf(tclCommand,299,"%s",curlMultiData->postCommand); tclCommandObjPtr=Tcl_NewStringObj(tclCommand,-1); if (Tcl_EvalObjEx(curlMultiData->interp,tclCommandObjPtr,TCL_EVAL_GLOBAL)!=TCL_OK) { /* fprintf(stdout,"Error invoking command\n"); fprintf(stdout,"Error: %s\n",Tcl_GetString(Tcl_GetObjResult(curlMultiData->interp))); */ } } } return 1; } tclcurl-ng-8.0.3/generic/multi.h000066400000000000000000000117371522613063100165230ustar00rootroot00000000000000/* * multi.h -- * * Header file for the part of the TclCurl extension that deals with libcurl's * 'multi' interface. * * Copyright (c) 2002-2011 Andres Garcia Garcia. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #ifndef __multi_h__ #define __multi_h__ #include "tclcurl.h" #ifdef __cplusplus extern "C" { #endif struct easyHandleList { CURL *curl; char *name; struct easyHandleList *next; }; struct curlMultiObjData { CURLM *mcurl; Tcl_Command token; Tcl_Interp *interp; struct easyHandleList *handleListFirst; struct easyHandleList *handleListLast; fd_set fdread; fd_set fdwrite; fd_set fdexcep; int runningTransfers; char *postCommand; }; struct curlEvent { Tcl_EventProc *proc; struct Tcl_Event *nextPtr; struct curlMultiObjData *curlMultiData; }; #define TCLCURL_MULTI_COMMAND_LIST(X) \ X(TCLCURL_MULTI_CMD_ADDHANDLE, "addhandle", TclCurl_MultiDispatchAddHandle) \ X(TCLCURL_MULTI_CMD_REMOVEHANDLE, "removehandle", TclCurl_MultiDispatchRemoveHandle) \ X(TCLCURL_MULTI_CMD_PERFORM, "perform", TclCurl_MultiDispatchPerform) \ X(TCLCURL_MULTI_CMD_CLEANUP, "cleanup", TclCurl_MultiDispatchCleanup) \ X(TCLCURL_MULTI_CMD_GETINFO, "getinfo", TclCurl_MultiDispatchGetInfo) \ X(TCLCURL_MULTI_CMD_ACTIVE, "active", TclCurl_MultiDispatchActive) \ X(TCLCURL_MULTI_CMD_AUTO, "auto", TclCurl_MultiDispatchAuto) \ X(TCLCURL_MULTI_CMD_CONFIGURE, "configure", TclCurl_MultiDispatchConfigure) typedef enum { #define TCLCURL_MULTI_COMMAND_ENUM_ENTRY(name, label, proc) name, TCLCURL_MULTI_COMMAND_LIST(TCLCURL_MULTI_COMMAND_ENUM_ENTRY) #undef TCLCURL_MULTI_COMMAND_ENUM_ENTRY TCLCURL_MULTI_CMD_COUNT } TclCurlMultiCommandId; const static char *multiCommandTable[TCLCURL_MULTI_CMD_COUNT + 1] = { #define TCLCURL_MULTI_COMMAND_TABLE_ENTRY(name, label, proc) [name] = label, TCLCURL_MULTI_COMMAND_LIST(TCLCURL_MULTI_COMMAND_TABLE_ENTRY) #undef TCLCURL_MULTI_COMMAND_TABLE_ENTRY NULL }; #define TCLCURL_MULTI_CONFIG_LIST(X) \ X(TCLCURL_MULTI_CONFIG_PIPELINING, "-pipelining", CURLMOPT_PIPELINING, SetMultiOptLong) \ X(TCLCURL_MULTI_CONFIG_MAXCONNECTS, "-maxconnects", CURLMOPT_MAXCONNECTS, SetMultiOptLong) typedef enum { #define TCLCURL_MULTI_CONFIG_ENUM_ENTRY(name, label, opt, proc) name, TCLCURL_MULTI_CONFIG_LIST(TCLCURL_MULTI_CONFIG_ENUM_ENTRY) #undef TCLCURL_MULTI_CONFIG_ENUM_ENTRY TCLCURL_MULTI_CONFIG_COUNT } TclCurlMultiConfigId; const static char *multiConfigTable[TCLCURL_MULTI_CONFIG_COUNT + 1] = { #define TCLCURL_MULTI_CONFIG_TABLE_ENTRY(name, label, opt, proc) [name] = label, TCLCURL_MULTI_CONFIG_LIST(TCLCURL_MULTI_CONFIG_TABLE_ENTRY) #undef TCLCURL_MULTI_CONFIG_TABLE_ENTRY NULL }; char *curlCreateMultiObjCmd (Tcl_Interp *interp,struct curlMultiObjData *curlMultiData); int Tclcurl_MultiInit (Tcl_Interp *interp); int curlMultiDeleteCmd(ClientData clientData); int curlInitMultiObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlMultiObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); CURLMcode curlAddMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandle ,Tcl_Obj *objvPtr); CURLMcode curlRemoveMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandle ,Tcl_Obj *objvPtr); int curlMultiPerform(Tcl_Interp *interp,CURLM *curlMultiHandle); int curlMultiGetInfo(Tcl_Interp *interp,CURLM *curlMultiHandlePtr); int curlMultiGetActiveTransfers( struct curlMultiObjData *curlMultiData); int curlMultiActiveTransfers(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData); struct curlObjData *curlGetEasyHandle(Tcl_Interp *interp,Tcl_Obj *nameObjPtr); void curlMultiFreeSpace(struct curlMultiObjData *curlMultiData); int curlReturnCURLMcode(Tcl_Interp *interp,CURLMcode errorCode); void curlEasyHandleListAdd(struct curlMultiObjData *multiDataPtr,CURL *easyHandle,char *name); void curlEasyHandleListRemove(struct curlMultiObjData *multiDataPtr,CURL *easyHandle); char *curlGetEasyName(struct curlMultiObjData *multiDataPtr,CURL *easyHandle); int curlMultiAutoTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc,Tcl_Obj *const objv[]); int curlMultiSetOpts(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData,Tcl_Obj *const objv,int tableIndex); int SetMultiOptLong(Tcl_Interp *interp,CURLM *curlMultiHandle,CURLMoption opt, int tableIndex,Tcl_Obj *tclObj); int curlMultiConfigTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc,Tcl_Obj *const objv[]); void curlEventSetup(ClientData clientData, int flags); void curlEventCheck(ClientData clientData, int flags); int curlEventProc(Tcl_Event *evPtr,int flags); #ifdef __cplusplus } #endif #endif /* __multi_h __ */ tclcurl-ng-8.0.3/generic/tcl_size.c000066400000000000000000000012301522613063100171630ustar00rootroot00000000000000/* * tcl_size.c -- * * Checking and conversion of * * Copyright (c) 2026 Massimo Manghi * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include #include "tclcompat.h" /* size_t -> Tcl_Size */ int TclCurl_SizeT2TclSize(size_t in, Tcl_Size *out) { if (in > (size_t)TCL_SIZE_MAX) return 0; /* overflow for Tcl_Size */ *out = (Tcl_Size)in; return 1; } /* Tcl_Size -> size_t */ int TclCurl_TclSize2SizeT(Tcl_Size in, size_t *out) { if (in < 0) return 0; /* negative not representable as size_t */ *out = (size_t)in; return 1; } tclcurl-ng-8.0.3/generic/tclcompat.h000066400000000000000000000020241522613063100173440ustar00rootroot00000000000000#ifndef __tclcompat_h__ #define __tclcompat_h__ #include #include #include /* for INT_MAX etc. */ #include #ifndef CONST # define CONST const #endif #ifndef CONST84 # define CONST84 const #endif #ifndef CONST86 # define CONST86 const #endif #ifndef CONST84_RETURN # define CONST84_RETURN const #endif #ifndef TCL_SIZE_MAX # define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj # define TCL_SIZE_MAX INT_MAX # ifndef Tcl_Size typedef int Tcl_Size; # endif # define TCL_SIZE_MODIFIER "" #endif /* Definition suggested in * * https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Particular-Headers.html * * in order to have a portable definition of the 'bool' data type */ #ifdef HAVE_STDBOOL_H # include #else # ifndef HAVE__BOOL # ifdef __cplusplus typedef bool _Bool; # else # define _Bool signed char # endif # endif # define bool _Bool # define false 0 # define true 1 # define __bool_true_false_are_defined 1 #endif #endif /* __tclcompat_h */ tclcurl-ng-8.0.3/generic/tclcurl.c000066400000000000000000002121561522613063100170320ustar00rootroot00000000000000/* * tclcurl.c -- * * Implementation of the TclCurl extension that creates the curl namespace * so that Tcl interpreters can access libcurl. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "tclcurl.h" #ifdef _WIN32 #define UNICODE #define _UNICODE #include #endif #include "tclcurl.h" #include "curl_mime.h" #ifndef _WIN32 #include #endif #include /* for size_t */ #ifndef multi_h #ifdef TCL_THREADS TCL_DECLARE_MUTEX(cookieLock) TCL_DECLARE_MUTEX(dnsLock) TCL_DECLARE_MUTEX(sslLock) TCL_DECLARE_MUTEX(connectLock) void curlShareLockFunc (CURL *handle, curl_lock_data data, curl_lock_access access, void *userptr); void curlShareUnLockFunc(CURL *handle, curl_lock_data data, void *userptr); #endif #endif const static char *lockData[] = { "cookies", "dns", (char *)NULL }; const static char *shareCmd[] = { "share", "unshare", "cleanup", (char *)NULL }; const static char *versionInfoTable[] = { "-version", "-versionnum", "-host", "-features", "-sslversion", "-sslversionnum", "-libzversion", "-protocols", (char *)NULL }; #define TCLCURL_COMMANDS(X) \ X(TCLCURL_CMD_SETOPT,"setopt") \ X(TCLCURL_CMD_PERFORM,"perform") \ X(TCLCURL_CMD_GETINFO,"getinfo") \ X(TCLCURL_CMD_CLEANUP,"cleanup") \ X(TCLCURL_CMD_CONFIGURE,"configure") \ X(TCLCURL_CMD_DUPHANDLE,"duphandle") \ X(TCLCURL_CMD_RESET,"reset") \ X(TCLCURL_CMD_PAUSE,"pause") \ X(TCLCURL_CMD_RESUME,"resume") typedef enum { #define X(sym,cmd) sym, TCLCURL_COMMANDS(X) #undef X TCLCURL_CMD_COUNT } tclcurl_cmd_id; static const char* const commandTable[TCLCURL_CMD_COUNT] = { #define X(sym, cmd) [sym] = cmd, TCLCURL_COMMANDS(X) #undef X }; static struct shcurlObjData * curlGetShareDataFromToken(Tcl_Command token) { Tcl_CmdInfo info; if ((token == NULL) || !Tcl_GetCommandInfoFromToken(token, &info)) { return NULL; } return (struct shcurlObjData *) info.objClientData; } static void curlLinkEasyToShare(struct curlObjData *curlData, struct shcurlObjData *shcurlData) { curlData->shareToken = shcurlData->token; curlData->nextSharedHandle = shcurlData->users; shcurlData->users = curlData; } void curlDetachShareHandle(struct curlObjData *curlData) { struct shcurlObjData *shcurlData; struct curlObjData **linkPtr; if (curlData->shareToken == NULL) { curlData->nextSharedHandle = NULL; return; } if (curlData->curl != NULL) { curl_easy_setopt(curlData->curl, CURLOPT_SHARE, NULL); } shcurlData = curlGetShareDataFromToken(curlData->shareToken); if (shcurlData != NULL) { for (linkPtr = &shcurlData->users; *linkPtr != NULL; linkPtr = &(*linkPtr)->nextSharedHandle) { if (*linkPtr == curlData) { *linkPtr = curlData->nextSharedHandle; break; } } } curlData->shareToken = NULL; curlData->nextSharedHandle = NULL; } /* *---------------------------------------------------------------------- * * Tclcurl_Init -- * * This procedure initializes the package * * Results: * A standard Tcl result. * *---------------------------------------------------------------------- */ EXTERN int Tclcurl_Init (Tcl_Interp *interp) { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp,"8.6-10",0)==NULL) { return TCL_ERROR; } #else if (Tcl_PkgRequire(interp,"Tcl","8.6-10",0)==NULL) { return TCL_ERROR; } #endif Tcl_CreateObjCommand (interp,"::curl::init",curlInitObjCmd, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::version",curlVersion, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::escape",curlEscape, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::unescape",curlUnescape, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::versioninfo",curlVersionInfo, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::shareinit",curlShareInitObjCmd, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::easystrerror",curlEasyStringError, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::sharestrerror",curlShareStringError, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand (interp,"::curl::multistrerror",curlMultiStringError, (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL); Tclcurl_MultiInit(interp); Tcl_PkgProvide(interp,"TclCurl",PACKAGE_VERSION); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlCreateObjCmd -- * * Looks for the first free handle (curl1, curl2,...) and creates a * Tcl command for it. * * Results: * A string with the name of the handle, don't forget to free it. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ Tcl_Obj * curlCreateObjCmd (Tcl_Interp *interp,struct curlObjData *curlData) { char handleName[32]; int i; Tcl_CmdInfo info; Tcl_Command cmdToken; /* We try with curl1, if it already exists with curl2...*/ for (i=1;;i++) { snprintf(handleName,sizeof(handleName),"curl%d",i); if (!Tcl_GetCommandInfo(interp,handleName,&info)) { cmdToken=Tcl_CreateObjCommand(interp,handleName,curlObjCmd, (ClientData)curlData, (Tcl_CmdDeleteProc *)curlDeleteCmd); break; } } curlData->token=cmdToken; return Tcl_NewStringObj(handleName,-1); } /* *---------------------------------------------------------------------- * * curlInitObjCmd -- * * This procedure is invoked to process the "curl::init" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlInitObjCmd (ClientData clientData,Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { Tcl_Obj *resultPtr; CURL *curlHandle; struct curlObjData *curlData; Tcl_Obj *handleObj; curlData = (struct curlObjData *)Tcl_Alloc(sizeof(struct curlObjData)); if (curlData == NULL) { resultPtr=Tcl_NewStringObj("Couldn't allocate memory",-1); Tcl_SetObjResult(interp,resultPtr); return TCL_ERROR; } memset(curlData, 0, sizeof(struct curlObjData)); curlData->interp = interp; curlData->postFieldSize = -1; /* This is required to be done when the package is loaded * and before any thread is created. It's not recommended to * assume curllib will call it implicitly */ curl_global_init(CURL_GLOBAL_DEFAULT); /* And then we call curl_easy_init() */ curlHandle = curl_easy_init(); if (curlHandle == NULL) { resultPtr=Tcl_NewStringObj("Couldn't open curl handle",-1); Tcl_SetObjResult(interp,resultPtr); return TCL_ERROR; } handleObj = curlCreateObjCmd(interp,curlData); /* This is the curl central data structure. In meany examples * it referred to as 'easy' because returned by the curl_easy_init() * call */ curlData->curl = curlHandle; Tcl_SetObjResult(interp,handleObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlObjCmd -- * * This procedure is invoked to process the "curl" commands. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { struct curlObjData *curlData = (struct curlObjData *)clientData; CURL *curlHandle=curlData->curl; int tableIndex; if (objc<2) { Tcl_WrongNumArgs(interp,1,objv,"option arg ?arg?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], commandTable, "option", TCL_EXACT,&tableIndex)==TCL_ERROR) { return TCL_ERROR; } switch(tableIndex) { case TCLCURL_CMD_SETOPT: if (objc != 4) { Tcl_WrongNumArgs(interp,2,objv,"option value"); return TCL_ERROR; } if (curlSetOptsTransfer(interp,curlData,objc,objv) == TCL_ERROR) { return TCL_ERROR; } break; case TCLCURL_CMD_PERFORM: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } if (curlPerform(interp,curlHandle,curlData)) { if (curlData->errorBuffer != NULL) { if (curlData->errorBufferKey == NULL) { Tcl_SetVar(interp,curlData->errorBufferName, curlData->errorBuffer,0); } else { Tcl_SetVar2(interp,curlData->errorBufferName, curlData->errorBufferKey, curlData->errorBuffer,0); } } return TCL_ERROR; } break; case TCLCURL_CMD_GETINFO: { Tcl_Obj* resultObjPtr; if (objc != 3) { Tcl_WrongNumArgs(interp,2,objv,"option"); return TCL_ERROR; } if (TclCurl_GetInfo(interp,objv[2],curlHandle,&resultObjPtr)) { return TCL_ERROR; } Tcl_SetObjResult(interp,resultObjPtr); break; } case TCLCURL_CMD_CLEANUP: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } Tcl_DeleteCommandFromToken (interp,curlData->token); break; case TCLCURL_CMD_CONFIGURE: if (objc < 4 || objc % 2) { Tcl_WrongNumArgs(interp,2,objv,"option value ?option value ...?"); return TCL_ERROR; } if (curlConfigTransfer(interp,curlData,objc,objv) == TCL_ERROR) { return TCL_ERROR; } break; case TCLCURL_CMD_DUPHANDLE: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } if (curlDupHandle(interp,curlData,objc,objv) == TCL_ERROR) { return TCL_ERROR; } break; case TCLCURL_CMD_RESET: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } if (curlResetHandle(interp,curlData) == TCL_ERROR) { return TCL_ERROR; } break; case TCLCURL_CMD_PAUSE: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } if (curl_easy_pause(curlData->curl,CURLPAUSE_ALL) == TCL_ERROR) { return TCL_ERROR; } break; case TCLCURL_CMD_RESUME: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } if (curl_easy_pause(curlData->curl,CURLPAUSE_CONT) == TCL_ERROR) { return TCL_ERROR; } break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * curlDeleteCmd -- * * This procedure is invoked when curl handle is deleted. * * Results: * A standard Tcl result. * * Side effects: * Cleans the curl handle and frees the memory. * *---------------------------------------------------------------------- */ int curlDeleteCmd(ClientData clientData) { struct curlObjData *curlData=(struct curlObjData *)clientData; CURL *curlHandle=curlData->curl; curlDetachShareHandle(curlData); curl_easy_cleanup(curlHandle); curlFreeSpace(curlData); Tcl_Free((char *)curlData); return TCL_OK; } /*---------------------------------------------------------------------- * * curlseek -- * * When the user requests the 'any' auth, libcurl may need * to send the PUT/POST data more than once and thus may need to ask * the app to "rewind" the read data stream to start. * *---------------------------------------------------------------------- */ static int curlseek(void *instream, curl_off_t offset, int origin) { if (-1 == fseek((FILE *)instream, 0, origin)) { return CURLIOE_FAILRESTART; } return CURLIOE_OK; } /* *---------------------------------------------------------------------- * * curlPerform -- * * Invokes the libcurl function 'curl_easy_perform' * * Parameter: * interp: Pointer to the interpreter we are using. * curlHandle: the curl handle for which the option is set. * objc and objv: The usual in Tcl. * * Results: * Standard Tcl return codes. *---------------------------------------------------------------------- */ int curlPerform(Tcl_Interp *interp,CURL *curlHandle,struct curlObjData *curlData) { int exitCode; Tcl_Obj *resultPtr; if (curlOpenFiles(interp,curlData)) { return TCL_ERROR; } if (TclCurl_SetPostData(interp,curlData)) { return TCL_ERROR; } exitCode = curl_easy_perform(curlHandle); resultPtr = Tcl_NewIntObj(exitCode); Tcl_SetObjResult(interp,resultPtr); curlCloseFiles(curlData); TclCurl_ResetPostData(curlData); if (curlData->bodyVarName) { curlSetBodyVarName(interp,curlData); } if (curlData->command) { Tcl_GlobalEval(interp,curlData->command); } return exitCode; } /* *---------------------------------------------------------------------- * * SetoptsList -- * * Prepares a slist for future use. * * Parameters: * slistPtr: Pointer to the slist to prepare. * objv: Tcl object with a list of the data. * * Results: * 0 if all went well. * 1 in case of error. * *---------------------------------------------------------------------- */ int SetoptsList(Tcl_Interp *interp,struct curl_slist **slistPtr,Tcl_Obj *CONST objv) { Tcl_Size i,headerNumber; Tcl_Obj** headers; if (slistPtr != NULL) { curl_slist_free_all(*slistPtr); *slistPtr = NULL; } if (Tcl_ListObjGetElements(interp,objv,&headerNumber,&headers) == TCL_ERROR) { return 1; } for (i=0;iinterp,"(.*?)(?::\\s*)(.*?)(\\r*)(\\n)"); match=Tcl_RegExpExec(curlData->interp,regExp,header,header); if (match) { Tcl_RegExpRange(regExp,1,&startPtr,&endPtr); charLength=endPtr-startPtr; headerName=Tcl_Alloc(charLength+1); strncpy(headerName,startPtr,charLength); headerName[charLength]=0; Tcl_RegExpRange(regExp,2,&startPtr,&endPtr); charLength=endPtr-startPtr; headerContent=Tcl_Alloc(charLength+1); strncpy(headerContent,startPtr,charLength); headerContent[charLength]=0; /* There may be multiple 'Set-Cookie' headers, so we use a list */ if (Tcl_StringCaseMatch(headerName,"Set-Cookie",1)) { Tcl_SetVar2 (curlData->interp, curlData->headerVar,headerName, headerContent,TCL_LIST_ELEMENT|TCL_APPEND_VALUE); } else { Tcl_SetVar2(curlData->interp, curlData->headerVar,headerName, headerContent,0); } Tcl_Free(headerContent); Tcl_Free(headerName); } regExp=Tcl_RegExpCompile(curlData->interp,"(^(HTTP|http)[^\r]+)(\r*)(\n)"); match=Tcl_RegExpExec(curlData->interp,regExp,header,header); if (match) { Tcl_RegExpRange(regExp,1,&startPtr,&endPtr); charLength=endPtr-startPtr; httpStatus=Tcl_Alloc(charLength+1); strncpy(httpStatus,startPtr,charLength); httpStatus[charLength]=0; Tcl_SetVar2(curlData->interp,curlData->headerVar,"http", httpStatus,0); Tcl_Free(httpStatus); } return size*nmemb; } /* *---------------------------------------------------------------------- * * curlBodyReader -- * * This is the function that will be invoked as a callback while * transferring the body of a request into a Tcl variable. * * This function has been adapted from an example in libcurl's FAQ. * * Parameters: * header: string with the header line. * size and nmemb: it so happens size * nmemb if the size of the * header string. * curlData: A pointer to the curlData structure for the transfer. * * Results: * The number of bytes actually written or -1 in case of error, in * which case 'libcurl' will abort the transfer. * *----------------------------------------------------------------------- */ size_t curlBodyReader(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr) { register int realsize = size * nmemb; struct MemoryStruct *mem=&(((struct curlObjData *)curlDataPtr)->bodyVar); mem->memory = (char *)Tcl_Realloc(mem->memory,mem->size + realsize); if (mem->memory) { memcpy(&(mem->memory[mem->size]), ptr, realsize); mem->size += realsize; } return realsize; } /* *---------------------------------------------------------------------- * * curlProgressCallback -- * * This is the function that will be invoked as a callback during a * transfer. * * This function has been adapted from an example in libcurl's FAQ. * * Parameters: * clientData: The curlData struct for the transfer. * dltotal: Total amount of bytes to download. * dlnow: Bytes downloaded so far. * ultotal: Total amount of bytes to upload. * ulnow: Bytes uploaded so far. * * Results: * Returning a non-zero value will make 'libcurl' abort the transfer * and return 'CURLE_ABORTED_BY_CALLBACK'. * *----------------------------------------------------------------------- */ int curlProgressCallback(void *clientData,curl_off_t dltotal,curl_off_t dlnow, curl_off_t ultotal,curl_off_t ulnow) { struct curlObjData *curlData=(struct curlObjData *)clientData; Tcl_Obj *tclProcPtr; if (curlData->cancelTransVarName) { if (curlData->cancelTrans) { curlData->cancelTrans=0; return -1; } } tclProcPtr = Tcl_NewListObj(0, 0); Tcl_ListObjAppendElement(curlData->interp, tclProcPtr, Tcl_NewStringObj(curlData->progressProc, -1)); Tcl_ListObjAppendElement(curlData->interp, tclProcPtr, Tcl_NewWideIntObj((Tcl_WideInt)dltotal)); Tcl_ListObjAppendElement(curlData->interp, tclProcPtr, Tcl_NewWideIntObj((Tcl_WideInt)dlnow)); Tcl_ListObjAppendElement(curlData->interp, tclProcPtr, Tcl_NewWideIntObj((Tcl_WideInt)ultotal)); Tcl_ListObjAppendElement(curlData->interp, tclProcPtr, Tcl_NewWideIntObj((Tcl_WideInt)ulnow)); Tcl_IncrRefCount(tclProcPtr); if (Tcl_EvalObjEx(curlData->interp,tclProcPtr,TCL_EVAL_GLOBAL)!=TCL_OK) { Tcl_DecrRefCount(tclProcPtr); return -1; } Tcl_DecrRefCount(tclProcPtr); return 0; } /* *---------------------------------------------------------------------- * * curlWriteProcInvoke -- * * This is the function that will be invoked as a callback when the user * wants to invoke a Tcl procedure to write the recieved data. * * This function has been adapted from an example in libcurl's FAQ. * * Parameters: * ptr: A pointer to the data. * size and nmemb: it so happens size * nmemb if the size of the * data read. * curlData: A pointer to the curlData structure for the transfer. * * Results: * The number of bytes actually written or -1 in case of error, in * which case 'libcurl' will abort the transfer. * *----------------------------------------------------------------------- */ size_t curlWriteProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr) { register int realsize = size * nmemb; struct curlObjData *curlData = (struct curlObjData *)curlDataPtr; register int curl_retcode; int code; int cmd_list_size; const char **argvPtr; Tcl_Size argcPtr; Tcl_Obj** objList; int i; if (curlData->cancelTransVarName) { if (curlData->cancelTrans) { curlData->cancelTrans = 0; return -1; } } curl_retcode = realsize; if (Tcl_SplitList(curlData->interp,curlData->writeProc,&argcPtr,&argvPtr) != TCL_OK) { return -1; } cmd_list_size = argcPtr; objList = (Tcl_Obj **) Tcl_Alloc((cmd_list_size+1)*sizeof(Tcl_Obj*)); for (i = 0; i < cmd_list_size; i++) { objList[i] = Tcl_NewStringObj(argvPtr[i],-1); Tcl_IncrRefCount(objList[i]); } objList[cmd_list_size] = Tcl_NewByteArrayObj(ptr,realsize); Tcl_IncrRefCount(objList[cmd_list_size]); code = Tcl_EvalObjv(curlData->interp,cmd_list_size+1,objList,TCL_EVAL_GLOBAL); if (code != TCL_OK) { curl_retcode = -1; } for (i = 0; i <= cmd_list_size; i++) { Tcl_DecrRefCount(objList[i]); } Tcl_Free((char *)objList); Tcl_Free((char *)argvPtr); return curl_retcode; } /* *---------------------------------------------------------------------- * * curlReadProcInvoke -- * * This is the function that will be invoked as a callback when the user * wants to invoke a Tcl procedure to read the data to send. * * Parameters: * header: string with the header line. * size and nmemb: it so happens size * nmemb if the size of the * header string. * curlData: A pointer to the curlData structure for the transfer. * * Results: * The number of bytes actually read or CURL_READFUNC_ABORT in case * of error, in which case 'libcurl' will abort the transfer. * *----------------------------------------------------------------------- */ size_t curlReadProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr) { register int realsize = size * nmemb; struct curlObjData *curlData=(struct curlObjData *)curlDataPtr; Tcl_Obj *tclProcPtr; Tcl_Obj *readDataPtr; unsigned char *readBytes; Tcl_Size sizeRead; if (curlData->cancelTransVarName) { if (curlData->cancelTrans) { curlData->cancelTrans=0; return CURL_READFUNC_ABORT; } } tclProcPtr=Tcl_ObjPrintf("%s %d",curlData->readProc,realsize); Tcl_IncrRefCount(tclProcPtr); if (Tcl_EvalObjEx(curlData->interp,tclProcPtr,TCL_EVAL_GLOBAL)!=TCL_OK) { Tcl_DecrRefCount(tclProcPtr); return CURL_READFUNC_ABORT; } Tcl_DecrRefCount(tclProcPtr); readDataPtr=Tcl_GetObjResult(curlData->interp); readBytes=Tcl_GetByteArrayFromObj(readDataPtr,&sizeRead); memcpy(ptr,readBytes,sizeRead); return sizeRead; } /* *---------------------------------------------------------------------- * * curlChunkBgnProcInvoke -- * * This is the function that will be invoked as a callback when the user * wants to invoke a Tcl procedure to process every wildcard matching file * on a ftp transfer. * * Parameters: * transfer_info: a curl_fileinfo structure about the file. * curlData: A pointer to the curlData structure for the transfer. * remains: number of chunks remaining. * *----------------------------------------------------------------------- */ long curlChunkBgnProcInvoke (const void *transfer_info, void *curlDataPtr, int remains) { struct curlObjData *curlData=(struct curlObjData *)curlDataPtr; Tcl_Obj *tclProcPtr; int i; const struct curl_fileinfo *fileinfoPtr=(const struct curl_fileinfo *)transfer_info; if (curlData->chunkBgnVar==NULL) { curlData->chunkBgnVar=curlstrdup("fileData"); } Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filename", fileinfoPtr->filename,0); switch(fileinfoPtr->filetype) { case 0: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","file",0); break; case 1: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","directory",0); break; case 2: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","symlink",0); break; case 3: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","device block",0); break; case 4: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","device char",0); break; case 5: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","named pipe",0); break; case 6: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","socket",0); break; case 7: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","door",0); break; case 8: Tcl_SetVar2(curlData->interp,curlData->chunkBgnVar,"filetype","error",0); break; } Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"time", Tcl_NewLongObj(fileinfoPtr->time),0); Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"perm", Tcl_NewIntObj(fileinfoPtr->perm),0); Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"uid", Tcl_NewIntObj(fileinfoPtr->uid),0); Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"gid", Tcl_NewIntObj(fileinfoPtr->gid),0); Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"size", Tcl_NewLongObj(fileinfoPtr->size),0); Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"hardlinks", Tcl_NewIntObj(fileinfoPtr->hardlinks),0); Tcl_SetVar2Ex(curlData->interp,curlData->chunkBgnVar,"flags", Tcl_NewIntObj(fileinfoPtr->flags),0); tclProcPtr=Tcl_ObjPrintf("%s %d",curlData->chunkBgnProc,remains); Tcl_IncrRefCount(tclProcPtr); if (Tcl_EvalObjEx(curlData->interp,tclProcPtr,TCL_EVAL_GLOBAL)!=TCL_OK) { Tcl_DecrRefCount(tclProcPtr); return CURL_CHUNK_BGN_FUNC_FAIL; } Tcl_DecrRefCount(tclProcPtr); if (Tcl_GetIntFromObj(curlData->interp,Tcl_GetObjResult(curlData->interp),&i)!=TCL_OK) { return CURL_CHUNK_BGN_FUNC_FAIL; } switch(i) { case 0: return CURL_CHUNK_BGN_FUNC_OK; case 1: return CURL_CHUNK_BGN_FUNC_SKIP; } return CURL_CHUNK_BGN_FUNC_FAIL; } /* *---------------------------------------------------------------------- * * curlChunkEndProcInvoke -- * * This is the function that will be invoked every time a file has * been downloaded or skipped, it does little more than called the * given proc. * * Parameters: * curlData: A pointer to the curlData structure for the transfer. * * Results: * *----------------------------------------------------------------------- */ long curlChunkEndProcInvoke (void *curlDataPtr) { struct curlObjData *curlData=(struct curlObjData *)curlDataPtr; Tcl_Obj *tclProcPtr; int i; tclProcPtr=Tcl_NewStringObj(curlData->chunkEndProc,-1); Tcl_IncrRefCount(tclProcPtr); if (Tcl_EvalObjEx(curlData->interp,tclProcPtr,TCL_EVAL_GLOBAL)!=TCL_OK) { Tcl_DecrRefCount(tclProcPtr); return CURL_CHUNK_END_FUNC_FAIL; } Tcl_DecrRefCount(tclProcPtr); if (Tcl_GetIntFromObj(curlData->interp,Tcl_GetObjResult(curlData->interp),&i)!=TCL_OK) { return CURL_CHUNK_END_FUNC_FAIL; } if (i==1) { return CURL_CHUNK_BGN_FUNC_FAIL; } return CURL_CHUNK_END_FUNC_OK; } /* *---------------------------------------------------------------------- * * curlfnmatchProcInvoke -- * * This is the function that will be invoked to tell whether a filename * matches a pattern when doing a 'wildcard' download. It invokes a Tcl * proc to do the actual work. * * Parameters: * curlData: A pointer to the curlData structure for the transfer. * pattern: The pattern to match. * filename: The file name to be matched. * *----------------------------------------------------------------------- */ int curlfnmatchProcInvoke(void *curlDataPtr, const char *pattern, const char *filename) { struct curlObjData *curlData=(struct curlObjData *)curlDataPtr; Tcl_Obj *tclProcPtr; int i; tclProcPtr=Tcl_ObjPrintf("%s %s %s",curlData->fnmatchProc,pattern,filename); Tcl_IncrRefCount(tclProcPtr); if (Tcl_EvalObjEx(curlData->interp,tclProcPtr,TCL_EVAL_GLOBAL)!=TCL_OK) { Tcl_DecrRefCount(tclProcPtr); return CURL_FNMATCHFUNC_FAIL; } Tcl_DecrRefCount(tclProcPtr); if (Tcl_GetIntFromObj(curlData->interp,Tcl_GetObjResult(curlData->interp),&i)!=TCL_OK) { return CURL_FNMATCHFUNC_FAIL; } switch(i) { case 0: return CURL_FNMATCHFUNC_MATCH; case 1: return CURL_FNMATCHFUNC_NOMATCH; } return CURL_FNMATCHFUNC_FAIL; } /* *---------------------------------------------------------------------- * * curlshkeyextract -- * * Out of one of libcurl's ssh key struct, this function will return a * Tcl_Obj with a list, the first element is the type ok key, the second * the key itself. * * Parameters: * interp: The interp need to deal with the objects. * key: a curl_khkey struct with the key. * * Results: * The object with the list. * *----------------------------------------------------------------------- */ Tcl_Obj * curlsshkeyextract(Tcl_Interp *interp,const struct curl_khkey *key) { Tcl_Obj *keyObjPtr; keyObjPtr=Tcl_NewListObj(0,(Tcl_Obj **)NULL); switch(key->keytype) { case CURLKHTYPE_RSA1: Tcl_ListObjAppendElement(interp,keyObjPtr,Tcl_NewStringObj("rsa1",-1)); break; case CURLKHTYPE_RSA: Tcl_ListObjAppendElement(interp,keyObjPtr,Tcl_NewStringObj("rsa",-1)); break; case CURLKHTYPE_DSS: Tcl_ListObjAppendElement(interp,keyObjPtr,Tcl_NewStringObj("dss",-1)); break; default: Tcl_ListObjAppendElement(interp,keyObjPtr,Tcl_NewStringObj("unknnown",-1)); break; } Tcl_ListObjAppendElement(interp,keyObjPtr,Tcl_NewStringObj(key->key,-1)); return keyObjPtr; } /* *---------------------------------------------------------------------- * * curlshkeycallback -- * * This is the function that will be invoked as a callback when the user * wants to invoke a Tcl procedure to decide about this new ssh host * * Parameters: * curl: curl's easy handle for the connection. * knownkey: The key from the hosts_file. * foundkey: The key from the remote site. * match: What libcurl thinks about how they match * curlDataPtr: Points to the structure with all the TclCurl data * for the connection. * * Results: * A libcurl return code so that libcurl knows what to do. * *----------------------------------------------------------------------- */ size_t curlsshkeycallback(CURL *curl ,const struct curl_khkey *knownkey, const struct curl_khkey *foundkey, enum curl_khmatch match,void *curlDataPtr) { struct curlObjData *tclcurlDataPtr=(struct curlObjData *)curlDataPtr; Tcl_Interp *interp; Tcl_Obj *objv[4]; Tcl_Obj *returnObjPtr; int action; int i, result; interp=tclcurlDataPtr->interp; objv[0]=Tcl_NewStringObj(tclcurlDataPtr->sshkeycallProc,-1); objv[1]=curlsshkeyextract(interp,knownkey); objv[2]=curlsshkeyextract(interp,foundkey); switch(match) { case CURLKHMATCH_OK: objv[3]=Tcl_NewStringObj("match",-1); break; case CURLKHMATCH_MISMATCH: objv[3]=Tcl_NewStringObj("mismatch",-1); break; case CURLKHMATCH_MISSING: objv[3]=Tcl_NewStringObj("missing",-1); break; case CURLKHMATCH_LAST: objv[3]=Tcl_NewStringObj("error",-1); } for (i=0;i<4;i++) Tcl_IncrRefCount(objv[i]); result=Tcl_EvalObjv(interp,4,objv,TCL_EVAL_GLOBAL); for (i=0;i<4;i++) Tcl_DecrRefCount(objv[i]); if (result!=TCL_OK) {return CURLKHSTAT_REJECT;} returnObjPtr=Tcl_GetObjResult(interp); if (Tcl_GetIntFromObj(interp,returnObjPtr,&action)!=TCL_OK) {return CURLKHSTAT_REJECT;} switch(action) { case 0: return CURLKHSTAT_FINE_ADD_TO_FILE; case 1: return CURLKHSTAT_FINE; case 2: return CURLKHSTAT_REJECT; case 3: return CURLKHSTAT_DEFER; } return CURLKHSTAT_REJECT; } /* *---------------------------------------------------------------------- * * curlDebugProcInvoke -- * * This is the function that will be invoked as a callback when the user * wants to invoke a Tcl procedure to write the debug data produce by * the verbose option. * * Parameters: * curlHandle: A pointer to the handle for the transfer. * infoType: Integer with the type of data. * dataPtr: the data passed to the procedure. * curlDataPtr: ointer to the curlData structure for the transfer. * * Results: * The number of bytes actually written or -1 in case of error, in * which case 'libcurl' will abort the transfer. * *----------------------------------------------------------------------- */ int curlDebugProcInvoke(CURL *curlHandle, curl_infotype infoType, char * dataPtr, size_t size, void *curlDataPtr) { struct curlObjData *curlData=(struct curlObjData *)curlDataPtr; Tcl_Obj *objv[3]; int i; if (curlData->cancelTransVarName) { if (curlData->cancelTrans) { curlData->cancelTrans=0; return -1; } } objv[0]=Tcl_NewStringObj(curlData->debugProc,-1); objv[1]=Tcl_NewIntObj(infoType); objv[2]=Tcl_NewByteArrayObj((const unsigned char *)dataPtr,size); for (i=0;i<3;i++) Tcl_IncrRefCount(objv[i]); Tcl_EvalObjv(curlData->interp,3,objv,TCL_EVAL_GLOBAL); for (i=0;i<3;i++) Tcl_DecrRefCount(objv[i]); return 0; } /* *---------------------------------------------------------------------- * * curlFreeSpace -- * * Frees the space taken by a curlObjData struct either because we are * deleting the handle or reseting it. * * Parameter: * interp: Pointer to the interpreter we are using. * curlHandle: the curl handle for which the option is set. * objc and objv: The usual in Tcl. * * Results: * A standard Tcl result. * *---------------------------------------------------------------------- */ void curlFreeSpace(struct curlObjData *curlData) { curl_slist_free_all(curlData->headerList); curl_slist_free_all(curlData->quote); curl_slist_free_all(curlData->prequote); curl_slist_free_all(curlData->postquote); Tcl_Free(curlData->outFile); Tcl_Free(curlData->inFile); Tcl_Free(curlData->postFields); Tcl_Free(curlData->proxy); Tcl_Free(curlData->errorBuffer); Tcl_Free(curlData->errorBufferName); Tcl_Free(curlData->errorBufferKey); Tcl_Free(curlData->stderrFile); Tcl_Free(curlData->randomFile); Tcl_Free(curlData->headerVar); Tcl_Free(curlData->bodyVarName); if (curlData->bodyVar.memory) { Tcl_Free(curlData->bodyVar.memory); } Tcl_Free(curlData->progressProc); if (curlData->cancelTransVarName) { Tcl_UnlinkVar(curlData->interp,curlData->cancelTransVarName); Tcl_Free(curlData->cancelTransVarName); } Tcl_Free(curlData->writeProc); Tcl_Free(curlData->readProc); Tcl_Free(curlData->debugProc); curl_slist_free_all(curlData->http200aliases); Tcl_Free(curlData->sshkeycallProc); curl_slist_free_all(curlData->mailrcpt); Tcl_Free(curlData->chunkBgnProc); Tcl_Free(curlData->chunkBgnVar); Tcl_Free(curlData->chunkEndProc); Tcl_Free(curlData->fnmatchProc); curl_slist_free_all(curlData->resolve); curl_slist_free_all(curlData->telnetoptions); #ifndef CURL_PRE_7_56_DEPR if (curlData->mime != NULL) { curl_mime_free(curlData->mime); } #endif Tcl_Free(curlData->command); } /* *---------------------------------------------------------------------- * * curlDupHandle -- * * This function is invoked by the 'duphandle' command, it will * create a duplicate of the given handle. * * Parameters: * The stantard parameters for Tcl commands * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlDupHandle(Tcl_Interp *interp, struct curlObjData *curlData, int objc, Tcl_Obj *const objv[]) { CURL *newCurlHandle; Tcl_Obj *result; struct curlObjData *newCurlData; Tcl_Obj *handleObj; newCurlHandle=curl_easy_duphandle(curlData->curl); if (newCurlHandle==NULL) { result=Tcl_NewStringObj("Couldn't create new handle.",-1); Tcl_SetObjResult(interp,result); return TCL_ERROR; } newCurlData=(struct curlObjData *)Tcl_Alloc(sizeof(struct curlObjData)); curlCopyCurlData(curlData,newCurlData); newCurlData->curl=newCurlHandle; if (newCurlData->shareToken != NULL) { struct shcurlObjData *shcurlData = curlGetShareDataFromToken(newCurlData->shareToken); if (shcurlData == NULL) { curl_easy_cleanup(newCurlHandle); curlFreeSpace(newCurlData); Tcl_Free((char *) newCurlData); result=Tcl_NewStringObj("Couldn't duplicate handle with deleted share handle.",-1); Tcl_SetObjResult(interp,result); return TCL_ERROR; } curlLinkEasyToShare(newCurlData, shcurlData); } handleObj=curlCreateObjCmd(interp,newCurlData); Tcl_SetObjResult(interp,handleObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlResetHandle -- * * This function is invoked by the 'reset' command, it reset all the * options in the handle to the state it had when 'init' was invoked. * * Parameters: * The stantard parameters for Tcl commands * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlResetHandle(Tcl_Interp *interp, struct curlObjData *curlData) { struct curlObjData *tmpPtr= (struct curlObjData *)Tcl_Alloc(sizeof(struct curlObjData)); tmpPtr->curl = curlData->curl; tmpPtr->token = curlData->token; tmpPtr->interp = curlData->interp; tmpPtr->shareToken = NULL; tmpPtr->nextSharedHandle = NULL; curlDetachShareHandle(curlData); curlFreeSpace(curlData); memset(curlData, 0, sizeof(struct curlObjData)); curlData->curl = tmpPtr->curl; curlData->token = tmpPtr->token; curlData->interp = tmpPtr->interp; curlData->postFieldSize = -1; curl_easy_reset(curlData->curl); Tcl_Free((char *)tmpPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlVersion -- * * This procedure is invoked to process the "curl::init" Tcl command. * See the user documentation for details on what it does. * * Parameters: * The stantard parameters for Tcl commands * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlVersion (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { Tcl_Obj *versionPtr; versionPtr=Tcl_ObjPrintf("TclCurl Version %s (%s)",TclCurlVersion, curl_version()); Tcl_SetObjResult(interp,versionPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlEscape -- * * This function is invoked to process the "curl::escape" Tcl command. * See the user documentation for details on what it does. * * * Parameters: * The stantard parameters for Tcl commands * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlEscape(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; char *escapedStr; escapedStr=curl_easy_escape(NULL,Tcl_GetString(objv[1]),0); if (!escapedStr) { resultObj=Tcl_NewStringObj("curl::escape bad parameter",-1); Tcl_SetObjResult(interp,resultObj); return TCL_ERROR; } resultObj=Tcl_NewStringObj(escapedStr,-1); Tcl_SetObjResult(interp,resultObj); curl_free(escapedStr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlUnescape -- * * This function is invoked to process the "curl::Unescape" Tcl command. * See the user documentation for details on what it does. * * * Parameters: * The stantard parameters for Tcl commands * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlUnescape(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; char *unescapedStr; unescapedStr=curl_easy_unescape(NULL,Tcl_GetString(objv[1]),0,NULL); if (!unescapedStr) { resultObj=Tcl_NewStringObj("curl::unescape bad parameter",-1); Tcl_SetObjResult(interp,resultObj); return TCL_ERROR; } resultObj=Tcl_NewStringObj(unescapedStr,-1); Tcl_SetObjResult(interp,resultObj); curl_free(unescapedStr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlVersionInfo -- * * This function invokes 'curl_version_info' to query how 'libcurl' was * compiled. * * Parameters: * The standard parameters for Tcl commands, but nothing is used. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlVersionInfo (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { int tableIndex; int i; curl_version_info_data *infoPtr; Tcl_Obj *resultObjPtr=NULL; if (objc!=2) { resultObjPtr=Tcl_NewStringObj("usage: curl::versioninfo -option",-1); Tcl_SetObjResult(interp,resultObjPtr); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], versionInfoTable, "option", TCL_EXACT,&tableIndex)==TCL_ERROR) { return TCL_ERROR; } infoPtr=curl_version_info(CURLVERSION_NOW); switch(tableIndex) { case 0: resultObjPtr=Tcl_NewStringObj(infoPtr->version,-1); break; case 1: resultObjPtr=Tcl_ObjPrintf("%X",infoPtr->version_num); break; case 2: resultObjPtr=Tcl_NewStringObj(infoPtr->host,-1); break; case 3: resultObjPtr=Tcl_NewListObj(0,(Tcl_Obj **)NULL); if (infoPtr->features&CURL_VERSION_IPV6) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("IPV6",-1)); } if (infoPtr->features&CURL_VERSION_KERBEROS4) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("KERBEROS4",-1)); } if (infoPtr->features&CURL_VERSION_SSL) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("SSL",-1)); } if (infoPtr->features&CURL_VERSION_LIBZ) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("LIBZ",-1)); } if (infoPtr->features&CURL_VERSION_NTLM) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("NTLM",-1)); } if (infoPtr->features&CURL_VERSION_GSSNEGOTIATE) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("GSSNEGOTIATE",-1)); } if (infoPtr->features&CURL_VERSION_DEBUG) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("DEBUG",-1)); } if (infoPtr->features&CURL_VERSION_ASYNCHDNS) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("ASYNCHDNS",-1)); } if (infoPtr->features&CURL_VERSION_SPNEGO) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("SPNEGO",-1)); } if (infoPtr->features&CURL_VERSION_LARGEFILE) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("LARGEFILE",-1)); } if (infoPtr->features&CURL_VERSION_IDN) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("IDN",-1)); } if (infoPtr->features&CURL_VERSION_SSPI) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("SSPI",-1)); } break; if (infoPtr->features&CURL_VERSION_CONV) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj("CONV",-1)); } case 4: resultObjPtr=Tcl_NewStringObj(infoPtr->ssl_version,-1); break; case 5: resultObjPtr=Tcl_NewLongObj(infoPtr->ssl_version_num); break; case 6: resultObjPtr=Tcl_NewStringObj(infoPtr->libz_version,-1); break; case 7: { resultObjPtr=Tcl_NewListObj(0,(Tcl_Obj **)NULL); for (i=0;;i++) { if (infoPtr->protocols[i]!=NULL) { Tcl_ListObjAppendElement(interp,resultObjPtr, Tcl_NewStringObj(infoPtr->protocols[i],-1)); } else { break; } } } } Tcl_SetObjResult(interp,resultObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlCopyCurlData -- * * This function copies the contents of a curlData struct into another. * * Parameters: * curlDataOld: The original one. * curlDataNew: The new one * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlCopyCurlData (struct curlObjData *curlDataOld, struct curlObjData *curlDataNew) { /* This takes care of the int and long values */ memcpy(curlDataNew, curlDataOld, sizeof(struct curlObjData)); /* Some of the data doesn't get copied */ curlDataNew->headerList=NULL; curlDataNew->quote=NULL; curlDataNew->prequote=NULL; curlDataNew->postquote=NULL; curlDataNew->postListFirst=NULL; curlDataNew->postListLast=NULL; curlDataNew->outHandle=NULL; curlDataNew->outFlag=0; curlDataNew->inHandle=NULL; curlDataNew->inFlag=0; curlDataNew->headerHandle=NULL; curlDataNew->headerFlag=0; curlDataNew->stderrHandle=NULL; curlDataNew->stderrFlag=0; curlDataNew->http200aliases=NULL; curlDataNew->mailrcpt=NULL; curlDataNew->resolve=NULL; curlDataNew->telnetoptions=NULL; #ifdef CURL_PRE_7_56_DEPR curlDataNew->formArray=NULL; #else curlDataNew->mime=NULL; #endif /* The strings need a special treatment. */ curlDataNew->outFile=curlstrdup(curlDataOld->outFile); curlDataNew->inFile=curlstrdup(curlDataOld->inFile); curlDataNew->postFields=curlstrdup(curlDataOld->postFields); curlDataNew->proxy=curlstrdup(curlDataOld->proxy); curlDataNew->errorBuffer=curlstrdup(curlDataOld->errorBuffer); curlDataNew->errorBufferName=curlstrdup(curlDataOld->errorBufferName); curlDataNew->errorBufferKey=curlstrdup(curlDataOld->errorBufferKey); curlDataNew->headerFile=curlstrdup(curlDataOld->headerFile); curlDataNew->stderrFile=curlstrdup(curlDataOld->stderrFile); curlDataNew->randomFile=curlstrdup(curlDataOld->randomFile); curlDataNew->headerVar=curlstrdup(curlDataOld->headerVar); curlDataNew->bodyVarName=curlstrdup(curlDataOld->bodyVarName); curlDataNew->progressProc=curlstrdup(curlDataOld->progressProc); curlDataNew->cancelTransVarName=curlstrdup(curlDataOld->cancelTransVarName); curlDataNew->writeProc=curlstrdup(curlDataOld->writeProc); curlDataNew->readProc=curlstrdup(curlDataOld->readProc); curlDataNew->debugProc=curlstrdup(curlDataOld->debugProc); curlDataNew->command=curlstrdup(curlDataOld->command); curlDataNew->sshkeycallProc=curlstrdup(curlDataOld->sshkeycallProc); curlDataNew->chunkBgnProc=curlstrdup(curlDataOld->chunkBgnProc); curlDataNew->chunkBgnVar=curlstrdup(curlDataOld->chunkBgnVar); curlDataNew->chunkEndProc=curlstrdup(curlDataOld->chunkEndProc); curlDataNew->fnmatchProc=curlstrdup(curlDataOld->fnmatchProc); curlDataNew->bodyVar.memory=(char *)Tcl_Alloc(curlDataOld->bodyVar.size); memcpy(curlDataNew->bodyVar.memory,curlDataOld->bodyVar.memory ,curlDataOld->bodyVar.size); curlDataNew->bodyVar.size=curlDataOld->bodyVar.size; return TCL_OK; } /* *---------------------------------------------------------------------- * * curlOpenFiles -- * * Before doing a transfer with the easy interface or adding an easy * handle to a multi one, this function takes care of opening all * necessary files for the transfer. * * Parameters: * curlData: The pointer to the struct with the transfer data. * * Results: * '0' all went well, '1' in case of error. * *---------------------------------------------------------------------- */ int curlOpenFiles(Tcl_Interp *interp,struct curlObjData *curlData) { if (curlData->outFlag) { if (curlOpenFile(interp,curlData->outFile,&(curlData->outHandle),1, curlData->transferText)) { return 1; } curl_easy_setopt(curlData->curl,CURLOPT_WRITEDATA,curlData->outHandle); } if (curlData->inFlag) { if (curlOpenFile(interp,curlData->inFile,&(curlData->inHandle),0, curlData->transferText)) { return 1; } curl_easy_setopt(curlData->curl,CURLOPT_READDATA,curlData->inHandle); if (curlData->anyAuthFlag) { curl_easy_setopt(curlData->curl, CURLOPT_SEEKFUNCTION, (curl_seek_callback)curlseek); curl_easy_setopt(curlData->curl, CURLOPT_SEEKDATA, curlData->inHandle); } } if (curlData->headerFlag) { if (curlOpenFile(interp,curlData->headerFile,&(curlData->headerHandle),1,1)) { return 1; } curl_easy_setopt(curlData->curl,CURLOPT_HEADERDATA,curlData->headerHandle); } if (curlData->stderrFlag) { if (curlOpenFile(interp,curlData->stderrFile,&(curlData->stderrHandle),1,1)) { return 1; } curl_easy_setopt(curlData->curl,CURLOPT_STDERR,curlData->stderrHandle); } return 0; } /*---------------------------------------------------------------------- * * curlCloseFiles -- * * Closes the files opened during a transfer. * * Parameters: * curlData: The pointer to the struct with the transfer data. * *---------------------------------------------------------------------- */ void curlCloseFiles(struct curlObjData *curlData) { if (curlData->outHandle!=NULL) { fclose(curlData->outHandle); curlData->outHandle=NULL; } if (curlData->inHandle!=NULL) { fclose(curlData->inHandle); curlData->inHandle=NULL; } if (curlData->headerHandle!=NULL) { fclose(curlData->headerHandle); curlData->headerHandle=NULL; } if (curlData->stderrHandle!=NULL) { fclose(curlData->stderrHandle); curlData->stderrHandle=NULL; } } /*---------------------------------------------------------------------- * * curlOpenFile -- * * Opens a file to be used during a transfer. * * Parameter: * fileName: name of the file. * handle: the handle for the file * writing: '0' if reading, '1' if writing. * text: '0' if binary, '1' if text. * * Results: * '0' all went well, '1' in case of error. *---------------------------------------------------------------------- */ int curlOpenFile(Tcl_Interp *interp,char *fileName, FILE **handle, int writing, int text) { Tcl_Obj *resultObjPtr; #ifdef _WIN32 Tcl_DString nativeString; TCHAR *nativeFile=Tcl_WinUtfToTChar(fileName,-1,&nativeString); #endif if (*handle!=NULL) { fclose(*handle); } if (writing==1) { #ifdef _WIN32 *handle=_tfopen(nativeFile, text==1 ? _T("w") : _T("wb")); #else *handle=fopen(fileName, text==1 ? "w" : "wb"); #endif } else { #ifdef _WIN32 *handle=_tfopen(nativeFile, text==1 ? _T("r") : _T("rb")); #else *handle=fopen(fileName, text==1 ? "r" : "rb"); #endif } #ifdef _WIN32 Tcl_DStringFree(&nativeString); #endif if (*handle==NULL) { resultObjPtr=Tcl_ObjPrintf("Couldn't open file %s",fileName); Tcl_SetObjResult(interp,resultObjPtr); return 1; } return 0; } /*---------------------------------------------------------------------- * * curlSetBodyVarName -- * * After performing a transfer, this function is invoked to set the * body of the recieved transfer into a user defined Tcl variable. * * Parameter: * interp: The Tcl interpreter we are using. * curlData: A pointer to the struct with the transfer data. *---------------------------------------------------------------------- */ void curlSetBodyVarName(Tcl_Interp *interp,struct curlObjData *curlDataPtr) { Tcl_Obj *bodyVarNameObjPtr, *bodyVarObjPtr; bodyVarNameObjPtr=Tcl_NewStringObj(curlDataPtr->bodyVarName,-1); bodyVarObjPtr=Tcl_NewByteArrayObj((unsigned char *)curlDataPtr->bodyVar.memory, curlDataPtr->bodyVar.size); Tcl_ObjSetVar2(interp,bodyVarNameObjPtr,(Tcl_Obj *)NULL,bodyVarObjPtr,0); Tcl_Free(curlDataPtr->bodyVar.memory); curlDataPtr->bodyVar.memory=NULL; curlDataPtr->bodyVar.size=0; } /*---------------------------------------------------------------------- * * curlstrdup -- * The same as strdup, but won't seg fault if the string to copy is NULL. * * Parameters: * old: The original one. * * Results: * Returns a pointer to the new string. * *---------------------------------------------------------------------- */ char *curlstrdup (char *old) { char *tmpPtr; if (old == NULL) { return NULL; } tmpPtr = Tcl_Alloc(strlen(old)+1); strcpy(tmpPtr,old); return tmpPtr; } /* *---------------------------------------------------------------------- * * curlCreateShareObjCmd -- * * Looks for the first free share handle (scurl1, scurl2,...) and * creates a Tcl command for it. * * Results: * A string with the name of the handle, don't forget to free it. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ Tcl_Obj * curlCreateShareObjCmd (Tcl_Interp *interp,struct shcurlObjData *shcurlData) { char shandleName[32]; int i; Tcl_CmdInfo info; Tcl_Command cmdToken; /* We try with scurl1, if it already exists with scurl2...*/ for (i=1;;i++) { snprintf(shandleName,sizeof(shandleName),"scurl%d",i); if (!Tcl_GetCommandInfo(interp,shandleName,&info)) { cmdToken=Tcl_CreateObjCommand(interp,shandleName,curlShareObjCmd, (ClientData)shcurlData, (Tcl_CmdDeleteProc *)curlCleanUpShareCmd); break; } } shcurlData->token=cmdToken; return Tcl_NewStringObj(shandleName,-1); } /* *---------------------------------------------------------------------- * * curlShareInitObjCmd -- * * This procedure is invoked to process the "curl::shareinit" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlShareInitObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { Tcl_Obj *resultPtr; CURLSH *shcurlHandle; struct shcurlObjData *shcurlData; Tcl_Obj *shandleObj; shcurlData=(struct shcurlObjData *)Tcl_Alloc(sizeof(struct shcurlObjData)); if (shcurlData == NULL) { resultPtr=Tcl_NewStringObj("Couldn't allocate memory",-1); Tcl_SetObjResult(interp,resultPtr); return TCL_ERROR; } memset(shcurlData, 0, sizeof(struct shcurlObjData)); shcurlHandle=curl_share_init(); if (shcurlHandle == NULL) { resultPtr=Tcl_NewStringObj("Couldn't create share handle",-1); Tcl_SetObjResult(interp,resultPtr); return TCL_ERROR; } shandleObj=curlCreateShareObjCmd(interp,shcurlData); shcurlData->shandle=shcurlHandle; Tcl_SetObjResult(interp,shandleObj); #ifdef TCL_THREADS curl_share_setopt(shcurlHandle, CURLSHOPT_LOCKFUNC, curlShareLockFunc); curl_share_setopt(shcurlHandle, CURLSHOPT_UNLOCKFUNC, curlShareUnLockFunc); #endif return TCL_OK; } #ifdef TCL_THREADS /* *---------------------------------------------------------------------- * * curlShareLockFunc -- * * This will be the function invoked by libcurl when it wants to lock * some data for the share interface. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ void curlShareLockFunc (CURL *handle, curl_lock_data data, curl_lock_access access, void *userptr) { switch(data) { case CURL_LOCK_DATA_COOKIE: Tcl_MutexLock(&cookieLock); break; case CURL_LOCK_DATA_DNS: Tcl_MutexLock(&dnsLock); break; case CURL_LOCK_DATA_SSL_SESSION: Tcl_MutexLock(&sslLock); break; case CURL_LOCK_DATA_CONNECT: Tcl_MutexLock(&connectLock); break; default: /* Prevent useless compile warnings */ break; } } /* *---------------------------------------------------------------------- * * curlShareUnLockFunc -- * * This will be the function invoked by libcurl when it wants to unlock * the previously locked data. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ void curlShareUnLockFunc(CURL *handle, curl_lock_data data, void *userptr) { switch(data) { case CURL_LOCK_DATA_COOKIE: Tcl_MutexUnlock(&cookieLock); break; case CURL_LOCK_DATA_DNS: Tcl_MutexUnlock(&dnsLock); break; case CURL_LOCK_DATA_SSL_SESSION: Tcl_MutexUnlock(&sslLock); break; case CURL_LOCK_DATA_CONNECT: Tcl_MutexUnlock(&connectLock); break; default: break; } } #endif /* *---------------------------------------------------------------------- * * curlShareObjCmd -- * * This procedure is invoked to process the "share curl" commands. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int curlShareObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { struct shcurlObjData *shcurlData = (struct shcurlObjData *)clientData; CURLSH *shcurlHandle = shcurlData->shandle; int tableIndex, dataIndex; int dataToLock=0; if (objc<2) { Tcl_WrongNumArgs(interp,1,objv,"option arg ?arg?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], shareCmd, "option",TCL_EXACT,&tableIndex)==TCL_ERROR) { return TCL_ERROR; } switch(tableIndex) { case 0: case 1: if (objc != 3) { Tcl_WrongNumArgs(interp,2,objv,"arg"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], lockData, "data to lock ",TCL_EXACT,&dataIndex) == TCL_ERROR) { return TCL_ERROR; } switch (dataIndex) { case 0: dataToLock = CURL_LOCK_DATA_COOKIE; break; case 1: dataToLock = CURL_LOCK_DATA_DNS; break; } if (tableIndex == 0) { curl_share_setopt(shcurlHandle, CURLSHOPT_SHARE, dataToLock); } else { curl_share_setopt(shcurlHandle, CURLSHOPT_UNSHARE, dataToLock); } break; case 2: if (objc != 2) { Tcl_WrongNumArgs(interp,2,objv,""); return TCL_ERROR; } if (shcurlData->users != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Share handle is still attached to one or more easy handles.", -1)); return TCL_ERROR; } Tcl_DeleteCommandFromToken(interp,shcurlData->token); break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * curlCleanUpShareCmd -- * * This procedure is invoked when curl share handle is deleted. * * Results: * A standard Tcl result. * * Side effects: * Cleans the curl share handle and frees the memory. * *---------------------------------------------------------------------- */ int curlCleanUpShareCmd(ClientData clientData) { struct shcurlObjData *shcurlData=(struct shcurlObjData *)clientData; CURLSH *shcurlHandle=shcurlData->shandle; struct curlObjData *curlData = shcurlData->users; while (curlData != NULL) { struct curlObjData *next = curlData->nextSharedHandle; curlData->shareToken = NULL; curlData->nextSharedHandle = NULL; if (curlData->curl != NULL) { curl_easy_setopt(curlData->curl, CURLOPT_SHARE, NULL); } curlData = next; } curl_share_cleanup(shcurlHandle); Tcl_Free((char *)shcurlData); return TCL_OK; } /* *---------------------------------------------------------------------- * * curlErrorStrings -- * * All the commands to return the error string from the error code have * this function in common. * * Results: * '0': All went well. * '1': The error code didn't make sense. *---------------------------------------------------------------------- */ int curlErrorStrings (Tcl_Interp *interp, Tcl_Obj *const objv,int type) { Tcl_Obj *resultPtr; int errorCode; if (Tcl_GetIntFromObj(interp,objv,&errorCode)) { resultPtr=Tcl_ObjPrintf("Invalid error code: %s",Tcl_GetString(objv)); Tcl_SetObjResult(interp,resultPtr); return 1; } switch(type) { case 0: resultPtr=Tcl_NewStringObj(curl_easy_strerror(errorCode),-1); break; case 1: resultPtr=Tcl_NewStringObj(curl_share_strerror(errorCode),-1); break; case 2: resultPtr=Tcl_NewStringObj(curl_multi_strerror(errorCode),-1); break; default: resultPtr=Tcl_NewStringObj("You're kidding,right?",-1); } Tcl_SetObjResult(interp,resultPtr); return 0; } /* *---------------------------------------------------------------------- * * curlEasyStringError -- * * This function is invoked to process the "curl::easystrerror" Tcl command. * It will return a string with an explanation of the error code given. * * Results: * A standard Tcl result. * * Side effects: * The interpreter will contain as a result the string with the error * message. * *---------------------------------------------------------------------- */ int curlEasyStringError (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { if (objc<2) { Tcl_WrongNumArgs(interp,1,objv,"errorCode"); return TCL_ERROR; } if (curlErrorStrings(interp,objv[1],0)) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * curlShareStringError -- * * This function is invoked to process the "curl::sharestrerror" Tcl command. * It will return a string with an explanation of the error code given. * * Results: * A standard Tcl result. * * Side effects: * The interpreter will contain as a result the string with the error * message. * *---------------------------------------------------------------------- */ int curlShareStringError (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { if (objc<2) { Tcl_WrongNumArgs(interp,1,objv,"errorCode"); return TCL_ERROR; } if (curlErrorStrings(interp,objv[1],1)) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * curlMultiStringError -- * * This function is invoked to process the "curl::multirerror" Tcl command. * It will return a string with an explanation of the error code given. * * Results: * A standard Tcl result. * * Side effects: * The interpreter will contain as a result the string with the error * message. * *---------------------------------------------------------------------- */ int curlMultiStringError (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]) { if (objc<2) { Tcl_WrongNumArgs(interp,1,objv,"errorCode"); return TCL_ERROR; } if (curlErrorStrings(interp,objv[1],2)) { return TCL_ERROR; } return TCL_OK; } tclcurl-ng-8.0.3/generic/tclcurl.h000066400000000000000000000234031522613063100170320ustar00rootroot00000000000000/* * tclcurl.h -- * * Implementation of the TclCurl extension that creates the curl namespace * so that Tcl interpreters can access libcurl. * * This file is partially derived from tclcurl-fa. * * Copyright (c) 2001-2011 Andres Garcia Garcia * Copyright (c) 2024-2026 Massimo Manghi * * SPDX-License-Identifier: TCL * * See the file "license.terms" at the top level of this distribution * for information on usage and redistribution of this file, and for the * complete disclaimer of warranties and limitation of liability. */ #ifndef __tclcurl_h__ #define __tclcurl_h__ #if (defined(WIN32) || defined(_WIN32)) #define CURL_STATICLIB 1 #endif #include #include #include #include #define _MPRINTF_REPLACE #include #ifdef __cplusplus extern "C" { #endif #include "tclcompat.h" /* * Windows needs to know which symbols to export. Unix does not. * BUILD_tclcurl should be undefined for Unix. * Actually I don't use this, but it was in TEA so I keep in case * I ever understand what it is for. */ #ifdef BUILD_TclCurl #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT #endif #define TclCurlVersion PACKAGE_VERSION /* * This struct will contain the data of a transfer if the user wants * to put the body into a Tcl variable */ struct MemoryStruct { char *memory; size_t size; }; #ifdef CURL_PRE_7_56_DEPR /* * Struct that will be used for a linked list with all the * data for a post */ struct formArrayStruct { struct curl_forms *formArray; struct curl_slist *formHeaderList; struct formArrayStruct *next; }; #endif struct curlObjData { CURL *curl; Tcl_Command token; Tcl_Command shareToken; struct curlObjData *nextSharedHandle; Tcl_Interp *interp; struct curl_slist *headerList; struct curl_slist *quote; struct curl_slist *prequote; struct curl_slist *postquote; struct curl_httppost *postListFirst; struct curl_httppost *postListLast; char *outFile; FILE *outHandle; int outFlag; char *inFile; FILE *inHandle; int inFlag; char *postFields; curl_off_t postFieldSize; char *proxy; int transferText; char *errorBuffer; char *errorBufferName; char *errorBufferKey; char *headerFile; FILE *headerHandle; int headerFlag; char *stderrFile; FILE *stderrHandle; int stderrFlag; char *randomFile; char *headerVar; char *bodyVarName; struct MemoryStruct bodyVar; char *progressProc; char *cancelTransVarName; int cancelTrans; char *writeProc; char *readProc; char *debugProc; struct curl_slist *http200aliases; char *command; int anyAuthFlag; char *sshkeycallProc; struct curl_slist *mailrcpt; char *chunkBgnProc; char *chunkBgnVar; char *chunkEndProc; char *fnmatchProc; struct curl_slist *resolve; struct curl_slist *telnetoptions; #ifdef CURL_PRE_7_56_DEPR struct formArrayStruct *formArray; #else curl_mime* mime; #endif }; struct shcurlObjData { Tcl_Command token; CURLSH *shandle; struct curlObjData *users; }; EXTERN int Tclcurl_Init(Tcl_Interp *interp); int Tclcurl_MultiInit (Tcl_Interp *interp); Tcl_Obj* curlCreateObjCmd(Tcl_Interp *interp,struct curlObjData *curlData); int curlInitObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlDeleteCmd(ClientData clientData); int curlPerform(Tcl_Interp *interp,CURL *curlHandle,struct curlObjData *curlData); int curlSetOptsTransfer(Tcl_Interp *interp, struct curlObjData *curlData,int objc,Tcl_Obj *const objv[]); int curlConfigTransfer(Tcl_Interp *interp, struct curlObjData *curlData,int objc,Tcl_Obj *const objv[]); int curlDupHandle(Tcl_Interp *interp, struct curlObjData *curlData,int objc,Tcl_Obj *const objv[]); int curlResetHandle(Tcl_Interp *interp, struct curlObjData *curlData); int curlSetOpts(Tcl_Interp *interp, struct curlObjData *curlData,Tcl_Obj *const objv,int tableIndex); //int SetoptInt(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,Tcl_Obj *tclObj); //int SetoptLong(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,Tcl_Obj *tclObj); //int SetoptCurlOffT(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,Tcl_Obj *tclObj); //int SetoptChar(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,Tcl_Obj *tclObj); //int SetoptBlob(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,Tcl_Obj *tclObj); int SetoptSHandle(Tcl_Interp *interp,struct curlObjData *curlData,CURLoption opt,int tableIndex,Tcl_Obj *tclObj); int SetoptsList(Tcl_Interp *interp,struct curl_slist **slistPtr,Tcl_Obj *const objv); //CURLcode curlGetInfo(Tcl_Interp *interp,CURL *curlHandle,int tableIndex); /* curl_getinfo.c public interface */ int TclCurl_GetInfo (Tcl_Interp* interp,Tcl_Obj* get_info_arg,CURL* curlHandle,Tcl_Obj** resultObjPtr); void curlFreeSpace(struct curlObjData *curlData); void curlErrorSetOpt(Tcl_Interp *interp,const char **configTable, int option,const char *parPtr); size_t curlHeaderReader(void *ptr,size_t size,size_t nmemb,FILE *stream); size_t curlBodyReader(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr); int curlProgressCallback(void *clientp,curl_off_t dltotal,curl_off_t dlnow,curl_off_t ultotal,curl_off_t ulnow); size_t curlWriteProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr); size_t curlReadProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr); long curlChunkBgnProcInvoke (const void *transfer_info, void *curlDataPtr, int remains); long curlChunkEndProcInvoke (void *curlDataPtr); int curlfnmatchProcInvoke(void *curlDataPtr, const char *pattern, const char *filename); /* Puts a ssh key into a Tcl object */ Tcl_Obj *curlsshkeyextract(Tcl_Interp *interp,const struct curl_khkey *key); /* Function that will be invoked by libcurl to see what the user wants to do about the new ssh host */ size_t curlsshkeycallback(CURL *easy, /* easy handle */ const struct curl_khkey *knownkey, /* known */ const struct curl_khkey *foundkey, /* found */ enum curl_khmatch, /* libcurl's view on the keys */ void *curlData); int curlDebugProcInvoke(CURL *curlHandle, curl_infotype infoType, char * dataPtr, size_t size, void *curlData); int curlVersion (ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); int curlEscape(ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); int curlUnescape(ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); int curlVersionInfo (ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); int curlCopyCurlData (struct curlObjData *curlDataOld,struct curlObjData *curlDataNew); int curlOpenFile(Tcl_Interp *interp,char *fileName, FILE **handle, int writing, int text); int curlOpenFiles (Tcl_Interp *interp,struct curlObjData *curlData); void curlCloseFiles(struct curlObjData *curlData); int curlSetPostData(Tcl_Interp *interp,struct curlObjData *curlData); void curlResetPostData(struct curlObjData *curlDataPtr); #ifdef CURL_PRE_7_56_DEPR void curlResetFormArray(struct curl_forms *formArray); #endif void curlSetBodyVarName(Tcl_Interp *interp,struct curlObjData *curlDataPtr); char *curlstrdup (char *old); void curlDetachShareHandle(struct curlObjData *curlData); Tcl_Obj* curlCreateShareObjCmd (Tcl_Interp *interp,struct shcurlObjData *shcurlData); int curlShareInitObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlShareObjCmd (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlCleanUpShareCmd(ClientData clientData); int curlErrorStrings (Tcl_Interp *interp, Tcl_Obj *const objv,int type); int curlEasyStringError (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlShareStringError (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); int curlMultiStringError (ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *const objv[]); /* */ int TclCurl_SetOpts(Tcl_Interp *interp, struct curlObjData *curlData,Tcl_Obj *const objv,int tableIndex); unsigned long int TclCurl_BuildProtocolMask(Tcl_Interp* interp, Tcl_Obj** protocols,Tcl_Size protocols_c); long TclCurl_FTPClearCommandChannelOpt(Tcl_Interp* interp,Tcl_Obj* opt_o); long TclCurl_FTPSSLMethod(Tcl_Interp* interp,Tcl_Obj* ssl_method_o); int TclCurl_ErrorBuffer(Tcl_Interp *interp, struct curlObjData * const curlData,Tcl_Obj *const tcl_o); char* TclCurl_StripSpaces(char* str); Tcl_Obj* TclCurl_JoinList (Tcl_Obj** objList,Tcl_Size obj_cnt,const char* join_c); int TclCurl_SizeT2TclSize(size_t in, Tcl_Size *out); int TclCurl_TclSize2SizeT(Tcl_Size in, size_t *out); #ifdef __cplusplus } #endif #endif tclcurl-ng-8.0.3/generic/tclcurl.tcl000077500000000000000000000111101522613063100173600ustar00rootroot00000000000000################################################################################ ################################################################################ #### tclcurl.tcl ################################################################################ ################################################################################ ## Includes the tcl part of TclCurl ################################################################################ ################################################################################ ## (c) 2001-2011 Andres Garcia Garcia. fandom@telefonica.net ## See the file "license.terms" for information on usage and redistribution ## of this file and for a DISCLAIMER OF ALL WARRANTIES. ################################################################################ ################################################################################ namespace eval curl { ################################################################################ # configure # Invokes the 'curl-config' script to be able to know what features have # been compiled in the installed version of libcurl. # Possible options are '-prefix', '-feature' and 'vernum' ################################################################################ proc ::curl::curlConfig {option} { if {$::tcl_platform(platform)=="windows"} { error "This command is not available in Windows" } switch -exact -- $option { -prefix { return [exec curl-config --prefix] } -feature { set featureList [exec curl-config --feature] regsub -all {\\n} $featureList { } featureList return $featureList } -vernum { return [exec curl-config --vernum] } -ca { return [exec curl-config --ca] } default { error "bad option '$option': must be '-prefix', '-feature', '-vernum' or '-ca'" } } return } ################################################################################ # transfer # The transfer command is used for simple transfers in which you don't # want to request more than one file. # # Parameters: # Use the same parameters you would use in the 'configure' command to # configure the download and the same as in 'getinfo' with a 'info' # prefix to get info about the transfer. ################################################################################ proc ::curl::transfer {args} { variable getInfo variable curlBodyVar set i 0 set newArgs "" catch {unset getInfo} if {[llength $args]==0} { puts "No transfer configured" return } foreach {option value} $args { set noPassOption 0 set block 1 switch -regexp -- $option { -info.* { set noPassOption 1 regsub -- {-info} $option {} option set getInfo($option) $value } -block { set noPassOption 1 set block $value } -bodyvar { upvar $value curlBodyVar set value curlBodyVar } -headervar { upvar $value curlHeaderVar set value curlHeaderVar } -errorbuffer { upvar $value curlErrorVar set value curlErrorVar } } if {$noPassOption==0} { lappend newArgs $option $value } } if {[catch {::curl::init} curlHandle]} { error "Could not init a curl session: $curlHandle" } if {[catch {eval $curlHandle configure $newArgs} result]} { $curlHandle cleanup error $result } if {$block==1} { if {[catch {$curlHandle perform} result]} { $curlHandle cleanup error $result } if {[info exists getInfo]} { foreach {option var} [array get getInfo] { upvar $var info set info [eval $curlHandle getinfo $option] } } if {[catch {$curlHandle cleanup} result]} { error $result } } else { # We create a multiHandle set multiHandle [curl::multiinit] # We add the easy handle to the multi handle. $multiHandle addhandle $curlHandle # So now we create the event source passing the multiHandle as a parameter. curl::createEventSource $multiHandle # And we return, it is non blocking after all. } return 0 } } tclcurl-ng-8.0.3/license.terms000077500000000000000000000041611522613063100162760ustar00rootroot00000000000000This software is copyrighted by Andres Garcia Garcia and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tclcurl-ng-8.0.3/packages/000077500000000000000000000000001522613063100153515ustar00rootroot00000000000000tclcurl-ng-8.0.3/packages/Linux/000077500000000000000000000000001522613063100164505ustar00rootroot00000000000000tclcurl-ng-8.0.3/packages/Linux/tclcurl-7.22.0.spec000077500000000000000000000024101522613063100215200ustar00rootroot00000000000000Name: tclcurl Version: 7.22.0 Release: 1 License: BSD revised Group: Development/Libraries Packager: Andres Garcia Vendor: Fandom Enterprise Source: http://personal1.iddeo.es/andresgarci/tclcurl/download/tarball/tclcurl-7.22.0.tar.gz Summary: A Tcl interface for libcurl. %description TclCurl provides a binding to libcurl, with it you can upload and download files using FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. %prep %setup %build ./configure --mandir=/usr/share/man --prefix=/usr make %install make install mkdir -p /usr/share/doc/tclcurl-7.22.0/tests cp -f ReadMe.txt /usr/share/doc/tclcurl-7.22.0/ cp -f license.terms /usr/share/doc/tclcurl-7.22.0/ cp -f doc/tclcurl.html /usr/share/doc/tclcurl-7.22.0/ cp -f doc/tclcurl_multi.html /usr/share/doc/tclcurl-7.22.0/ cp -f doc/tclcurl_share.html /usr/share/doc/tclcurl-7.22.0/ cp -f doc/aolserver.txt /usr/share/doc/tclcurl-7.22.0/ cp -f tests/*.tcl /usr/share/doc/tclcurl-7.22.0/tests %files /usr/lib/TclCurl7.22.0/ /usr/share/doc/tclcurl-7.22.0/ /usr/share/man/mann/tclcurl.n.gz /usr/share/man/mann/tclcurl_multi.n.gz /usr/share/man/mann/tclcurl_share.n.gz tclcurl-ng-8.0.3/packages/Windows/000077500000000000000000000000001522613063100170035ustar00rootroot00000000000000tclcurl-ng-8.0.3/packages/Windows/SetUp.tcl000077500000000000000000000022621522613063100205540ustar00rootroot00000000000000# This script inst`pwd+alls TclCurl in a Windows system, you only # have to double-click on it and, provided Tcl/Tk is already # installed, TclCurl will be ready to use. # # Copyright (c) 2001-2011 Andres Garcia Garcia. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. wm withdraw . set tclLibDir [file dirname $tcl_library] set tclBinDir [file join [file dirname $tclLibDir] bin] set windowsSystem [file join $env(windir) SYSTEM] cd [file dirname [info script]] foreach oldie [glob -nocomplain $tclLibDir/tclcurl*] { catch {file delete -force $oldie} } file copy -force tclcurl7.22.0 $tclLibDir foreach sslFile [glob -nocomplain ssl/*] { catch {file copy -force $sslFile $windowsSystem} } foreach sslFile [glob -nocomplain certs/*] { file copy -force $sslFile [file join $env(windir) cacert.pem] } package forget TclCurl if {[catch {package require TclCurl} version]} { tk_messageBox -icon error -type ok -title Error \ -message "Install failed\n$version" } else { tk_messageBox -icon info -type ok -title Installed \ -message "Version $version installed" } exit tclcurl-ng-8.0.3/packages/Windows/tclcurl.mk000077500000000000000000000072321522613063100210130ustar00rootroot00000000000000TCL_VERSION = 8.5.10 TCLCURL_VERSION = 7.22.0 TclCurl_nodot = 7.220 CURL_VERSION = 7.22.0 ZLIB_VERSION = 1.2.5 installFiles = ChangeLog.txt changes.txt license.terms ReadMe.txt ReadMeW32.txt packages/Windows/SetUp.tcl installDirs = tests certFiles = cacert.pem sslFiles = libeay32.dll ssleay32.dll docFiles = aolserver.txt OpenSSL-LICENSE.txt tclcurl.html tclcurl_multi.html tclcurl_share.html tclcurl-plain: DESTDIR = TclCurl-${TCLCURL_VERSION} tclcurl-plain: TclCurlFlags= --disable-threads tclcurl-ssl: DESTDIR = TclCurl-SSL-${TCLCURL_VERSION} tclcurl-ssl: TclCurlFlags = --enable-ssl --disable-threads tclcurl-ssl: curlFlags = --with-ssl=/usr/local/ tclcurl-threaded: DESTDIR = TclCurl-THREADED-${TCLCURL_VERSION} tclcurl-threaded: TclFlags = --enable-threads tclcurl-threaded-ssl: DESTDIR = TclCurl-THREADED-SSL-${TCLCURL_VERSION} tclcurl-threaded-ssl: TclFlags = --enable-threads tclcurl-threaded-ssl: TclCurlFlags = --enable-ssl tclcurl-threaded-ssl: curlFlags = --with-ssl=/usr/local/ tclcurl-plain: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs rar tclcurl-ssl: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs ssl rar tclcurl-threaded: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs rar tclcurl-threaded-ssl: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs ssl rar clean: rm TclCurl-${TCLCURL_VERSION}.exe TclCurl-SSL-${TCLCURL_VERSION}.exe TclCurl-THREADED-${TCLCURL_VERSION}.exe TclCurl-THREADED-SSL-${TCLCURL_VERSION}.exe tcl: cd tcl${TCL_VERSION}/win ;\ make distclean ;\ ./configure ${TclFlags} ;\ make ;\ make install curl: cd curl-${CURL_VERSION} ;\ ./configure ${curlFlags} --enable-shared=no ;\ make ;\ make install-strip zlib: cd zlib-${ZLIB_VERSION} ;\ make distclean ;\ ./configure ;\ make ;\ make install ;\ tclcurlComp: cd TclCurl ;\ make distclean ;\ CC=gcc ./configure ${TclFlags} ${TclCurlFlags} -enable-zlib ;\ make ;\ make install createDir: mkdir ${DESTDIR} ;\ cp -r /usr/local/lib/TclCurl${TCLCURL_VERSION} ${DESTDIR} ;\ extraFiles: for f in $(installFiles) ; do \ cp TclCurl/$$f ${DESTDIR} ;\ done extraDirs: for f in $(installDirs) ; do \ cp -r TclCurl/$$f ${DESTDIR}/TclCurl${TCLCURL_VERSION} ;\ done ssl: mkdir ${DESTDIR}/certs ;\ cp ${certFiles} ${DESTDIR}/certs ;\ mkdir ${DESTDIR}/ssl ;\ for f in $(sslFiles) ; do \ cp -r /usr/local/bin/$$f ${DESTDIR}/ssl ;\ done docs: mkdir ${DESTDIR}/tclcurl${TCLCURL_VERSION}/doc ;\ for f in $(docFiles) ; do \ cp -r TclCurl/doc/$$f ${DESTDIR}/tclcurl${TCLCURL_VERSION}/doc;\ done rar: "c:/Program Files (x86)/WinRAR/rar" a -r -s -sfx ${DESTDIR}.exe ${DESTDIR};\ rm -r ${DESTDIR} tclcurl-ng-8.0.3/pkgIndex.tcl.in000066400000000000000000000007611522613063100164610ustar00rootroot00000000000000# -*- tcl -*- # Tcl package index file, version 1.1 # if {[package vsatisfies [package provide Tcl] 9.0-]} { set tclcurl_ext_lib [file join $dir @PKG_LIB_FILE9@] } else { set tclcurl_ext_lib [file join $dir @PKG_LIB_FILE8@] } set tclcurl_load_script [subst { load $tclcurl_ext_lib [string totitle @PACKAGE_NAME@] source [file join $dir @TCLCURL_SCRIPTS@] }] package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ $tclcurl_load_script unset tclcurl_load_script unset tclcurl_ext_lib tclcurl-ng-8.0.3/tclconfig/000077500000000000000000000000001522613063100155435ustar00rootroot00000000000000tclcurl-ng-8.0.3/tclconfig/install-sh000077500000000000000000000357761522613063100175710ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: tclcurl-ng-8.0.3/tclconfig/tcl.m4000077500000000000000000004064051522613063100166030ustar00rootroot00000000000000# tcl.m4 -- # # This file provides a set of autoconf macros to help TEA-enable # a Tcl extension. # # Copyright (c) 1999-2000 Ajuba Solutions. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. AC_PREREQ([2.69]) # Possible values for key variables defined: # # TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') # TEA_PLATFORM - windows unix # TEA_TK_EXTENSION - True if this is a Tk extension # #------------------------------------------------------------------------ # TEA_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the directory containing # the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_TCLCONFIG], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_INIT]) # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), [with_tclconfig="${withval}"]) AC_ARG_WITH(tcl8, AS_HELP_STRING([--with-tcl8], [Compile for Tcl8 in Tcl9 environment]), [with_tcl8="${withval}"]) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_PATH_TKCONFIG -- # # Locate the tkConfig.sh file # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tk=... # # Defines the following vars: # TK_BIN_DIR Full path to the directory containing # the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_TKCONFIG], [ # # Ok, lets find the tk configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tk # if test x"${no_tk}" = x ; then # we reset no_tk in case something fails here no_tk=true AC_ARG_WITH(tk, AS_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), [with_tkconfig="${withval}"]) AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ # First check to see if --with-tkconfig was specified. if test x"${with_tkconfig}" != x ; then case "${with_tkconfig}" in */tkConfig.sh ) if test -f "${with_tkconfig}"; then AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" fi ;; esac if test -f "${with_tkconfig}/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" else AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) fi fi # then check for a private Tk library if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ../tk \ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tk \ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tk \ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ; do if test -f "$i/Tk.framework/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tk9.1 2>/dev/null` \ `ls -d /usr/lib/tk9.0 2>/dev/null` \ `ls -d /usr/lib/tk8.6 2>/dev/null` \ `ls -d /usr/lib/tk8.5 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tk9.1 2>/dev/null` \ `ls -d /usr/local/lib/tk9.0 2>/dev/null` \ `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tk8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ${srcdir}/../tk \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_LOAD_TCLCONFIG -- # # Load the tclConfig.sh file # # Arguments: # # Requires the following vars to be set: # TCL_BIN_DIR # # Results: # # Substitutes the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE # TCL_ZIP_FILE # TCL_ZIPFS_SUPPORT #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TCLCONFIG], [ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TCL_BIN_DIR}/tclConfig.sh" else AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi AC_SUBST(TCL_VERSION) AC_SUBST(TCL_PATCH_LEVEL) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) AC_MSG_CHECKING([platform]) hold_cc=$CC; CC="$TCL_CC" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ #ifdef _WIN32 #error win32 #endif ]])],[ # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo ],[ TEA_PLATFORM="windows" AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) ]) CC=$hold_cc AC_MSG_RESULT($TEA_PLATFORM) # The BUILD_$pkg is to define the correct extern storage class # handling when making this package # To be able to sefely use the package name in a #define, it must not # contain anything other than alphanumeric characters and underscores SAFE_PKG_NAME=patsubst(AC_PACKAGE_NAME, [[^A-Za-z0-9_]], [_]) AC_DEFINE_UNQUOTED(BUILD_${SAFE_PKG_NAME}, [], [Building extension source?]) # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: AC_SUBST(CLEANFILES) AC_SUBST(TCL_LIBS) AC_SUBST(TCL_DEFS) AC_SUBST(TCL_EXTRA_CFLAGS) AC_SUBST(TCL_LD_FLAGS) AC_SUBST(TCL_SHLIB_LD_LIBS) ]) #------------------------------------------------------------------------ # TEA_LOAD_TKCONFIG -- # # Load the tkConfig.sh file # # Arguments: # # Requires the following vars to be set: # TK_BIN_DIR # # Results: # # Sets the following vars that should be in tkConfig.sh: # TK_BIN_DIR #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TKCONFIG], [ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TK_BIN_DIR}/tkConfig.sh" else AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) fi # If the TK_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TK_LIB_SPEC will be set to the value # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC # instead of TK_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TK_BIN_DIR}/Makefile" ; then TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tk.framework installed in an arbitrary location. case ${TK_DEFS} in *TK_FRAMEWORK*) if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then for i in "`cd "${TK_BIN_DIR}"; pwd`" \ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" break fi done fi if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" fi ;; esac fi # TEA specific: Ensure windowingsystem is defined if test "${TEA_PLATFORM}" = "unix" ; then case ${TK_DEFS} in *MAC_OSX_TK*) AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) TEA_WINDOWINGSYSTEM="aqua" ;; *) TEA_WINDOWINGSYSTEM="x11" ;; esac elif test "${TEA_PLATFORM}" = "windows" ; then TEA_WINDOWINGSYSTEM="win32" fi AC_SUBST(TK_VERSION) AC_SUBST(TK_BIN_DIR) AC_SUBST(TK_SRC_DIR) AC_SUBST(TK_LIB_FILE) AC_SUBST(TK_LIB_FLAG) AC_SUBST(TK_LIB_SPEC) AC_SUBST(TK_STUB_LIB_FILE) AC_SUBST(TK_STUB_LIB_FLAG) AC_SUBST(TK_STUB_LIB_SPEC) # TEA specific: AC_SUBST(TK_LIBS) AC_SUBST(TK_XINCLUDES) ]) #------------------------------------------------------------------------ # TEA_PROG_TCLSH # Determine the fully qualified path name of the tclsh executable # in the Tcl build directory or the tclsh installed in a bin # directory. This macro will correctly determine the name # of the tclsh executable even if tclsh has not yet been # built in the build directory. The tclsh found is always # associated with a tclConfig.sh file. This tclsh should be used # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # # Arguments: # none # # Results: # Substitutes the following vars: # TCLSH_PROG #------------------------------------------------------------------------ AC_DEFUN([TEA_PROG_TCLSH], [ AC_MSG_CHECKING([for tclsh]) if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi AC_MSG_RESULT([${TCLSH_PROG}]) AC_SUBST(TCLSH_PROG) ]) #------------------------------------------------------------------------ # TEA_PROG_WISH # Determine the fully qualified path name of the wish executable # in the Tk build directory or the wish installed in a bin # directory. This macro will correctly determine the name # of the wish executable even if wish has not yet been # built in the build directory. The wish found is always # associated with a tkConfig.sh file. This wish should be used # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # # Arguments: # none # # Results: # Substitutes the following vars: # WISH_PROG #------------------------------------------------------------------------ AC_DEFUN([TEA_PROG_WISH], [ AC_MSG_CHECKING([for wish]) if test -f "${TK_BIN_DIR}/Makefile" ; then # tkConfig.sh is in Tk build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}s${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}$s{EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" fi else WISH_PROG="${TK_BIN_DIR}/wish" fi else # tkConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" else WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}" fi list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TK_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${WISH_PROG}" ; then REAL_TK_BIN_DIR="`cd "$i"; pwd`/" break fi done WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" fi AC_MSG_RESULT([${WISH_PROG}]) AC_SUBST(WISH_PROG) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=yes|no # --enable-stubs=yes|no # # Defines the following vars: # STATIC_BUILD Used for building import/export libraries # on Windows. # # Sets the following vars: # SHARED_BUILD Value of 1 or 0 # STUBS_BUILD Value if 1 or 0 # USE_TCL_STUBS Value true: if SHARED_BUILD or --enable-stubs # USE_TCLOO_STUBS Value true: if SHARED_BUILD or --enable-stubs # USE_TK_STUBS Value true: if SHARED_BUILD or --enable-stubs # AND TEA_WINDOWING_SYSTEM != "" #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SHARED], [ AC_MSG_CHECKING([how to build libraries]) AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared], [build and link with shared libraries (default: on)]), [shared_ok=$enableval], [shared_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi AC_ARG_ENABLE(stubs, AS_HELP_STRING([--enable-stubs], [build and link with stub libraries. Always true for shared builds (default: on)]), [stubs_ok=$enableval], [stubs_ok=yes]) if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 STUBS_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [This a static build]) if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) AC_DEFINE(USE_TCLOO_STUBS, 1, [Use TclOO stubs]) if test "${TEA_WINDOWINGSYSTEM}" != ""; then AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) fi fi AC_SUBST(SHARED_BUILD) AC_SUBST(STUBS_BUILD) ]) #------------------------------------------------------------------------ # TEA_ENABLE_THREADS -- # # Specify if thread support should be enabled. If "yes" is specified # as an arg (optional), threads are enabled by default, "no" means # threads are disabled. "yes" is the default. # # TCL_THREADS is checked so that if you are compiling an extension # against a threaded core, your extension must be compiled threaded # as well. # # Note that it is legal to have a thread enabled extension run in a # threaded or non-threaded Tcl core, but a non-threaded extension may # only run in a non-threaded Tcl core. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-threads # # Sets the following vars: # THREADS_LIBS Thread library(s) # # Defines the following vars: # TCL_THREADS # _REENTRANT # _THREAD_SAFE #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_THREADS], [ AC_ARG_ENABLE(threads, AS_HELP_STRING([--enable-threads], [build with threads (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention AC_DEFINE(USE_THREAD_ALLOC, 1, [Do we want to use the threaded memory allocator?]) AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) if test "`uname -s`" = "SunOS" ; then AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) fi AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] AC_CHECK_LIB(pthread, __pthread_mutex_init, tcl_ok=yes, tcl_ok=no) fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else AC_CHECK_LIB(pthreads, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else AC_CHECK_LIB(c, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "no"; then AC_CHECK_LIB(c_r, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output AC_MSG_CHECKING([for building with threads]) if test "${TCL_THREADS}" = 1; then AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) AC_MSG_RESULT([yes (default)]) else AC_MSG_RESULT([no]) fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then AC_MSG_WARN([ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads.]) fi ;; esac AC_SUBST(TCL_THREADS) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SYMBOLS -- # # Specify if debugging symbols should be used. # Memory (TCL_MEM_DEBUG) debugging can also be enabled. # # Arguments: # none # # TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives # the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. # Requires the following vars to be set in the Makefile: # CFLAGS_DEFAULT # LDFLAGS_DEFAULT # # Results: # # Adds the following arguments to configure: # --enable-symbols # # Defines the following vars: # CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true # Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false # LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true # Sets to $(LDFLAGS_OPTIMIZE) if false #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SYMBOLS], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_CONFIG_CFLAGS]) AC_MSG_CHECKING([for build with symbols]) AC_ARG_ENABLE(symbols, AS_HELP_STRING([--enable-symbols], [build with debugging symbols (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" AC_MSG_RESULT([no]) AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?]) else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then AC_MSG_RESULT([yes (standard debugging)]) fi fi AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then AC_MSG_RESULT([enabled symbols mem debugging]) else AC_MSG_RESULT([enabled $tcl_ok debugging]) fi fi ]) #------------------------------------------------------------------------ # TEA_ENABLE_LANGINFO -- # # Allows use of modern nl_langinfo check for better l10n. # This is only relevant for Unix. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-langinfo=yes|no (default is yes) # # Defines the following vars: # HAVE_LANGINFO Triggers use of nl_langinfo if defined. #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_LANGINFO], [ AC_ARG_ENABLE(langinfo, AS_HELP_STRING([--enable-langinfo], [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), [langinfo_ok=$enableval], [langinfo_ok=yes]) HAVE_LANGINFO=0 if test "$langinfo_ok" = "yes"; then AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) fi AC_MSG_CHECKING([whether to use nl_langinfo]) if test "$langinfo_ok" = "yes"; then AC_CACHE_VAL(tcl_cv_langinfo_h, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[nl_langinfo(CODESET);]])], [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) AC_MSG_RESULT([$tcl_cv_langinfo_h]) if test $tcl_cv_langinfo_h = yes; then AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) fi else AC_MSG_RESULT([$langinfo_ok]) fi ]) #-------------------------------------------------------------------- # TEA_CONFIG_SYSTEM # # Determine what the system is (some things cannot be easily checked # on a feature-driven basis, alas). This can usually be done via the # "uname" command. # # Arguments: # none # # Results: # Defines the following var: # # system - System/platform/version identification code. # #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_SYSTEM], [ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then AC_MSG_WARN([can't find uname command]) tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ]) system=$tcl_cv_sys_version ]) #-------------------------------------------------------------------- # TEA_CONFIG_CFLAGS # # Try to determine the proper flags to pass to the compiler # for building shared libraries and other such nonsense. # # Arguments: # none # # Results: # # Defines and substitutes the following vars: # # DL_OBJS, DL_LIBS - removed for TEA, only needed by core. # LDFLAGS - Flags to pass to the compiler when linking object # files into an executable application binary such # as tclsh. # LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. Could # be the same as CC_SEARCH_FLAGS if ${CC} is used to link. # CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. # SHLIB_CFLAGS - Flags to pass to cc when compiling the components # of a shared library (may request position-independent # code, among other things). # SHLIB_LD - Base command to use for combining object files # into a shared library. # SHLIB_LD_LIBS - Dependent libraries for the linker to scan when # creating shared libraries. This symbol typically # goes at the end of the "ld" commands that build # shared libraries. The value of the symbol defaults to # "${LIBS}" if all of the dependent libraries should # be specified when creating a shared library. If # dependent libraries should not be specified (as on # SunOS 4.x, where they cause the link to fail, or in # general if Tcl and Tk aren't themselves shared # libraries), then this symbol has an empty string # as its value. # SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable # extensions. An empty string means we don't know how # to use shared libraries on this platform. # LIB_SUFFIX - Specifies everything that comes after the "libfoo" # in a static or shared library name, using the $PACKAGE_VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. # Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs # to have a version after the .so, and ${PACKAGE_VERSION}.a # on AIX, since a shared library needs to have # a .a extension whereas shared objects for loadable # extensions have a .so extension. Defaults to # ${PACKAGE_VERSION}${SHLIB_SUFFIX}. # CFLAGS_DEBUG - # Flags used when running the compiler in debug mode # CFLAGS_OPTIMIZE - # Flags used when running the compiler in optimize mode # CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_CFLAGS], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_INIT]) # Step 0.a: Enable 64 bit support? AC_MSG_CHECKING([if 64bit support is requested]) AC_ARG_ENABLE(64bit, AS_HELP_STRING([--enable-64bit], [enable 64bit support (default: off)]), [do64bit=$enableval], [do64bit=no]) AC_MSG_RESULT([$do64bit]) # Step 0.b: Enable Solaris 64 bit VIS support? AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) AC_ARG_ENABLE(64bit-vis, AS_HELP_STRING([--enable-64bit-vis], [enable 64bit Sparc VIS support (default: off)]), [do64bitVIS=$enableval], [do64bitVIS=no]) AC_MSG_RESULT([$do64bitVIS]) # Force 64bit on with VIS AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. AC_CACHE_CHECK([if compiler supports visibility "hidden"], tcl_cv_cc_visibility_hidden, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {}]], [[f();]])],[tcl_cv_cc_visibility_hidden=yes], [tcl_cv_cc_visibility_hidden=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ AC_DEFINE(MODULE_SCOPE, [extern __attribute__((__visibility__("hidden")))], [Compiler support for module scope symbols]) AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) ]) # Step 0.d: Disable -rpath support? AC_MSG_CHECKING([if rpath support is requested]) AC_ARG_ENABLE(rpath, AS_HELP_STRING([--disable-rpath], [disable rpath support (default: on)]), [doRpath=$enableval], [doRpath=yes]) AC_MSG_RESULT([$doRpath]) # Set the variable "system" to hold the name and version number # for the system. TEA_CONFIG_SYSTEM # Require ranlib early so we can override it in special cases below. AC_REQUIRE([AC_PROG_RANLIB]) # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g AS_IF([test "$GCC" = yes], [ CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" ], [ CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" ]) AC_CHECK_TOOL(AR, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION=""],[SHLIB_VERSION=".$SHLIB_VERSION"]) case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac do64bit_ok=yes fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[[4-9]]*) lflags="${lflags} -nodefaultlib:ucrt.lib" TEA_ADD_LIBS([ucrt.lib]) ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 TEA_ADD_LIBS([bufferoverflowU.lib]) else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode AC_CHECK_TOOL(RC, windres) CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" AC_CACHE_CHECK(for cross-compile version of gcc, ac_cv_cross, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef _WIN32 #error cross-compiler #endif ]], [[]])], [ac_cv_cross=yes], [ac_cv_cross=no]) ) if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) AS_IF([test "$GCC" != "yes"], [ # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` ;; esac AC_MSG_RESULT([Using $CC for compiling with threads]) ]) LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported with GCC on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" ]) ]) AS_IF([test "`uname -m`" = ia64], [ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" AS_IF([test "$GCC" = yes], [ CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' ], [ CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' ]) LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ], [ AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared -Wl,-bexpall' ], [ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" ]) SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" if test "${TEA_PLATFORM}" = "unix" -a "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$(patsubst cyg%.dll,lib%.dll,\$[@]).a" else SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a" fi EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) ;; HP-UX-*.11.*) # Use updated header definitions where possible AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library AS_IF([test "`uname -m`" = ia64], [ SHLIB_SUFFIX=".so" ], [ SHLIB_SUFFIX=".sl" ]) AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ CFLAGS="$CFLAGS -z" ]) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = "yes"], [ AS_IF([test "$GCC" = yes], [ case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]) ;; esac ], [ do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" ]) ]) ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" AC_LIBOBJ(mkstemp) AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) AS_IF([test "$GCC" = yes], [ CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" ], [ case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" ]) ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported by gcc]) ], [ do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" ]) ]) ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) AS_IF([test "${TCL_THREADS}" = "1"], [ # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) ;; esac AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) AS_IF([test $do64bit = yes], [ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_m64 = yes], [ CFLAGS="$CFLAGS -m64" do64bit_ok=yes ]) ]) # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" AS_IF([test $do64bit = yes], [ case `arch` in ppc) AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], tcl_cv_cc_arch_ppc64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes ]);; i386) AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], tcl_cv_cc_arch_x86_64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes ]);; *) AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; esac ], [ # Check for combined 32-bit and 64-bit fat build AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ fat_32_64=yes]) ]) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_search_paths_first=yes],[tcl_cv_ld_search_paths_first=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [__private_extern__], [Compiler support for module scope symbols]) tcl_cv_cc_visibility_hidden=yes ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[XrmInitialize();]])], [tcl_cv_lib_x11_64=yes],[tcl_cv_lib_x11_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) ]) AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[Tk_InitStubs(NULL, "", 0);]])], [tcl_cv_lib_tk_64=yes],[tcl_cv_lib_tk_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) ]) # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done]) ]) ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h [Should OS/390 do the right thing with sockets?]) ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" AS_IF([test "$SHARED_BUILD" = 1], [ SHLIB_LD='ld -shared -expect_unresolved "*"' ], [ SHLIB_LD='ld -non_shared -expect_unresolved "*"' ]) SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` AS_IF([test "$GCC" = yes], [ LIBS="$LIBS -lpthread -lmach -lexc" ], [ CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ]) ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) AS_IF([test "$GCC" = yes], [ SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ], [ SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ]) SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[[0-6]]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ arch=`isainfo` AS_IF([test "$arch" = "sparcv9 sparc"], [ AS_IF([test "$GCC" = yes], [ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" ]) ], [ do64bit_ok=yes AS_IF([test "$do64bitVIS" = yes], [ CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" ], [ CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" ]) # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ]) ], [AS_IF([test "$arch" = "amd64 i386"], [ AS_IF([test "$GCC" = yes], [ case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]);; esac ], [ do64bit_ok=yes case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac ]) ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) ]) SHLIB_SUFFIX=".so" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "$do64bit_ok" = yes], [ AS_IF([test "$arch" = "sparcv9 sparc"], [ # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" ], [AS_IF([test "$arch" = "amd64 i386"], [ # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" ])]) ]) ], [ case $system in SunOS-5.[[1-9]][[0-9]]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ]) ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_Bexport = yes], [ LDFLAGS="$LDFLAGS -Wl,-Bexport" ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) ]) dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so dnl # until the end of configure, as configure's compile and link tests use dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's dnl # preprocessing tests use only CPPFLAGS. AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. AS_IF([test "$GCC" = yes], [ case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [extern], [No Compiler support for module scope symbols]) ]) AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then AC_CACHE_CHECK(for SEH support in compiler, tcl_cv_seh, AC_RUN_IFELSE([AC_LANG_SOURCE([[ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } ]])], [tcl_cv_seh=yes], [tcl_cv_seh=no], [tcl_cv_seh=no]) ) if test "$tcl_cv_seh" = "no" ; then AC_DEFINE(HAVE_NO_SEH, 1, [Defined when mingw does not support SEH]) fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, tcl_cv_eh_disposition, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN ]], [[ EXCEPTION_DISPOSITION x; ]])], [tcl_cv_eh_disposition=yes], [tcl_cv_eh_disposition=no]) ) if test "$tcl_cv_eh_disposition" = "no" ; then AC_DEFINE(EXCEPTION_DISPOSITION, int, [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. AC_CACHE_CHECK(for winnt.h that ignores VOID define, tcl_cv_winnt_ignore_void, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN ]], [[ CHAR c; SHORT s; LONG l; ]])], [tcl_cv_winnt_ignore_void=yes], [tcl_cv_winnt_ignore_void=no]) ) if test "$tcl_cv_winnt_ignore_void" = "yes" ; then AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, [Defined when cygwin/mingw ignores VOID define in winnt.h]) fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. AC_CACHE_CHECK(for cast to union support, tcl_cv_cast_to_union, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ union foo { int i; double d; }; union foo f = (union foo) (int) 0; ]])], [tcl_cv_cast_to_union=yes], [tcl_cv_cast_to_union=no]) ) if test "$tcl_cv_cast_to_union" = "yes"; then AC_DEFINE(HAVE_CAST_TO_UNION, 1, [Defined when compiler supports casting to union type.]) fi AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have ?])],) AC_SUBST(CFLAGS_DEBUG) AC_SUBST(CFLAGS_OPTIMIZE) AC_SUBST(CFLAGS_WARNING) AC_SUBST(LDFLAGS_DEBUG) AC_SUBST(LDFLAGS_OPTIMIZE) AC_SUBST(STLIB_LD) AC_SUBST(SHLIB_LD) AC_SUBST(SHLIB_LD_LIBS) AC_SUBST(SHLIB_CFLAGS) AC_SUBST(LD_LIBRARY_PATH_VAR) # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary TEA_TCL_EARLY_FLAGS TEA_TCL_64BIT_FLAGS ]) #-------------------------------------------------------------------- # TEA_SERIAL_PORT # # Determine which interface to use to talk to the serial port. # Note that #include lines must begin in leftmost column for # some compilers to recognize them as preprocessor directives, # and some build environments have stdin not pointing at a # pseudo-terminal (usually /dev/null instead.) # # Arguments: # none # # Results: # # Defines only one of the following vars: # HAVE_SYS_MODEM_H # USE_TERMIOS # USE_TERMIO # USE_SGTTY #-------------------------------------------------------------------- AC_DEFUN([TEA_SERIAL_PORT], [ AC_CHECK_HEADERS(sys/modem.h) AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct termios t; if (tcgetattr(0, &t) == 0) { cfsetospeed(&t, 0); t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct termio t; if (ioctl(0, TCGETA, &t) == 0) { t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct sgttyb t; if (ioctl(0, TIOCGETP, &t) == 0) { t.sg_ospeed = 0; t.sg_flags |= ODDP | EVENP | RAW; return 0; } return 1; }]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct termios t; if (tcgetattr(0, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { cfsetospeed(&t, 0); t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct termio t; if (ioctl(0, TCGETA, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct sgttyb t; if (ioctl(0, TIOCGETP, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { t.sg_ospeed = 0; t.sg_flags |= ODDP | EVENP | RAW; return 0; } return 1; }]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=none],[tcl_cv_api_serial=none]) fi]) case $tcl_cv_api_serial in termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; esac ]) #-------------------------------------------------------------------- # TEA_PATH_X # # Locate the X11 header files and the X11 library archive. Try # the ac_path_x macro first, but if it doesn't find the X stuff # (e.g. because there's no xmkmf program) then check through # a list of possible directories. Under some conditions the # autoconf macro will return an include directory that contains # no include files, so double-check its result just to be safe. # # This should be called after TEA_CONFIG_CFLAGS as setting the # LIBS line can confuse some configure macro magic. # # Arguments: # none # # Results: # # Sets the following vars: # XINCLUDES # XLIBSW # PKG_LIBS (appends to) #-------------------------------------------------------------------- AC_DEFUN([TEA_PATH_X], [ if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then TEA_PATH_UNIX_X fi ]) AC_DEFUN([TEA_PATH_UNIX_X], [ AC_PATH_X not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[not_really_there="yes"]) else if test ! -r $x_includes/X11/Xlib.h; then not_really_there="yes" fi fi fi if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then AC_MSG_CHECKING([for X11 header files]) found_xincludes="no" AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[found_xincludes="yes"],[found_xincludes="no"]) if test "$found_xincludes" = "no"; then dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" for i in $dirs ; do if test -r $i/X11/Xlib.h; then AC_MSG_RESULT([$i]) XINCLUDES=" -I$i" found_xincludes="yes" break fi done fi else if test "$x_includes" != ""; then XINCLUDES="-I$x_includes" found_xincludes="yes" fi fi if test "$found_xincludes" = "no"; then AC_MSG_RESULT([couldn't find any!]) fi if test "$no_x" = yes; then AC_MSG_CHECKING([for X11 libraries]) XLIBSW=nope dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" for i in $dirs ; do if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then AC_MSG_RESULT([$i]) XLIBSW="-L$i -lX11" x_libraries="$i" break fi done else if test "$x_libraries" = ""; then XLIBSW=-lX11 else XLIBSW="-L$x_libraries -lX11" fi fi if test "$XLIBSW" = nope ; then AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) fi if test "$XLIBSW" = nope ; then AC_MSG_RESULT([could not find any! Using -lX11.]) XLIBSW=-lX11 fi # TEA specific: if test x"${XLIBSW}" != x ; then PKG_LIBS="${PKG_LIBS} ${XLIBSW}" fi ]) #-------------------------------------------------------------------- # TEA_BLOCKING_STYLE # # The statements below check for systems where POSIX-style # non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. # On these systems (mostly older ones), use the old BSD-style # FIONBIO approach instead. # # Arguments: # none # # Results: # # Defines some of the following vars: # HAVE_SYS_IOCTL_H # HAVE_SYS_FILIO_H # USE_FIONBIO # O_NONBLOCK #-------------------------------------------------------------------- AC_DEFUN([TEA_BLOCKING_STYLE], [ AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/filio.h) TEA_CONFIG_SYSTEM AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) case $system in OSF*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; *) AC_MSG_RESULT([O_NONBLOCK]) ;; esac ]) #-------------------------------------------------------------------- # TEA_TIME_HANDLER # # Checks how the system deals with time.h, what time structures # are used on the system, and what fields the structures have. # # Arguments: # none # # Results: # # Defines some of the following vars: # USE_DELTA_FOR_TZ # HAVE_TM_GMTOFF # HAVE_TM_TZADJ # HAVE_TIMEZONE_VAR # #-------------------------------------------------------------------- AC_DEFUN([TEA_TIME_HANDLER], [ AC_CHECK_HEADERS(sys/time.h) AC_HEADER_TIME AC_STRUCT_TIMEZONE AC_CHECK_FUNCS(gmtime_r localtime_r mktime) AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_tzadj;]])], [tcl_cv_member_tm_tzadj=yes], [tcl_cv_member_tm_tzadj=no])]) if test $tcl_cv_member_tm_tzadj = yes ; then AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) fi AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_gmtoff;]])], [tcl_cv_member_tm_gmtoff=yes], [tcl_cv_member_tm_gmtoff=no])]) if test $tcl_cv_member_tm_gmtoff = yes ; then AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) fi # # Its important to include time.h in this check, as some systems # (like convex) have timezone functions, etc. # AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern long timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])]) if test $tcl_cv_timezone_long = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) else # # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. # AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern time_t timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])]) if test $tcl_cv_timezone_time = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) fi fi ]) #-------------------------------------------------------------------- # TEA_BUGGY_STRTOD # # Under Solaris 2.4, strtod returns the wrong value for the # terminating character under some conditions. Check for this # and if the problem exists use a substitute procedure # "fixstrtod" (provided by Tcl) that corrects the error. # Also, on Compaq's Tru64 Unix 5.0, # strtod(" ") returns 0.0 instead of a failure to convert. # # Arguments: # none # # Results: # # Might defines some of the following vars: # strtod (=fixstrtod) #-------------------------------------------------------------------- AC_DEFUN([TEA_BUGGY_STRTOD], [ AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) if test "$tcl_strtod" = 1; then AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include extern double strtod(); int main() { char *infString="Inf", *nanString="NaN", *spaceString=" "; char *term; double value; value = strtod(infString, &term); if ((term != infString) && (term[-1] == 0)) { exit(1); } value = strtod(nanString, &term); if ((term != nanString) && (term[-1] == 0)) { exit(1); } value = strtod(spaceString, &term); if (term == (spaceString+1)) { exit(1); } exit(0); }]])], [tcl_cv_strtod_buggy=ok], [tcl_cv_strtod_buggy=buggy], [tcl_cv_strtod_buggy=buggy])]) if test "$tcl_cv_strtod_buggy" = buggy; then AC_LIBOBJ([fixstrtod]) USE_COMPAT=1 AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) fi fi ]) #-------------------------------------------------------------------- # TEA_TCL_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. # Things like the math library (-lm), socket stuff (-lsocket vs. # -lnsl), zlib (-lz) and libtommath (-ltommath) are dealt with here. # # Arguments: # None. # # Results: # # Might append to the following vars: # LIBS # MATH_LIBS # # Might define the following vars: # HAVE_NET_ERRNO_H # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_LINK_LIBS], [ #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. #-------------------------------------------------------------------- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) AC_CHECK_HEADER(net/errno.h, [ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have ?])]) #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) if test "$tcl_checkSocket" = 1; then AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) fi AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])]) AC_CHECK_FUNC(mp_log_u32, , [AC_CHECK_LIB(tommath, mp_log_u32, [LIBS="$LIBS -ltommath"])]) AC_CHECK_FUNC(deflateSetHeader, , [AC_CHECK_LIB(z, deflateSetHeader, [LIBS="$LIBS -lz"])]) ]) #-------------------------------------------------------------------- # TEA_TCL_EARLY_FLAGS # # Check for what flags are needed to be passed so the correct OS # features are available. # # Arguments: # None # # Results: # # Might define the following vars: # _ISOC99_SOURCE # _FILE_OFFSET_BITS # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_EARLY_FLAG],[ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[ ]$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)])) if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then AC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building]) tcl_flags="$tcl_flags $1" fi ]) AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ AC_MSG_CHECKING([for required early compiler flags]) tcl_flags="" TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) if test "${TCL_MAJOR_VERSION}" -ne 8 ; then TEA_TCL_EARLY_FLAG(_FILE_OFFSET_BITS,[#include ], [switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }],64) fi if test "x${tcl_flags}" = "x" ; then AC_MSG_RESULT([none]) else AC_MSG_RESULT([${tcl_flags}]) fi ]) #-------------------------------------------------------------------- # TEA_TCL_64BIT_FLAGS # # Check for what is defined in the way of 64-bit features. # # Arguments: # None # # Results: # # Might define the following vars: # TCL_WIDE_INT_IS_LONG # TCL_WIDE_INT_TYPE # HAVE_STRUCT_DIRENT64, HAVE_DIR64 # HAVE_STRUCT_STAT64 # HAVE_TYPE_OFF64_T # _TIME_BITS # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ AC_MSG_CHECKING([for 64-bit integer type]) AC_CACHE_VAL(tcl_cv_type_64bit,[ tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__int64 value = (__int64) 0;]])], [tcl_type_64bit=__int64],[tcl_type_64bit="long long"]) # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; }]])],[tcl_cv_type_64bit=${tcl_type_64bit}],[])]) if test "${tcl_cv_type_64bit}" = none ; then AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?]) AC_MSG_RESULT([yes]) elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* AC_MSG_RESULT([using Tcl header defaults]) else AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, [What type should be used to define wide integers?]) AC_MSG_RESULT([${tcl_cv_type_64bit}]) # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then AC_CACHE_CHECK([for 64-bit time_t], tcl_cv_time_t_64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], [tcl_cv_time_t_64=yes],[tcl_cv_time_t_64=no])]) if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. AC_CACHE_CHECK([if _TIME_BITS=64 enables 64-bit time_t], tcl_cv__time_bits,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define _TIME_BITS 64 #include ]], [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], [tcl_cv__time_bits=yes],[tcl_cv__time_bits=no])]) if test "x${tcl_cv__time_bits}" = "xyes" ; then AC_DEFINE(_TIME_BITS, 64, [_TIME_BITS=64 enables 64-bit time_t.]) fi fi fi AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 p;]])], [tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])]) if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in ?]) fi AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d);]])], [tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])]) if test "x${tcl_cv_DIR64}" = "xyes" ; then AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct stat64 p; ]])], [tcl_cv_struct_stat64=yes], [tcl_cv_struct_stat64=no])]) if test "x${tcl_cv_struct_stat64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[off64_t offset; ]])], [tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])]) dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the dnl functions lseek64 and open64 are defined. if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in ?]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi ]) ## ## Here ends the standard Tcl configuration bits and starts the ## TEA specific functions ## #------------------------------------------------------------------------ # TEA_INIT -- # # Init various Tcl Extension Architecture (TEA) variables. # This should be the first called TEA_* macro. # # Arguments: # none # # Results: # # Defines and substs the following vars: # CYGPATH # EXEEXT # Defines only: # TEA_VERSION # TEA_INITED # TEA_PLATFORM (windows or unix) # # "cygpath" is used on windows to generate native path names for include # files. These variables should only be used with the compiler and linker # since they generate native path names. # # EXEEXT # Select the executable extension based on the host type. This # is a lightweight replacement for AC_EXEEXT that doesn't require # a compiler. #------------------------------------------------------------------------ AC_DEFUN([TEA_INIT], [ TEA_VERSION="3.13" AC_MSG_CHECKING([TEA configuration]) if test x"${PACKAGE_NAME}" = x ; then AC_MSG_ERROR([ The PACKAGE_NAME variable must be defined by your TEA configure.ac]) fi AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) AC_SUBST(EXEEXT) AC_SUBST(CYGPATH) # This package name must be replaced statically for AC_SUBST to work AC_SUBST(PKG_LIB_FILE) AC_SUBST(PKG_LIB_FILE8) AC_SUBST(PKG_LIB_FILE9) # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... AC_SUBST(PKG_STUB_SOURCES) AC_SUBST(PKG_STUB_OBJECTS) AC_SUBST(PKG_TCL_SOURCES) AC_SUBST(PKG_HEADERS) AC_SUBST(PKG_INCLUDES) AC_SUBST(PKG_LIBS) AC_SUBST(PKG_CFLAGS) # Configure the installer. TEA_INSTALLER ]) #------------------------------------------------------------------------ # TEA_ADD_SOURCES -- # # Specify one or more source files. Users should check for # the right platform before adding to their list. # It is not important to specify the directory, as long as it is # in the generic, win or unix subdirectory of $(srcdir). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_SOURCES # PKG_OBJECTS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_SOURCES], [ vars="$@" for i in $vars; do case $i in [\$]*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then AC_MSG_ERROR([could not find source file '$i']) fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done AC_SUBST(PKG_SOURCES) AC_SUBST(PKG_OBJECTS) ]) #------------------------------------------------------------------------ # TEA_ADD_STUB_SOURCES -- # # Specify one or more source files. Users should check for # the right platform before adding to their list. # It is not important to specify the directory, as long as it is # in the generic, win or unix subdirectory of $(srcdir). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_STUB_SOURCES # PKG_STUB_OBJECTS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_STUB_SOURCES], [ vars="$@" for i in $vars; do # check for existence - allows for generic/win/unix VPATH if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then AC_MSG_ERROR([could not find stub source file '$i']) fi PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" done AC_SUBST(PKG_STUB_SOURCES) AC_SUBST(PKG_STUB_OBJECTS) ]) #------------------------------------------------------------------------ # TEA_ADD_TCL_SOURCES -- # # Specify one or more Tcl source files. These should be platform # independent runtime files. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_TCL_SOURCES #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_TCL_SOURCES], [ vars="$@" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done AC_SUBST(PKG_TCL_SOURCES) ]) #------------------------------------------------------------------------ # TEA_ADD_HEADERS -- # # Specify one or more source headers. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_HEADERS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_HEADERS], [ vars="$@" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then AC_MSG_ERROR([could not find header file '${srcdir}/$i']) fi PKG_HEADERS="$PKG_HEADERS $i" done AC_SUBST(PKG_HEADERS) ]) #------------------------------------------------------------------------ # TEA_ADD_INCLUDES -- # # Specify one or more include dirs. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_INCLUDES], [ vars="$@" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done AC_SUBST(PKG_INCLUDES) ]) #------------------------------------------------------------------------ # TEA_ADD_LIBS -- # # Specify one or more libraries. Users should check for # the right platform before adding to their list. For Windows, # libraries provided in "foo.lib" format will be converted to # "-lfoo" when using GCC (mingw). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_LIBS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_LIBS], [ vars="$@" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.[[lL]][[iI]][[bB]][$]/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done AC_SUBST(PKG_LIBS) ]) #------------------------------------------------------------------------ # TEA_ADD_CFLAGS -- # # Specify one or more CFLAGS. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_CFLAGS], [ PKG_CFLAGS="$PKG_CFLAGS $@" AC_SUBST(PKG_CFLAGS) ]) #------------------------------------------------------------------------ # TEA_ADD_CLEANFILES -- # # Specify one or more CLEANFILES. # # Arguments: # one or more file names to clean target # # Results: # # Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_CLEANFILES], [ CLEANFILES="$CLEANFILES $@" ]) #------------------------------------------------------------------------ # TEA_PREFIX -- # # Handle the --prefix=... option by defaulting to what Tcl gave # # Arguments: # none # # Results: # # If --prefix or --exec-prefix was not specified, $prefix and # $exec_prefix will be set to the values given to Tcl when it was # configured. #------------------------------------------------------------------------ AC_DEFUN([TEA_PREFIX], [ if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) prefix=${TCL_PREFIX} else AC_MSG_NOTICE([--prefix defaulting to /usr/local]) prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) exec_prefix=${TCL_EXEC_PREFIX} else AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) exec_prefix=$prefix fi fi ]) #------------------------------------------------------------------------ # TEA_SETUP_COMPILER_CC -- # # Do compiler checks the way we want. This is just a replacement # for AC_PROG_CC in TEA configure.ac files to make them cleaner. # # Arguments: # none # # Results: # # Sets up CC var and other standard bits we need to make executables. #------------------------------------------------------------------------ AC_DEFUN([TEA_SETUP_COMPILER_CC], [ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. AC_PROG_CC AC_PROG_CPP #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- AC_PROG_MAKE_SET #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- AC_CHECK_TOOL(RANLIB, ranlib) #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- AC_OBJEXT AC_EXEEXT ]) #------------------------------------------------------------------------ # TEA_SETUP_COMPILER -- # # Do compiler checks that use the compiler. This must go after # TEA_SETUP_COMPILER_CC, which does the actual compiler check. # # Arguments: # none # # Results: # # Sets up CC var and other standard bits we need to make executables. #------------------------------------------------------------------------ AC_DEFUN([TEA_SETUP_COMPILER], [ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. AC_REQUIRE([TEA_SETUP_COMPILER_CC]) #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then AC_CACHE_CHECK([if the compiler understands -pipe], tcl_cv_cc_pipe, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no]) CFLAGS=$hold_cflags]) if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then AC_DEFINE(Tcl_Size, int, [Is 'Tcl_Size' in ?]) fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- AC_C_BIGENDIAN(,,,[#]) ]) #------------------------------------------------------------------------ # TEA_MAKE_LIB -- # # Generate a line that can be used to build a shared/unshared library # in a platform independent manner. # # Arguments: # none # # Requires: # # Results: # # Defines the following vars: # CFLAGS - Done late here to note disturb other AC macros # MAKE_LIB - Command to execute to build the Tcl library; # differs depending on whether or not Tcl is being # compiled as a shared library. # MAKE_SHARED_LIB Makefile rule for building a shared library # MAKE_STATIC_LIB Makefile rule for building a static library # MAKE_STUB_LIB Makefile rule for building a stub library # VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL # VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE #------------------------------------------------------------------------ AC_DEFUN([TEA_MAKE_LIB], [ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" AC_EGREP_CPP([manifest needed], [ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif ], [ # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" TEA_ADD_CLEANFILES([*.manifest]) ]) MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- if test "$TEA_PLATFORM" = "unix"; then PACKAGE_LIB_PREFIX8="lib" if test "$EXEEXT" = ".exe" -a "$SHARED_BUILD" != "0"; then PACKAGE_LIB_PREFIX9="cygtcl9" else PACKAGE_LIB_PREFIX9="libtcl9" fi else PACKAGE_LIB_PREFIX8="" PACKAGE_LIB_PREFIX9="tcl9" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" AC_DEFINE(TCL_MAJOR_VERSION, 8, [Compile for Tcl8?]) AC_DEFINE(TK_MAJOR_VERSION, 8, [Compile for Tk8?]) fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi AC_CACHE_CHECK([if the linker understands --disable-high-entropy-va], tcl_cv_ld_high_entropy, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Wl,--disable-high-entropy-va" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_ld_high_entropy=yes],[tcl_cv_ld_high_entropy=no]) CFLAGS=$hold_cflags]) if test $tcl_cv_ld_high_entropy = yes; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--disable-high-entropy-va" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi AC_SUBST(MAKE_LIB) AC_SUBST(MAKE_SHARED_LIB) AC_SUBST(MAKE_STATIC_LIB) AC_SUBST(MAKE_STUB_LIB) # Substitute STUB_LIB_FILE in case package creates a stub library too. AC_SUBST(PKG_STUB_LIB_FILE) AC_SUBST(RANLIB_STUB) AC_SUBST(VC_MANIFEST_EMBED_DLL) AC_SUBST(VC_MANIFEST_EMBED_EXE) ]) #------------------------------------------------------------------------ # TEA_LIB_SPEC -- # # Compute the name of an existing object library located in libdir # from the given base name and produce the appropriate linker flags. # # Arguments: # basename The base name of the library without version # numbers, extensions, or "lib" prefixes. # extra_dir Extra directory in which to search for the # library. This location is used first, then # $prefix/$exec-prefix, then some defaults. # # Requires: # TEA_INIT and TEA_PREFIX must be called first. # # Results: # # Defines the following vars: # ${basename}_LIB_NAME The computed library name. # ${basename}_LIB_SPEC The computed linker flags. #------------------------------------------------------------------------ AC_DEFUN([TEA_LIB_SPEC], [ AC_MSG_CHECKING([for $1 library]) # Look in exec-prefix for the library (defined by TEA_PREFIX). tea_lib_name_dir="${exec_prefix}/lib" # Or in a user-specified location. if test x"$2" != x ; then tea_extra_lib_dir=$2 else tea_extra_lib_dir=NONE fi for i in \ `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do if test -f "$i" ; then tea_lib_name_dir=`dirname $i` $1_LIB_NAME=`basename $i` $1_LIB_PATH_NAME=$i break fi done if test "${TEA_PLATFORM}" = "windows"; then $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" else # Strip off the leading "lib" and trailing ".a" or ".so" tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" fi if test "x${$1_LIB_NAME}" = x ; then AC_MSG_ERROR([not found]) else AC_MSG_RESULT([${$1_LIB_SPEC}]) fi ]) #------------------------------------------------------------------------ # TEA_PRIVATE_TCL_HEADERS -- # # Locate the private Tcl include files # # Arguments: # # Requires: # TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has # already been called. # # Results: # # Substitutes the following vars: # TCL_TOP_DIR_NATIVE # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) AC_MSG_CHECKING([for Tcl private include files]) TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" # Check to see if tclPort.h isn't already with the public headers # Don't look for tclInt.h because that resides with tcl.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tclh}/tclWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then result="private headers found with public headers" else TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" else TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TCL_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -d "${TCL_BIN_DIR}/Headers" -a \ -d "${TCL_BIN_DIR}/PrivateHeaders"; then TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" else TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TCL_INCLUDES}" else if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) fi result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" fi fi AC_SUBST(TCL_TOP_DIR_NATIVE) AC_SUBST(TCL_INCLUDES) AC_MSG_RESULT([${result}]) ]) #------------------------------------------------------------------------ # TEA_PUBLIC_TCL_HEADERS -- # # Locate the installed public Tcl header files # # Arguments: # None. # # Requires: # CYGPATH must be set # # Results: # # Adds a --with-tclinclude switch to configure. # Result is cached. # # Substitutes the following vars: # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ AC_MSG_CHECKING([for Tcl public headers]) AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) AC_CACHE_VAL(ac_cv_c_tclh, [ # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi ]) # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) else AC_MSG_RESULT([${ac_cv_c_tclh}]) fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TCL_INCLUDES) ]) #------------------------------------------------------------------------ # TEA_PRIVATE_TK_HEADERS -- # # Locate the private Tk include files # # Arguments: # # Requires: # TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has # already been called. # # Results: # # Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) AC_MSG_CHECKING([for Tk private include files]) TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" # Check to see if tkPort.h isn't already with the public headers # Don't look for tkInt.h because that resides with tk.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tkh}/tkWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tkh}/tkUnixPort.h"; then result="private headers found with public headers" else TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" if test "${TEA_PLATFORM}" = "windows"; then TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" else TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TK_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" # Detect and add ttk subdir if test -d "${TK_SRC_DIR}/generic/ttk"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" fi if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" fi if test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TK_DEFS} in *TK_FRAMEWORK*) if test -d "${TK_BIN_DIR}/Headers" -a \ -d "${TK_BIN_DIR}/PrivateHeaders"; then TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" else TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TK_INCLUDES}" else if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) fi result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" fi fi AC_SUBST(TK_TOP_DIR_NATIVE) AC_SUBST(TK_XLIB_DIR_NATIVE) AC_SUBST(TK_INCLUDES) AC_MSG_RESULT([${result}]) ]) #------------------------------------------------------------------------ # TEA_PUBLIC_TK_HEADERS -- # # Locate the installed public Tk header files # # Arguments: # None. # # Requires: # CYGPATH must be set # # Results: # # Adds a --with-tkinclude switch to configure. # Result is cached. # # Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ AC_MSG_CHECKING([for Tk public headers]) AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) AC_CACHE_VAL(ac_cv_c_tkh, [ # Use the value from --with-tkinclude, if it was given if test x"${with_tkinclude}" != x ; then if test -f "${with_tkinclude}/tk.h" ; then ac_cv_c_tkh=${with_tkinclude} else AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) fi else list="" if test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use # the framework's Headers directory. case ${TK_DEFS} in *TK_FRAMEWORK*) list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tk is not installed, # and in that situation, look there before installed locations. if test -f "${TK_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tk's --prefix location, # relative to directory of tkConfig.sh, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TK_PREFIX}/include 2>/dev/null` \ `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TK_INCLUDE_SPEC}" != x ; then d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tk.h" ; then ac_cv_c_tkh=$i break fi done fi ]) # Print a message based on how we determined the include path if test x"${ac_cv_c_tkh}" = x ; then AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) else AC_MSG_RESULT([${ac_cv_c_tkh}]) fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TK_INCLUDES) if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then # On Windows and Aqua, we need the X compat headers AC_MSG_CHECKING([for X11 header files]) if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TK_XINCLUDES) fi AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) fi ]) #------------------------------------------------------------------------ # TEA_PATH_CONFIG -- # # Locate the ${1}Config.sh file and perform a sanity check on # the ${1} compile flags. These are used by packages like # [incr Tk] that load *Config.sh files from more than Tcl and Tk. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-$1=... # # Defines the following vars: # $1_BIN_DIR Full path to the directory containing # the $1Config.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_CONFIG], [ # # Ok, lets find the $1 configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-$1 # if test x"${no_$1}" = x ; then # we reset no_$1 in case something fails here no_$1=true AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) AC_MSG_CHECKING([for $1 configuration]) AC_CACHE_VAL(ac_cv_c_$1config,[ # First check to see if --with-$1 was specified. if test x"${with_$1config}" != x ; then case ${with_$1config} in */$1Config.sh ) if test -f ${with_$1config}; then AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` fi;; esac if test -f "${with_$1config}/$1Config.sh" ; then ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` else AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) fi fi # then check for a private $1 installation if test x"${ac_cv_c_$1config}" = x ; then for i in \ ../$1 \ `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ../../$1 \ `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ../../../$1 \ `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ${srcdir}/../$1 \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ; do if test -f "$i/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i; pwd)` break fi if test -f "$i/unix/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i/unix; pwd)` break fi done fi # check in a few common install locations if test x"${ac_cv_c_$1config}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ ; do if test -f "$i/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i; pwd)` break fi done fi ]) if test x"${ac_cv_c_$1config}" = x ; then $1_BIN_DIR="# no $1 configs found" AC_MSG_WARN([Cannot find $1 configuration definitions]) exit 0 else no_$1= $1_BIN_DIR=${ac_cv_c_$1config} AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_LOAD_CONFIG -- # # Load the $1Config.sh file # # Arguments: # # Requires the following vars to be set: # $1_BIN_DIR # # Results: # # Substitutes the following vars: # $1_SRC_DIR # $1_LIB_FILE # $1_LIB_SPEC #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG], [ AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) if test -f "${$1_BIN_DIR}/$1Config.sh" ; then AC_MSG_RESULT([loading]) . "${$1_BIN_DIR}/$1Config.sh" else AC_MSG_RESULT([file not found]) fi # # If the $1_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable $1_LIB_SPEC will be set to the value # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC # instead of $1_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. # if test -f "${$1_BIN_DIR}/Makefile" ; then AC_MSG_WARN([Found Makefile - using build library specs for $1]) $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} $1_LIBRARY_PATH=${$1_LIBRARY_PATH} fi AC_SUBST($1_VERSION) AC_SUBST($1_BIN_DIR) AC_SUBST($1_SRC_DIR) AC_SUBST($1_LIB_FILE) AC_SUBST($1_LIB_SPEC) AC_SUBST($1_STUB_LIB_FILE) AC_SUBST($1_STUB_LIB_SPEC) AC_SUBST($1_STUB_LIB_PATH) # Allow the caller to prevent this auto-check by specifying any 2nd arg AS_IF([test "x$2" = x], [ # Check both upper and lower-case variants # If a dev wanted non-stubs libs, this function could take an option # to not use _STUB in the paths below AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], [TEA_LOAD_CONFIG_LIB($1_STUB)]) ]) ]) #------------------------------------------------------------------------ # TEA_LOAD_CONFIG_LIB -- # # Helper function to load correct library from another extension's # ${PACKAGE}Config.sh. # # Results: # Adds to LIBS the appropriate extension library #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ AC_MSG_CHECKING([For $1 library for LIBS]) # This simplifies the use of stub libraries by automatically adding # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, # but this is called before CONFIG_CFLAGS. More importantly, this adds # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. if test "x${$1_LIB_SPEC}" != "x" ; then if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) else TEA_ADD_LIBS([${$1_LIB_SPEC}]) AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) fi else AC_MSG_RESULT([file not found]) fi ]) #------------------------------------------------------------------------ # TEA_EXPORT_CONFIG -- # # Define the data to insert into the ${PACKAGE}Config.sh file # # Arguments: # # Requires the following vars to be set: # $1 # # Results: # Substitutes the following vars: #------------------------------------------------------------------------ AC_DEFUN([TEA_EXPORT_CONFIG], [ #-------------------------------------------------------------------- # These are for $1Config.sh #-------------------------------------------------------------------- # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}" eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}" else eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`" eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval $1_STUB_LIB_FLAG="-l$1stub" fi $1_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${$1_LIB_FLAG}" $1_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${$1_LIB_FLAG}" $1_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` [$]{$1_STUB_LIB_FLAG}" $1_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` [$]{$1_STUB_LIB_FLAG}" $1_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/[$]{PKG_STUB_LIB_FILE}" $1_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/[$]{PKG_STUB_LIB_FILE}" AC_SUBST($1_BUILD_LIB_SPEC) AC_SUBST($1_LIB_SPEC) AC_SUBST($1_BUILD_STUB_LIB_SPEC) AC_SUBST($1_STUB_LIB_SPEC) AC_SUBST($1_BUILD_STUB_LIB_PATH) AC_SUBST($1_STUB_LIB_PATH) AC_SUBST(MAJOR_VERSION) AC_SUBST(MINOR_VERSION) AC_SUBST(PATCHLEVEL) ]) #------------------------------------------------------------------------ # TEA_INSTALLER -- # # Configure the installer. # # Arguments: # none # # Results: # Substitutes the following vars: # INSTALL # INSTALL_DATA_DIR # INSTALL_DATA # INSTALL_PROGRAM # INSTALL_SCRIPT # INSTALL_LIBRARY #------------------------------------------------------------------------ AC_DEFUN([TEA_INSTALLER], [ INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' TEA_CONFIG_SYSTEM case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac AC_SUBST(INSTALL) AC_SUBST(INSTALL_DATA_DIR) AC_SUBST(INSTALL_DATA) AC_SUBST(INSTALL_PROGRAM) AC_SUBST(INSTALL_SCRIPT) AC_SUBST(INSTALL_LIBRARY) ]) ### # Tip 430 - ZipFS Modifications ### #------------------------------------------------------------------------ # TEA_ZIPFS_SUPPORT # Locate a zip encoder installed on the system path, or none. # # Arguments: # none # # Results: # Substitutes the following vars: # MACHER_PROG # ZIP_PROG # ZIP_PROG_OPTIONS # ZIP_PROG_VFSSEARCH # ZIP_INSTALL_OBJS #------------------------------------------------------------------------ AC_DEFUN([TEA_ZIPFS_SUPPORT], [ MACHER_PROG="" ZIP_PROG="" ZIP_PROG_OPTIONS="" ZIP_PROG_VFSSEARCH="" ZIP_INSTALL_OBJS="" AC_MSG_CHECKING([for macher]) AC_CACHE_VAL(ac_cv_path_macher, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/macher 2> /dev/null` \ `ls -r $dir/macher 2> /dev/null` ; do if test x"$ac_cv_path_macher" = x ; then if test -f "$j" ; then ac_cv_path_macher=$j break fi fi done done ]) if test -f "$ac_cv_path_macher" ; then MACHER_PROG="$ac_cv_path_macher" AC_MSG_RESULT([$MACHER_PROG]) AC_MSG_RESULT([Found macher in environment]) fi AC_MSG_CHECKING([for zip]) AC_CACHE_VAL(ac_cv_path_zip, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/zip 2> /dev/null` \ `ls -r $dir/zip 2> /dev/null` ; do if test x"$ac_cv_path_zip" = x ; then if test -f "$j" ; then ac_cv_path_zip=$j break fi fi done done ]) if test -f "$ac_cv_path_zip" ; then ZIP_PROG="$ac_cv_path_zip" AC_MSG_RESULT([$ZIP_PROG]) ZIP_PROG_OPTIONS="-rq" ZIP_PROG_VFSSEARCH="*" AC_MSG_RESULT([Found INFO Zip in environment]) # Use standard arguments for zip else # It is not an error if an installed version of Zip can't be located. # We can use the locally distributed minizip instead ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}" ZIP_PROG_OPTIONS="-o -r" ZIP_PROG_VFSSEARCH="*" ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}" AC_MSG_RESULT([No zip found on PATH. Building minizip]) fi AC_SUBST(MACHER_PROG) AC_SUBST(ZIP_PROG) AC_SUBST(ZIP_PROG_OPTIONS) AC_SUBST(ZIP_PROG_VFSSEARCH) AC_SUBST(ZIP_INSTALL_OBJS) ]) # Local Variables: # mode: autoconf # End: tclcurl-ng-8.0.3/tests/000077500000000000000000000000001522613063100147355ustar00rootroot00000000000000tclcurl-ng-8.0.3/tests/TESTING.md000066400000000000000000000267141522613063100164060ustar00rootroot00000000000000--- title: Tclcurl tiny web server --- # TclCurl Test Suite The repository now has two distinct kinds of files under `tests/`: - `*.test`: real `tcltest` test cases that are executed by `tests/all.tcl` - `legacy/*.tcl`: legacy example scripts that are useful as references, but are not part of the automated suite *Last update: 2026-05-16* ## Running the suite `tests/all.tcl` tries to load TclCurl from the build tree first and falls back to an installed package if needed. By default, `tests/all.tcl` enables `tcltest`'s `start` verbosity, so each test prints a line when it begins running. You can still override that from the command line with `-verbose`. To run the server-backed suite from a normal working tree, use this sequence: 1. Start the local test servers in one terminal: ```sh tclsh testservers/testserver.tcl ``` 2. Run the suite in a second terminal from the repository root: ```sh tclsh tests/all.tcl ``` 3. To run only one test file, add `-file`: ```sh tclsh tests/all.tcl -file http.test ``` 4. If you want the test runner to shut down the HTTP test server when it finishes, add `-exitserver`: ```sh tclsh tests/all.tcl -exitserver ``` If one of the configured protocol endpoints is not reachable, the corresponding server-backed tests are skipped. ## Related Manual Pages The generated HTML manuals for TclCurl are available at: - [tclcurl.html](tclcurl.html) - [tclcurl\_multi.html](tclcurl_multi.html) - [tclcurl\_share.html](tclcurl_share.html) ## `testservers/testserver.tcl` The local server framework accepts the following general command form: ```text tclsh testservers/testserver.tcl \ ?--host host? \ ?--httpport port? ?--httpsport port? ?--ftpport port? ?--proxyport port? \ ?--certfile path? ?--keyfile path? \ ?--service protocol:port? ... \ ?--docroot path? ?--ftproot path? ?--keepdocroot? \ ?--logfile path? \ ?--startservers protocol[,protocol,...]|all? \ ?--quiet? ?--debug? ``` By default, `testservers/testserver.tcl` starts four services: - HTTP on `127.0.0.1:8990` - HTTPS on `127.0.0.1:9443` - FTP on `127.0.0.1:8991` - HTTP proxy on `127.0.0.1:8992` The HTTP test server keeps its explicit dynamic routes for protocol behaviors such as redirects, request inspection, and authentication. For `GET` and `HEAD` requests that do not match one of those routes, it falls back to static file serving rooted at `TCLCURL_TEST_DOC_ROOT` or `--docroot`. Unless `--keepdocroot` is given, the server removes the configured document root when it shuts down. The server framework appends timestamped per-request log lines to `/tmp/tclcurl.log` by default. Override that path with `--logfile` when you want to keep the request log elsewhere. ## `tests/all.tcl` `tests/all.tcl` accepts a small set of TclCurl-specific options together with the usual `tcltest` command-line filters and output controls. The general form is: ```text tclsh tests/all.tcl \ ?--httpserver path/to/server.tcl? \ ?--httpport port? ?--httpsport port? ?--ftpport port? ?--proxyport port? \ ?--docroot path? ?--ftproot path? \ ?--certfile path? ?--keyfile path? \ ?--exitserver? ?--debug? \ ?--file pattern? ?--notfile pattern? ?--match pattern? ?--skip pattern? \ ?--verbose level...? ``` When the Tcl HTTP test server is wired in, the server script path precedence is: - `--httpserver /path/to/server.tcl` - `TCLCURL_TEST_HTTP_SERVER_SCRIPT` - `testservers/testserver.tcl` `testservers/testserver.tcl` accepts `--httpport`, `--httpsport`, `--ftpport`, and `--proxyport` to override the default ports `8990`, `9443`, `8991`, and `8992`. `tests/all.tcl` accepts the same double-dash options `--httpport`, `--httpsport`, `--ftpport`, and `--proxyport`. It also accepts `--docroot`, `--ftproot`, `--certfile`, and `--keyfile`, and maps them to the corresponding `TCLCURL_TEST_*` environment overrides used by the test support layer. When you need both entry points to target the same services, pass matching values to each script. The Tcl test support layer uses protocol-specific base URLs. You can override them before running `make test` or `tclsh tests/all.tcl`: - `TCLCURL_TEST_HTTP_BASE_URL`: base URL for the running Tcl HTTP test server, default `http://127.0.0.1:8990/` - `TCLCURL_TEST_HTTPS_BASE_URL`: base URL for the running Tcl HTTPS test server, default `https://127.0.0.1:9443/` - `TCLCURL_TEST_FTP_BASE_URL`: base URL for the running Tcl FTP test server, default `ftp://127.0.0.1:8991/` - `TCLCURL_TEST_PROXY_BASE_URL`: base URL for the running Tcl HTTP proxy test server, default `http://127.0.0.1:8992/` - `TCLCURL_TEST_DOC_ROOT`: shared document root used by the Tcl test servers, default `/tmp/tclcurl` - `TCLCURL_TEST_FTP_ROOT`: root directory used by the Tcl FTP test server, default `TCLCURL_TEST_DOC_ROOT` - `TCLCURL_TEST_HTTPS_CERT_FILE`: path to the certificate file used by the Tcl HTTPS test server, default `tests/certs/server.crt` - `TCLCURL_TEST_HTTPS_KEY_FILE`: path to the private key file used by the Tcl HTTPS test server, default `tests/certs/server.key` - `TCLCURL_TEST_HTTP_SERVER_SCRIPT`: path to the Tcl test server framework script, used when no `-httpserver` CLI override is given; default `testservers/testserver.tcl` ## Running secure protocol tests In order to test the https series of tests you have to create a self-signed pair of key/certificate to be stored in tests/certs If you want to keep the credentials elsewhere, either: - start `testservers/testserver.tcl` with `--certfile /path/to/server.crt --keyfile /path/to/server.key` - or run `tests/all.tcl --certfile /path/to/server.crt --keyfile /path/to/server.key` - or export `TCLCURL_TEST_HTTPS_CERT_FILE` and `TCLCURL_TEST_HTTPS_KEY_FILE` ``` mkdir -p tests/certs openssl req -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \ -keyout tests/certs/server.key \ -out tests/certs/server.crt \ -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" ``` ## Shared transport scenarios `tests/http_common.tcl` contains transport-oriented scenario helpers that are shared by `http.test`, `https.test`, `redir.test`, and `cookies.test`. The common layer currently covers: - basic GET / HEAD requests - callback delivery through `-writeproc` - `getinfo` transfer metadata - redirect handling through `-followlocation`, `-maxredirs`, `-autoreferer`, and `-postredir` - request body handling through `-post`, `-postfields`, `-postfieldsize`, `-upload`, `-readproc`, and `-range` - timeout handling through `-timeout` and `-timeoutms` - cookie engine behaviors such as `-cookiefile`, `-cookielist`, `-cookiejar`, and `-cookiesession` Tests that are primarily about easy-handle lifecycle or share-handle lifecycle stay in the protocol-specific files instead of being pulled into `http_common.tcl`. ## Current server-backed coverage `tests/http.test` focuses on TclCurl behaviors exercised over plain HTTP: - basic GET transfers with `-bodyvar` - HEAD requests with `-headervar` - callback delivery through `-writeproc` - `getinfo` transfer metadata - easy handle lifecycle operations such as `reset` and `duphandle` - HTTP error handling through `-failonerror` and `-errorbuffer` - share handle wiring for DNS sharing - request body handling through `-post`, `-postfields`, `-postfieldsize`, `-upload`, `-readproc`, and `-range` - timeout handling through `-timeout` and `-timeoutms` `tests/output.test` covers output routing: - `-file` and resetting it to the default destination - `-writeheader` and resetting it to the default destination - `-stderr` and resetting it to the default destination `tests/progress.test` covers transfer callbacks and related controls: - `-command` - `-progressproc` - pause / resume callback behavior - `-buffersize` `tests/negotiation.test` covers HTTP negotiation-oriented options: - `-httpversion` - `-encoding` - `-transferencoding` - `-contentdecoding` - `-transferdecoding` `tests/https.test` covers the TLS-specific aspects of the same HTTP behaviors: - HTTPS GET with certificate verification disabled - HTTPS GET with `-cainfo` pointing at the local self-signed certificate - expected verification failure when the certificate is not trusted - shared transport scenarios reused from `tests/http_common.tcl` `tests/ftp.test` covers the local Tcl FTP server: - upload and download of text and binary files - directory listing via `LIST` / `NLST` - `-dirlistonly` - `-quote` / `-postquote` - `-ftpcreatemissingdirs` - `-resumefrom` `tests/redir.test` and `tests/cookies.test` are thin wrappers around the shared transport scenarios, kept as separate files for readability and focused `tcltest` runs. `tests/mime.test` currently covers multipart form submission through `-httppost`: - mixed textual parts - buffer-backed parts - file-backed parts ## HTTPS setup The HTTPS server requires: - the Tcl `tls` package - a local certificate and private key, by default at: - `tests/certs/server.crt` - `tests/certs/server.key` You can override those paths: - for direct server runs, with `--certfile /path/to/server.crt --keyfile /path/to/server.key` - for the test suite, with `TCLCURL_TEST_HTTPS_CERT_FILE` and `TCLCURL_TEST_HTTPS_KEY_FILE` These files are intentionally not required to live in the repository. When they are missing, HTTPS-backed tests are skipped. One simple way to generate them locally is: ```bash mkdir -p tests/certs openssl req -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \ -keyout tests/certs/server.key \ -out tests/certs/server.crt \ -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" ``` ## Areas of Active Coverage Growth The current suite already covers the core HTTP, HTTPS, and FTP behaviors used by TclCurl, but some areas are still being expanded. If you are looking for the parts of the option surface that are most likely to gain broader automated coverage next, the main groups are: - transfer controls such as `-connecttimeout` - name resolution and routing options such as `-resolve`, `-ipresolve`, `-interface`, `-port`, and `-tcpnodelay` - authentication options supported by the linked libcurl build, such as `-userpwd`, `-username`, `-password`, `-httpauth`, and `-proxyauth` Other areas that are also expected to grow over time include: - callback diagnostics such as `-debugproc` - advanced multipart form handling through `-httppost`, including `contentheader`, overridden `filename`, and `filecontent` - broader metadata and utility APIs such as `getinfo`, `curl::curlConfig`, `easystrerror`, `multistrerror`, and `sharestrerror` ## Current Limitations Although the local test framework now covers a substantial part of TclCurl's single-transfer behavior, some categories still have more limited automated coverage. The main remaining limitations are: - scenarios that depend on more specialized server setups, such as proxy, SMTP, POP3, or authentication-specific environments - cases that require response scripts or fixtures derived from `curl/tests/data` - feature-conditional behaviors such as HTTP/2, HTTP/3, TLS auth, or compression variants that depend on how the local libcurl build was configured In practice, this means that the absence of a test in one of those areas does not necessarily indicate lack of support in TclCurl. It more often means that the local test framework has not yet been extended to exercise that behavior in a reproducible way. tclcurl-ng-8.0.3/tests/all.tcl000077500000000000000000000175201522613063100162210ustar00rootroot00000000000000#!/usr/bin/env tclsh # all.tcl -- # # Central hub for all tests # # This file is partially derived from tclcurl-fa. # # Copyright (c) 2001-2011 Andres Garcia Garcia # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. set tcl_conf_path [file join [file dirname [file normalize [info script]]] tcl_conf.tcl] if {[file exists $tcl_conf_path]} { source $tcl_conf_path set configured_tclsh $::tclcurl::test::conf::tclsh_prog if {$configured_tclsh ne {} && [file normalize [info nameofexecutable]] ne [file normalize $configured_tclsh]} { if {[info exists ::env(TCLCURL_TEST_REEXEC)] && $::env(TCLCURL_TEST_REEXEC) eq $configured_tclsh} { error "configured Tcl shell re-exec loop detected: $configured_tclsh" } set ::env(TCLCURL_TEST_REEXEC) $configured_tclsh set reexec_code [catch { exec $configured_tclsh [file normalize [info script]] {*}$argv >@ stdout 2>@ stderr } reexec_result reexec_options] if {$reexec_code == 0} { exit 0 } if {[dict get $reexec_options -errorcode] ni {{} NONE}} { set error_code [dict get $reexec_options -errorcode] if {[lindex $error_code 0] eq "CHILDSTATUS"} { exit [lindex $error_code 2] } } return -options $reexec_options $reexec_result } } unset -nocomplain tcl_conf_path configured_tclsh set ::argv_saved_for_all_tests $argv set argv {} package require tcltest set argv $::argv_saved_for_all_tests unset ::argv_saved_for_all_tests namespace eval ::tclcurl::test {} proc ::tclcurl::test::parse_port_value {name value} { if {![string is integer -strict $value] || $value < 1 || $value > 65535} { error "invalid value for $name: $value" } return $value } proc ::tclcurl::test::rewrite_base_url_port {url default_scheme default_host default_port} { set candidate $url if {$candidate eq {}} { set candidate "${default_scheme}://${default_host}:${default_port}" } if {![regexp {^([a-z]+)://([^/:]+)(?::([0-9]+))?(/.*)?$} $candidate -> scheme host existing_port path]} { error "cannot override port in malformed URL: $candidate" } if {$path eq {}} { set path {} } return "${scheme}://${host}:${default_port}${path}" } proc ::tclcurl::test::normalize_tcltest_arg {arg} { if {[string length $arg] >= 2 && [string range $arg 0 1] eq "--"} { return "-[string range $arg 2 end]" } return $arg } set tcltestArgv {} set exitServer 0 set debug 0 set configuredHttpServer {} array set root_overrides {} array set https_credential_overrides {} array set port_overrides {} for {set i 0} {$i < [llength $argv]} {incr i} { set arg [lindex $argv $i] switch -- $arg { --httpserver { incr i if {$i >= [llength $argv]} { error "missing path after --httpserver" } set configuredHttpServer [lindex $argv $i] } --httpport - --httpsport - --ftpport - --proxyport { incr i if {$i >= [llength $argv]} { error "missing value after $arg" } set port_overrides($arg) [::tclcurl::test::parse_port_value $arg [lindex $argv $i]] } --docroot - --ftproot { incr i if {$i >= [llength $argv]} { error "missing value after $arg" } set root_overrides($arg) [file normalize [lindex $argv $i]] } --certfile - --keyfile { incr i if {$i >= [llength $argv]} { error "missing value after $arg" } set https_credential_overrides($arg) [file normalize [lindex $argv $i]] } --exitserver { set exitServer 1 } --debug { set debug 1 } default { lappend tcltestArgv [::tclcurl::test::normalize_tcltest_arg $arg] } } } if {[info exists port_overrides(--httpport)]} { set ::env(TCLCURL_TEST_HTTP_BASE_URL) \ [::tclcurl::test::rewrite_base_url_port \ [expr {[info exists ::env(TCLCURL_TEST_HTTP_BASE_URL)] ? $::env(TCLCURL_TEST_HTTP_BASE_URL) : {}}] \ http 127.0.0.1 $port_overrides(--httpport)] } if {[info exists port_overrides(--httpsport)]} { set ::env(TCLCURL_TEST_HTTPS_BASE_URL) \ [::tclcurl::test::rewrite_base_url_port \ [expr {[info exists ::env(TCLCURL_TEST_HTTPS_BASE_URL)] ? $::env(TCLCURL_TEST_HTTPS_BASE_URL) : {}}] \ https 127.0.0.1 $port_overrides(--httpsport)] } if {[info exists port_overrides(--ftpport)]} { set ::env(TCLCURL_TEST_FTP_BASE_URL) \ [::tclcurl::test::rewrite_base_url_port \ [expr {[info exists ::env(TCLCURL_TEST_FTP_BASE_URL)] ? $::env(TCLCURL_TEST_FTP_BASE_URL) : {}}] \ ftp 127.0.0.1 $port_overrides(--ftpport)] } if {[info exists port_overrides(--proxyport)]} { set ::env(TCLCURL_TEST_PROXY_BASE_URL) \ [::tclcurl::test::rewrite_base_url_port \ [expr {[info exists ::env(TCLCURL_TEST_PROXY_BASE_URL)] ? $::env(TCLCURL_TEST_PROXY_BASE_URL) : {}}] \ http 127.0.0.1 $port_overrides(--proxyport)] } if {[info exists root_overrides(--docroot)]} { set ::env(TCLCURL_TEST_DOC_ROOT) $root_overrides(--docroot) } if {[info exists root_overrides(--ftproot)]} { set ::env(TCLCURL_TEST_FTP_ROOT) $root_overrides(--ftproot) } if {[info exists https_credential_overrides(--certfile)]} { set ::env(TCLCURL_TEST_HTTPS_CERT_FILE) $https_credential_overrides(--certfile) } if {[info exists https_credential_overrides(--keyfile)]} { set ::env(TCLCURL_TEST_HTTPS_KEY_FILE) $https_credential_overrides(--keyfile) } ::tcltest::configure -testdir [file dirname [file normalize [info script]]] source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package namespace import ::tcltest::* # The following will be upleveled and run whenever a test calls # ::tcltest::loadTestedCommands ::tcltest::configure -load { ::tclcurl::test::load_package namespace import ::tcltest::* } ::tcltest::skipFiles [list] # Hook to determine if any of the tests failed. Then we can exit with # proper exit code: 0=all passed, 1=one or more failed proc tcltest::cleanupTestsHook {} { variable numTests set ::exitCode [expr {$numTests(Failed) > 0}] } proc ::tclcurl::test::shutdown_http_server {} { set shutdownUrl [::tclcurl::test::server::base_url shutdown] if {![regexp {^https?://([^/:]+)(?::([0-9]+))?(/.*)$} $shutdownUrl -> host port path]} { return } if {$port eq {}} { set port 80 } if {[catch {set sock [socket $host $port]}]} { return } try { chan configure $sock -translation binary -buffering none puts -nonewline $sock "GET $path HTTP/1.1\r\nHost: $host\r\nConnection: close\r\n\r\n" flush $sock catch {read $sock} } finally { catch {close $sock} } } if {$configuredHttpServer ne {}} { ::tclcurl::test::server::set_http_server_script $configuredHttpServer } ::tclcurl::test::configure_debug_output $debug # Allow command line arguments to be passed to the configure command # This supports only running a single test or a single test file if {[lsearch -exact $tcltestArgv -verbose] < 0} { ::tcltest::configure -verbose {start error} } ::tcltest::configure {*}$tcltestArgv try { ::tcltest::runAllTests } finally { if {$exitServer} { ::tclcurl::test::shutdown_http_server } } if {$exitCode == 1} { puts "====== FAIL =====" exit $exitCode } else { puts "====== SUCCESS =====" } tclcurl-ng-8.0.3/tests/auth.test000066400000000000000000000075521522613063100166100ustar00rootroot00000000000000# auth.test -- # # Tests HTTP authentication options against the local test server. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package test auth-1.1 {a protected endpoint returns 401 without credentials} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::tclcurl::test::normalizedBody $body] eq "auth=missing"}] } } -result {0 401 1} test auth-1.2 {-userpwd authenticates with HTTP Basic credentials} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -userpwd "testuser:testpass" \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response auth] \ [dict get $response user] } } -result {0 200 ok testuser} test auth-1.3 {-username and -password authenticate with HTTP Basic credentials} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -username "testuser" \ -password "testpass" \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response auth] \ [dict get $response user] } } -result {0 200 ok testuser} test auth-1.4 {wrong credentials are rejected} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -userpwd "testuser:wrongpass" \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::tclcurl::test::normalizedBody $body] eq "auth=denied"}] } } -result {0 401 1} test auth-1.5 {-httpauth basic works together with explicit credentials} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -httpauth basic \ -userpwd "testuser:testpass" \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response auth] \ [dict get $response user] } } -result {0 200 ok testuser} cleanupTests tclcurl-ng-8.0.3/tests/config.test000066400000000000000000000033601522613063100171050ustar00rootroot00000000000000# config.test -- # # Tests build-time libcurl metadata exposed through curl::curlConfig. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package test config-1.1 {curl::curlConfig -prefix returns a non-empty installation prefix} -body { set prefix [curl::curlConfig -prefix] expr {[string length [string trim $prefix]] > 0} } -result 1 test config-1.2 {curl::curlConfig -feature returns a Tcl list of compiled features} -body { set features [curl::curlConfig -feature] list \ [expr {[catch {llength $features}] == 0}] \ [expr {[llength $features] > 0}] } -result {1 1} test config-1.3 {curl::curlConfig -vernum returns a positive hexadecimal version number} -body { set vernum [string trim [curl::curlConfig -vernum]] list \ [string is xdigit -strict $vernum] \ [expr {[scan $vernum %x numeric] == 1 && $numeric > 0}] } -result {1 1} test config-1.4 {curl::curlConfig -ca returns a string result} -body { set caPath [curl::curlConfig -ca] string length $caPath } -match glob -result * test config-1.5 {curl::curlConfig rejects unsupported options} -body { set status [catch {curl::curlConfig -bogus} result] list $status [string match {bad option*} $result] } -result {1 1} cleanupTests tclcurl-ng-8.0.3/tests/cookies.test000066400000000000000000000034671522613063100173040ustar00rootroot00000000000000# cookies.test -- # # Tests cookie engine behavior, cookie injection, and cookie sharing. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package test cookies-1.1 {cookies stay on one easy handle and are not shared implicitly} -constraints http_server -body { ::tclcurl::test::transport_cookies_isolated ::tclcurl::test::server::base_url {} } -result {1 1} test cookies-1.2 {share cookies lets a second easy handle reuse cookies set by the first} -constraints http_server -body { ::tclcurl::test::transport_cookies_shared ::tclcurl::test::server::base_url {} } -result {1 1} test cookies-1.3 {-cookielist injects a cookie into the easy handle cookie engine} -constraints http_server -body { ::tclcurl::test::transport_cookielist_inject ::tclcurl::test::server::base_url {} } -result {0 1 1} test cookies-1.4 {-cookielist FLUSH writes in-memory cookies to the -cookiejar file} -constraints http_server -body { ::tclcurl::test::transport_cookielist_flush ::tclcurl::test::server::base_url {} } -result {1 1} test cookies-1.5 {-cookiesession ignores session cookies loaded from -cookiefile} -constraints http_server -body { ::tclcurl::test::transport_cookiesession ::tclcurl::test::server::base_url {} } -result {1 1} cleanupTests tclcurl-ng-8.0.3/tests/debug.test000066400000000000000000000054641522613063100167350ustar00rootroot00000000000000# debug.test -- # # Tests verbose transfer diagnostics delivered through -debugproc. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package proc ::tclcurl::test::debugproc_reset {} { set ::tclcurl::test::debugproc(calls) 0 set ::tclcurl::test::debugproc(records) {} } proc ::tclcurl::test::debugproc_capture {infoType data} { incr ::tclcurl::test::debugproc(calls) lappend ::tclcurl::test::debugproc(records) [list $infoType [string range $data 0 end]] return 0 } proc ::tclcurl::test::debugproc_contains {expectedType needle} { foreach record $::tclcurl::test::debugproc(records) { lassign $record infoType payload if {$infoType == $expectedType && [string first $needle $payload] >= 0} { return 1 } } return 0 } test debug-1.1 {-debugproc receives outgoing and incoming headers when verbose mode is enabled} -constraints http_server -body { ::tclcurl::test::debugproc_reset ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -nobody 1 \ -verbose 1 \ -debugproc ::tclcurl::test::debugproc_capture \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$::tclcurl::test::debugproc(calls) > 0}] \ [::tclcurl::test::debugproc_contains 2 "HEAD / HTTP/1.1"] \ [::tclcurl::test::debugproc_contains 1 "HTTP/1.1 200 OK"] } } -cleanup { unset -nocomplain ::tclcurl::test::debugproc } -result {0 200 1 1 1} test debug-1.2 {-debugproc is not invoked when verbose mode is disabled} -constraints http_server -body { ::tclcurl::test::debugproc_reset ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -nobody 1 \ -verbose 0 \ -debugproc ::tclcurl::test::debugproc_capture \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ $::tclcurl::test::debugproc(calls) } } -cleanup { unset -nocomplain ::tclcurl::test::debugproc } -result {0 200 0} cleanupTests tclcurl-ng-8.0.3/tests/escape.test000077500000000000000000000016121522613063100171010ustar00rootroot00000000000000# escape.test -- # # Tests URL escaping and unescaping helpers. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package package require TclCurl test 1.01 {: Test escape} -body { set escaped [curl::escape {What about this?}] return $escaped } -result {What%20about%20this%3F} test 1.02 {: Test unescape} -body { return [curl::unescape $escaped] } -result {What about this?} cleanupTests tclcurl-ng-8.0.3/tests/ftp.test000066400000000000000000000341111522613063100164270ustar00rootroot00000000000000# ftp.test -- # # Tests FTP transfers and related FTP-specific options. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest package require sha256 namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package proc ::tclcurl::test::file_sha256_hex {path} { set fh [open $path rb] try { return [::sha2::sha256 -hex [read $fh]] } finally { close $fh } } proc ::tclcurl::test::seed_ftp_file {source_path target_name} { file mkdir [::tclcurl::test::ftp_root] file copy -force $source_path [file join [::tclcurl::test::ftp_root] $target_name] } proc ::tclcurl::test::write_binary_file {path data} { set fh [open $path wb] try { puts -nonewline $fh $data } finally { close $fh } } test ftp-1.1 {-upload stores README.md on the FTP server} -constraints ftp_server -body { set readme [file join [::tclcurl::test::repo_root] README.md] ::tclcurl::test::ftp_reset_root ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url README.md] \ -upload 1 \ -infile $readme \ -infilesize [file size $readme] \ -noprogress 1 set rc [$handle perform] set uploaded [file join [::tclcurl::test::ftp_root] README.md] list $rc \ [file exists $uploaded] \ [expr {[::tclcurl::test::file_sha256_hex $uploaded] eq [::tclcurl::test::file_sha256_hex $readme]}] } } -result {0 1 1} test ftp-1.2 {-upload stores a binary file on the FTP server} -constraints ftp_server -body { set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::ftp_reset_root ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url tcl9.png] \ -upload 1 \ -infile $fixture \ -infilesize [file size $fixture] \ -noprogress 1 set rc [$handle perform] set uploaded [file join [::tclcurl::test::ftp_root] tcl9.png] list $rc \ [file exists $uploaded] \ [expr {[::tclcurl::test::file_sha256_hex $uploaded] eq [::tclcurl::test::file_sha256_hex $fixture]}] } } -result {0 1 1} test ftp-1.3 {-ftplistonly returns uploaded files from the remote directory} -constraints ftp_server -body { set body {} set readme [file join [::tclcurl::test::repo_root] README.md] set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $readme README.md ::tclcurl::test::seed_ftp_file $fixture tcl9.png ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url] \ -ftplistonly 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set listing [split [::tclcurl::test::normalizedBody $body] "\n"] list $rc \ [expr {[lsearch -exact $listing README.md] >= 0}] \ [expr {[lsearch -exact $listing tcl9.png] >= 0}] } } -result {0 1 1} test ftp-1.4 {download retrieves README.md from the FTP server} -constraints ftp_server -body { set body {} set readme [file join [::tclcurl::test::repo_root] README.md] ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $readme README.md ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url README.md] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::sha2::sha256 -hex $body] eq [::tclcurl::test::file_sha256_hex $readme]}] } } -result {0 226 1} test ftp-1.5 {download retrieves a binary file from the FTP server} -constraints ftp_server -body { set body {} set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $fixture tcl9.png ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url tcl9.png] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::sha2::sha256 -hex $body] eq [::tclcurl::test::file_sha256_hex $fixture]}] } } -result {0 226 1} test ftp-2.1 {-dirlistonly returns names only for an FTP directory URL} -constraints ftp_server -body { set body {} set readme [file join [::tclcurl::test::repo_root] README.md] set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $readme README.md ::tclcurl::test::seed_ftp_file $fixture tcl9.png ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url] \ -dirlistonly 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set listing [split [::tclcurl::test::normalizedBody $body] "\n"] list $rc \ [expr {[lsearch -exact $listing README.md] >= 0}] \ [expr {[lsearch -exact $listing tcl9.png] >= 0}] \ [expr {[string first "owner group" $body] < 0}] } } -result {0 1 1 1} test ftp-2.2 {-dirlistonly implies a directory listing without a trailing slash} -constraints ftp_server -body { set body {} set readme [file join [::tclcurl::test::repo_root] README.md] set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $readme README.md ::tclcurl::test::seed_ftp_file $fixture tcl9.png ::tclcurl::test::with_easy_handle handle { $handle configure -url [string trimright [::tclcurl::test::server::ftp_base_url] /] \ -dirlistonly 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set listing [split [::tclcurl::test::normalizedBody $body] "\n"] list $rc \ [expr {[lsearch -exact $listing README.md] >= 0}] \ [expr {[lsearch -exact $listing tcl9.png] >= 0}] } } -result {0 1 1} test ftp-3.1 {-quote can create and enter a subdirectory before uploading a file} -constraints ftp_server -body { set library [lindex [::tclcurl::test::build_library_candidates] 0] if {$library eq {}} { return -code error "no built TclCurl library available for ftp quote test" } ::tclcurl::test::ftp_reset_root ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url [file tail $library]] \ -upload 1 \ -infile $library \ -infilesize [file size $library] \ -quote [list "MKD uploads" "CWD uploads"] \ -noprogress 1 set rc [$handle perform] set uploaded [file join [::tclcurl::test::ftp_root] uploads [file tail $library]] list $rc \ [file isdirectory [file join [::tclcurl::test::ftp_root] uploads]] \ [file exists $uploaded] \ [expr {[::tclcurl::test::file_sha256_hex $uploaded] eq [::tclcurl::test::file_sha256_hex $library]}] } } -result {0 1 1 1} test ftp-3.2 {-quote can change directory before download and -postquote can delete the remote file} -constraints ftp_server -body { set body {} set library [lindex [::tclcurl::test::build_library_candidates] 0] if {$library eq {}} { return -code error "no built TclCurl library available for ftp quote test" } ::tclcurl::test::ftp_reset_root file mkdir [file join [::tclcurl::test::ftp_root] uploads] file copy -force $library [file join [::tclcurl::test::ftp_root] uploads [file tail $library]] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url [file tail $library]] \ -quote [list "CWD uploads"] \ -postquote [list "DELE [file tail $library]"] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set remote_copy [file join [::tclcurl::test::ftp_root] uploads [file tail $library]] list $rc \ [expr {[::sha2::sha256 -hex $body] eq [::tclcurl::test::file_sha256_hex $library]}] \ [expr {![file exists $remote_copy]}] \ [file isdirectory [file join [::tclcurl::test::ftp_root] uploads]] } } -result {0 1 1 1} test ftp-4.1 {upload to a missing FTP subdirectory fails without -ftpcreatemissingdirs} -constraints ftp_server -body { set errbuf {} set readme [file join [::tclcurl::test::repo_root] README.md] set remote_path "missing/subdir/README.md" ::tclcurl::test::ftp_reset_root ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url $remote_path] \ -upload 1 \ -infile $readme \ -infilesize [file size $readme] \ -errorbuffer errbuf \ -noprogress 1 list [catch {$handle perform}] \ [expr {[string length $errbuf] > 0}] \ [expr {![file exists [file join [::tclcurl::test::ftp_root] missing subdir README.md]]}] } } -result {1 1 1} test ftp-4.2 {-ftpcreatemissingdirs creates remote directories before upload} -constraints ftp_server -body { set readme [file join [::tclcurl::test::repo_root] README.md] set remote_path "missing/subdir/README.md" ::tclcurl::test::ftp_reset_root ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url $remote_path] \ -upload 1 \ -infile $readme \ -infilesize [file size $readme] \ -ftpcreatemissingdirs 1 \ -noprogress 1 set rc [$handle perform] set uploaded [file join [::tclcurl::test::ftp_root] missing subdir README.md] list $rc \ [file isdirectory [file join [::tclcurl::test::ftp_root] missing]] \ [file isdirectory [file join [::tclcurl::test::ftp_root] missing subdir]] \ [file exists $uploaded] \ [expr {[::tclcurl::test::file_sha256_hex $uploaded] eq [::tclcurl::test::file_sha256_hex $readme]}] } } -result {0 1 1 1 1} test ftp-4.3 {-filetime retrieves the remote modification time for an FTP file} -constraints ftp_server -body { set body {} set remote_name filetime-fixture.txt set temp_path [file join [::tcltest::temporaryDirectory] $remote_name] set payload "filetime fixture\n" set expected_mtime 1735689600 ::tclcurl::test::write_binary_file $temp_path $payload file mtime $temp_path $expected_mtime ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $temp_path $remote_name file mtime [file join [::tclcurl::test::ftp_root] $remote_name] $expected_mtime ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url $remote_name] \ -filetime 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [$handle getinfo filetime] \ [expr {$body eq $payload}] } } -cleanup { catch {file delete -force [file join [::tcltest::temporaryDirectory] filetime-fixture.txt]} } -result [list 0 226 1735689600 1] test ftp-5.1 {-resumefrom downloads the remaining tail of an FTP file} -constraints ftp_server -body { set body {} set payload [string range [::tclcurl::test::range_fixture] 0 4095] set resume_from 257 set remote_name resumefrom-fixture.txt set temp_path [file join [::tcltest::temporaryDirectory] $remote_name] ::tclcurl::test::write_binary_file $temp_path $payload ::tclcurl::test::ftp_reset_root ::tclcurl::test::seed_ftp_file $temp_path $remote_name ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::ftp_base_url $remote_name] \ -resumefrom $resume_from \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [string index $body 0] \ [expr {$body eq [string range $payload $resume_from end]}] } } -cleanup { catch {file delete -force [file join [::tcltest::temporaryDirectory] resumefrom-fixture.txt]} } -result [list 0 226 [string index [::tclcurl::test::range_fixture] 257] 1] test ftp-5.2 {-resumefrom rejects malformed values} -constraints ftp_server -body { ::tclcurl::test::with_easy_handle handle { set status [catch { $handle configure -url [::tclcurl::test::server::ftp_base_url resumefrom-fixture.txt] \ -resumefrom bogus \ -noprogress 1 } result] list $status [string match {setting option -resumefrom:*} $result] } } -result {1 1} cleanupTests tclcurl-ng-8.0.3/tests/getinfo.test000066400000000000000000000131061522613063100172720ustar00rootroot00000000000000# getinfo.test -- # # Tests a focused set of high-value getinfo fields on easy handles. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package test getinfo-1.1 {basic HTTP transfer exposes core connection and sizing metadata} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { set url [::tclcurl::test::server::base_url tclcurl-http-root] $handle configure -url $url \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list \ $rc \ [expr {[$handle getinfo effectiveurl] eq $url}] \ [$handle getinfo responsecode] \ [expr {[string length [$handle getinfo primaryip]] > 0}] \ [expr {[$handle getinfo primaryport] == 8990}] \ [expr {[string length [$handle getinfo localip]] > 0}] \ [expr {[$handle getinfo localport] > 0}] \ [expr {[$handle getinfo headersize] > 0}] \ [expr {[$handle getinfo requestsize] > 0}] \ [expr {[$handle getinfo sizedownload] == [string length $body]}] \ [expr {[$handle getinfo contentlengthdownload] == [string length $body]}] \ [expr {[string match "text/plain*" [$handle getinfo contenttype]]}] \ [expr {[$handle getinfo numconnects] >= 1}] \ [expr {[$handle getinfo totaltime] >= 0.0}] \ [expr {[$handle getinfo namelookuptime] >= 0.0}] \ [expr {[$handle getinfo connecttime] >= 0.0}] \ [expr {[$handle getinfo pretransfertime] >= 0.0}] \ [expr {[$handle getinfo starttransfertime] >= 0.0}] } } -result {0 1 200 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1} test getinfo-1.2 {redirect-related metadata is populated after following a redirect} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { set targetUrl [::tclcurl::test::server::base_url redir_5] $handle configure -url [::tclcurl::test::server::base_url redir_1] \ -followlocation 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list \ $rc \ [$handle getinfo responsecode] \ [expr {[$handle getinfo effectiveurl] eq $targetUrl}] \ [expr {[$handle getinfo redirectcount] == 4}] \ [expr {[$handle getinfo redirecttime] >= 0.0}] \ [expr {[::tclcurl::test::normalizedBody $body] eq "path=/redir_5\nmethod=GET"}] } } -result {0 200 1 1 1 1} test getinfo-1.3 {httpauthavail reports basic after a Basic-auth challenge} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set authAvail [$handle getinfo httpauthavail] list \ $rc \ [$handle getinfo responsecode] \ [expr {[lsearch -exact $authAvail basic] >= 0}] \ [expr {[::tclcurl::test::normalizedBody $body] eq "auth=missing"}] } } -result {0 401 1 1} test getinfo-1.4 {successful Basic authentication still exposes consistent transfer metadata} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url auth-basic] \ -userpwd "testuser:testpass" \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list \ $rc \ [$handle getinfo responsecode] \ [expr {[$handle getinfo redirectcount] == 0}] \ [expr {[$handle getinfo sizedownload] == [string length $body]}] \ [expr {[$handle getinfo contentlengthdownload] == [string length $body]}] \ [expr {[string match "text/plain*" [$handle getinfo contenttype]]}] \ [expr {[::tclcurl::test::normalizedBody $body] eq "auth=ok\nuser=testuser"}] } } -result {0 200 1 1 1 1 1} test getinfo-1.5 {cookielist reports cookies loaded into the cookie engine} -constraints http_server -body { set body {} set cookieRecord [::tclcurl::test::netscapeCookieRecordFor ::tclcurl::test::server::base_url session_id abc123] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url cookie-echo] \ -cookielist $cookieRecord \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set cookieList [$handle getinfo cookielist] list \ $rc \ [$handle getinfo responsecode] \ [expr {[lsearch -glob $cookieList "*\tsession_id\tabc123"] >= 0}] \ [expr {[::tclcurl::test::normalizedBody $body] eq "cookie=session_id=abc123"}] } } -result {0 200 1 1} cleanupTests tclcurl-ng-8.0.3/tests/http.test000066400000000000000000000321061522613063100166170ustar00rootroot00000000000000# http.test -- # # Tests HTTP transport features including bodies, headers, callbacks, and ranges. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest package require sha256 namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package test http-1.1 {GET into -bodyvar returns a body and 200 response code} -constraints http_server -body { ::tclcurl::test::transport_basic_get ::tclcurl::test::server::base_url {} } -result {0 200 1} test http-1.2 {HEAD populates -headervar and reports 200} -constraints http_server -body { ::tclcurl::test::transport_head ::tclcurl::test::server::base_url {} } -result {0 200 1} test http-1.3 {-writeproc receives body data} -constraints http_server -body { ::tclcurl::test::transport_writeproc ::tclcurl::test::server::base_url {} } -cleanup { unset -nocomplain ::tclcurl::test::writeBuffer } -result {0 200 1} test http-1.4 {getinfo exposes transfer metadata after a successful request} -constraints http_server -body { ::tclcurl::test::transport_metadata ::tclcurl::test::server::base_url {} } -result {1 1 1} test http-1.5 {reset allows the same easy handle to be reused} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] -bodyvar body -noprogress 1 $handle perform set firstLength [string length $body] set body {} $handle reset $handle configure -url [::tclcurl::test::server::base_url] -bodyvar body -noprogress 1 set rc [$handle perform] list $rc [expr {$firstLength > 0}] [expr {[string length $body] > 0}] } } -result {0 1 1} test http-1.6 {duphandle keeps a reusable request configuration} -constraints http_server -body { set body {} set dupBody {} set primary [curl::init] set duplicate {} set code [catch { $primary configure -url [::tclcurl::test::server::base_url] -bodyvar body -noprogress 1 set duplicate [$primary duphandle] $duplicate configure -bodyvar dupBody set rc [$duplicate perform] list $rc [expr {[string length $dupBody] > 0}] } result options] catch {$duplicate cleanup} catch {$primary cleanup} return -options $options $result } -result {0 1} test http-1.7 {-http200aliases accepts a custom response line from the server} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure \ -url [::tclcurl::test::server::base_url tclcurl-http200alias] \ -bodyvar body \ -http200aliases [list "yummy/4.5 200 OK" "great/1.3 350 WRONG"] \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {$body eq "http200aliases=matched\n"}] } } -result {0 200 1} test http-1.8 {-failonerror turns a missing resource into a Tcl error} -constraints http_server -body { set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url tclcurl-missing-resource] -failonerror 1 -errorbuffer errbuf -noprogress 1 list [catch {$handle perform}] [expr {[string length $errbuf] > 0}] } } -result {1 1} test http-1.9 {share handle can be attached to two easy handles} -constraints http_server -body { set share [curl::shareinit] set first [curl::init] set second [curl::init] set firstBody {} set secondBody {} set code [catch { $share share dns $first configure -url [::tclcurl::test::server::base_url] -share $share -bodyvar firstBody -noprogress 1 $second configure -url [::tclcurl::test::server::base_url] -share $share -bodyvar secondBody -noprogress 1 $first perform $second perform list [expr {[string length $firstBody] > 0}] [expr {[string length $secondBody] > 0}] } result options] catch {$second cleanup} catch {$first cleanup} catch {$share cleanup} return -options $options $result } -result {1 1} test http-1.10 {share handle cleanup is rejected while an easy handle still uses it} -constraints http_server -body { set share [curl::shareinit] set handle [curl::init] set code [catch { $share share dns $handle configure -url [::tclcurl::test::server::base_url] -share $share -noprogress 1 $share cleanup } result] catch {$handle cleanup} catch {$share cleanup} list $code $result } -result {1 {Share handle is still attached to one or more easy handles.}} test http-1.11 {/tclcurl-man serves the HTML manual through the HTTP test server} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url tclcurl-man] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[string first "TclCurl" $body] >= 0}] \ [expr {[$handle getinfo contenttype] eq "text/html; charset=utf-8"}] } } -result {0 200 1 1} test http-1.12 {the default path serves the seeded doc root index page} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::env_or_default TCLCURL_TEST_HTTP_BASE_URL "http://127.0.0.1:8990/"] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[string first "Tclcurl tiny web server" $body] >= 0}] \ [expr {[$handle getinfo contenttype] eq "text/html; charset=utf-8"}] } } -result {0 200 1 1} test http-1.13 {unknown GET paths fall back to files under the configured doc root} -constraints http_server -body { set fixtureRoot [::tclcurl::test::doc_root] set fixturePath [file join $fixtureRoot http-static-fixture.txt] file mkdir [file dirname $fixturePath] set fh [open $fixturePath wb] try { puts -nonewline $fh "static-docroot-fixture\n" } finally { close $fh } set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url http-static-fixture.txt] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq "static-docroot-fixture\n"}] \ [expr {[$handle getinfo contenttype] eq "text/plain; charset=utf-8"}] } } -cleanup { catch {file delete -force [file join [::tclcurl::test::doc_root] http-static-fixture.txt]} } -result {0 200 1 1} test http-1.14 {static file serving preserves binary response bytes} -constraints http_server -body { set sourcePath [file join [file dirname [file normalize [info script]]] tcl9.png] set fixturePath [file join [::tclcurl::test::doc_root] http-static-fixture.png] file copy -force $sourcePath $fixturePath set fh [open $sourcePath rb] try { set expectedSha [::sha2::sha256 -hex [read $fh]] } finally { close $fh } set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url http-static-fixture.png] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::sha2::sha256 -hex $body] eq $expectedSha}] \ [expr {[$handle getinfo contenttype] eq "image/png"}] } } -cleanup { catch {file delete -force [file join [::tclcurl::test::doc_root] http-static-fixture.png]} } -result {0 200 1 1} test http-2.1.0 {-post with -postfields sends application/x-www-form-urlencoded data} -constraints http_server -body { set payload "firstName=Massimo&lastName=Manghi&city=Parma+Italy" ::tclcurl::test::transport_postfields ::tclcurl::test::server::base_url {} $payload } -result {0 200 POST application/x-www-form-urlencoded 1 1} test http-2.1.1 {-postfields with -postfieldsize sends application/x-www-form-urlencoded data} -constraints http_server -body { set payload "firstName=Massimo&lastName=Manghi&city=Parma+Italy" ::tclcurl::test::transport_postfieldsize ::tclcurl::test::server::base_url {} $payload } -result {0 200 POST application/x-www-form-urlencoded 1 1} test http-2.1.2 {-postfieldsize rejects malformed size values} -constraints http_server -body { set payload "firstName=Massimo&lastName=Manghi&city=Parma+Italy" ::tclcurl::test::transport_postfieldsize_invalid ::tclcurl::test::server::base_url {} $payload } -result {1 {setting option -postfieldsize: bogus}} test http-2.2 {-post can stream request data through -readproc} -constraints http_server -body { set payload "upload=from-readproc&mode=form-urlencoded" ::tclcurl::test::transport_post_readproc ::tclcurl::test::server::base_url {} $payload } -cleanup { unset -nocomplain ::tclcurl::test::readproc } -result {0 200 POST application/x-www-form-urlencoded 1 1} test http-2.3 {-upload with -infile sends a binary HTTP PUT body} -constraints http_server -body { set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::transport_upload_infile ::tclcurl::test::server::base_url {} $fixture } -result {0 200 PUT 19698 1} test http-2.4 {-upload with -readproc streams the same binary payload} -constraints http_server -body { set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] set fh [open $fixture rb] try { set payload [read $fh] } finally { close $fh } ::tclcurl::test::transport_upload_readproc ::tclcurl::test::server::base_url {} $payload } -cleanup { unset -nocomplain ::tclcurl::test::readproc } -result {0 200 PUT 19698 1 1} test http-3.1 {-range returns the requested byte subset from a large response} -constraints http_server -body { set start 16384 set end 98303 ::tclcurl::test::transport_range_single ::tclcurl::test::server::base_url {} $start $end } -cleanup { unset -nocomplain ::tclcurl::test::writeBuffer unset -nocomplain ::tclcurl::test::writeProcCalls catch {unset headers} } -result {0 206 1 1 1} test http-3.2 {-range can request multiple byte subsets in a single transfer} -constraints http_server -body { set ranges {{16 47} {102 134} {1233 2643}} ::tclcurl::test::transport_range_multi ::tclcurl::test::server::base_url {} $ranges } -cleanup { catch {unset headers} } -result {0 206 1 1} test http-4.1 {-timeoutms succeeds when the server responds before the deadline} -constraints http_server -body { ::tclcurl::test::transport_timeout_success ::tclcurl::test::server::base_url {} wait-200ms -timeoutms 900 "waited=200ms" } -result {0 200 1 1} test http-4.2 {-timeoutms fails when the response takes too long} -constraints http_server -body { ::tclcurl::test::transport_timeout_failure ::tclcurl::test::server::base_url {} wait-600ms?reply=none -timeoutms 100 } -result {1 1 1} test http-4.3 {-lowspeedlimit and -lowspeedtime abort a transfer that stays below the minimum rate} -constraints http_server -body { set body {} set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url slow-body-1] \ -lowspeedlimit 20 \ -lowspeedtime 5 \ -bodyvar body \ -errorbuffer errbuf \ -noprogress 1 list [catch {$handle perform}] \ [expr {[string length $errbuf] > 0}] \ [expr {[string length $body] > 0}] } } -result {1 1 1} test http-4.4 {-lowspeedlimit and -lowspeedtime allow a transfer that stays above the minimum rate} -constraints http_server -body { set body {} set payload [string range [::tclcurl::test::range_fixture] 0 191] set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url slow-body-2] \ -lowspeedlimit 20 \ -lowspeedtime 5 \ -bodyvar body \ -errorbuffer errbuf \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $payload}] \ [expr {$errbuf eq {}}] } } -result {0 200 1 1} cleanupTests tclcurl-ng-8.0.3/tests/http_common.tcl000066400000000000000000000552321522613063100177770ustar00rootroot00000000000000package require sha256 proc ::tclcurl::test::captureWriteProc {chunk} { append ::tclcurl::test::writeBuffer $chunk incr ::tclcurl::test::writeProcCalls return } proc ::tclcurl::test::parse_server_response {body} { set parsed [dict create] foreach line [split [string trim $body] "\n"] { if {$line eq {}} { continue } set separator [string first "=" $line] if {$separator < 0} { continue } dict set parsed \ [string range $line 0 [expr {$separator - 1}]] \ [string range $line [expr {$separator + 1}] end] } return $parsed } proc ::tclcurl::test::readproc_reset {data} { set ::tclcurl::test::readproc(data) $data set ::tclcurl::test::readproc(offset) 0 set ::tclcurl::test::readproc(calls) 0 } proc ::tclcurl::test::readproc_chunk {size} { incr ::tclcurl::test::readproc(calls) set offset $::tclcurl::test::readproc(offset) set chunk [string range $::tclcurl::test::readproc(data) $offset [expr {$offset + $size - 1}]] incr ::tclcurl::test::readproc(offset) [string length $chunk] return $chunk } proc ::tclcurl::test::sha256_hex {data} { return [::sha2::sha256 -hex $data] } proc ::tclcurl::test::transport_url {base_url_proc {path {}}} { return [uplevel #0 [list $base_url_proc $path]] } proc ::tclcurl::test::transport_basic_get {base_url_proc extra_opts} { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc] \ {*}$extra_opts \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[string length $body] > 0}] } } proc ::tclcurl::test::transport_head {base_url_proc extra_opts} { catch {unset headers} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc] \ {*}$extra_opts \ -nobody 1 \ -header 1 \ -headervar headers \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[array size headers] > 0}] } } proc ::tclcurl::test::transport_writeproc {base_url_proc extra_opts} { set ::tclcurl::test::writeBuffer {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc] \ {*}$extra_opts \ -writeproc ::tclcurl::test::captureWriteProc \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[string length $::tclcurl::test::writeBuffer] > 0}] } } proc ::tclcurl::test::transport_metadata {base_url_proc extra_opts} { set body {} set base [::tclcurl::test::transport_url $base_url_proc] ::tclcurl::test::with_easy_handle handle { $handle configure -url $base \ {*}$extra_opts \ -bodyvar body \ -noprogress 1 $handle perform list [string match ${base}* [$handle getinfo effectiveurl]] \ [expr {[$handle getinfo headersize] > 0}] \ [expr {[$handle getinfo sizedownload] > 0}] } } proc ::tclcurl::test::transport_postfields {base_url_proc extra_opts payload} { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc request-inspect] \ {*}$extra_opts \ -post 1 \ -postfields $payload \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [dict get $response content-type] \ [expr {[dict get $response content-length] == [string length $payload]}] \ [expr {[dict get $response body-sha256] eq [::tclcurl::test::sha256_hex $payload]}] } } proc ::tclcurl::test::transport_postfieldsize {base_url_proc extra_opts payload} { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc request-inspect] \ {*}$extra_opts \ -post 1 \ -postfields $payload \ -postfieldsize [string length $payload] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [dict get $response content-type] \ [expr {[dict get $response content-length] == [string length $payload]}] \ [expr {[dict get $response body-sha256] eq [::tclcurl::test::sha256_hex $payload]}] } } proc ::tclcurl::test::transport_postfieldsize_invalid {base_url_proc extra_opts payload} { set body {} ::tclcurl::test::with_easy_handle handle { list [catch { $handle configure -url [::tclcurl::test::transport_url $base_url_proc request-inspect] \ {*}$extra_opts \ -post 1 \ -postfields $payload \ -postfieldsize bogus \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 } result] $result } } proc ::tclcurl::test::transport_post_readproc {base_url_proc extra_opts payload} { set body {} ::tclcurl::test::readproc_reset $payload ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc request-inspect] \ {*}$extra_opts \ -post 1 \ -readproc ::tclcurl::test::readproc_chunk \ -infilesize [string length $payload] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [dict get $response content-type] \ [expr {[dict get $response body-sha256] eq [::tclcurl::test::sha256_hex $payload]}] \ [expr {$::tclcurl::test::readproc(calls) > 0}] } } proc ::tclcurl::test::transport_upload_infile {base_url_proc extra_opts fixture} { set body {} set fh [open $fixture rb] try { set payload [read $fh] } finally { close $fh } ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc request-inspect] \ {*}$extra_opts \ -upload 1 \ -infile $fixture \ -infilesize [file size $fixture] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [dict get $response content-length] \ [expr {[dict get $response body-sha256] eq [::tclcurl::test::sha256_hex $payload]}] } } proc ::tclcurl::test::transport_upload_readproc {base_url_proc extra_opts payload} { set body {} ::tclcurl::test::readproc_reset $payload ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc request-inspect] \ {*}$extra_opts \ -upload 1 \ -readproc ::tclcurl::test::readproc_chunk \ -infilesize [string length $payload] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [dict get $response content-length] \ [expr {[dict get $response body-sha256] eq [::tclcurl::test::sha256_hex $payload]}] \ [expr {$::tclcurl::test::readproc(calls) > 0}] } } proc ::tclcurl::test::transport_followlocation_chain {base_url_proc extra_opts} { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc redir_0] \ {*}$extra_opts \ -followlocation 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [$handle getinfo redirectcount] \ [string match [::tclcurl::test::transport_url $base_url_proc redir_5] [$handle getinfo effectiveurl]] \ [expr {[::tclcurl::test::normalizedBody $body] eq "path=/redir_5\nmethod=GET"}] } } proc ::tclcurl::test::transport_maxredirs_error {base_url_proc extra_opts} { set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc redir_0] \ {*}$extra_opts \ -followlocation 1 \ -maxredirs 4 \ -errorbuffer errbuf \ -noprogress 1 list [catch {$handle perform}] \ [expr {[string length $errbuf] > 0}] } } proc ::tclcurl::test::transport_autoreferer {base_url_proc extra_opts} { set body {} set start_url [::tclcurl::test::transport_url $base_url_proc autoreferer-start] ::tclcurl::test::with_easy_handle handle { $handle configure -url $start_url \ {*}$extra_opts \ -followlocation 1 \ -autoreferer 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [expr {[::tclcurl::test::normalizedBody $body] eq "method=GET\nreferer=$start_url"}] } } proc ::tclcurl::test::transport_postredir_as_get {base_url_proc extra_opts} { set body {} set start_url [::tclcurl::test::transport_url $base_url_proc postredir-301] ::tclcurl::test::with_easy_handle handle { $handle configure -url $start_url \ {*}$extra_opts \ -post 1 \ -followlocation 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [expr {[::tclcurl::test::normalizedBody $body] eq "method=GET"}] } } proc ::tclcurl::test::transport_postredir_keep_post {base_url_proc extra_opts} { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc postredir-301] \ {*}$extra_opts \ -post 1 \ -followlocation 1 \ -postredir 301 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [expr {[::tclcurl::test::normalizedBody $body] eq "method=POST"}] } } proc ::tclcurl::test::transport_range_single {base_url_proc extra_opts start end} { set ::tclcurl::test::writeBuffer {} set ::tclcurl::test::writeProcCalls 0 catch {unset headers} set full_payload [::tclcurl::test::range_fixture] set expected [string range $full_payload $start $end] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc range-data] \ {*}$extra_opts \ -range "$start-$end" \ -writeproc ::tclcurl::test::captureWriteProc \ -headervar headers \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$::tclcurl::test::writeBuffer eq $expected}] \ [expr {$::tclcurl::test::writeProcCalls > 1}] \ [expr {[info exists headers(Content-Range)] && \ $headers(Content-Range) eq "bytes $start-$end/[string length $full_payload]"}] } } proc ::tclcurl::test::transport_range_multi {base_url_proc extra_opts ranges} { set body {} catch {unset headers} set full_payload [::tclcurl::test::range_fixture] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc range-data] \ {*}$extra_opts \ -range [join [lmap r $ranges { join $r "-" }] ","] \ -bodyvar body \ -headervar headers \ -noprogress 1 set rc [$handle perform] set checks [list] foreach range $ranges { lassign $range start end lappend checks [expr {[string first "Content-Range: bytes $start-$end/[string length $full_payload]" $body] >= 0}] lappend checks [expr {[string first [string range $full_payload $start $end] $body] >= 0}] } list $rc \ [$handle getinfo responsecode] \ [string match "multipart/byteranges; boundary=*" $headers(Content-Type)] \ [expr {[lsearch -exact $checks 0] < 0}] } } proc ::tclcurl::test::transport_timeout_success {base_url_proc extra_opts wait_path timeout_opt timeout_value expected_body} { set body {} set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc $wait_path] \ {*}$extra_opts \ $timeout_opt $timeout_value \ -bodyvar body \ -errorbuffer errbuf \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::tclcurl::test::normalizedBody $body] eq $expected_body}] \ [expr {$errbuf eq {}}] } } proc ::tclcurl::test::transport_timeout_failure {base_url_proc extra_opts wait_path timeout_opt timeout_value} { set body {} set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::transport_url $base_url_proc $wait_path] \ {*}$extra_opts \ $timeout_opt $timeout_value \ -bodyvar body \ -errorbuffer errbuf \ -noprogress 1 list [catch {$handle perform}] \ [expr {[string length $errbuf] > 0}] \ [expr {$body eq {}}] } } proc ::tclcurl::test::cookieEnginePath {name} { set token [format "%X" [clock clicks]] return [file join [pwd] "${name}-${token}.cookies"] } proc ::tclcurl::test::transport_host {base_url_proc} { if {![regexp {^[a-z]+://([^/:]+)} [::tclcurl::test::transport_url $base_url_proc] -> host]} { error "unable to determine transport host" } return $host } proc ::tclcurl::test::netscapeCookieRecordFor {base_url_proc name value} { return "[::tclcurl::test::transport_host $base_url_proc]\tFALSE\t/\tFALSE\t0\t${name}\t${value}" } proc ::tclcurl::test::netscapePersistentCookieRecordFor {base_url_proc name value} { set tomorrow [expr {[clock seconds] + 86400}] return "[::tclcurl::test::transport_host $base_url_proc]\tFALSE\t/\tFALSE\t${tomorrow}\t${name}\t${value}" } proc ::tclcurl::test::transport_cookies_isolated {base_url_proc extra_opts} { set primaryBody {} set secondaryBody {} set primary [curl::init] set secondary [curl::init] set primaryCookieFile [::tclcurl::test::cookieEnginePath primary] set secondaryCookieFile [::tclcurl::test::cookieEnginePath secondary] set code [catch { $primary configure -url [::tclcurl::test::transport_url $base_url_proc cookie-set/session/alpha] \ {*}$extra_opts \ -cookiefile $primaryCookieFile \ -bodyvar primaryBody \ -noprogress 1 $primary perform set primaryBody {} $primary configure -url [::tclcurl::test::transport_url $base_url_proc cookie-echo] \ {*}$extra_opts \ -bodyvar primaryBody \ -noprogress 1 $primary perform $secondary configure -url [::tclcurl::test::transport_url $base_url_proc cookie-echo] \ {*}$extra_opts \ -cookiefile $secondaryCookieFile \ -bodyvar secondaryBody \ -noprogress 1 $secondary perform list [expr {[::tclcurl::test::normalizedBody $primaryBody] eq "cookie=session=alpha"}] \ [expr {[::tclcurl::test::normalizedBody $secondaryBody] eq "cookie="}] } result options] catch {$secondary cleanup} catch {$primary cleanup} file delete -force $primaryCookieFile $secondaryCookieFile return -options $options $result } proc ::tclcurl::test::transport_cookies_shared {base_url_proc extra_opts} { set firstBody {} set secondBody {} set share [curl::shareinit] set first [curl::init] set second [curl::init] set firstCookieFile [::tclcurl::test::cookieEnginePath shared-first] set secondCookieFile [::tclcurl::test::cookieEnginePath shared-second] set code [catch { $share share cookies $first configure -url [::tclcurl::test::transport_url $base_url_proc cookie-set/session/bravo] \ {*}$extra_opts \ -share $share \ -cookiefile $firstCookieFile \ -bodyvar firstBody \ -noprogress 1 $first perform $second configure -url [::tclcurl::test::transport_url $base_url_proc cookie-echo] \ {*}$extra_opts \ -share $share \ -cookiefile $secondCookieFile \ -bodyvar secondBody \ -noprogress 1 $second perform list [expr {[::tclcurl::test::normalizedBody $firstBody] eq "set-cookie=session=bravo"}] \ [expr {[::tclcurl::test::normalizedBody $secondBody] eq "cookie=session=bravo"}] } result options] catch {$second cleanup} catch {$first cleanup} catch {$share cleanup} file delete -force $firstCookieFile $secondCookieFile return -options $options $result } proc ::tclcurl::test::transport_cookielist_inject {base_url_proc extra_opts} { set body {} set cookieFile [::tclcurl::test::cookieEnginePath cookielist] set handle [curl::init] set code [catch { $handle configure -url [::tclcurl::test::transport_url $base_url_proc cookie-echo] \ {*}$extra_opts \ -cookiefile $cookieFile \ -cookielist [::tclcurl::test::netscapeCookieRecordFor $base_url_proc manual delta] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [expr {[::tclcurl::test::normalizedBody $body] eq "cookie=manual=delta"}] \ [expr {[llength [$handle getinfo cookielist]] > 0}] } result options] catch {$handle cleanup} file delete -force $cookieFile return -options $options $result } proc ::tclcurl::test::transport_cookielist_flush {base_url_proc extra_opts} { set body {} set cookieJar [::tclcurl::test::cookieEnginePath cookiejar] set handle [curl::init] set jarContents {} set code [catch { $handle configure -url [::tclcurl::test::transport_url $base_url_proc cookie-echo] \ {*}$extra_opts \ -cookiejar $cookieJar \ -cookielist [::tclcurl::test::netscapeCookieRecordFor $base_url_proc flushme echo] \ -bodyvar body \ -noprogress 1 $handle perform $handle configure -cookielist FLUSH set jarChan [open $cookieJar r] set jarContents [read $jarChan] close $jarChan list [file exists $cookieJar] \ [expr {[string first "flushme" $jarContents] >= 0}] } result options] catch {$handle cleanup} file delete -force $cookieJar return -options $options $result } proc ::tclcurl::test::transport_cookiesession {base_url_proc extra_opts} { set body {} set cookieFile [::tclcurl::test::cookieEnginePath cookiesession] set handle [curl::init] set cookieChan [open $cookieFile w] puts $cookieChan "# Netscape HTTP Cookie File" puts $cookieChan [::tclcurl::test::netscapeCookieRecordFor $base_url_proc session stale] puts $cookieChan [::tclcurl::test::netscapePersistentCookieRecordFor $base_url_proc persistent alive] close $cookieChan set code [catch { $handle configure -url [::tclcurl::test::transport_url $base_url_proc cookie-echo] \ {*}$extra_opts \ -cookiefile $cookieFile \ -cookiesession 1 \ -bodyvar body \ -noprogress 1 $handle perform list [expr {[string first "session=stale" $body] < 0}] \ [expr {[string first "persistent=alive" $body] >= 0}] } result options] catch {$handle cleanup} file delete -force $cookieFile return -options $options $result } tclcurl-ng-8.0.3/tests/https.test000066400000000000000000000072231522613063100170040ustar00rootroot00000000000000# https.test -- # # Tests HTTPS transport scenarios shared with the HTTP coverage. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package set ::tclcurl::test::https_common_opts [list -cainfo [::tclcurl::test::https_cert_file]] test https-2.1 {HTTPS GET shares the common GET transport scenario} -constraints https_server -body { ::tclcurl::test::transport_basic_get ::tclcurl::test::server::https_base_url $::tclcurl::test::https_common_opts } -result {0 200 1} test https-2.2 {HTTPS HEAD shares the common HEAD transport scenario} -constraints https_server -body { ::tclcurl::test::transport_head ::tclcurl::test::server::https_base_url $::tclcurl::test::https_common_opts } -result {0 200 1} test https-2.3 {HTTPS -writeproc shares the common callback delivery scenario} -constraints https_server -body { ::tclcurl::test::transport_writeproc ::tclcurl::test::server::https_base_url $::tclcurl::test::https_common_opts } -cleanup { unset -nocomplain ::tclcurl::test::writeBuffer } -result {0 200 1} test https-2.4 {HTTPS POST shares the common request body scenario} -constraints https_server -body { set payload "firstName=Massimo&lastName=Manghi&city=Parma+Italy" ::tclcurl::test::transport_postfields ::tclcurl::test::server::https_base_url $::tclcurl::test::https_common_opts $payload } -result {0 200 POST application/x-www-form-urlencoded 1 1} test https-1.1 {HTTPS GET succeeds when certificate verification is disabled} -constraints https_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::https_base_url tclcurl-http-root] \ -sslverifypeer 0 \ -sslverifyhost 0 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::tclcurl::test::normalizedBody $body] eq "tclcurl test server"}] } } -result {0 200 1} test https-1.2 {HTTPS GET succeeds with -cainfo for the local self-signed certificate} -constraints https_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::https_base_url tclcurl-http-root] \ -cainfo [::tclcurl::test::https_cert_file] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[::tclcurl::test::normalizedBody $body] eq "tclcurl test server"}] } } -result {0 200 1} test https-1.3 {HTTPS certificate validation fails without a trusted CA} -constraints https_server -body { set errbuf {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::https_base_url] \ -errorbuffer errbuf \ -noprogress 1 list [catch {$handle perform}] \ [expr {[string length $errbuf] > 0}] } } -result {1 1} cleanupTests tclcurl-ng-8.0.3/tests/legacy/000077500000000000000000000000001522613063100162015ustar00rootroot00000000000000tclcurl-ng-8.0.3/tests/legacy/basic.tcl000077500000000000000000000000761522613063100177740ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" tclcurl-ng-8.0.3/tests/legacy/bodyVar.tcl000077500000000000000000000013741522613063100203230ustar00rootroot00000000000000package require TclCurl # These tests has some urls that don't exists outside my system, # so IT WON'T WORK FOR YOU unless you change them. set curlHandle [curl::init] $curlHandle configure -url "127.0.0.1" -bodyvar body -noprogress 1 $curlHandle perform $curlHandle configure -url "127.0.0.1/~andres/" -bodyvar newBody $curlHandle perform $curlHandle cleanup puts "First page:" puts $body puts "Second page:" puts $newBody # You can also use it for binary transfers curl::transfer \ -url {127.0.0.1/~andres/HomePage/getleft/images/getleft.png} \ -bodyvar image -noprogress 1 -verbose 1 if [catch {open "getleft.png" w} out] { puts "Could not open $out." exit } fconfigure $out -translation binary puts $out $image close $out tclcurl-ng-8.0.3/tests/legacy/bufferSize.tcl000077500000000000000000000012421522613063100210130ustar00rootroot00000000000000package require TclCurl package require fileutil # This is one contrived example, but it works. proc writeToFile {readData} { incr ::i switch $::i { 1 { set card "first" } 2 { set card "second" } 3 { set card "third" } default { set card "${::i}th" } } puts "$card call to writeToFile" puts -nonewline $::inFile $readData return } set i 0 set inFile [open "/tmp/cosa.tar" w+] fconfigure $inFile -translation binary curl::transfer -url "https://github.com/flightaware/tclcurl-fa/archive/refs/tags/v7.22.1.tar.gz" \ -writeproc writeToFile \ -buffersize 250 close $inFile tclcurl-ng-8.0.3/tests/legacy/command.tcl000077500000000000000000000001521522613063100203240ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -command "puts \"\nTransfer complete\n\"" tclcurl-ng-8.0.3/tests/legacy/cookie.tcl000077500000000000000000000001401522613063100201540ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -cookie "name=andres;" -verbose 1 tclcurl-ng-8.0.3/tests/legacy/cookieFile.tcl000077500000000000000000000003431522613063100207610ustar00rootroot00000000000000package require TclCurl if {![file exists /home/andres/.getleft/cookies]} { puts "The given cookie file doesn't exist" } curl::transfer -url 127.0.0.1 \ -cookiefile "/home/andres/.getleft/cookies" -verbose 1 tclcurl-ng-8.0.3/tests/legacy/curlConfig.tcl000077500000000000000000000005531522613063100210060ustar00rootroot00000000000000package require TclCurl puts "cURL is installed in: [curl::curlConfig -prefix]" set compiledOptions [curl::curlConfig -feature] regsub -all {\n} $compiledOptions { - } compiledOptions puts "The compiled options: $compiledOptions" puts "The version in hex: [curl::curlConfig -vernum]" puts "The built-in path to the CA cert bundle:\n\t[curl::curlConfig -ca]" tclcurl-ng-8.0.3/tests/legacy/debugProc.tcl000077500000000000000000000013171522613063100206240ustar00rootroot00000000000000package require TclCurl proc DebugProc {infoType data} { switch $infoType { 0 { set type "text" } 1 { set type "incoming header" } 2 { set type "outgoing header" } 3 { set type "incoming data" } 4 { set type "outgoing data" } 5 { set type "incoming SSL data" } 6 { set type "outgoing SSL data" } } puts "Type: $type - Data:" puts "$data" return 0 } set curlHandle [curl::init] $curlHandle configure -url 127.0.0.1 -verbose 1 \ -debugproc DebugProc $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/dict.tcl000077500000000000000000000001121522613063100176250ustar00rootroot00000000000000package require TclCurl curl::transfer -url "dict://dict.org/m:curl" tclcurl-ng-8.0.3/tests/legacy/dupHandle.tcl000077500000000000000000000003721522613063100206160ustar00rootroot00000000000000package require TclCurl set curlHandle1 [curl::init] $curlHandle1 configure -url 127.0.0.1 set curlHandle2 [$curlHandle1 duphandle] $curlHandle1 configure -url 127.0.0.1/~andres/ $curlHandle2 perform $curlHandle1 cleanup $curlHandle2 cleanup tclcurl-ng-8.0.3/tests/legacy/encoding.tcl000077500000000000000000000002501522613063100204730ustar00rootroot00000000000000package require TclCurl curl::transfer -url "http://127.0.0.1" -encoding deflated -verbose 1 curl::transfer -url "http://127.0.0.1" -encoding all -verbose 1 tclcurl-ng-8.0.3/tests/legacy/errorBuffer.tcl000077500000000000000000000007501522613063100211750ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] $curlHandle configure -url "Shire.Asturias.com" -errorbuffer errorMsg if {[catch {$curlHandle perform}]} { puts "The error message: $errorMsg" } $curlHandle configure -url "Shire.Asturias.com" -errorbuffer error(msg) if {[catch {$curlHandle perform}]} { puts "The error message: $error(msg)" } $curlHandle cleanup unset error catch {curl::transfer -url "Shire.Asturias.com" -errorbuffer error(msg)} puts "Error: $error(msg)" tclcurl-ng-8.0.3/tests/legacy/failOnError.tcl000077500000000000000000000005431522613063100211340ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] $curlHandle configure -url "127.0.0.1/cosa.html" $curlHandle configure -failonerror 0 ; # This is the default puts "With failonerror==0:" catch {$curlHandle perform} puts "\n\n\n\n\n" puts "With failonerror==1:" $curlHandle configure -failonerror 1 catch {$curlHandle perform} $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/file.tcl000077500000000000000000000004051522613063100176260ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] $curlHandle configure -url "127.0.0.1" -file "index.html" $curlHandle perform puts "First transfer finished\n" $curlHandle configure -header 1 -file cosa.html $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/fileNoFile.tcl000077500000000000000000000004411522613063100207230ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] puts "First we save in 'index.html'" $curlHandle configure -noprogress 1 -url "127.0.0.1" -file "index.html" $curlHandle perform puts "And now in stdout" $curlHandle configure -file "" $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/formGet.tcl000077500000000000000000000005271522613063100203170ustar00rootroot00000000000000package require TclCurl curl::transfer -url "http://www.google.com/search?q=TclCurl&hl=en&btnG=Google+Search+&lr=" \ -file tclcurl.html -cookiejar [file join [file dirname [info script]] cookieJar.txt] puts "Transfer saved in 'tclcurl.html'" puts "Cookies en el fichero: [file join [file dirname [info script]] cookieJar.txt]" tclcurl-ng-8.0.3/tests/legacy/ftp.tcl000077500000000000000000000006361522613063100175060ustar00rootroot00000000000000package require TclCurl puts "nobody==1 --- header==1" curl::transfer -url "ftp://127.0.0.1/pub/indust2.gif" -nobody 1 -header 1 puts "nobody==0 --- header ignored" curl::transfer -url "ftp://127.0.0.1/pub/indust2.gif" -nobody 0 \ -file cosa.gif puts "nobody==1 --- HEADERS==0" curl::transfer -url "ftp://127.0.0.1/pub/indust2.gif" -nobody 1 \ -header 0 -postquote [list "mkdir nada"] tclcurl-ng-8.0.3/tests/legacy/ftpList.tcl000077500000000000000000000001311522613063100203300ustar00rootroot00000000000000package require TclCurl curl::transfer -url "ftp://127.0.0.1/pub/" -ftplistonly 1 tclcurl-ng-8.0.3/tests/legacy/ftpUpload.tcl000077500000000000000000000007061522613063100206510ustar00rootroot00000000000000package require TclCurl set buffer "" if {[catch {curl::transfer -url ftp://127.0.0.1/Test/cosa.tcl \ -userpwd "user:pwd" -verbose 1 \ -infile ftpUpload.tcl -upload 1 -errorbuffer buffer \ -quote [list "mkd Test"] \ -postquote [list "rnfr cosa.tcl" "rnto script.tcl"] \ } buffer]} { puts "Error: $buffer" } else { puts "Upload complete" } tclcurl-ng-8.0.3/tests/legacy/ftpWildcard.tcl000077500000000000000000000027701522613063100211610ustar00rootroot00000000000000package require TclCurl proc FtpMatch {pattern filename} { puts "Pattern: $pattern - File: $filename" # For this example everything matches return 0 } proc FtpCheck {remains} { global someVar # Lets forget about directories: if {($someVar(filetype) eq "directory") || ([regexp {^\.} $someVar(filename)])} { return 1 } puts -nonewline "File to download $someVar(filename) ($someVar(size)B) (y/N): " flush stdout set line [string tolower [gets stdin]] if {$line eq y} { return 0 } return 1 } proc FtpSaveFile {readData} { global outFile global openedFile global someVar if {$openedFile==0} { if {![file exists downloads]} { file mkdir downloads } set outFile [open "downloads/$someVar(filename)" w+] fconfigure $outFile -translation binary } puts -nonewline $outFile $readData return 0 } proc FtpDone {} { global outFile global openedFile puts "Done\n" close $outFile set openedFile 0 return 0 } set openedFile 0 set curlHandle [curl::init] $curlHandle configure -url ftp://sunsite.rediris.es/sites/metalab.unc.edu/ldp/* $curlHandle configure -chunkbgnproc FtpCheck $curlHandle configure -chunkbgnvar someVar $curlHandle configure -chunkendproc FtpDone $curlHandle configure -writeproc FtpSaveFile $curlHandle configure -wildcardmatch 1 $curlHandle configure -fnmatchproc FtpMatch $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/getInfo.tcl000077500000000000000000000047131522613063100203100ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] $curlHandle configure -url "127.0.0.1" -filetime 1 -verbose 1 \ -cookielist "127.0.0.1\tFALSE\t/\tFALSE\t1262307600\tad_browser_id\t 18864635" $curlHandle perform puts "Url: [$curlHandle getinfo effectiveurl]" puts "Primary IP: [$curlHandle getinfo primaryip]" puts "Primary port: [$curlHandle getinfo primaryport]" puts "Local IP: [$curlHandle getinfo localip]" puts "Local port: [$curlHandle getinfo localport]" puts "Redirect url: [$curlHandle getinfo redirecturl]" puts "Http-code: [$curlHandle getinfo responsecode]" puts "Proxy response code: [$curlHandle getinfo httpconnectcode]" set fileTime [$curlHandle getinfo filetime] puts "Filetime: $fileTime - [clock format $fileTime]" puts "Total time: [$curlHandle getinfo totaltime]" puts "Name lookup time: [$curlHandle getinfo namelookuptime]" puts "Name connect time: [$curlHandle getinfo connecttime]" puts "Name pretransfer time: [$curlHandle getinfo pretransfertime]" puts "Name start transfer time: [$curlHandle getinfo starttransfertime]" puts "Name app connect time: [$curlHandle getinfo appconnecttime]" puts "Name size upload: [$curlHandle getinfo sizeupload]" puts "Name size download: [$curlHandle getinfo sizedownload]" puts "Name speed download: [$curlHandle getinfo speeddownload]" puts "Name speed upload: [$curlHandle getinfo speedupload]" puts "Name header size: [$curlHandle getinfo headersize]" puts "Name request size: [$curlHandle getinfo requestsize]" puts "Name ssl verifyresult: [$curlHandle getinfo sslverifyresult]" puts "SSL engines: [$curlHandle getinfo sslengines]" puts "Name length download: [$curlHandle getinfo contentlengthdownload]" puts "Name length upload: [$curlHandle getinfo contentlengthupload]" puts "Content-Type: [$curlHandle getinfo contenttype]" puts "Redirect time: [$curlHandle getinfo redirecttime]" puts "Redirect count: [$curlHandle getinfo redirectcount]" puts "Authentication methods available: [$curlHandle getinfo httpauthavail]" puts "Authentication methods at the proxy: [$curlHandle getinfo proxyauthavail]" puts "Operating System error number: [$curlHandle getinfo oserrno]" puts "Number of successful connects: [$curlHandle getinfo numconnects]" puts "Known cookies: [$curlHandle getinfo cookielist]" set certList [$curlHandle getinfo certinfo] set certNum [lindex $certList 0] puts "Nş de certificados: $certNum" for {set i 1} {$i<=$certNum} {incr i} { puts [lindex $certList $i] } $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/headNoHead.tcl000077500000000000000000000005361522613063100206740ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] puts "First we save the headers in 'header.txt'" $curlHandle configure -noprogress 1 -nobody 1 -url "127.0.0.1" \ -writeheader header.txt $curlHandle perform puts "And now we dump them to the console" $curlHandle configure -writeheader "" $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/header.tcl000077500000000000000000000001221522613063100201330ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -header 1 -nobody 1 tclcurl-ng-8.0.3/tests/legacy/headerVar.tcl000077500000000000000000000003211522613063100206050ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -header 1 -nobody 1 -headervar headers puts "The received headers" foreach {key content} [array get headers] { puts "headers($key): $content" } tclcurl-ng-8.0.3/tests/legacy/http200Aliases.tcl000077500000000000000000000002471522613063100214160ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 -header 1 \ -http200aliases [list "yummy/4.5 200 OK" "great/1.3 350 WRONG"] tclcurl-ng-8.0.3/tests/legacy/httpBufferPost.tcl000077500000000000000000000012371522613063100216720ustar00rootroot00000000000000package require TclCurl set fileContent "This is what we will send if it the content is a file" curl::transfer -url 127.0.0.1/cgi-bin/post1.tcl -verbose 1 -post 1 \ -httppost [list name "firstName" contents "Andres" contenttype "text/plain" contentheader [list "adios: goodbye"]] \ -httppost [list name "lastName" contents "Garcia"] \ -httppost [list name "nombre" bufferName noFile.txt buffer $fileContent contenttype "text/html"] \ -httppost [list name "submit" contents "send"] -verbose 1 tclcurl-ng-8.0.3/tests/legacy/httpHeader.tcl000077500000000000000000000002221522613063100207740ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 \ -httpheader [list "hola: hello" "adios: goodbye"] tclcurl-ng-8.0.3/tests/legacy/httpPost.tcl000077500000000000000000000011041522613063100205310ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1/cgi-bin/post1.tcl -verbose 1 -post 1 \ -httppost [list name "firstName" contents "Andres" contenttype "text/plain" contentheader [list "adios: goodbye"]] \ -httppost [list name "lastName" contents "Garcia"] \ -httppost [list name "file" file "httpPost.tcl" file "basico.tcl" contenttype text/plain filename "c:\\basico.tcl"] \ -httppost [list name "AnotherFile" filecontent "httpBufferPost.tcl"] \ -httppost [list name "submit" contents "send"] -verbose 1 tclcurl-ng-8.0.3/tests/legacy/httpVersion.tcl000077500000000000000000000003661522613063100212420ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -httpversion none -verbose 1 -nobody 1 curl::transfer -url "127.0.0.1" -httpversion 1.0 -verbose 1 -nobody 1 curl::transfer -url "127.0.0.1" -httpversion 1.1 -verbose 1 -nobody 1 tclcurl-ng-8.0.3/tests/legacy/https.tcl000077500000000000000000000005321522613063100200520ustar00rootroot00000000000000package require TclCurl if {$tcl_platform(platform)=="windows"} { set certFile [file join $env(windir) curl-ca-bundle.crt] } else { set certFile /usr/local/share/curl/curl-ca-bundle.crt } ::curl::transfer -url https://www.paypal.com/ -cainfo $certFile \ -file paypal.html puts "https://www.paypal.com/ saved in 'paypal.html'" tclcurl-ng-8.0.3/tests/legacy/interface.tcl000077500000000000000000000001511522613063100206450ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -verbose 1 -interface 127.0.0.1 -nobody 1 tclcurl-ng-8.0.3/tests/legacy/ipresolve.tcl000077500000000000000000000003131522613063100207150ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] $curlHandle configure -url "http://127.0.0.1" -filetime 1 -ipresolve v4 \ -verbose 1 -nobody 1 $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/netrcfile.tcl000077500000000000000000000002421522613063100206610ustar00rootroot00000000000000package require TclCurl curl::transfer -url "ftp://Strider.Asturias.es" -verbose 1 \ -netrc required -netrcfile "/home/andres/testnetrc" tclcurl-ng-8.0.3/tests/legacy/noProgress.tcl000077500000000000000000000001761522613063100210550ustar00rootroot00000000000000package require TclCurl # The default is not to show the progress meter. curl::transfer -url 127.0.0.1 -noprogress 1 tclcurl-ng-8.0.3/tests/legacy/nobody.tcl000077500000000000000000000001201522613063100201730ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -header 1 -nobody 1 tclcurl-ng-8.0.3/tests/legacy/ntlm.tcl000077500000000000000000000010311522613063100176550ustar00rootroot00000000000000# Contributed by Jos Decoster set curlHandle [curl::init] $curlHandle configure \ -verbose 1 -failonerror 1 -errorbuffer ::errorBuffer \ -url $::url -file $::file \ -proxy $::proxy_host -proxyport $::proxy_port \ -proxyauth ntlm \ -proxyuserpwd $::proxy_user:$::proxy_password if { [catch {$curlHandle perform} r] } { return -code error "$r $::errorBuffer" } $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/pop3.tcl000077500000000000000000000010441522613063100175700ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] # This just checks the server for messages, if you want to download them # you need: -url "pop3://pop3.telefonica.net:110/1", -url "pop3://pop3.telefonica.net:110/2", etc $curlHandle configure -url "pop3://pop3.telefonica.net:110" $curlHandle configure -username "fandom\$telefonica.net" $curlHandle configure -password "XXXXXXXX" $curlHandle configure -bodyvar recieved $curlHandle configure -verbose 1 $curlHandle perform $curlHandle cleanup puts "Recieved:" puts \n$recieved\n\n tclcurl-ng-8.0.3/tests/legacy/postdebug.tcl000066400000000000000000000004311522613063100206770ustar00rootroot00000000000000::curl::transfer -post 1 -verbose 1 -url http://127.0.0.1/mime-1.1 \ -httppost [list name "text_entry" contents "TCLCURL" contenttype "text/plain"] \ -httppost [list name "option_selected" contents "opt1"] \ -httppost [list name "submit" contents "Search"] tclcurl-ng-8.0.3/tests/legacy/progressProc.tcl000077500000000000000000000010021522613063100213710ustar00rootroot00000000000000package require TclCurl proc ProgressCallback {dltotal dlnow ultotal ulnow} { set dltotal [expr int($dltotal)] set dlnow [expr int($dlnow)] set ultotal [expr int($ultotal)] set ulnow [expr int($ulnow)] puts "Progress callback: $dltotal - $dlnow - $ultotal - $ulnow" return } set curlHandle [curl::init] $curlHandle configure -url "127.0.0.1/~andres/cosa&co.tar" \ -progressproc ProgressCallback -file cosa.tar -noprogress 0 $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/progressProcPause.tcl000077500000000000000000000013101522613063100223710ustar00rootroot00000000000000package require TclCurl # Another one of my contrived but working examples. proc ProgressCallback {dltotal dlnow ultotal ulnow} { global i curlHandle set dltotal [expr int($dltotal)] set dlnow [expr int($dlnow)] set ultotal [expr int($ultotal)] set ulnow [expr int($ulnow)] puts "$i Progress callback: $dlnow of $dltotal downloaded" if {$i==10} { $curlHandle pause } elseif {$i==30} { $curlHandle resume } incr i return } set i 0 set curlHandle [curl::init] $curlHandle configure -url "127.0.0.1/~andres/cosa&co.tar" \ -progressproc ProgressCallback -file cosa.tar -noprogress 0 $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/proxy.tcl000077500000000000000000000001521522613063100200670ustar00rootroot00000000000000package require TclCurl curl::transfer -url http://curl.haxx.se -verbose 1 -proxy "192.168.0.0" tclcurl-ng-8.0.3/tests/legacy/proxyPort.tcl000077500000000000000000000002031522613063100207310ustar00rootroot00000000000000package require TclCurl curl::transfer -url http://curl.haxx.com -verbose 1 \ -proxy 192.168.0.0 -proxyport 8080 tclcurl-ng-8.0.3/tests/legacy/proxyTunnel.tcl000077500000000000000000000002121522613063100212520ustar00rootroot00000000000000package require TclCurl curl::transfer -url http://curl.haxx.se -verbose 1 \ -proxy "192.168.0.0:8080" -httpproxytunnel 1 tclcurl-ng-8.0.3/tests/legacy/range.tcl000077500000000000000000000001151522613063100200010ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -range "100-500" tclcurl-ng-8.0.3/tests/legacy/readProc.tcl000077500000000000000000000005661522613063100204560ustar00rootroot00000000000000package require TclCurl # As an example this is very contrived, but it works. proc readFile {size} { set chunk [read $::inFile $size] return $chunk } set inFile [open "cosa.tar" r] fconfigure $inFile -translation binary curl::transfer -url "ftp://127.0.0.1/cosa.tar" -verbose 1 \ -username user -password pass -readproc readFile -upload 1 close $inFile tclcurl-ng-8.0.3/tests/legacy/referer.tcl000077500000000000000000000001731522613063100203430ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -referer "127.0.0.1/cosa.html" \ -verbose 1 -nobody 1 tclcurl-ng-8.0.3/tests/legacy/reset.tcl000077500000000000000000000005031522613063100200300ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] puts "First we save in 'index.html'" $curlHandle configure -noprogress 1 -url "127.0.0.1" -file "index.html" $curlHandle perform puts "And now in stdout" $curlHandle reset $curlHandle configure -url "http://127.0.0.1/" $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/resume.tcl000077500000000000000000000001141522613063100202040ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -resumefrom 500 tclcurl-ng-8.0.3/tests/legacy/share.tcl000077500000000000000000000007761522613063100200240ustar00rootroot00000000000000# The share interface support is not yet completely done, since # you can't use it with the multi interface. package require TclCurl set sHandle [curl::shareinit] $sHandle share dns set easyHandle1 [curl::init] set easyHandle2 [curl::init] $easyHandle1 configure -url http://127.0.0.1/ -share $sHandle $easyHandle2 configure -url http://127.0.0.1/~andres/ -share $sHandle $easyHandle1 perform $easyHandle2 perform $easyHandle1 cleanup $easyHandle2 cleanup $sHandle unshare dns $sHandle cleanup tclcurl-ng-8.0.3/tests/legacy/smtp.tcl000077500000000000000000000021031522613063100176670ustar00rootroot00000000000000package require TclCurl # As an example this is contrived, but it works. set alreadySent 0 set mailToSend \ "Date: Mon, 12 Sep 2011 20:34:29 +0200 To: fandom@telefonica.net From: andres@verot.com Subject: SMTP example The body of the message starts here. It could be a lot of lines, could be MIME encoded, whatever. Check RFC5322. " proc sendString {size} { global alreadySent mailToSend set toSend [string range $mailToSend $alreadySent [incr $alreadySent $size]] incr alreadySent [string length $toSend] return $toSend } set curlHandle [curl::init] $curlHandle configure -url "smtp://smtp.telefonica.net:25" $curlHandle configure -username "fandom\$telefonica.net" $curlHandle configure -password "XXXXXXXX" $curlHandle configure -mailfrom "fandom@telefonica.net" $curlHandle configure -mailrcpt [list "fandom@telefonica.net" "andresgarci@telefonica.net"] # You could put the mail in a file and use the '-infile' option $curlHandle configure -readproc sendString $curlHandle configure -verbose 1 $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/stderrNoStderr.tcl000077500000000000000000000005371522613063100217010ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] puts "First it goes into error.txt" $curlHandle configure -url 127.0.0.1/~andres/cosa&co.tar -stderr error.txt \ -noprogress 0 -file cosa.tar catch {$curlHandle perform} puts "And then to stderr:" $curlHandle configure -stderr "" catch {$curlHandle perform} $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/strerror.tcl000077500000000000000000000007421522613063100205750ustar00rootroot00000000000000package require TclCurl puts "The error string for code 6 is '[curl::easystrerror 6]'" puts "If the number is too big: '[curl::easystrerror 2000]'" puts "It works the same way for the multi interface: '[curl::multistrerror 1]'" puts "And the share interface: '[curl::sharestrerror 1]'" catch {curl::easystrerror frelled} errorMsg puts "And if we use a nonsensical code: '$errorMsg'" catch {curl::sharestrerror} errorMsg puts "And if we forget the error code:\n '$errorMsg'" tclcurl-ng-8.0.3/tests/legacy/timeout.tcl000077500000000000000000000001071522613063100203740ustar00rootroot00000000000000package require TclCurl curl::transfer -timeout 0 -url 127.0.0.1 tclcurl-ng-8.0.3/tests/legacy/transfer.tcl000077500000000000000000000037041522613063100205400ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -filetime 1 \ -infoeffectiveurl effectiveUrl -inforesponsecode httpCode \ -infofiletime fileTime -infototaltime totalTime \ -infonamelookuptime nameLookUpTime \ -infoconnecttime connectTime -infopretransfertime preTime \ -infostarttransfertime startTransferTime \ -infosizeupload sizeUpload -infosizedownload sizeDownload \ -infospeeddownload speedDownload -infospeedupload speedUpload \ -infoheadersize headerSize -inforequestsize requestSize \ -infosslverifyresult sslVerifyResult \ -infocontentlengthupload contentLengthUpload \ -infocontentlengthdownload contentLengthDownload \ -infocontenttype contentType \ -inforedirecttime redirectTime \ -inforedirectcount redirectCount puts "Url: $effectiveUrl" puts "Response code: $httpCode" puts "Filetime: $fileTime - [clock format $fileTime]" puts "Total time: $totalTime" puts "Name lookup time: $nameLookUpTime" puts "Name connect time: $connectTime" puts "Name pretransfer time: $preTime" puts "Name start transfer time: $startTransferTime" puts "Name size upload: $sizeUpload" puts "Name size download: $sizeDownload" puts "Name speed download: $speedDownload" puts "Name speed upload: $speedUpload" puts "Name header size: $headerSize" puts "Name request size: $requestSize" puts "Name ssl verifyresult: $sslVerifyResult" puts "Name length download: $contentLengthDownload" puts "Name length upload: $contentLengthUpload" puts "Content-Type: $contentType" puts "Redirect time: $redirectTime" puts "Redirect count: $redirectCount" tclcurl-ng-8.0.3/tests/legacy/upload.tcl000077500000000000000000000003151522613063100201730ustar00rootroot00000000000000package require TclCurl curl::transfer -url ftp://andres:ciclope4@127.0.01/cosa.tcl \ -infilesize [file size writeProc.tcl] -infile writeProc.tcl -upload 1 \ -verbose 1 tclcurl-ng-8.0.3/tests/legacy/userAgent.tcl000077500000000000000000000002251522613063100206440ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 \ -useragent "Mozilla 4.0 (compatible; Getleft 0.10.4)" tclcurl-ng-8.0.3/tests/legacy/verbose.tcl000077500000000000000000000004161522613063100203560ustar00rootroot00000000000000package require TclCurl set curlHandle [curl::init] $curlHandle configure -url 127.0.0.1 -verbose 1 -nobody 1 puts "First one is verbose" $curlHandle perform puts "The second isn't" $curlHandle configure -verbose 0 $curlHandle perform $curlHandle cleanup tclcurl-ng-8.0.3/tests/legacy/writeHeader.tcl000077500000000000000000000001621522613063100211520ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -header 1 -nobody 1 \ -writeheader header.txt tclcurl-ng-8.0.3/tests/legacy/writeProc.tcl000077500000000000000000000005721522613063100206720ustar00rootroot00000000000000package require TclCurl # This is one contrived example, but it works. proc writeToFile {readData} { puts "writeToFile called [incr ::i]" puts -nonewline $::outFile $readData return } set i 0 set outFile [open "cosa.tar" w+] fconfigure $outFile -translation binary curl::transfer -url "127.0.0.1/~andres/cosa&co.tar" -writeproc writeToFile close $outFile tclcurl-ng-8.0.3/tests/mime.test000066400000000000000000000253731522613063100165770ustar00rootroot00000000000000# mime.test -- # # Tests MIME-based multipart form data submission. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package proc ::tclcurl::test::parse_server_response {body} { set parsed [dict create] foreach line [split [string trim $body] "\n"] { if {$line eq {}} { continue } set separator [string first "=" $line] if {$separator < 0} { continue } dict set parsed \ [string range $line 0 [expr {$separator - 1}]] \ [string range $line [expr {$separator + 1}] end] } return $parsed } test mime-1.1 {-httppost sends mixed textual form data as multipart/form-data} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -post 1 \ -httppost [list name "text_entry" contents "TCLCURL" contenttype "text/plain"] \ -httppost [list name "option_selected" contents "opt1"] \ -httppost [list name "result_limit" contents "25"] \ -httppost [list name "submit" contents "Search"] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] set payload [binary decode hex [dict get $response body-hex]] list \ $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [string match "multipart/form-data*" [dict get $response content-type]] \ [expr {[string first {name="text_entry"} $payload] >= 0}] \ [expr {[string first "TCLCURL" $payload] >= 0}] \ [expr {[string first {name="option_selected"} $payload] >= 0}] \ [expr {[string first "opt1" $payload] >= 0}] \ [expr {[string first {name="result_limit"} $payload] >= 0}] \ [expr {[string first "25" $payload] >= 0}] \ [expr {[string first {name="submit"} $payload] >= 0}] \ [expr {[string first "Search" $payload] >= 0}] } } -result {0 200 POST 1 1 1 1 1 1 1 1 1} test mime-1.2 {-httppost can send a binary buffer part} -constraints http_server -body { set body {} set payload [binary format H* 000102ff54434c007f80] set payloadHex [binary encode hex $payload] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -post 1 \ -httppost [list name "metadata" contents "buffer-upload"] \ -httppost [list name "blob" bufferName "blob.bin" buffer $payload contenttype "application/octet-stream"] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] set bodyHex [dict get $response body-hex] set multipartPayload [binary decode hex $bodyHex] list \ $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [string match "multipart/form-data*" [dict get $response content-type]] \ [expr {[string first {name="blob"; filename="blob.bin"} $multipartPayload] >= 0}] \ [expr {[string first "application/octet-stream" $multipartPayload] >= 0}] \ [expr {[string first $payloadHex $bodyHex] >= 0}] \ [expr {[string first {name="metadata"} $multipartPayload] >= 0}] \ [expr {[string first "buffer-upload" $multipartPayload] >= 0}] } } -result {0 200 POST 1 1 1 1 1 1} test mime-1.3 {-httppost can send a file part from disk} -constraints http_server -body { set body {} set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -post 1 \ -httppost [list name "description" contents "logo file"] \ -httppost [list name "image" file $fixture contenttype "image/png"] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] set bodyHex [dict get $response body-hex] set multipartPayload [binary decode hex $bodyHex] list \ $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [string match "multipart/form-data*" [dict get $response content-type]] \ [expr {[string first {name="image"; filename="tcl9.png"} $multipartPayload] >= 0}] \ [expr {[string first "image/png" $multipartPayload] >= 0}] \ [expr {[string first "89504e470d0a1a0a" $bodyHex] >= 0}] \ [expr {[string first "49454e44ae426082" $bodyHex] >= 0}] \ [expr {[string first {name="description"} $multipartPayload] >= 0}] \ [expr {[string first "logo file" $multipartPayload] >= 0}] } } -result {0 200 POST 1 1 1 1 1 1 1} test mime-2.1 {-httppost can attach custom headers to an individual part} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -post 1 \ -httppost [list \ name "meta" \ contents "hello" \ contenttype "text/plain" \ contentheader [list "X-Part-Test: yes" "Content-ID: "]] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] set multipartPayload [binary decode hex [dict get $response body-hex]] list \ $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [string match "multipart/form-data*" [dict get $response content-type]] \ [expr {[string first {name="meta"} $multipartPayload] >= 0}] \ [expr {[string first "Content-Type: text/plain" $multipartPayload] >= 0}] \ [expr {[string first "X-Part-Test: yes" $multipartPayload] >= 0}] \ [expr {[string first "Content-ID: " $multipartPayload] >= 0}] \ [expr {[string first "hello" $multipartPayload] >= 0}] } } -result {0 200 POST 1 1 1 1 1 1} test mime-2.2 {-httppost can override the advertised filename of a file part} -constraints http_server -body { set body {} set fixture [file join [file dirname [file normalize [info script]]] tcl9.png] set advertisedName "custom-image.bin" ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -post 1 \ -httppost [list \ name "image" \ file $fixture \ filename $advertisedName \ contenttype "application/octet-stream"] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] set bodyHex [dict get $response body-hex] set multipartPayload [binary decode hex $bodyHex] list \ $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [string match "multipart/form-data*" [dict get $response content-type]] \ [expr {[string first "filename=\"$advertisedName\"" $multipartPayload] >= 0}] \ [expr {[string first {filename="tcl9.png"} $multipartPayload] < 0}] \ [expr {[string first "application/octet-stream" $multipartPayload] >= 0}] \ [expr {[string first "89504e470d0a1a0a" $bodyHex] >= 0}] } } -result {0 200 POST 1 1 1 1 1} test mime-2.3 {-httppost can send file-backed content without using the original filename} -constraints http_server -body { set body {} set generated [string range [::tclcurl::test::range_fixture] 0 127] set fixturePath [file join [::tcltest::temporaryDirectory] mime-filecontent.txt] set fh [open $fixturePath wb] try { puts -nonewline $fh $generated } finally { close $fh } ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -post 1 \ -httppost [list \ name "generated" \ filecontent $fixturePath \ filename "generated.txt" \ contenttype "text/plain"] \ -bodyvar body \ -httpheader [list "Expect:"] \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] set multipartPayload [binary decode hex [dict get $response body-hex]] list \ $rc \ [$handle getinfo responsecode] \ [dict get $response method] \ [string match "multipart/form-data*" [dict get $response content-type]] \ [expr {[string first {name="generated"; filename="generated.txt"} $multipartPayload] >= 0}] \ [expr {[string first "Content-Type: text/plain" $multipartPayload] >= 0}] \ [expr {[string first $generated $multipartPayload] >= 0}] } } -cleanup { catch {file delete -force [file join [::tcltest::temporaryDirectory] mime-filecontent.txt]} } -result {0 200 POST 1 1 1 1} cleanupTests tclcurl-ng-8.0.3/tests/multi/000077500000000000000000000000001522613063100160675ustar00rootroot00000000000000tclcurl-ng-8.0.3/tests/multi/auto.tcl000077500000000000000000000010521522613063100175440ustar00rootroot00000000000000#!/usr/bin/wish package require TclCurl #wm withdraw . proc CleanUp {multiHandle easyHandle} { puts "\n\nCleaning up\n\n" $::multiHandle removehandle $::easyHandle $::multiHandle cleanup $::easyHandle cleanup puts "\n\nAll done\n\n" exit } set multiHandle [curl::multiinit] set easyHandle [curl::init] $easyHandle configure -url http://127.0.0.1/~andres/HomePage.tar.gz -file home.tar.gz $multiHandle addhandle $easyHandle puts "Starting transfer..." $multiHandle auto -command "CleanUp $multiHandle $easyHandle" tclcurl-ng-8.0.3/tests/multi/autoGUI.tcl000077500000000000000000000013451522613063100201160ustar00rootroot00000000000000#!/usr/bin/wish package require TclCurl proc CleanUp {multiHandle easyHandle} { puts "\n\nCleaning up $multiHandle - $easyHandle\n\n" $multiHandle removehandle $easyHandle $multiHandle cleanup $easyHandle cleanup puts "\n\nAll done\n\n" exit } proc StartTransfer {} { set multiHandle [curl::multiinit] set easyHandle [curl::init] $easyHandle configure -url http://127.0.0.1/~andres/HomePage.tar.gz -file home.tar.gz $multiHandle addhandle $easyHandle $multiHandle auto -command "CleanUp $multiHandle $easyHandle" } set start [button .start -text Start -command StartTransfer] set stop [button .stop -text Stop -command StopTransfer] pack $start $stop -side left -padx 10 -pady 10 tclcurl-ng-8.0.3/tests/multi/cancelTrans.tcl000077500000000000000000000033511522613063100210350ustar00rootroot00000000000000#!/usr/bin/wish package require TclCurl proc ProgressCallback {dltotal dlnow ultotal ulnow} { set dltotal [expr round($dltotal)] set dlnow [expr round($dlnow)] set ultotal [expr round($ultotal)] set ulnow [expr round($ulnow)] puts "Progress callback: $dltotal - $dlnow - $ultotal - $ulnow" return } proc Perform {multiHandle} { if {[catch {$multiHandle active} activeTransfers]} { puts "Error checking active transfers: $activeTransfers" return -1 } if {[catch {$multiHandle perform} running]} { puts "Error: $running" return -1 } return $running } proc Transfer {multiHandle easyHandle} { global eventId set runningTransfers [Perform $multiHandle] if {$runningTransfers>0} { set eventId [after 200 "Transfer $multiHandle $easyHandle"] } else { puts "Were are done, cleaning up..." $multiHandle removehandle $easyHandle $easyHandle cleanup $multiHandle cleanup puts "All done" } return } proc StartTransfer {} { set curlEasyHandle [curl::init] $curlEasyHandle configure -url "127.0.0.1/~andres/cosa&co.tar" \ -canceltransvarname cancel -progressproc ProgressCallback\ -file cosa.tar -noprogress 0 set curlMultiHandle [curl::multiinit] $curlMultiHandle addhandle $curlEasyHandle after 100 "Transfer $curlMultiHandle $curlEasyHandle" return } proc StopTransfer {} { global cancel eventId puts "The download has been cancelled" set cancel 1 return } set start [button .start -text Start -command StartTransfer] set stop [button .stop -text Stop -command StopTransfer] pack $start $stop -side left -padx 10 -pady 10 tclcurl-ng-8.0.3/tests/multi/double.tcl000077500000000000000000000024021522613063100200460ustar00rootroot00000000000000package require TclCurl proc Perform {multiHandle} { if {[catch {$multiHandle active} activeTransfers]} { puts "Error checking active transfers: $activeTransfers" return -1 } if {[catch {$multiHandle perform} running]} { puts "Error: $running" return 1 } return $running } proc StartTransfer {multiHandle} { while {1==1} { set runningTransfers [Perform $multiHandle] if {$runningTransfers>0} { after 500 } else { break } } } puts "We create and configure the easy handles" set curlEasyHandle1 [curl::init] set curlEasyHandle2 [curl::init] $curlEasyHandle1 configure -url http://127.0.0.1/~andres/ -file index.html $curlEasyHandle2 configure -url http://127.0.0.1/ -file index2.html puts "Creating the multi handle" set curlMultiHandle [curl::multiinit] puts "Adding easy handles to the multi one" $curlMultiHandle addhandle $curlEasyHandle1 $curlMultiHandle addhandle $curlEasyHandle2 puts "We start the transfer" StartTransfer $curlMultiHandle puts "Transfer done, cleanning up" $curlMultiHandle removehandle $curlEasyHandle1 $curlMultiHandle removehandle $curlEasyHandle2 $curlMultiHandle cleanup $curlEasyHandle1 cleanup $curlEasyHandle2 cleanup tclcurl-ng-8.0.3/tests/multi/single.tcl000077500000000000000000000022171522613063100200610ustar00rootroot00000000000000package require TclCurl proc Perform {multiHandle} { if {[catch {$multiHandle active} activeTransfers]} { puts "Error checking active transfers: $activeTransfers" return -1 } if {[catch {$multiHandle perform} running]} { puts "Error: $running" return 1 } return $running } proc StartTransfer {multiHandle} { while {1==1} { set runningTransfers [Perform $multiHandle] if {$runningTransfers>0} { after 500 } else { break } } } set curlEasyHandle [curl::init] $curlEasyHandle configure -url http://127.0.0.1/ -file index.html if {[catch {curl::multiinit} curlMultiHandle]} { puts "Error with multi handle init" } puts "The multi handle: $curlMultiHandle" puts -nonewline "We add the easy handle: " puts [$curlMultiHandle addhandle $curlEasyHandle] StartTransfer $curlMultiHandle puts "Calling getinfo [$curlMultiHandle getinfo]" puts -nonewline "Removing the easy handle: " puts [$curlMultiHandle removehandle $curlEasyHandle] puts -nonewline "Cleanup the multi handle handle: " puts [$curlMultiHandle cleanup] $curlEasyHandle cleanup tclcurl-ng-8.0.3/tests/negotiation.test000066400000000000000000000250701522613063100201620ustar00rootroot00000000000000# negotiation.test -- # # Tests HTTP protocol negotiation and related transfer options. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest if {[info commands zlib] eq {}} { package require zlib } namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package proc ::tclcurl::test::chunk_encode_fixture {body {chunkSize 16}} { set encoded {} set bodyLength [string length $body] for {set offset 0} {$offset < $bodyLength} {incr offset $chunkSize} { set chunk [string range $body $offset [expr {$offset + $chunkSize - 1}]] append encoded [format %X [string length $chunk]] "\r\n" $chunk "\r\n" } append encoded "0\r\n\r\n" return $encoded } proc ::tclcurl::test::chunk_encode_segments_fixture {segments} { set encoded {} foreach chunk $segments { append encoded [format %X [string length $chunk]] "\r\n" $chunk "\r\n" } append encoded "0\r\n\r\n" return $encoded } test negotiation-1.1 {-httpversion 1.0 sends an HTTP/1.0 request} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -httpversion 1.0 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response request-version] } } -result {0 200 1.0} test negotiation-1.2 {-httpversion 1.1 sends an HTTP/1.1 request} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -httpversion 1.1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response request-version] } } -result {0 200 1.1} test negotiation-1.3 {-httpversion rejects malformed values} -constraints http_server -body { ::tclcurl::test::with_easy_handle handle { set status [catch { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -httpversion bogus \ -noprogress 1 } result] list $status [string match {bad http version "bogus"*} $result] } } -result {1 1} test negotiation-2.1 {-encoding identity sends Accept-Encoding: identity} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -encoding identity \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response accept-encoding] } } -result {0 200 identity} test negotiation-2.2 {-encoding deflated sends Accept-Encoding: deflated} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -encoding deflated \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response accept-encoding] } } -result {0 200 deflated} test negotiation-2.3 {-encoding all enables libcurl-supported encodings} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -encoding all \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [expr {[dict get $response accept-encoding] ne {}}] } } -result {0 200 1} test negotiation-2.4 {-encoding rejects malformed values} -constraints http_server -body { ::tclcurl::test::with_easy_handle handle { set status [catch { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -encoding bogus \ -noprogress 1 } result] list $status [string match {bad encoding "bogus"*} $result] } } -result {1 1} test negotiation-3.1 {-transferencoding requests transfer-encoded content} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -transferencoding 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [expr {[dict get $response te] ne {}}] \ [expr {[string first "TE" [dict get $response connection]] >= 0}] } } -result {0 200 1 1} test negotiation-3.2 {-transferencoding rejects malformed values} -constraints http_server -body { ::tclcurl::test::with_easy_handle handle { set status [catch { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -transferencoding bogus \ -noprogress 1 } result] list $status [string match {setting option -transferencoding:*} $result] } } -result {1 1} test negotiation-4.1 {-contentdecoding decodes a deflated response body} -constraints http_server -body { set body {} set payload [::tclcurl::test::negotiation_payload] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url deflated-data] \ -encoding deflated \ -contentdecoding 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $payload}] } } -result {0 200 1} test negotiation-4.2 {-contentdecoding 0 preserves the compressed response body} -constraints http_server -body { set body {} set payload [::tclcurl::test::negotiation_payload] set compressed [zlib compress $payload] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url deflated-data] \ -encoding deflated \ -contentdecoding 0 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $compressed}] } } -result {0 200 1} test negotiation-5.1 {-transferdecoding decodes a chunked response body} -constraints http_server -body { set body {} set payload [::tclcurl::test::negotiation_payload] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url chunked-data] \ -transferdecoding 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $payload}] } } -result {0 200 1} test negotiation-5.2 {-transferdecoding 0 preserves chunk framing} -constraints http_server -body { set body {} set payload [::tclcurl::test::negotiation_payload] set chunked [::tclcurl::test::chunk_encode_fixture $payload] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url chunked-data] \ -transferdecoding 0 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $chunked}] } } -result {0 200 1} test negotiation-5.3 {-transferdecoding decodes streamed chunked response bodies} -constraints http_server -body { set body {} set payload [::tclcurl::test::negotiation_payload] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url slow-chunked-data] \ -transferdecoding 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $payload}] } } -result {0 200 1} test negotiation-5.4 {-transferdecoding 0 preserves streamed chunk framing} -constraints http_server -body { set body {} set payload [::tclcurl::test::negotiation_payload] set chunked [::tclcurl::test::chunk_encode_segments_fixture [list \ [string range $payload 0 9] \ [string range $payload 10 end]]] ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url slow-chunked-data] \ -transferdecoding 0 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$body eq $chunked}] } } -result {0 200 1} cleanupTests tclcurl-ng-8.0.3/tests/output.test000066400000000000000000000222441522613063100172020ustar00rootroot00000000000000# output.test -- # # Tests output routing to files for bodies, headers, and diagnostics. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package proc ::tclcurl::test::slurp_file {path {translation auto}} { set fh [open $path] try { if {$translation ne "auto"} { chan configure $fh -translation $translation } return [read $fh] } finally { close $fh } } proc ::tclcurl::test::run_child_capture {name body_script} { set tempdir [::tcltest::temporaryDirectory] set scriptPath [file join $tempdir ${name}-child.tcl] set resultPath [file join $tempdir ${name}-result.txt] set stdoutPath [file join $tempdir ${name}-stdout.txt] set stderrPath [file join $tempdir ${name}-stderr.txt] set supportPath [file join [file dirname [file normalize [info script]]] support.tcl] foreach path [list $scriptPath $resultPath $stdoutPath $stderrPath] { catch {file delete -force $path} } set scriptTemplate { source _TCL_SUPPORT_PATH_ ::tclcurl::test::load_package set result {} _TCL_BODY_SCRIPT_ set fh [open _TCL_RESULT_PATH_ w] try { puts -nonewline $fh $result } finally { close $fh } } set script [string map [list \ _TCL_SUPPORT_PATH_ [list $supportPath] \ _TCL_BODY_SCRIPT_ $body_script \ _TCL_RESULT_PATH_ [list $resultPath]] $scriptTemplate] ::tclcurl::test::write_text_file $scriptPath $script try { exec [info nameofexecutable] $scriptPath > $stdoutPath 2> $stderrPath return [list \ 0 \ [::tclcurl::test::slurp_file $stdoutPath] \ [::tclcurl::test::slurp_file $stderrPath] \ [::tclcurl::test::slurp_file $resultPath]] } finally { foreach path [list $scriptPath $resultPath $stdoutPath $stderrPath] { catch {file delete -force $path} } } } proc ::tclcurl::test::write_text_file {path data} { set fh [open $path w] try { puts -nonewline $fh $data } finally { close $fh } } test output-1.1 {-file writes the HTTP response body to disk} -constraints http_server -body { set bodyPath [file join [::tcltest::temporaryDirectory] output-body.txt] catch {file delete -force $bodyPath} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url tclcurl-http-root] \ -file $bodyPath \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {[file exists $bodyPath]}] \ [expr {[::tclcurl::test::slurp_file $bodyPath] eq "tclcurl test server\n"}] } } -cleanup { catch {file delete -force [file join [::tcltest::temporaryDirectory] output-body.txt]} } -result {0 200 1 1} test output-1.2 {-writeheader writes HTTP response headers to disk} -constraints http_server -body { set headerPath [file join [::tcltest::temporaryDirectory] output-headers.txt] catch {file delete -force $headerPath} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -nobody 1 \ -writeheader $headerPath \ -noprogress 1 set rc [$handle perform] set headerText [::tclcurl::test::slurp_file $headerPath] list $rc \ [$handle getinfo responsecode] \ [expr {[file exists $headerPath]}] \ [expr {[string first "HTTP/1.1 200 OK" $headerText] >= 0}] \ [expr {[string first "Content-Length:" $headerText] >= 0}] } } -cleanup { catch {file delete -force [file join [::tcltest::temporaryDirectory] output-headers.txt]} } -result {0 200 1 1 1} test output-1.3 {-stderr redirects verbose diagnostics to a file} -constraints http_server -body { set stderrPath [file join [::tcltest::temporaryDirectory] output-stderr.txt] catch {file delete -force $stderrPath} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -stderr $stderrPath \ -verbose 1 \ -nobody 1 \ -noprogress 1 set rc [$handle perform] set stderrText [::tclcurl::test::slurp_file $stderrPath] list $rc \ [$handle getinfo responsecode] \ [expr {[file exists $stderrPath]}] \ [expr {[string length $stderrText] > 0}] \ [expr {[string first "HEAD / HTTP/1.1" $stderrText] >= 0}] } } -cleanup { catch {file delete -force [file join [::tcltest::temporaryDirectory] output-stderr.txt]} } -result {0 200 1 1 1} test output-1.4 {-file can be reset to the default destination} -constraints http_server -body { set bodyPath [file join [::tcltest::temporaryDirectory] output-body-reset.txt] set childScriptTemplate { set bodyPath _TCL_BODY_PATH_ catch {file delete -force $bodyPath} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url tclcurl-http-root] \ -file $bodyPath \ -noprogress 1 set firstRc [$handle perform] file delete -force $bodyPath $handle configure -url [::tclcurl::test::server::base_url tclcurl-http-root] \ -file "" \ -noprogress 1 set secondRc [$handle perform] set result [list $firstRc $secondRc [$handle getinfo responsecode] [expr {![file exists $bodyPath]}]] } } set childScript [string map [list \ _TCL_BODY_PATH_ [list $bodyPath]] $childScriptTemplate] set runResult [::tclcurl::test::run_child_capture output-1.4 $childScript] list [lindex $runResult 0] \ [string trim [lindex $runResult 1]] \ [string length [lindex $runResult 2]] \ [lindex $runResult 3] } -result {0 {tclcurl test server} 0 {0 0 200 1}} test output-1.5 {-writeheader can be reset to the default destination} -constraints http_server -body { set headerPath [file join [::tcltest::temporaryDirectory] output-headers-reset.txt] set childScriptTemplate { set headerPath _TCL_HEADER_PATH_ catch {file delete -force $headerPath} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -nobody 1 \ -writeheader $headerPath \ -noprogress 1 set firstRc [$handle perform] file delete -force $headerPath $handle configure -url [::tclcurl::test::server::base_url] \ -nobody 1 \ -writeheader "" \ -noprogress 1 set secondRc [$handle perform] set result [list $firstRc $secondRc [$handle getinfo responsecode] [expr {![file exists $headerPath]}]] } } set childScript [string map [list \ _TCL_HEADER_PATH_ [list $headerPath]] $childScriptTemplate] set runResult [::tclcurl::test::run_child_capture output-1.5 $childScript] set capturedText "[lindex $runResult 1][lindex $runResult 2]" list [lindex $runResult 0] \ [expr {[string first "HTTP/1.1 200 OK" $capturedText] >= 0}] \ [expr {[string first "Content-Length:" $capturedText] >= 0}] \ [lindex $runResult 3] } -result {0 1 1 {0 0 200 1}} test output-1.6 {-stderr can be reset to the default destination} -constraints http_server -body { set stderrPath [file join [::tcltest::temporaryDirectory] output-stderr-reset.txt] set childScriptTemplate { set stderrPath _TCL_STDERR_PATH_ catch {file delete -force $stderrPath} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -stderr $stderrPath \ -verbose 1 \ -nobody 1 \ -noprogress 1 set firstRc [$handle perform] file delete -force $stderrPath $handle configure -url [::tclcurl::test::server::base_url] \ -stderr "" \ -verbose 1 \ -nobody 1 \ -noprogress 1 set secondRc [$handle perform] set result [list $firstRc $secondRc [$handle getinfo responsecode] [expr {![file exists $stderrPath]}]] } } set childScript [string map [list \ _TCL_STDERR_PATH_ [list $stderrPath]] $childScriptTemplate] set runResult [::tclcurl::test::run_child_capture output-1.6 $childScript] set stderrText [lindex $runResult 2] list [lindex $runResult 0] \ [string length [lindex $runResult 1]] \ [expr {[string first "HEAD / HTTP/1.1" $stderrText] >= 0}] \ [lindex $runResult 3] } -result {0 0 1 {0 0 200 1}} cleanupTests tclcurl-ng-8.0.3/tests/progress.test000066400000000000000000000141541522613063100175070ustar00rootroot00000000000000# progress.test -- # # Tests transfer completion and progress callbacks. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package proc ::tclcurl::test::command_probe {} { incr ::tclcurl::test::command_calls return 0 } proc ::tclcurl::test::progress_probe {dltotal dlnow ultotal ulnow} { incr ::tclcurl::test::progress_calls set ::tclcurl::test::progress_last [list $dltotal $dlnow $ultotal $ulnow] if {$dltotal > $::tclcurl::test::progress_max_dltotal} { set ::tclcurl::test::progress_max_dltotal $dltotal } if {$dlnow > $::tclcurl::test::progress_max_dlnow} { set ::tclcurl::test::progress_max_dlnow $dlnow } return 0 } proc ::tclcurl::test::progress_pause_probe {dltotal dlnow ultotal ulnow} { incr ::tclcurl::test::progress_calls set ::tclcurl::test::progress_last [list $dltotal $dlnow $ultotal $ulnow] if {!$::tclcurl::test::pause_done && ($dlnow > 0)} { set ::tclcurl::test::pause_done 1 incr ::tclcurl::test::pause_count set ::tclcurl::test::pause_start_dlnow $dlnow set pause_started_ms [clock milliseconds] $::tclcurl::test::progress_handle pause after $::tclcurl::test::pause_duration_ms $::tclcurl::test::progress_handle resume incr ::tclcurl::test::pause_total_ms [expr {[clock milliseconds] - $pause_started_ms}] } elseif {$::tclcurl::test::pause_done && !$::tclcurl::test::resume_seen && ($dlnow > 0)} { set ::tclcurl::test::resume_seen 1 set ::tclcurl::test::resume_seen_dlnow $dlnow } return 0 } test progress-1.1 {-command runs after a successful transfer} -constraints http_server -body { set ::tclcurl::test::command_calls 0 set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url] \ -command ::tclcurl::test::command_probe \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ $::tclcurl::test::command_calls \ [expr {[string length $body] > 0}] } } -result {0 200 1 1} test progress-1.2 {-progressproc reports download progress during transfer} -constraints http_server -body { set ::tclcurl::test::progress_calls 0 set ::tclcurl::test::progress_last {} set ::tclcurl::test::progress_max_dltotal 0 set ::tclcurl::test::progress_max_dlnow 0 set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url slow-body-2] \ -progressproc ::tclcurl::test::progress_probe \ -bodyvar body \ -noprogress 0 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$::tclcurl::test::progress_calls > 0}] \ [expr {[llength $::tclcurl::test::progress_last] == 4}] \ [string length $body] } } -result [list 0 200 1 1 192] test progress-1.3 {-buffersize accepts a valid integer value} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url range-data] \ -buffersize 4096 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [string length $body] } } -result [list 0 200 131072] test progress-1.4 {-buffersize rejects malformed values} -constraints http_server -body { ::tclcurl::test::with_easy_handle handle { list [catch { $handle configure -url [::tclcurl::test::server::base_url range-data] \ -buffersize bogus \ -noprogress 1 } result] $result } } -result {1 {setting option -buffersize: bogus}} test progress-1.5 {-progressproc can pause and resume a transfer} -constraints http_server -body { set expectedSize 192 set ::tclcurl::test::progress_calls 0 set ::tclcurl::test::progress_last {} set ::tclcurl::test::progress_handle {} set ::tclcurl::test::pause_done 0 set ::tclcurl::test::pause_count 0 set ::tclcurl::test::pause_duration_ms 300 set ::tclcurl::test::pause_total_ms 0 set ::tclcurl::test::pause_start_dlnow 0 set ::tclcurl::test::resume_seen 0 set ::tclcurl::test::resume_seen_dlnow 0 set body {} set started_ms [clock milliseconds] ::tclcurl::test::with_easy_handle handle { set ::tclcurl::test::progress_handle $handle $handle configure -url [::tclcurl::test::server::base_url slow-body-2] \ -progressproc ::tclcurl::test::progress_pause_probe \ -buffersize 1024 \ -bodyvar body \ -noprogress 0 set rc [$handle perform] set elapsed_ms [expr {[clock milliseconds] - $started_ms}] list $rc [$handle getinfo responsecode] \ [expr {$::tclcurl::test::pause_count == 1}] \ [expr {$::tclcurl::test::pause_total_ms >= $::tclcurl::test::pause_duration_ms}] \ [expr {$elapsed_ms >= $::tclcurl::test::pause_duration_ms}] \ [expr {$::tclcurl::test::pause_start_dlnow > 0}] \ [string length $body] } } -result [list 0 200 1 1 1 1 192] cleanupTests tclcurl-ng-8.0.3/tests/proxy.test000066400000000000000000000111251522613063100170170ustar00rootroot00000000000000# proxy.test -- # # Tests plain HTTP proxy forwarding and Basic proxy authentication. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package set proxy_host 127.0.0.1 set proxy_port 8992 test proxy-1.1 {-proxy accepts an inline host:port proxy specification} -constraints {http_server proxy_server} -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url proxy-target] \ -proxy "${proxy_host}:${proxy_port}" \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[::tclcurl::test::normalizedBody $body] eq "proxy=ok"}] } } -result {0 200 1} test proxy-1.2 {-proxy and -proxyport work together for plain HTTP proxying} -constraints {http_server proxy_server} -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url proxy-target] \ -proxy $proxy_host \ -proxyport $proxy_port \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[::tclcurl::test::normalizedBody $body] eq "proxy=ok"}] } } -result {0 200 1} test proxy-1.3 {a proxy-auth protected route returns 407 without proxy credentials} -constraints {http_server proxy_server} -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url proxy-auth-target] \ -proxy $proxy_host \ -proxyport $proxy_port \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[::tclcurl::test::normalizedBody $body] eq "proxy-auth=missing"}] } } -result {0 407 1} test proxy-1.4 {wrong proxy credentials are rejected} -constraints {http_server proxy_server} -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url proxy-auth-target] \ -proxy $proxy_host \ -proxyport $proxy_port \ -proxyuserpwd "proxyuser:wrongpass" \ -proxyauth basic \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[::tclcurl::test::normalizedBody $body] eq "proxy-auth=denied"}] } } -result {0 407 1} test proxy-1.5 {-proxyuserpwd and -proxyauth basic authenticate through the proxy} -constraints {http_server proxy_server} -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url proxy-auth-target] \ -proxy $proxy_host \ -proxyport $proxy_port \ -proxyuserpwd "proxyuser:proxypass" \ -proxyauth basic \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[::tclcurl::test::normalizedBody $body] eq "proxy-auth=ok"}] } } -result {0 200 1} test proxy-1.6 {-httpproxytunnel tunnels an HTTP request through CONNECT} -constraints {http_server proxy_server} -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url proxy-target] \ -proxy $proxy_host \ -proxyport $proxy_port \ -httpproxytunnel 1 \ -bodyvar body \ -noprogress 1 set rc [$handle perform] list $rc [$handle getinfo responsecode] [expr {[::tclcurl::test::normalizedBody $body] eq "proxy=ok"}] } } -result {0 200 1} cleanupTests tclcurl-ng-8.0.3/tests/redir.test000066400000000000000000000033451522613063100167500ustar00rootroot00000000000000# redir.test -- # # Tests HTTP redirect handling and redirect-related request semantics. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package test redir-1.1 {-followlocation follows a five-step redirect chain} -constraints http_server -body { ::tclcurl::test::transport_followlocation_chain ::tclcurl::test::server::base_url {} } -result {0 200 5 1 1} test redir-1.2 {-maxredirs 4 rejects the fifth redirect} -constraints http_server -body { ::tclcurl::test::transport_maxredirs_error ::tclcurl::test::server::base_url {} } -result {1 1} test redir-1.3 {-autoreferer sets Referer on the redirected request} -constraints http_server -body { ::tclcurl::test::transport_autoreferer ::tclcurl::test::server::base_url {} } -result {0 1} test redir-1.4 {without -postredir a POST 301 redirect is retried as GET} -constraints http_server -body { ::tclcurl::test::transport_postredir_as_get ::tclcurl::test::server::base_url {} } -result {0 1} test redir-1.5 {-postredir 301 keeps POST on a 301 redirect} -constraints http_server -body { ::tclcurl::test::transport_postredir_keep_post ::tclcurl::test::server::base_url {} } -result {0 1} cleanupTests tclcurl-ng-8.0.3/tests/repro_share.tcl000066400000000000000000000012201522613063100177450ustar00rootroot00000000000000source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package set share [curl::shareinit] set first [curl::init] set second [curl::init] set firstBody {} set secondBody {} $share share dns $first configure -url [::tclcurl::test::server::base_url] -share $share -bodyvar firstBody -noprogress 1 $second configure -url [::tclcurl::test::server::base_url] -share $share -bodyvar secondBody -noprogress 1 puts before1 $first perform puts after1 $second perform puts after2 puts [list [string length $firstBody] [string length $secondBody]] catch {$second cleanup} catch {$first cleanup} catch {$share cleanup} tclcurl-ng-8.0.3/tests/request_headers.test000066400000000000000000000053271522613063100210300ustar00rootroot00000000000000# request_headers.test -- # # Tests explicit outgoing request header customization. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] source [file join [file dirname [file normalize [info script]]] http_common.tcl] ::tclcurl::test::load_package test request_headers-1.1 {-httpheader sends a custom request header} -constraints http_server -body { set body {} ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -httpheader [list "Expect:" "X-TclCurl-Test: hello"] \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc [$handle getinfo responsecode] \ [dict get $response x-tclcurl-test] } } -result {0 200 hello} test request_headers-1.2 {-useragent sends the configured User-Agent header} -constraints http_server -body { set body {} set agent "TclCurl Test Agent/1.0" ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -useragent $agent \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response user-agent] } } -result {0 200 {TclCurl Test Agent/1.0}} test request_headers-1.3 {-referer sends the configured Referer header} -constraints http_server -body { set body {} set refererUrl "https://example.test/origin" ::tclcurl::test::with_easy_handle handle { $handle configure -url [::tclcurl::test::server::base_url request-inspect] \ -referer $refererUrl \ -bodyvar body \ -noprogress 1 set rc [$handle perform] set response [::tclcurl::test::parse_server_response $body] list $rc \ [$handle getinfo responsecode] \ [dict get $response referer] } } -result {0 200 https://example.test/origin} cleanupTests tclcurl-ng-8.0.3/tests/support.tcl000066400000000000000000000323251522613063100171620ustar00rootroot00000000000000# --support.tcl # # package require tcltest namespace eval ::tclcurl::test { variable debug 0 variable support_dir [file dirname [file normalize [info script]]] } namespace eval ::tclcurl::test::server { variable cached_http_availability variable cached_http_url variable cached_https_availability variable cached_https_url variable cached_ftp_availability variable cached_ftp_url variable cached_proxy_availability variable cached_proxy_url variable configured_http_server_script } namespace eval ::tclcurl::test::paths { variable configured_doc_root variable configured_ftp_root variable configured_https_cert_file variable configured_https_key_file } proc ::tclcurl::test::repo_root {} { variable support_dir return [file dirname $support_dir] } proc ::tclcurl::test::load_config {} { set confPath [file join [repo_root] tests tcl_conf.tcl] if {[file exists $confPath]} { source $confPath } } proc ::tclcurl::test::msgoutput_enabled {args} { puts stderr [join $args {}] } proc ::tclcurl::test::msgoutput_disabled {args} { } proc ::tclcurl::test::configure_debug_output {{enabled 0}} { variable debug set debug [expr {$enabled ? 1 : 0}] if {$debug} { proc ::tclcurl::test::msgoutput args { ::tclcurl::test::msgoutput_enabled {*}$args } } else { proc ::tclcurl::test::msgoutput args { ::tclcurl::test::msgoutput_disabled {*}$args } } return $debug } proc ::tclcurl::test::build_library_candidates {} { set root [repo_root] lassign [split $::tcl_version "."] tcl_major tcl_minor load_config if {$tcl_major == 8} { if {[info exists ::tclcurl::test::conf::pkg_lib_file8]} { return [list [file join $root $::tclcurl::test::conf::pkg_lib_file8]] } return [glob -nocomplain [file join $root lib*TclCurl*.so]] } elseif {$tcl_major == 9} { if {[info exists ::tclcurl::test::conf::pkg_lib_file9]} { return [list [file join $root $::tclcurl::test::conf::pkg_lib_file9]] } return [glob -nocomplain [file join $root libtcl9*TclCurl*.so]] } else { puts "no supported shared library library model found" } # return [concat \ # [glob -nocomplain [file join $root libtcl9*TclCurl*.so]] \ # [glob -nocomplain [file join $root lib*TclCurl*.so]] \ # [glob -nocomplain [file join $root lib*TclCurl*.dylib]] \ # [glob -nocomplain [file join $root TclCurl*.dll]]] return "" } proc ::tclcurl::test::incompatible_build_libraries {} { set root [repo_root] lassign [split $::tcl_version "."] tcl_major tcl_minor if {$tcl_major == 8} { return [glob -nocomplain [file join $root libtcl9*TclCurl*.so]] } elseif {$tcl_major == 9} { return [glob -nocomplain [file join $root libTclCurl*.so]] } return "" } proc ::tclcurl::test::load_package {} { set loadErrors {} foreach libraryPath [build_library_candidates] { if {![catch {load $libraryPath Tclcurl} result options]} { set scriptPath [file join [repo_root] generic tclcurl.tcl] if {[file exists $scriptPath]} { source $scriptPath } ::tclcurl::test::msgoutput "TclCurl loaded from $libraryPath" package require TclCurl return } lappend loadErrors "$libraryPath: $result" } set incompatibleLibraries [incompatible_build_libraries] if {[llength $incompatibleLibraries] > 0} { error "found TclCurl build-tree libraries for a different Tcl ABI: [join $incompatibleLibraries {, }]. Use the Tcl shell selected by configure (for example, make test) or rebuild for Tcl $::tcl_version." } if {[llength $loadErrors] > 0} { error "unable to load the locally built TclCurl library: [join $loadErrors {; }]" } error "unable to find a locally built TclCurl library for Tcl $::tcl_version in [repo_root]" } proc ::tclcurl::test::env_or_default {name defaultValue} { if {[info exists ::env($name)] && $::env($name) ne {}} { return $::env($name) } return $defaultValue } proc ::tclcurl::test::range_fixture {{ntimes 8192}} { return [string repeat "0123456789abcdef" $ntimes] } proc ::tclcurl::test::negotiation_payload {} { return [string range [::tclcurl::test::range_fixture] 0 255] } proc ::tclcurl::test::normalizedBody {body} { set normalized [string map [list "\r\n" "\n" "\r" "\n"] $body] set lines {} foreach line [split $normalized "\n"] { if {$line eq {}} { continue } lappend lines $line } return [join $lines "\n"] } proc ::tclcurl::test::server::set_http_server_script {path} { variable configured_http_server_script set configured_http_server_script [file normalize $path] return $configured_http_server_script } proc ::tclcurl::test::server::http_server_script {} { variable configured_http_server_script if {[info exists configured_http_server_script] && \ ($configured_http_server_script ne {})} { return $configured_http_server_script } set defaultScript [file join [::tclcurl::test::repo_root] testservers testserver.tcl] set scriptPath [::tclcurl::test::env_or_default TCLCURL_TEST_HTTP_SERVER_SCRIPT $defaultScript] return [file normalize $scriptPath] } proc ::tclcurl::test::server::base_url {{path {}}} { set base [::tclcurl::test::env_or_default TCLCURL_TEST_HTTP_BASE_URL "http://127.0.0.1:8990"] set base [string trimright $base /] if {$path eq {}} { return "${base}/" } return "${base}/[string trimleft $path /]" } proc ::tclcurl::test::server::ftp_base_url {{path {}}} { set base [::tclcurl::test::env_or_default TCLCURL_TEST_FTP_BASE_URL "ftp://127.0.0.1:8991"] set base [string trimright $base /] if {$path eq {}} { return "${base}/" } return "${base}/[string trimleft $path /]" } proc ::tclcurl::test::server::https_base_url {{path {}}} { set base [::tclcurl::test::env_or_default TCLCURL_TEST_HTTPS_BASE_URL "https://127.0.0.1:9443"] set base [string trimright $base /] if {$path eq {}} { return "${base}/" } return "${base}/[string trimleft $path /]" } proc ::tclcurl::test::server::proxy_base_url {{path {}}} { set base [::tclcurl::test::env_or_default TCLCURL_TEST_PROXY_BASE_URL "http://127.0.0.1:8992"] set base [string trimright $base /] if {$path eq {}} { return "${base}/" } return "${base}/[string trimleft $path /]" } proc ::tclcurl::test::https_cert_file {} { variable ::tclcurl::test::paths::configured_https_cert_file if {[info exists configured_https_cert_file] && ($configured_https_cert_file ne {})} { return $configured_https_cert_file } if {[info exists ::env(TCLCURL_TEST_HTTPS_CERT_FILE)] && $::env(TCLCURL_TEST_HTTPS_CERT_FILE) ne {}} { return [file normalize $::env(TCLCURL_TEST_HTTPS_CERT_FILE)] } return [file join [::tclcurl::test::repo_root] tests certs server.crt] } proc ::tclcurl::test::https_key_file {} { variable ::tclcurl::test::paths::configured_https_key_file if {[info exists configured_https_key_file] && ($configured_https_key_file ne {})} { return $configured_https_key_file } if {[info exists ::env(TCLCURL_TEST_HTTPS_KEY_FILE)] && $::env(TCLCURL_TEST_HTTPS_KEY_FILE) ne {}} { return [file normalize $::env(TCLCURL_TEST_HTTPS_KEY_FILE)] } return [file join [::tclcurl::test::repo_root] tests certs server.key] } proc ::tclcurl::test::https_credentials_available {} { return [expr {[file exists [https_cert_file]] && [file exists [https_key_file]]}] } proc ::tclcurl::test::set_https_cert_file {path} { variable ::tclcurl::test::paths::configured_https_cert_file set configured_https_cert_file [file normalize $path] return $configured_https_cert_file } proc ::tclcurl::test::set_https_key_file {path} { variable ::tclcurl::test::paths::configured_https_key_file set configured_https_key_file [file normalize $path] return $configured_https_key_file } proc ::tclcurl::test::set_doc_root {path} { variable ::tclcurl::test::paths::configured_doc_root set configured_doc_root [file normalize $path] return $configured_doc_root } proc ::tclcurl::test::doc_root {} { variable ::tclcurl::test::paths::configured_doc_root if {[info exists configured_doc_root] && ($configured_doc_root ne {})} { return $configured_doc_root } return [file normalize [env_or_default TCLCURL_TEST_DOC_ROOT "/tmp/tclcurl"]] } proc ::tclcurl::test::set_ftp_root {path} { variable ::tclcurl::test::paths::configured_ftp_root set configured_ftp_root [file normalize $path] return $configured_ftp_root } proc ::tclcurl::test::tls_package_available {} { return [expr {![catch {package require tls}]}] } proc ::tclcurl::test::ftp_root {} { variable ::tclcurl::test::paths::configured_ftp_root if {[info exists configured_ftp_root] && ($configured_ftp_root ne {})} { return $configured_ftp_root } if {[info exists ::env(TCLCURL_TEST_FTP_ROOT)] && $::env(TCLCURL_TEST_FTP_ROOT) ne {}} { return [file normalize $::env(TCLCURL_TEST_FTP_ROOT)] } return [doc_root] } proc ::tclcurl::test::ftp_reset_root {} { set root [ftp_root] catch {file delete -force $root} file mkdir $root return $root } proc ::tclcurl::test::curl_root {} { return [env_or_default CURL_ROOT {}] } proc ::tclcurl::test::curl_http_dir {} { set root [curl_root] if {$root eq {}} { return $root } return [file join $root tests http] } proc ::tclcurl::test::curl_server_built {} { set root [curl_root] if {$root eq {}} { return 0 } return [file isdirectory [file join $root tests server]] } proc ::tclcurl::test::server::url_endpoint_available {url} { if {![regexp {^(?:https?|ftp)://([^/:]+)(?::([0-9]+))?(/.*)?$} $url -> host port]} { return 0 } if {$port eq {}} { if {[string match "ftp://*" $url]} { set port 21 } else { set port 80 } } if {[catch {set sock [socket $host $port]}]} { return 0 } close $sock return 1 } proc ::tclcurl::test::server::http_server_available {} { variable cached_http_availability variable cached_http_url set url [base_url] if {[info exists cached_http_availability] && \ [info exists cached_http_url] && \ $cached_http_url eq $url} { return $cached_http_availability } set cached_http_url $url set cached_http_availability [url_endpoint_available $url] return $cached_http_availability } proc ::tclcurl::test::server::ftp_server_available {} { variable cached_ftp_availability variable cached_ftp_url set url [ftp_base_url] if {[info exists cached_ftp_availability] && \ [info exists cached_ftp_url] && \ $cached_ftp_url eq $url} { return $cached_ftp_availability } set cached_ftp_url $url set cached_ftp_availability [url_endpoint_available $url] return $cached_ftp_availability } proc ::tclcurl::test::server::https_server_available {} { variable cached_https_availability variable cached_https_url set url [https_base_url] if {[info exists cached_https_availability] && \ [info exists cached_https_url] && \ $cached_https_url eq $url} { return $cached_https_availability } set cached_https_url $url set cached_https_availability [url_endpoint_available $url] return $cached_https_availability } proc ::tclcurl::test::server::proxy_server_available {} { variable cached_proxy_availability variable cached_proxy_url set url [proxy_base_url] if {[info exists cached_proxy_availability] && \ [info exists cached_proxy_url] && \ $cached_proxy_url eq $url} { return $cached_proxy_availability } set cached_proxy_url $url set cached_proxy_availability [url_endpoint_available $url] return $cached_proxy_availability } proc ::tclcurl::test::with_easy_handle {varName body} { upvar 1 $varName handle set handle [curl::init] catch {uplevel 1 $body} result options catch {$handle cleanup} unset handle return -options $options $result } ::tclcurl::test::configure_debug_output [::tclcurl::test::env_or_default TCLCURL_TEST_DEBUG 0] ::tcltest::testConstraint curl_http_dir [expr {[::tclcurl::test::curl_http_dir] ne {} && \ [file isdirectory [::tclcurl::test::curl_http_dir]]}] ::tcltest::testConstraint curl_server_built [::tclcurl::test::curl_server_built] ::tcltest::testConstraint http_server [::tclcurl::test::server::http_server_available] ::tcltest::testConstraint tls_package [::tclcurl::test::tls_package_available] ::tcltest::testConstraint https_credentials [::tclcurl::test::https_credentials_available] ::tcltest::testConstraint https_server [expr {[::tclcurl::test::tls_package_available] && \ [::tclcurl::test::https_credentials_available] && \ [::tclcurl::test::server::https_server_available]}] ::tcltest::testConstraint ftp_server [::tclcurl::test::server::ftp_server_available] ::tcltest::testConstraint proxy_server [::tclcurl::test::server::proxy_server_available] tclcurl-ng-8.0.3/tests/tcl9.png000066400000000000000000000463621522613063100163310ustar00rootroot00000000000000‰PNG  IHDRôúW«µN pHYsĂĂÇo¨dtEXtSoftwarewww.inkscape.org›î< IDATxśěÝ{|Őů?đĎsf—@ 7Ą% —jQ+xCH‚V«VČBµZ©ŇÍî~ĄbżVýĆŘ_m­UlH6‰x©Ö*lPë˝&cUÔ*j˝ pń‚®"×dwÎóű#ÁrÉegvfgvsŢŻ—ŻÚěž™'Čî3sćśç!f†˘(Š˘(©M8€˘(Š˘(‰S ]QEQŇ€J芢(Š’TBWEQ”4 ş˘(Š˘¤•ĐEQ% ¨„®(Š˘(i@%tEQEI*ˇ+Š˘(JP ]QEQŇ€J芢(Š’TBWEQ”4 ş˘(Š˘¤•ĐEQ% ¨„®(Š˘(i@%tEQEI*ˇ+Š˘(JP ]QEQŇ€J芢(Š’TBWEQ”4 ş˘(Š˘¤•ĐEQ% ¨„®(Š˘(i@%tEQEI*ˇ+Š˘(JP ]QEQŇ€J芢(Š’TBWEQ”4 ş˘(Š˘¤•ĐEQ% xś@Q’幯/îŐkGĎţL2C˘˙ÁŻ{X|#…Üśwld»ń)Š˘$‚Ůé%aő+|}š=bŹBgĆ1 0Ś! Đ«‹ĂD XĂŔÇz5ýéüc7Ř»˘(ŠTBWRJýşé=ő–='2é'tNă8G ‡jđ.Ţó›¬ayƛ֍˙rĚžČEQěĄz ŞY}Ů Ö=Ă5AĂ™ĺpGÄÉ<€˛Ŕ8Ŕah}¤Búµ Ő|Űöď»AŘ ĆV[‰ékřśż ÂZÍýdüđ§ľIöď¶żúúó<ŃŁžćS‰č4NpŻ‰Ă­hŢÉ·t޵ü‚ěš-YQĹ1*ˇ»XÍWő=÷ž"źD,NbđI8[“u2¬° ÷Ŕü¦ü{Bnd˝]'«ůŕŞŢČÜ;ŽŔgt.Zx¦ÉĂíáרfbvd……ˇ*Š˘¸ŽJč.ňŇ'“‡j^ĎŮĚňLŤăd¸oáâLô2$–BK F<ţ…Ů˝ŘřóĂ5n>G€Îaŕl§"±ß·‰€§%ó?t±k©şWĄ;Q ÝAőőçyZŽ4Žçů|'ĂŘs`7ř?E:?5qäâ:+Q]ă䓥¤ó‰h€q07}ľż/A´:žZ6rôĹ(– OQ%%©„ždË—ű˝ßôŰ6QJň|)€C¶OĄ*V ŕI"<őZöńoŁXÖŻş<+Jz>Î'ćI[pŞoŔxBjô÷7GŚ~E%qEQ•Đ“fIŁo,3®f`2€NÇc7fl jŃ!%€Z-ŇŽçÔtş˘(ĘTB·QÝ__©c*´N§+µ^đĂ|ßÄśĹkśŽGQŭܶŕ*-Ô¬š2 ‚ćÓ•ôt:žTDŔ«ýĺýž3¦*ęt<Š˘(n§îĐ-T×X8LżfŕB¤Ţâ67á ’â ßv:EQ”T˘îĐ-Đ–ČogĐŮNÇ’ŠŘÁ„ZT/ťpÜź9Ź˘(J*R =5« Ç‘¤Űščt,©¨5‘ó|Šé÷äŤzr‹Óń(Š˘¤2•ĐMx±qň0ŹÔî ˘źCM­›± ŕČă˝#ďÇšśFQ%¨gčÔŻđő‰öŕ›Ŕ4j±›{.ő˛÷ĎăsŰět0Š˘(éD%ô8Ő6ú.ŁŔ0§cIAL Ç ńoóŽŤ|ît0Š˘(éHMąwaÉÚËËhě.®t:–ő ž“?"˛Ěé@EQŇ™J蝨kđ]ÎŔ|Žp:–´†@7ćĺ,zÂé@EQş•ĐŰńbăĎ÷rË] üĘéXRP ŕ0ďÉümţIŹěr:EQ”îB=C?ČK« Ď żp´Ó±¤Ć2Ö„ż`ÄÂŹśEQĄ»Nŕ&5 ľ_ ˘%*™¶Ŕ˙,Ë=ţl•ĚEQśˇîĐѶÍK\čt,)čÓ‹&÷Ä×N˘(ŠŇťuű„^»fJtńŁťŽ%Ĺě$¦9yą‹8˘(ŠŇÍĹŐ5N;,ž0ĐéXRĚż….®ś8já*§QEQZuŰgč5Ťľ)Ěr)T27"đťG|Ű˙,•ĚEQÜĄ[ޡ×5L˝€?AŐa7bť`áSmM%ýMź>˝§Çă雑‘Ń—™ű2s_ýôŐuý媪ŞŐNǨŞŰ%ôÚĆ©żřŹNÇ‘Jń˛ÔbÓ&ŽxrŁÓ±(ŠŇ9żßďĐ@_MÓú !úí—”żű_!D_)ĺáDÔŹúíű9€ľ™™™ Ą<äřš¦˝ `Bň~#%^Ý(ˇŐ6úî󯝎$…0ŔÚ–K7âIÝé`EéX0¬0NÓ´^ű˙üŕ¤LÔ:1ÉĚü»Ű‰S±O7IčDµŤSć9ät$)ä&şŞ ;ň¬Ó(ŠŇ9żßßKÓ´sxí>3żf÷9sşEBo»3WÉ<^„%á˛I#5:Š˘(]óx𩧠’y<¶3䤂ÜĹo9b˝–––ł„Ş€’ĹůU)›ĐĂáp]0|ŔE&†ŻPÉÜÝŇh•;QÔĂ8ŢéHRŔ7’QPŁ’yşB$kŐs·’Ď™ů%3ăŇáwOwi“Đk¦Ě‘Ďé8RŔ6Á˘`RnäßN˘ŘJ%tH)Ó!©­73H”qż´Hč/­*< ß;G Ř,Yś§¬¤·¶Zާ9Gâh4şĚé %„ŘdrhĘ˙îé.埡׭ńőDŹ ~›m$y“F-üĐé@{ !NĐ«Ë7š· ŔV[ÚţWh°»÷Źp¬™1󿨩—CŰçžúčĂĚYŔžNŠźŢ˙ý[m8nRµ5a1ę«p8ĽĆň`KĄ~Ô©ŕáN‡árM’äÄIŁět Šý„gZ´{Ą…ŞĄ”ĎX!ĄÜ’‘‘±µ´´´ŮČA‚ÁŕË0™Đ˝^便Ą_SRR"6lŘ%„ ĄMD—ŠÄëś§Ăt; 21&]~÷´–Ň ˝®Áw9W8‡Ë5 „üěĹ+śDI‹Ę€>)„SVVöY"ńűý^MÓN79ü3ŁÉŠ‹‹%€Ťm˙|ŕ‰˘˘˘?ŃB":Ńd,é´(ěŁÔóóÔ˛ĎĐëW]žĹ)Ľ}$I6˛ył#*™w/‰$ôÝ~‡''šĚ„§˙-K •••+zöěy€ĺfʎëzZ$t"kbLZüîé.ezLÄĘ ö›wć[ɢ `ÄÂŹśDIżß?Ŕ“Ă7H)Ď ‡ĂYťev¬Őw…óćÍű†™/`f/őĆĘĘĘ+ăqÂś9s2™ů$Ăv <ř?¶¤X*%z]ďBfLu:‹‘oRîBő!ěf4M3›@‰čěĘĘĘw, (Ů;î +**ÖŃCÓbĘąĄĄĺ4=ŚŚać7‹‹‹c6…¤X(ĺzý _*ťŽĂͨ(/{‘©âJj33ťŠÖduzyyą-sÇ™÷íćÍ›mYÄY^^ţW"Ş52†Ţ°#–d“RľŔB¤ĹĹLwr =Úo0Ěé8\‹řŽ‚ěE:FŞ+))ˇPč*§ă0Š™Ď6ň~"zŁąąůÇv”ôLpúY$Ń­ŚgRĘ;ŚĽź^µ+–$3śĐÓeí@wR ˝fĄď°©é˛î˘ö›lú?§H6lđ3󂢢˘§c‰W0ě`TĽďgćw™ůÂx`‡ń$0ýŘĽMŞ˘˘˘@ĽĄŹ÷lܸń=ĂI ""FgptfVU%SDJ%tÜŐµ}ŚĎĽěąĽöÝŐt3gÎ@D·č!„řÓńÄKJ9ń¦—÷ěŮs˘ÍÍ6ĚN·™mŻJĆĚĺqľőťH$Ňbk0I …F8Âŕ°ŞŞŞ¶ŰŹb˝”Ič5« Ç0Ůé8\j ůÓńąŹmvâäuk|}ëV^Użî§‰ôYv )ĺťřďŠÉÁ`ĐĐ4¶S„ńŢŻgćKćÍ›÷Ť­fďĐcBŰď Ű ćÄ“¨ÓⲙççH“ß˝»H™„N’nw:·b¬ĽěĹIź|fĺ%‡Ő5łŽuЧă‡?ew‚°](: Ŕô~ü—’’×Vâ,(łSJyaEE…©ń2:ýż?"zżĽĽ|§Ĺ!˘ŞŞj{[;Ô®¤Ë3dĂ ]í?O-®˙’€şĆÂń&:‡K-.ČŽ<ě“Ö¬ňMÍŤĚ4‡Hřҡ{›ĎçÓ¤”•8ôsqĘĆŤ ť)^>źŻťÚĹŰtfţYeee2¶3Žůď—¤5!˘çşx ·´´¤Ĺ wŰB¨˛¤”HčĚt›Ó1¸ÔzˇÇŠ’yÂúuľ!5 ľĹDX 7~’—˝đÍdĆ`—¬¬¬ëč‡í˝ĆĚ·¸ů.}Đ A]Vd#˘âŠŠŠ®UL??Or‹Ň®ţî~’ YfĚ1ŔĂ>+//˙ÂŽx{¸ö jź¶»ósťŽĂ…¤tĺÄQOnIÎéę §GŁř¤m-ĂNbś_łč_É9ż˝BˇĐqţ_'o9aÆ —$+Łt]ďęyőË›6múcR‚i•Čş¤%ô={öĽ ÚÉ[Ňâ˛Çă1łžAM·§×'t0ýÚé܉ţÍËĚk;řyZL9ďŮłçGDd¨! l.˝kTÍęi'®O‚ ‰`ś)2ľ'!€Ńz ŮöuEűţŤÁĚđ¨mđ}Đ20^‹§ňG>ţ•CżŽm\›ĐÉK?¸«gšÝÍZŢÝÓÖŇ®Ő+|=Ćyéa€¦ř ßYS}—ťçN¦`08ŔťŘď‚%^Ěŕš„ŽV”3ó5v•uí‚ŮîŰł˛˛ś¸+\ÓŢ“Q­.L^`9~1S»rʩڵ_DŔQ Ě]'îó}€żÂ4^ZŰŕ{ŤŔŤŇ®Ç.Č~ˇŮ˘°ĺŢ„žát .ĂRĐ5“Nzd—]'¨[ăëŰĎ‹<ţŔ3ăüÜĹ7ŮuŢd*))ń455ý?żIŕ0Ó®˝öÚ\´ť©˝ĚŐK“HQQQŽb°ÉáËŠ‹‹ĄĄĹA×őMš¦ňsMÓŇârś‡ŕÔ‚¸úľ>Q/_A _A&šÁ;!śĂ s<Üç÷µ …÷öɤůc‡EöŘuÂdpĺóé%Ťľ±Np:7!Đcv.D{é“ÉCYG=€ń˝ôŚ÷«ME€É9T Gmذa K晑‘ń +bJTŮZ(éSí iš«úźÇ###Ł˝­źéÔĺG‡Ec±XĽŤk,ńÜ×÷Şmđ]×âA@• tąHŐBCşs笪[Ur÷çĘ;t<ťŚĎ„¦łí/ß`×ÁkVM%4ퟎ>ŕÂRݧ÷Ôńă#1»Îť DDÁ`đJ"šăÍ)ÚĹĚA"ş—Í>,¶BH)z<‚ N-ć’RŽK`gź#SÜ6lŘš••ĺŰ˙gĚüm:4d)**:Ć˙ÎżWUUµŰŽx¶|ąß»őđmÁ ôĽ Ŕ`uöř€€Ť’h«`ŢËŚL†1á0ţ{c˘‡ë¦x˘\4~tÄöňĂVs]B_ľÜďĄĂ鲮ßŮ}řÖńĂ«mŮvT»rĘ©$Ä? 8čĄ÷öčÍ—ćgGl_Mo§P(”0ô!qŮ@ŕ,ŽöÉ.++Ű ÚÉöGDf˛$ý®pź¶Ĺ_®ů3´’™˙ÉZ X×8í y¸¬"ŕ$ĂÖ3ÓýĨŤi;ŢéčŮw JÄ™ŤźśÉW2ńŐ0°Ť’ÁWÄĽ8őĄĆ)“'e/víJ˙ö¸.ˇo9lkN.ÝáCĎ—›+`CWîšŐľ1$ÄK8ôJv}Śô‹/ů´ Ş,1}úôž™™™sÜŚC?ĚßQ33›}Ö»ĎT8śĐݤmú¤ÉáI»+LD(ú3ź@D'8‰™‡1óaDÔ@_ZďwřŔ6čSfţPńzŰEX˛í!„­3%ő+|}˘=đ0‚ďc_Â*ÝÚ{ż§Ćک欞 ĹŮxŔ›őë|ż‹Ĺp/3¦Ć##‹Ő4LůqAÎbG.4Íp]B'…6.„H5 ťăÇżlů”wÝ*ßYDxŔá˝´M .Č~âK«Ď™,ˇPč'™™™÷8öŕ×čS?łč.d˛Ďç»ÎMŰ{śDDg±ÉşnÝ"ćóůz 8p<3_ĘĚ?!˘a°˙“–1P`ßűĄ” ßđ„Çăů[ii©Ýź3Ăkb±m˙-–4úFK/q\Ľá|wźžT2vŘ"S ÖĆŹl0­vUaĘÄ»…«mô]”źyĹĚą“ÍU ˝ľţ<Žx©Óq¸suţČĺ®ÚFßą < ĎA/5ńeł«WX}Îd(**úâĎňÚyYQ8‹ýF1LU2;Čś  Ţ‚cĄ<3«©÷㪄î÷űGišö묬¬Bfî t¸Ť"´–Ĺ‹ĹJ‚Á`µ®ë˙WUUµÚŠďĎď÷Ő4ÍhC–ŐUUU_[ Ô6Lý€űpč÷NG¶0貂ś%ý"ňs«ďŻ]5ő+?…ř“z0ţńR㔳RaúÝU«Ü[Ž4@§ăp‰Mh–ŻT®môť n7™33ň˛«ë­>§ÝŠŠŠ~  !ŢCűÉĽŔřňňňYUUU»‰čŕ~禑Żëwu¦ş”Ň{ľCˇĐY@ŕš¦} ŕZ´NŁŰĹ ŕrMÓVÁ˙óů|‡îťK€ÂL=[.¬j oř1Ä™Ě X)ΰşůS~î˘0úůď'¤x~ÉÚË}Dg;W%t"śďt îÁó&d/´ôŞ˝¦Á—Ć‹hçCE„ßćgGţfĺůě4gÎśĚP(tU0|]ń>Z;Ŕ| µ…ćx<žĂáđ«ŕ÷űGř‰UqŃeV§˘ŮłggčŞ{GÖŘuWŻ`0xl0|†™_%˘KÜďĆJ˛˛˛jŻżţú~]ľ;~f.°,NčDµ ľ{ş5îŔJňxÎť4"bËNŤĽśČc—D8ZĆbîlÎ´Ź«¦ÜÁěĘĆŘHýÁĘÖ¬.G 'ŃnG1~8/»:™­5M™;wnďť;w^(„ĚĚ?FÇWű;‰¨,‹ý±ŞŞjűţ/hšvZďŚ,ÁĚł˛˛NC×}µÓZKKË…=Mw¬€Ëś9s2›››ÖÚńĆeć„/X&ĄülČ![‹‹‹c~ż?KÓ´DtĽ”ň":ńŻâ>Żąąů•`08>o3óűěĎLC!„e ˝%â̆) üŇŔ°µQŇó.8&ŇdUíiîÓ|SŹť=/$c=â/¬i(śQűl ,Aäđ6ÚďĽôÉäˇÂŁ­‡‰Rśé‡ů9‹*­:Ú’UÓN“$ëpč8ř×7QäŽvçž[żßßWqQ[?ť·8ý@eŰbŁo~1ś@D˙őw_7‡Ăá;,>fJ …B70łŮŇŔţp8śô/ɶ5‹˙ĘüíDtWKKËý ,;áÁ1ć!ţńŻéş>ˇŞŞëŐÜńűý˝4MűĆ.^·VTTdYU[ˇ¦ˇđ.Ĺ]?€€řQ^ÎÂO¬8Wj§ţ„ź12†€RIJ F<ąŃ®¸áš;tŇ´s ’9¬ý&ĘZu°şO}'˛†Ń~2_#LqS2÷ů|Ú ANŐu˝€ 4M;€§“ďÍĚü=¸oZ˝#Dô{Ř3•:@·Nč‰,łň®0^Á`đWB{ŃůâţŽFŁż1’Č÷ ‡ĂË}>ßy XHDSâr–¦i%LݎBśă3QˬJću«|3‰âOćŕ«“•Ě  {Ńłµ ľ8=Ţ1 FěąŔ,ű"3Ď5 DgŞíjßZ8şÚ’[»fJ QC‡Ť€oY‹/±Đń–‚3fĚěőz§8/++k‚”˛'+Š7xŔDTżiÓ¦·âŮ6 …~ŕbë˘>Ŕ¸9sćdŢsĎ=)]Ú,"˘@ `¶!Ë7LÚ—¸Ďçë‘••ő€źÇ9d3ű+**ţžČy#‘ …f1s{k=ÚsĂĚ™3˙ZVV¶ĘĚůĚ4d±jë`MCáEDtݱQáń TłŇw ±”¨Ý>Ů1¦ŚXř‘§JŘ‚ šćÎťű×]»v˝ĘĚ%˘Ě¶bŰh‡”˛©ĄĄĄŃL÷°ŮłgcćrBß§gKKË8Ií;îˇP(GJ9ČĚX"JZC–ąsçöÎĘĘz@Ľ±Ťň+**>°âüRʱ˙Ţ7/3˙Ŕ5fÎĺTC–ş5ľďč´؉×:o”nNôÜflŹá©~^l0ĐŔ°0צ°LsEBŻůŕŞŢ”‰“ťŽĂiĚtk1˙r[˛öňÁ¨0¬Ýó_W]]›čy¬t×]wíđAŰ?–i»{|6o‡”RN@7MčRJÓÓíÉ*( űŃółr5éş>ˇ˛˛Ň˛š DddqyÚÜąsg·}6âVRR"`ĽB\óž={j \ źÖ_ÇŁ0řY#˘˘ńŁ9R7˝pt¤Ą¶qęÓ`ľÖČ8MŻ_7ýÖńĂrUilWl[=÷ž—\\8čí‚ÜČÓ‰äĹĆź.c±;Z˝IŔ}ŮŐáDĎ“*ŔMhoşŐâ~—†\]PfîÜą˝‰¨†™ăMr;„ůV&óYłf Ţ–ŰkçÎťç=×ćÍ›Ź`tűŰň‡J,9őoä[8ţ…űĽ—˝čĄDΛ8~ÖÄ --;]WÍ ťA?p:Ç1Ý–h‹ŇęľnY ŕ”öĎeQÚ9;‘s¤’@ đSżKŇéÚ˙3ďĚlŹjŐu=ˇ»Â®”””]»v=ĘĚńî‘g×Ěź?˙C+ăĐuý0wÓ2Ćč€X,f¦!KB[k×LÉa¦› “híµŕ(Ż'úݶX !˛mMŽi®Hč śčt{/?7ňb"(A‰čçĄGäwđ–ŻŔZaG݉ŇM(:™ţ†äý0{öěvq¤3żßźĹĚf˛ĽkwC– 6ÜŔČťÔďĂá°Ąť×Úž›_mr¬ŃŇ­ "Ă 5MK¨Rë" ĂĐ`a~NäýDÎk…ńĂźúŔJă#éüúúó\5łěŠ„Î`#íóŇ3ÝžčÝů¸†Źć\ŘÁË{‹KóG>ţU"çHłfÍ:RJů,€ŢÉ&3SŕÇÔt{ JÍ|żěŮÍ-O™9§]c{×ďjąęq±ăôÉŕôP:aĆÝ…čşĘY{jVO;ˇăňŽ_{˝řąŮă§’Ůłg‹Ĺž`řîÄbÝjQ\4=•Ě6d±eş˝mĘůĂn5S°(RĘ'2žŢ3ň~3âĚ–Ţ×řńE03ĆüěĹ#ź¶ĺĎŰ, ţÖäBď[IbżC'AĂťŽÁ!›Ë„©vĄKWůŽ")_@Ç˝šŁÄđŤŮ`>ĽÔpýő×÷‹Ĺb/ÁřţW;důýţ^N‘,B×=?×uýŹłçv›µţ«±ý0ᒙߊ÷ÍsçÎíÍĚF×ql,//o08¦ĂP1–ďzÎÔ8 f/0<÷őĹ®ůĚ;žĐÁňH§CpŁbě°áÚßuk|}uÂ?|ŻăCÓ yąÇZR&K ÔÜÜü2€3śŽe":Ęé’%‘qş®[žĐÁŕżFű>wǬŽef6=Ýŕ•ňňň¸/ĘwîÜů#śu%˘×Í4d©Y}Ů /”Đ$–šg+ÓSî@Ćž®ůĚ;žĐ”ĺt Ř+ĽĂŐÚęëĎó°Ž'Đé®ZXł¨4ŘR¬YłŽ$˘—w• &˘/´ŇIŰŢjŁĺE÷Ů6tčĐO­Ś§Ím0¶…nSŰâ9;™nŘĂĚFc3seęůą`írďćźLČŤ¬7sN;b¦ësHéq͢nÇ:Ý/ˇ=:ńÇ ·aŚx'Z[u¶X`eŚĽţ„bK~ż„®ë˙0ÚéXÖ]z Č…±†ű{Ýę†,ˇPčdÄßteź‡í.lŕM“ăV 2äq#Čđ"ę´ĺpGXRG5/ş÷lUŰ łkA tŽ·ŻíOč átÉ&ˇl-Ô4ú¦€q}Gݰ?˝ űŃo‹ÎÝBˇĐiš¦˝jŐ»@{­jÓN"Óív4d‘RŢ nůa«ăhG9Łíu)ĺL#ŹÚ¶ÇýČŕyölܸŃТ;xfĺ%‡pšŃq­ŘLŰéÓIYóc­ć|Bçîń¸źW&e/ţŘČ€®ôŤŚŃÉ–dĚČËY´ľŇNyĚĽćď “Á5 děä¦q~ż]fpŘňŠŠ ŰۇĂá•Ěl´ÍćM•••†ş!655ť€Žɶ‹™ßŽD"F/6ĐSô8ć¦Ű!H¸2ˇ Ý|Rf2Ô*ÖVÎ'ônň¸zv^óÁU˝5':/ľCUą‘E‰ĆćfÁ`đç^€ű‹ąćjÝNĚlv‹`T×őĺVƢiÚŐ0ţ]fi˝öÎTTT”đčjz˙["ş<ßeô&§ŰM-ś%"ĂŕľăŃ,/Ţc™ŔşN†g`lㆄŢĂé’…¶µđ? ęŐFç{=?nîłgNBą\(şŔĂ0yWdię÷űłäľÜĘçÖmSÍż0:NÓ´¬Š!ápř>]׏đkĎ0ó‡ÖxŹ™źfć˘ŚŚŚŁËËË =7ßOŇ Ę€ÍbĆ3k‡’Hč隆WŽ–A7Jč c÷ÂGý‘nt:Ň>ˇ{˝Ţ3Ą”f˛XşťrăĆŤyčd gľ(++űhţüůV†ŇĄŞŞŞÍîiűÇRĚl´·´´*˝ËŚ‘dâż> XÖ_Ţj,‘ićwf-ˇ>ňVR =ytOL_ď›ë§ťAŕN§ŢëʦM›N0Čč8f¶ě˘Â Ln!45S‚Mo3f–†:Ç%“ĚV{‹ć[íš­ÂnHč®yţ`Ł­QÚWýâš߯ę¬r3‘ôĄă~ó`0x”ňmąNÇ’€´n†ŁëúiLá°z˙ąÉĆ';·lŮ’nŰ; /k»h6L‚Mď2Â|Ő<»Ř\c%ĆW‰´ż¶šăSîĚŘkv1BĘ ~ü‚ěş\ ą¤Ń7š€yť <7/{±ábnVRRâٸqă-n…;.2M#˘´N艔±z˙9ĺťj&˘O#‘ôé@ …úřÁa_Íź?­™ój|s vńĹ.a¸©w‚©>ęvq<ˇŕš%˙vRë˛"Ő‹Ť?ÎđpźżŁóEUµy9‹Ë¬‹Ěy~ż”âď vĄr f¶­Ń‡K$ŇŲî~żß«išá:ţĚĽĘŞÜ€™Ď€ń†,¦˙;!Óěý(Cô3{^;• DŚcgj0ó燓Çď†Ň~Ęý“‰ą ßîęMôľť7Ů©]í¦éťDLź>˝g(şYÓ´ĺé’Ě€ŇvMH[Cłťí¶Üwß}+­ŠEqLń!"s­B]ĘĚŚ‰”ŇôL‰™ľ#–ýÍŽµÓŘ• ŔÔÚh´8ś„8~‡Î€k–üŰŹtőžÚFßĹ` vz?oäă_Y™3Ŕ”ĚĚĚ?1óp§ă±AZÖ€`08Š™Í–Ý]fĺV1!ÄÍNJąÚŞÜ€ ??gfse'Đ=ŽČ• Ć\ŕ°°˝|°Î'tFS:?Cť–|±Ń7Đøť6– ‡ňr=aqhI5wîÜŢ;wîĽ*\`¤ÓńŘȵ •ČósXż˙ü“C7Z‡“|>ź–••etĆdçСCß7{N!x›4ß'/‘Ţđ¶!Đ0™Ń%ë†úrŘÍń„NDĚţa¦€·'d/ěôŽŔè0¸“·¬Ť‘÷¬ ë@@`8Z·É­2dČ—FşÝ™u·„Ý!„+»I%Ęď÷giš–mrřň‡zČęĹŻ¦zĎž=·[‡“’ץÍECźŮ]Űčk›»/•š§@Ü%°í¦Qď1`su÷Ut|•;¤Hů…^x{bÎâ5í˝P źFŹtÚ•đN˙oűÝn[t)//ŻŃuýCšG± 3ďŐuÝ•ýžĄiÚY0wWXüüüúëŻďăSÍ€ożý6mv!1Ń5MKĽJžä›ĘÄS>ż…HЉ¦ÇTB?&Ňk_čńâŽ^é×H7č¬qł„ĽzĚŞ¨őqu¬ŞŞęóp8|…¦ißđżŇjE°Ýh›Çă1U°#^'„°4ˇďŢ˝ŰT2 «Ş’ű™˛K 8 g)ů?ĄĄĄ ?ľ#%0üĽ% SŽM4«8ßäĐŐ[‹Oč[[ĐŔUĎ!¬ŔĚĎ´÷óş†iÇů¶ÎÓ퓲;¶zrţüů_…Ăá;+**r„cКܗ˘JĐŽ˛˛˛-Na“Î.@;Ăş®[}'cvqeÚüýBśctŚU É«=ó+ă„NôżVÄ‘¨š•ľcŘl]Â[yÇF\÷řĆń„^8:ŇÂpWů< ¬-Č]üéÁ?¬†OcȇŃy-ě÷ŹŘŃŻÓ¶©ÉÂĚ\VVön8ľ3Oôx<}‰čt÷x €ëţR;…Ň2™·5d1»MlUEE…Ą Ń„f[]¦SgǤî?ßßÄck`ú.ť®®Y=í+b1kIŁo, Ľ Ŕkň5VĆcÇĹ+Ńş::=žoďÇ­Sí|Z'#[HÇUÉžjŹWiii3€·ŰţůάYłŽ”RËĚĂ™y ]âL„Î’R¦Ó ęďÄb±Ódkőv5Bô6ąłÇôéÓ{Ú°@/éŮđŚ‰•Ź>¨‚™Ç›î…”÷-_î?׉ďşÚFß•h­ýar1 ĄxÚÂ,㊄§`éśäJ,ů…VłjĘ("q[§ żĎIąUŇóçĎ˙ ŔW^ †űS§‹t++şO"űĎ)3jŹÇÓ)Ţáńšk®9,##ăDĂ>+//˙ÂŞúoď÷ÔÖĂ·} ŔT—2Ćní»íŹ~mUL]©[ăë+u„ ¸<ÁC5NĘ]čĘĹŻŽOą1–;…öÖëŔĹ%(Db:ż"üĎŰű˙ÁÖČl6sćĚ\…NÇáfÖĄ”/;‡ŘnË:3›®Ć—‘‘Ń×ĘXśŕőzĎ€Álj4diĎ1UQ&Ü–ĐAsę m-šµOí*ßOYÇ$s0ŁĂĎNsEB$Ţr:«°dě°Č_8ăV}ü?č|QQ@ŇWµ[©¤¤DH)€ůgR©nŁ®ëéta ໆ,cMß\QQaů.)Ąé„®ëş+;~ˇiš™ ,Kžźďo{6ţĘŔ‰™î©k,,ě)^»rĘ©µ ľ—Ax&kLHźOkënÄÎ!C†Ř’„ FD–é¶„ĸ@'¬¬mzgÝźá;é7ľôeÖ4řňk¦VökŔzfú:Nä:Z×üF„‡ĚŚKw,ŠĐ[_čt Úţm¶ün±DÍ*ßT"t¶HL Ŕ_8:’˛Ő«¦OźŢłgĎž‡‰ŢÔé„LWĎrł;¬YúÜvźH$˘ÁŻ|ĎÄđÎv™8fĆŚă™áikČŇq…ÉöýŰŠ†KÉĎŤüˇ¶Áw2Ŕ‰®źé đŤ¬ă†şßë’i)€÷Yč Ţ(ďŚőŕ=š}Đ—H fŮLśĐéĆૣŃW#1¦3𨉺‡ŰŁčńwżWҸçť8‘ęC®@Ŕ«…č@ëŠJ"ÜÓŮű¨šq]ů@#233ç‘Ůćéb;ýĂé l’HC–w-Ťä@Ťf1ó™>źĎUűŃCˇĐi^ŻwM(ş˝¤¤¤«›,W{'¨µű\&ĽGŚs r"Á‚“ŮEĚך8Ć^ŤÍ·<2‹ą&ˇŹSeFJoűŃąu–ˇn•ď,şřKC×_řýżoKF\v(**ÍĚ÷;‡0sŁ‹żś&„0˝Č‘™mÝÎ̦ďţĄ”S¬ŚĹ,źĎ§išö8\}}63ż:ޤf¦ejRöL_4ô™Ý}2q Ü2-˝‰˙˛śăOÍËŤĽőë|C`˘đM:­ŃZ®IčÁ®,§§–ocxżz…Ż*Ńůźmm~΢ǓŐü~–âit¶ŘŻű@ű•S]"ĎĎíZ·3ż‚8vŕ żßo¶Ľ%˛˛˛*äµóňj)ĺĘ8kÖ¬#a|ÝŔÖŠŠŠőfb4cě°ČžĽśE?gĐup®€Ď× Ü¸G6Ź(ȉÜWŚâďęÎǢ‚ńއş‡ÄÝÖ†hw%tť^t:ÓŽŽ´ôőňŤŽďäťÍşÄ¬d…eµéÓ§÷Ô4íiźŠM+DôU4í°ď}Š3›ĐŮăńŘ:ÍŰ–¤ĚnőX `B¦`(Ćŕm€ŘĹŚĎAü•¦‹Ď¶Ž’«÷m 6Ş%¶;@ĆÉljÉđ¦T."7.έkđ-g Őö6ŻĐqéBĆßňs#Ž>·3#Ž/˘î¬>źçtVóűýYš¦5Â|2¨‡Ă>+cęH0<­ű¬ÍÖß ëúŹŞŞŞ>·0¬Ěž=űđX,ö €ÉĽĺm"šP^^ľłŁcĚ™3'sďŢ˝;a|VuKEEĹŔtÜ…Żúľ>Q/Vddţ‚śČ}6…e ÷Mą`p*N»wV‡x'X33Ý㨒’Â*™·‹¤ň®Śišö{$vg7ŇŞXş‡ßđl‡âńx^ –Ô?X 8%‹˝‡’9}ęńx.ě,™Ŕ®]»Ž„ąďëÁ`đ&ĆĄŤhľ “9€÷·çŕ;ⱓ+zŚäcpÁł«0óů#7U;Ř)~żßŰÔÔô TᎬőx<ĺNaµ¶~öf oěď¤P(”´…“Bąv›ĎĚŁčőP(dYYŘ믿ľ_0Ľ›ŢBÇ aŢÖ4íśx‘é-˘Ěü[łcS]íš)9`2ÚsťtťŮé}'ą2ˇ_ýÄ—DxÎé8,˛¦GŹ>óśÂk®ąć0ŹÇóżp:·bć˙”––¦xeĂ…BˇźX ľyń¬YłNL<Ş®•••­pc‚‡9š™_ …B·Ďť;··ŮÁţˇPčşććć•ć ă’¤5D4!ŢÝB]ż«C…Á`đOłgĎ6´˙zúôé=ý~Vçuž.ćÁŕľsbŞ(ČY”’ĄČ]ů j Ŕô’Óq$Š™~Z»(eę|Łč9[€Ó-0ófľ¨˛˛2%?ô+**ú•‰ Z]2sXÓ´GĘĘĘě¬ë"˘@ PŤŽźS9V3/đh8îr‹éĚ™3čş>V1Ť™'Łłť.­Ç˙ű¦M›~‰Äß”iîÜą˝wíÚµć× ŔçDô€eD´˛ąąy;ddddéş>Ŕ!ÄPf`4€S\‡S˛>Hmca!"‡­ńFńńŁ#ť>q+×&t€¨¶±đS0rťŽÄ4ÂŇüěČD§ĂW0<ŔBCśŽĹÍůťŠŠ WvíęĘěŮł3t]?VJ9ŠÎ"˘sůÔ$śú őDô*€× ´˛¸¸ŘĚÖĄµ-«…ů‚8íůŚŢećŐ6Dt3AD™ůd îď¨ffľ±˛˛rľ™EjÁ`đ?N2:.2##cŔĽyóľIâ9-QżÎ7$ŇŚĚ0č’ůĽIąŐŻÚ—Ý\·míż! ďŃźťŽÄ$ťbř§Q0ś ŕ.tݵ¨[cf]±Đé8:Ň–° y03B bćˇٵfř0bß–´$^ĐŔ•Ě|%455í …Bř@JŮ@DMD´ĽĽĽüł'¸çž{ö\{íµgdd<ÇĚc-Šűhf> 3׾?3vŤ¦UTT,ݍ¨0Ë3HnB˙(“9DُĆ’9|[*'sŔĄĎĐ÷iéŮăA¤j6BEިȇN‡Ńżß?4Ôµ»PÉĽ D´j÷îÝ®] 'Ą<‹™ź°€ngć™hť†> ­ Ý-źů>Ě<–™ýÔzŃţ7 oĽ˙ţű·Ćb±<$¶ňÝRĚü¸Ç㇗'rśh4Z ™SÁ¶Öă·KíŞ©!¬MŔ@Ý9'ÜaSHIă–w».üţß·1#ět&l±ŘmNŃ"˘P(t•¦iŕt<©‚™kěl š()ĺ9NÇ`–”Ň’5 UUU»|)ZĘĹýśÚë\TQQqą (,XĐDDÉ(t˛…™˙˘iZĘUµ¬kśvď14ńDěŠý›¸¤*W'tčĎÝv9‡L|ëÄQOnq:ŽŽ„Bˇ“ŔĚü0 NKugĚĽ&ŤŢît]8×éLÚ:dČËJlËp8|3źŕ5«Ž§oů&]׏‡Ă–vâ ‡ĂwŮŇžTđO>ŹÇsTEEĹ˙Ěź?­ ç±MÍęË1Ëj+YĽ‡5L.ńäF»âJ&/ŠűŻÚß˝®s:Ž8}ě]żéäńă_vÝ>ú˘˘˘!ÄŤ®†«×O¸Ve86Ń­)9fĎžť‹ĹľA«¬Ýž*//żĚ®ăÉDt3Ëâő5€2ápx›]')))ń455Ýŕ$¶ęţĂĚ ˝^ĄĄ_Zž#ę×MďŤîŞE룥xIćĺT?iW\É–_ę1Ň˙ěa­ĆűŘ&ßl6™—”” 6śCD"zł«ęQń §!ţW1€fĹ1»ˇŐ---ťvŇsÚ®]»zddd¤\yaRš^ ŹŠŠŠ'<Î$˘küÖĚN53ó?ümË–-ĎŮŠfVqqq ŔŤ@ŕ!Äo™9ßŕ!>"˘§t]_XYY™2ŤG:R‚1.şëo0–ĚAÄżÎËNźd¤Č:Ô6úîcŽÓqtá­üśę±@b¨@`•ŃgĚü˝‹ĹţUUUµ9Ţc´ÝŤOik˛‘juń]‡JËËËSe–Hé‚ĎçÓ8–™Ďp:Zë.|]/ ý­}Řß°´wďŢőwÝu—ŁŹÁŕ±Îp€!Ě|„ÂËĚßŘĆĚßŃz´&ň———op2^«Ő4L-%đ,#c¸+/'’h1"×I™„^żî§ý˘Qo#Ś÷łM">//»şŢŠcÍš5ë]ןÄ ĽHf~Ŕ«BŹ|ĆĚߢµxG_ý‰(­=¬OmE `ĄÇă9=Ý*Ă)*))›7o˘ëúP"Ę`ć^ŔĚ{l—R~QUUµÝá0•ýÔ5řţÄŔ\#c)ś—™™čŤ—ĄLB€šĆ©×\Á$<——ů‰•Çôűý}5M«’ELŇDŔmáp8ĺ·´(J:©mśzo24čîüěČÜtLć@ ¬rßßö.Đŕtí ÜjőA«ŞŞ¶{<ž ¤Tc—4óÁćÍ›ďt:EQZUçŐ6–Mć ü>?{Ń éšĚKč…Ł#-`üĆé8ÁüX~Nä};]ZZş‰¦ŰqlĄKŰĄ”ż‹DRŻë’˘¤Łš®ęÝŻO‚)ddßVąĹ®¸Ü"Ą:äçFž"‚›šť´âb;OP^^^CDµvžC93ż^YYů´Óq(Š,]ĺ;Š2÷ľŕbĂ$ÍÉË®NFAǥ͵±®… ôóôŁ… Ľ gIDATu:€+'ć,^Ď;ý~żWÓ´ď !úI)wőîÝűËxWČQą‰í)Šyk<Ď §PxiőÔóxŚ 4Ž"`‡dşŞ 'uş]&*ĄĹíŻ®ˇpJc§đx˛'óXSgojŰűz=€|‡ôňZf~“žëŮłçS÷ÜsĎžöŽ‘ĘECRĐ"úżňňňTm ¤(iˇ>­_t3 Ě(°2&qÉů##]¶żM')›ĐKP"Ć5|ü:Z÷^:‚™J rÝÖŃë~ż?KÓ´.Ťó[ünđŕÁemĹ# ß˝•®”VŻVTTśk¦ĹĄ˘(ÖXŇč-ř‘ˇ„˝žčĺă‡?•’ťâ‘rĎĐ÷)F±ÔHüś€…°˝GŹ–{;z1ś˘iÚű?™Ŕć555ý{Ö¬YÇ´óúzŁA*†­pµJćŠâŚúúó<µ«¦ţV2Ţ…±d.A|Dzěă/ęŽÉHᄲ®–DÎôgüĄŁż4ˇPh-p”ÉŁź˘ëú+EEE9ý<ŃşÍJçvřs8ŽkM„˘(ÖŞYé›6đ]˙ĆJ}Żc‰üüěę›ÓˇkšY)ťĐ  {Ń-Lňiwzá™ßŢ ~ż3?  _‚çřžâsćĚÉÜďg<¦Ň f^‡]Űë\QŇŐ’O§ĺÖ6řž!%`śh`(3PáŤâÄ‚‘‘Ą¶"Rr•űÁĽŢ–@´Ĺ;„Ł“q>f”ŤĎ}ěşęłgĎ>\Ó´çŃ:un…Ń{÷îý-ţ[´ć{W9ÔG^Ż7%›(JŞŞYé;Fü/kř%ŚçŁĎ蚉9‹ęě-Ąě˘¸Ő5N;YÖĂţŽl»b„c.ČŽl:ř…@ đ]mńův´´´ ×4­ż¦iŤ[@D_2sa8~ÓéXĄ;¨kśr Xű5§ÁxH űcä˝ń‚ěGU…ý¤Ĺ:äe/|ł¶Ń7ŚGl=ˇŞdţS’9ćőz/G<q©íRĘ{***T2W• DŚm\q!gD`ęfr €ňsŮR™3ŐĄÍú>fZé°R‘?ňńj«Ď1c°×ëýŔ@›Îű€ĂڶéřÝ•ŕńp8|ĄÓ(JşŞűÔw˘Ôř*]ŕH“‡Y¦ąůą‹^°2¶t“6wčűôXżqNěČ'0á<«ŹÍ %sđz˝€}É0şS‰ 3żľeË–kśŽCQŇÍ’O§ĺJMż Ëˇád~ÎF€Š˝ë7Ţ?~üˇÔćP”vwč°äÓËHÍó*€ă,¤'v ¸@žÇW’gťâŠŠŠŠuN˘(©ň ŕű°fW‘đ‚¸`YöńÇdW‡U27'-ďĐ÷™”˝řăšŐ…?!Iµz™?=Q0rŃÚC~Jô „§$ßĚ\TVVö–Ó(Š‚Ď~\€ďŰ×±r˘ÓĄ¸´NčP0˘zYMĂÔ ü<€>fŽÁЩ٠…ÎpZ˘ń)Ił^J9§˛˛ň%§Q”nl ź¤=‘—˝PmµXÚ't(ČYôŻşUľ @x[·Ĺʱ¬ wń!wtĚ|łe*¶bćőŹç×ápx±Ó±(J7ÓLŚe\+˙3/{ń{N”ÎşEB€ĽÜČkµ+§^Á/ŕĐžä|ČÝůĚ™3Ďp–…á)öů\qýüůóźt:Eé¶3ă !řMÉ´ {z.Ë?é‘]NŐ]t›„ů#˝ľ¤Ńwľd< C>÷~ąů)dřC)ĺ\;âS¬ĹĚë4MűUYYY­Ó±(JšŮ` Ŕkô1?"ć'ć<±¶µ_Šâ„´Ü‡Ţ•—Vű˛…Ä‹ŔÁ©ú@š›—łčĎű˙lćĚ™ÇK)?„jeęv«„W©pŠb­7ľôeŽŮătʡŇvŰZg&Ť4z˝8„w:yŰn=ĘüC]×oJćn÷fž¤’ą˘XO%s÷ę– ĆŹlŕÝ=Çđ\»o <8itä€=ěˇPčd"šś”3tőŹçµĎ\Q”î¦Ű&t(8é‘]Űrp)3• µ¸Á>ĚR–ü~)ĺmPwçnő-€Çu]/(--U-Eévşĺ3ôöÔ4^D żčŕŮüśČĹűż …˛™yTBw"úŔ_ĘËË˙Üĺ›EQŇT·ľCß_ANősĐäé |ćżüş”2•ĚÝčŁćććÉ*™+ŠŇÝ©;ô<÷őĹ˝.úěžý·^Ě™3'sďŢ˝_8ÂÁĐ”ýŃ.f~Ŕĺápx›Óń(Š˘8­[íCŹÇECźŮ}đĎöěŮs©d”ĄĄN˘(Šâ*ˇÇ®r:†˙ßŢÝ„ĆQ‡q˙=3«Ä·z•R"¤ DDlAĽPjŠB‹·›Íć`EĽ•i…ŮéJ@(úB•R…ŇâUzĐB…RÚŠÔš,©F ­!™}XřÎI:0>>ţŃáÇłĽ‡€Ő€ ßÜö9¶ťŘż˙§îîµZíŘŘŘŘI{%=ąÂł…č‚»źěęęzßľ}y« ‹âćQ*•î‰ăřWIk;6O …ޡˇˇËť?[,ďíîî~ÇĚŢ“ôřŠwżhf'$}ŔgĘŕÖôy”ËĺWÍěxç63Űž$ÉůŢS«Ő Ífs‹»ď’ôܲąŠą{ffg%}EQmxxřjŢ3ŔjFĐçQ©T>w÷7˙yíîÇŇ4}í˙ľ``ŕĹ,ËŢ5ł>ńi‚ąű5Iç˘(:Çń'CCC“yĎ! čs(•J÷Çq<&éÁö¦q3ëM’dt±űŞV«ë[­ÖVw[ŇÓK:čęrEŇŹY–}Üh4Nĺ= „† Ďˇ\.ÍěPǦb˝^?r»űÝąsç QíTÔĚSÝBwEŇyIß …„ÇšŔň!čs¨T*_¸űëí—ëőú¶ĄÜ{ÁÝKfÖçî}’žXĘýç¨efżşűĎ’N™Yz+W5‹GĐg)•JÇq<*©ËĚĆ̬gąlU«ŐŢ,Ëú$˝,éyI,çń–Řź’.»ű…(Šľšśś<:22ň{ŢCŔ݆ ĎR©Tv¸űg’äîo¤izt%Źß^)˙Ś»ov÷Íf¶IŇú•śa>îžić†:ŁfvŮÝżŹ˘čË$I~â–¬/‚>K˙7’^‘t¤^ŻóžG’ş%ődY¶ÁĚzÜ}٤§Ělť–áć@îţ—™ý!éš»_•ÔŚ˘čb–e'Ěětš¦ÍĄ>&ŕöôk§§§ŻHšp÷ž;=\µZ-j6›ŹJZçŮ:wÄÝ2ł‚¤5šy°ĚÍüźţ>ISffî~ÝĚZî~ĂĚ®·żŹI:+éĚôôôĄFŁ1žŰ/XnýÚ!˲­’ î^˝Óc.I»wďnImýó8€qĂ“îľMŇń4Mć= ‹ÁzŰŕŕŕZI˛,ëÍ{‹3ô¶©©©^I»ŤĆoyĎŔbq†ŢEŃů$INć=·‚Uî€K‚@: 耠‚@: 耠‚@: 耠‚@: 耠‚@: 耠‚@: 耠‚@: čŕođéťŕŇ©áIEND®B`‚tclcurl-ng-8.0.3/tests/tcl_conf.tcl.in000066400000000000000000000006421522613063100176370ustar00rootroot00000000000000# tcl_conf.tcl -- # # Generated by configure from tcl_conf.tcl.in. namespace eval ::tclcurl::test::conf { variable package_name {@PACKAGE_NAME@} variable package_version {@PACKAGE_VERSION@} variable tclsh_prog {@TCLSH_PROG@} variable pkg_lib_file {@PKG_LIB_FILE@} variable pkg_lib_file8 {@PKG_LIB_FILE8@} variable pkg_lib_file9 {@PKG_LIB_FILE9@} variable script_file {@TCLCURL_SCRIPTS@} } tclcurl-ng-8.0.3/tests/version.test000077500000000000000000000015731522613063100173340ustar00rootroot00000000000000# version.test -- # # Tests the TclCurl version reporting command. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package package require TclCurl test version-1.01 {: Test that curl::version returns something} -body { set result [curl::version] return $result } -match regexp -result {^TclCurl Version \d+\.\d+\.\d+(-DEV)? \(libcurl/\d+\.\d+\.\d+(-DEV)? .*?\)$} cleanupTests tclcurl-ng-8.0.3/tests/version_info.test000077500000000000000000000040201522613063100203350ustar00rootroot00000000000000#!/usr/bin/tclsh # versionInfo.test -- # # Tests versioninfo queries exposed by TclCurl. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. # # Portions of this file were drafted or revised with AI assistance # under the direction and review of Massimo Manghi package require tcltest namespace import ::tcltest::* source [file join [file dirname [file normalize [info script]]] support.tcl] ::tclcurl::test::load_package package require TclCurl test versioninfo-1.01 {: Test that -version returns something} -body { return [curl::versioninfo -version] } -match regexp -result {^\d+\.\d+\.\d+(-DEV)?$} test versioninfo-1.02 {: Test that -versionnum returns something} -body { return [curl::versioninfo -versionnum] } -match regexp -result {^[0-9A-F]+$} test versioninfo-1.03 {: Test that -features returns something} -body { return [curl::versioninfo -features] } -match regexp -result {^([A-Z0-9]+ ?)+$} test versioninfo-1.04 {: Test that -sslversion returns something} -body { # unix sslversion string looks like {^(OpenSSL|GnuTLS|LibreSSL)/\d+\.\d+\.\d+\w*$} # macosx sslversion string looks like {^SecureTransport \(OpenSSL/\d+\.\d+\.\d+\w*\)$} # On Windows, Schannel does not provide any version numbers return [curl::versioninfo -sslversion] } -match regexp -result {((OpenSSL|GnuTLS|LibreSSL)/\d+\.\d+\.\d+\w*)|Schannel} test versioninfo-1.05 {: Test that -sslversionnum returns something} -body { return [curl::versioninfo -sslversionnum] } -match regexp -result {^\d+$} test versioninfo-1.06 {: Test that -libzversion returns something} -body { return [curl::versioninfo -libzversion] } -match regexp -result {^\d+\.\d+(\.\d+)?$} test versioninfo-1.07 {: Test that -protocols returns something} -body { return [curl::versioninfo -protocols] } -match regexp -result {^([a-z0-9]+ ?)+$} cleanupTests tclcurl-ng-8.0.3/testservers/000077500000000000000000000000001522613063100161645ustar00rootroot00000000000000tclcurl-ng-8.0.3/testservers/ftp_server.tcl000066400000000000000000000427731522613063100210640ustar00rootroot00000000000000# ftp_server.tcl -- # # Implementation of a simple FTP server for testing of the tclcurl extension # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. namespace eval ::tclcurl::testserver {} oo::class create ::tclcurl::testserver::ftp_service { superclass ::tclcurl::testserver::service variable ftp_root sessions constructor args { set ftp_root [::tclcurl::test::ftp_root] array set sessions {} next {*}$args } destructor { foreach chan [array names sessions] { my close_session $chan } next } method start {} { file mkdir $ftp_root set listener [socket -server [list [self] accept] \ -myaddr [my host] [my port]] my set_listener $listener my log [my listening_message] return $listener } method description {} { return "FTP test server" } method accept {chan host port} { chan configure $chan -blocking 0 \ -buffering line \ -translation crlf \ -encoding utf-8 set sessions($chan) [dict create cwd / \ type A \ passive_listener {} \ data_chan {} \ pending_action {} \ restart_offset 0 \ rename_from {} \ last_command {} \ last_argument {}] my send_reply $chan 220 "TclCurl FTP test server ready" chan event $chan readable [list [self] read_command $chan] } method read_command {chan} { if {[eof $chan]} { my close_session $chan return } set line [gets $chan] if {$line eq {} && [chan pending input $chan] == 0} { return } if {$line eq {} && [eof $chan]} { my close_session $chan return } ::tclcurl::test::msgoutput "ftp command chan=$chan line=$line" set command [string toupper [lindex [split $line] 0]] set argument [string trim [string range $line [string length $command] end]] dict set sessions($chan) last_command $command dict set sessions($chan) last_argument $argument my handle_command $chan $command $argument } method handle_command {chan command argument} { if {![info exists sessions($chan)]} { return } ::tclcurl::test::msgoutput "TclCurl FTP Server: command '$command' received" switch -- $command { USER { my send_reply $chan 331 "Anonymous login ok, send password" } PASS { my send_reply $chan 230 "Login successful" } SYST { my send_reply $chan 215 "UNIX Type: L8" } FEAT { puts $chan "211-Features" puts $chan " EPSV" puts $chan " PASV" puts $chan " SIZE" puts $chan " MDTM" puts $chan "211 End" flush $chan my log_request "command=FEAT status=211 path=[dict get $sessions($chan) cwd]" } PWD - XPWD { my send_reply $chan 257 "\"[dict get $sessions($chan) cwd]\" is the current directory" } TYPE { dict set sessions($chan) type [string toupper $argument] my send_reply $chan 200 "Type set to [dict get $sessions($chan) type]" } SITE { my handle_site_command $chan $argument } MKD { set virtual_path [my normalize_virtual_path [dict get $sessions($chan) cwd] $argument] file mkdir [my virtual_to_fs $virtual_path] my send_reply $chan 257 "\"$virtual_path\" created" } CWD { set virtual_path [my normalize_virtual_path [dict get $sessions($chan) cwd] $argument] set fs_path [my virtual_to_fs $virtual_path] if {![file isdirectory $fs_path]} { my send_reply $chan 550 "Failed to change directory" return } dict set sessions($chan) cwd $virtual_path my send_reply $chan 250 "Directory changed to $virtual_path" } CDUP { my handle_command $chan CWD .. } NOOP { my send_reply $chan 200 "NOOP ok" } EPSV { if {[string toupper $argument] eq "ALL"} { my send_reply $chan 200 "EPSV ALL ok" return } set port [my open_passive_listener $chan] my send_reply $chan 229 \ "Entering Extended Passive Mode ([my passive_triplet $port])" } PASV { set port [my open_passive_listener $chan] lassign [split [my host] .] h1 h2 h3 h4 set p1 [expr {$port / 256}] set p2 [expr {$port % 256}] my send_reply $chan 227 "Entering Passive Mode ($h1,$h2,$h3,$h4,$p1,$p2)" } SIZE { set fs_path [my resolve_path $chan $argument] if {![file exists $fs_path] || [file isdirectory $fs_path]} { my send_reply $chan 550 "Could not get file size" return } my send_reply $chan 213 [file size $fs_path] } MDTM { set fs_path [my resolve_path $chan $argument] if {![file exists $fs_path] || [file isdirectory $fs_path]} { my send_reply $chan 550 "Could not get file modification time" return } set mtime [file mtime $fs_path] set timestamp [clock format $mtime -gmt 1 -format "%Y%m%d%H%M%S"] my send_reply $chan 213 $timestamp } REST { if {![string is entier -strict $argument] || $argument < 0} { my send_reply $chan 501 "Invalid restart position" return } dict set sessions($chan) restart_offset $argument my send_reply $chan 350 "Restarting at $argument" } DELE { set fs_path [my resolve_path $chan $argument] if {![file exists $fs_path] || [file isdirectory $fs_path]} { my send_reply $chan 550 "File unavailable" return } file delete -force $fs_path my send_reply $chan 250 "File deleted" } RNFR { set fs_path [my resolve_path $chan $argument] if {![file exists $fs_path]} { my send_reply $chan 550 "File unavailable" return } dict set sessions($chan) rename_from $fs_path my send_reply $chan 350 "Ready for RNTO" } RNTO { set from_path [dict get $sessions($chan) rename_from] if {$from_path eq {}} { my send_reply $chan 503 "Bad sequence of commands" return } set to_path [my resolve_path $chan $argument] file mkdir [file dirname $to_path] file rename -force $from_path $to_path dict set sessions($chan) rename_from {} my send_reply $chan 250 "Rename successful" } LIST { my begin_transfer $chan LIST $argument } NLST { my begin_transfer $chan NLST $argument } RETR { my begin_transfer $chan RETR $argument } STOR { my begin_transfer $chan STOR $argument } QUIT { my send_reply $chan 221 "Goodbye" my close_session $chan } default { my send_reply $chan 502 "Command not implemented" } } } method send_reply {chan code message} { if {[catch { puts $chan "$code $message" flush $chan }]} { my close_session $chan return } if {[info exists sessions($chan)]} { set command [dict get $sessions($chan) last_command] if {$command eq {}} { return } set argument [dict get $sessions($chan) last_argument] set path [expr {$argument eq {} ? [dict get $sessions($chan) cwd] : $argument}] my log_request \ "command=$command status=$code path=[::tclcurl::testserver::log_value $path]" } } method handle_site_command {chan argument} { set subcommand [string toupper [lindex [split $argument] 0]] switch -- $subcommand { CHMOD { set mode [lindex [split $argument] 1] set target [lindex [split $argument] 2] if {$mode eq {} || $target eq {}} { my send_reply $chan 501 "Missing SITE CHMOD arguments" return } set fs_path [my resolve_path $chan $target] if {![file exists $fs_path]} { my send_reply $chan 550 "SITE CHMOD target does not exist" return } if {[catch {file attributes $fs_path -permissions $mode}]} { # Keep the test server lenient on platforms that do not # honor POSIX mode changes the same way. } my send_reply $chan 200 "SITE CHMOD command successful" } default { my send_reply $chan 502 "SITE command not implemented" } } } method passive_triplet {port {delimiter |}} { return "${delimiter}${delimiter}${delimiter}${port}${delimiter}" } method normalize_virtual_path {cwd path} { if {$path eq {}} { return $cwd } if {[string match "/*" $path]} { set candidate $path } else { set candidate [file join $cwd $path] } set parts {} foreach element [split $candidate /] { switch -- $element { {} - . { continue } .. { if {[llength $parts] > 0} { set parts [lrange $parts 0 end-1] } } default { lappend parts $element } } } if {[llength $parts] == 0} { return / } return /[join $parts /] } method virtual_to_fs {virtual_path} { set relative [string trimleft $virtual_path /] if {$relative eq {}} { return $ftp_root } return [file join $ftp_root {*}[split $relative /]] } method resolve_path {chan path} { return [my virtual_to_fs [my normalize_virtual_path [dict get $sessions($chan) cwd] $path]] } method transfer_path {argument} { set path {} foreach token [split $argument] { if {$token eq {}} { continue } if {[string match "-*" $token]} { continue } set path $token break } return $path } method open_passive_listener {chan} { my reset_passive_state $chan set listener [socket -server [list [self] accept_data $chan] -myaddr [my host] 0] dict set sessions($chan) passive_listener $listener return [lindex [fconfigure $listener -sockname] end] } method accept_data {control_chan data_chan host port} { if {![info exists sessions($control_chan)]} { catch {close $data_chan} return } chan configure $data_chan -blocking 1 -buffering none -translation binary set listener [dict get $sessions($control_chan) passive_listener] if {$listener ne {}} { catch {close $listener} } dict set sessions($control_chan) passive_listener {} dict set sessions($control_chan) data_chan $data_chan if {[dict get $sessions($control_chan) pending_action] ne {}} { my perform_pending_action $control_chan } } method begin_transfer {chan action argument} { if {$action in {LIST NLST}} { set argument [my transfer_path $argument] } dict set sessions($chan) pending_action [dict create action $action argument $argument] my send_reply $chan 150 "Opening data connection" if {[dict get $sessions($chan) data_chan] ne {}} { my perform_pending_action $chan } } method perform_pending_action {chan} { if {![info exists sessions($chan)]} { return } set pending [dict get $sessions($chan) pending_action] if {$pending eq {}} { return } set data_chan [dict get $sessions($chan) data_chan] if {$data_chan eq {}} { return } set action [dict get $pending action] set argument [dict get $pending argument] set restart_offset [dict get $sessions($chan) restart_offset] dict set sessions($chan) pending_action {} dict set sessions($chan) restart_offset 0 set status [catch { switch -- $action { LIST { puts -nonewline $data_chan [my directory_listing $chan $argument 0] } NLST { puts -nonewline $data_chan [my directory_listing $chan $argument 1] } RETR { set fs_path [my resolve_path $chan $argument] if {![file exists $fs_path] || [file isdirectory $fs_path]} { error "missing file" } set fh [open $fs_path rb] try { if {$restart_offset > 0} { chan seek $fh $restart_offset start } puts -nonewline $data_chan [read $fh] } finally { close $fh } } STOR { set fs_path [my resolve_path $chan $argument] if {![file isdirectory [file dirname $fs_path]]} { error "missing directory" } set fh [open $fs_path wb] fconfigure $fh -translation binary try { puts -nonewline $fh [read $data_chan] } finally { close $fh } } } flush $data_chan }] my reset_passive_state $chan if {$status} { my send_reply $chan 550 "Transfer failed" return } my send_reply $chan 226 "Transfer complete" } method directory_listing {chan argument names_only} { set fs_path [my resolve_path $chan $argument] if {![file exists $fs_path]} { error "missing path" } if {[file isdirectory $fs_path]} { set entries [lsort [glob -nocomplain -directory $fs_path *]] } else { set entries [list $fs_path] } set listing {} foreach entry $entries { set name [file tail $entry] if {$names_only} { append listing "$name\r\n" continue } if {[file isdirectory $entry]} { set mode drwxr-xr-x set size 0 } else { set mode -rw-r--r-- set size [file size $entry] } set timestamp [clock format [file mtime $entry] -format "%b %d %H:%M"] append listing [format "%s 1 owner group %8d %s %s\r\n" \ $mode $size $timestamp $name] } return $listing } method reset_passive_state {chan} { if {![info exists sessions($chan)]} { return } set listener [dict get $sessions($chan) passive_listener] if {$listener ne {}} { catch {close $listener} } set data_chan [dict get $sessions($chan) data_chan] if {$data_chan ne {}} { catch {close $data_chan} } dict set sessions($chan) passive_listener {} dict set sessions($chan) data_chan {} } method close_session {chan} { if {![info exists sessions($chan)]} { return } my reset_passive_state $chan catch {close $chan} unset sessions($chan) } } ::tclcurl::testserver register_service_class ftp ::tclcurl::testserver::ftp_service tclcurl-ng-8.0.3/testservers/http_endpoint.tcl000066400000000000000000000125351522613063100215550ustar00rootroot00000000000000# http_endpoint.tcl -- # # Shared HTTP endpoint plumbing for TclCurl test servers. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. namespace eval ::tclcurl::testserver {} if {[info commands ::tclcurl::testserver::http_endpoint_service] eq {}} { # Shared HTTP connection plumbing for test services that speak HTTP on the # client-facing side. Concrete subclasses keep their own request # completion details and response behavior, but they all share the same # listener setup, per-channel buffering, header parsing and socket # cleanup. oo::class create ::tclcurl::testserver::http_endpoint_service { superclass ::tclcurl::testserver::service variable request_data constructor args { array set request_data {} next {*}$args } destructor { foreach chan [array names request_data] { catch {close $chan} } next } method start {} { set listener [socket -server [list [self] accept] -myaddr [my host] [my port]] my set_listener $listener my log [my listening_message] return $listener } method accept {chan host port} { chan configure $chan -blocking 0 -buffering none -translation binary ::tclcurl::test::msgoutput "accept connection chan=$chan host=$host port=$port" chan event $chan readable [list [self] read_request $chan] } method read_request {chan} { if {[eof $chan]} { my close_client $chan return } set chunk [read $chan] if {$chunk eq {}} { return } append request_data($chan) $chunk set request [my complete_request $request_data($chan)] if {$request eq {}} { return } unset request_data($chan) chan event $chan readable {} if {[catch {my handle_request $chan $request} request_error request_options]} { ::tclcurl::test::msgoutput \ "request handling failed chan=$chan error=$request_error options=$request_options" my close_client $chan } } # Default request framing for simple HTTP services: a complete header # block plus an optional fixed-size body announced by Content-Length. method complete_request {request_data} { set header_end [string first "\r\n\r\n" $request_data] if {$header_end < 0} { return {} } set headers [my parse_headers $request_data] set content_length 0 if {[dict exists $headers content-length]} { set content_length [dict get $headers content-length] } set request_length [expr {$header_end + 4 + $content_length}] if {[string length $request_data] < $request_length} { return {} } return [string range $request_data 0 [expr {$request_length - 1}]] } method header_lines {header_block} { return [regexp -all -inline {[^\r\n]+} $header_block] } # Parse the header block into a lower-cased dictionary so subclasses # can reason about headers without repeating the same parsing logic. method parse_headers {request} { set header_end [string first "\r\n\r\n" $request] if {$header_end < 0} { return [dict create] } set header_block [string range $request 0 [expr {$header_end - 1}]] set header_lines [my header_lines $header_block] set headers [dict create] foreach header_line [lrange $header_lines 1 end] { # Example match: "Content-Type: text/plain" if {![regexp {^([^:]+):\s*(.*)$} $header_line -> name value]} { continue } dict set headers [string tolower $name] $value } return $headers } # Parse the request line and return the method, target and HTTP version # in a dictionary that both origin and proxy handlers can consume. method parse_request_line {request} { set request_line [lindex [split $request "\r\n"] 0] # Example matches: # "GET /request-inspect HTTP/1.1" # "GET http://127.0.0.1:8990/proxy-target HTTP/1.1" if {![regexp {^([A-Z]+) ([^ ]+) HTTP/([0-9.]+)$} $request_line -> method target version]} { return {} } return [dict create method $method target $target version $version] } # Subclasses receive a fully buffered request and are responsible for # producing the service-specific response or forwarding behavior. method handle_request {chan request} { error "handle_request must be implemented by subclasses" } method close_client {chan} { catch {unset request_data($chan)} catch {close $chan} } } } tclcurl-ng-8.0.3/testservers/http_server.tcl000066400000000000000000000760421522613063100212460ustar00rootroot00000000000000# http_server.tcl -- Implementation of a simple HTTP server # # Implementation of the HTTP server support used by the TclCurl extension. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. namespace eval ::tclcurl::testserver {} package require sha256 if {[info commands zlib] eq {}} { package require zlib } package require base64 package require uri if {[info commands ::tclcurl::testserver::http_endpoint_service] eq {}} { source [file join [file dirname [file normalize [info script]]] http_endpoint.tcl] } # HTTP origin service used by the tests. The shared base handles connection # lifecycle and buffering; this class adds origin-specific request framing, # routing and response generation. oo::class create ::tclcurl::testserver::http_service { superclass ::tclcurl::testserver::http_endpoint_service method escape_response_value {value} { return [string map [list "\\" "\\\\" "\n" "\\n" "\r" "\\r"] $value] } method decode_query_component {value} { set decoded [string map [list + " "] $value] while {[regexp -indices {%[0-9A-Fa-f][0-9A-Fa-f]} $decoded match]} { lassign $match first last set replacement [format %c 0x[string range $decoded [expr {$first + 1}] $last]] set decoded [string replace $decoded $first $last $replacement] } return $decoded } method parse_query {target} { set uri_parts [::uri::split "http://localhost$target"] if {![dict exists $uri_parts query]} { return [dict create] } set query [dict get $uri_parts query] if {$query eq {}} { return [dict create] } set params [dict create] foreach pair [split $query &] { if {$pair eq {}} { continue } set separator [string first = $pair] if {$separator < 0} { dict set params [my decode_query_component $pair] {} continue } dict set params \ [my decode_query_component [string range $pair 0 [expr {$separator - 1}]]] \ [my decode_query_component [string range $pair [expr {$separator + 1}] end]] } return $params } method guess_content_type {path} { switch -exact -- [string tolower [file extension $path]] { .css { return "text/css; charset=utf-8" } .gif { return "image/gif" } .htm - .html { return "text/html; charset=utf-8" } .jpg - .jpeg { return "image/jpeg" } .js { return "application/javascript; charset=utf-8" } .json { return "application/json; charset=utf-8" } .md { return "text/markdown; charset=utf-8" } .png { return "image/png" } .svg { return "image/svg+xml; charset=utf-8" } .tcl { return "text/plain; charset=utf-8" } .txt { return "text/plain; charset=utf-8" } .xml { return "application/xml; charset=utf-8" } default { return "application/octet-stream" } } } method description {} { return "HTTP origin test server" } # Origin tests also exercise chunked uploads, so request completion needs # to understand both fixed-size and chunked request bodies. method complete_request {request_data} { set header_end [string first "\r\n\r\n" $request_data] if {$header_end < 0} { return {} } set headers [my parse_headers $request_data] if {[string tolower [my header_value $headers transfer-encoding]] eq "chunked"} { return [my complete_chunked_request $request_data $header_end] } set content_length 0 if {[dict exists $headers content-length]} { set content_length [dict get $headers content-length] } set request_length [expr {$header_end + 4 + $content_length}] if {[string length $request_data] < $request_length} { return {} } return [string range $request_data 0 [expr {$request_length - 1}]] } method complete_chunked_request {request_data header_end} { set chunk_data [string range $request_data [expr {$header_end + 4}] end] set chunk_info [my parse_chunked_body $chunk_data] if {![dict get $chunk_info complete]} { return {} } set request_end [expr {$header_end + 4 + [dict get $chunk_info consumed_length] - 1}] return [string range $request_data 0 $request_end] } # Build the standard origin-server reply for malformed HTTP requests. method bad_request_response {} { return [my build_response_dict [dict create \ status 400 \ reason "Bad Request" \ body "bad request\n" \ head_only 0]] } # Dispatch a parsed origin request to the route table, then normalize and # emit the resulting response dictionary. method handle_request {chan request} { set request_info [my parse_request_line $request] if {$request_info eq {}} { my log_request "method=? status=400 path=?" my send_response $chan [my bad_request_response] return } dict with request_info {} set path [lindex [split $target ?] 0] ::tclcurl::test::msgoutput "route request method=$method path=$path" set headers [my parse_headers $request] set response [my route_request $method $path $target $version $headers $request] dict set response head_only [expr {$method eq "HEAD"}] set response [my build_response_dict $response] my log_request "method=$method status=[dict get $response status] path=[::tclcurl::testserver::log_value $path]" if {[dict exists $response delay_ms]} { set callback [list [self] send_response $chan $response] if {[dict exists $response close_only] && [dict get $response close_only]} { set callback [list [self] close_client $chan] } after [dict get $response delay_ms] $callback return } my send_response $chan $response } # Extract the request body after the header block and transparently decode # chunked uploads so route handlers can inspect the payload directly. method request_body {request} { set header_end [string first "\r\n\r\n" $request] if {$header_end < 0} { return {} } set headers [my parse_headers $request] if {[string tolower [my header_value $headers transfer-encoding]] eq "chunked"} { return [my decode_chunked_body [string range $request [expr {$header_end + 4}] end]] } return [string range $request [expr {$header_end + 4}] end] } method decode_chunked_body {body} { return [dict get [my parse_chunked_body $body] decoded_body] } method parse_chunked_body {body} { set decoded {} set cursor 0 # libcurl can emit "Transfer-Encoding: chunked" for an empty POST # request without sending an explicit terminating zero-size chunk. if {$body eq {}} { return [dict create complete 1 decoded_body {} consumed_length 0] } while 1 { set line_end [string first "\r\n" $body $cursor] if {$line_end < 0} { return [dict create complete 0 decoded_body {} consumed_length 0] } set size_line [string trim [string range $body $cursor [expr {$line_end - 1}]]] set size_token [lindex [split $size_line ";"] 0] if {[scan $size_token %x chunk_size] != 1} { return [dict create complete 0 decoded_body {} consumed_length 0] } set data_start [expr {$line_end + 2}] if {$chunk_size == 0} { if {[string range $body $data_start [expr {$data_start + 1}]] eq "\r\n"} { return [dict create \ complete 1 \ decoded_body $decoded \ consumed_length [expr {$data_start + 2}]] } set trailer_end [string first "\r\n\r\n" $body $data_start] if {$trailer_end < 0} { return [dict create complete 0 decoded_body {} consumed_length 0] } return [dict create \ complete 1 \ decoded_body $decoded \ consumed_length [expr {$trailer_end + 4}]] } set data_end [expr {$data_start + $chunk_size}] if {[string length $body] < ($data_end + 2)} { return [dict create complete 0 decoded_body {} consumed_length 0] } if {[string range $body $data_end [expr {$data_end + 1}]] ne "\r\n"} { return [dict create complete 0 decoded_body {} consumed_length 0] } append decoded [string range $body $data_start [expr {$data_end - 1}]] set cursor [expr {$data_end + 2}] } } method header_value {headers name} { if {[dict exists $headers $name]} { return [dict get $headers $name] } return {} } method chunk_encode {body {chunk_size 16}} { set encoded {} set body_length [string length $body] for {set offset 0} {$offset < $body_length} {incr offset $chunk_size} { set chunk [string range $body $offset [expr {$offset + $chunk_size - 1}]] append encoded [my chunk_frame $chunk] } append encoded [my chunk_terminator] return $encoded } method chunk_frame {chunk_data} { return [format %X [string length $chunk_data]]\r\n$chunk_data\r\n } method chunk_terminator {} { return "0\r\n\r\n" } method streaming_payload_length {stream_chunks} { set total 0 foreach stream_chunk $stream_chunks { lassign $stream_chunk delay_ms chunk_data incr total [string length $chunk_data] } return $total } method stream_response_body {chan response_headers head_only transfer_encoding stream_chunks} { if {[catch { puts -nonewline $chan [join $response_headers "\r\n"] puts -nonewline $chan "\r\n\r\n" flush $chan } write_error]} { ::tclcurl::test::msgoutput "response write failed chan=$chan error=$write_error" my close_client $chan return } if {$head_only} { my close_client $chan return } my send_stream_chunk $chan $transfer_encoding $stream_chunks 0 } method send_stream_chunk {chan transfer_encoding stream_chunks index} { if {$index >= [llength $stream_chunks]} { if {$transfer_encoding eq "chunked"} { if {[catch { puts -nonewline $chan [my chunk_terminator] flush $chan } write_error]} { ::tclcurl::test::msgoutput "stream write failed chan=$chan error=$write_error" } } my close_client $chan return } lassign [lindex $stream_chunks $index] delay_ms chunk_data after $delay_ms [list [self] write_stream_chunk $chan $transfer_encoding $stream_chunks $index $chunk_data] } method write_stream_chunk {chan transfer_encoding stream_chunks index chunk_data} { if {[catch { if {$transfer_encoding eq "chunked"} { puts -nonewline $chan [my chunk_frame $chunk_data] } else { puts -nonewline $chan $chunk_data } flush $chan } write_error]} { ::tclcurl::test::msgoutput "stream write failed chan=$chan error=$write_error" my close_client $chan return } my send_stream_chunk $chan $transfer_encoding $stream_chunks [expr {$index + 1}] } method redirect_response {location {reason "Found"}} { set body "redirect=$location\n" return [dict create status 302 \ reason $reason \ body $body \ headers [list "Location: $location"]] } method static_file_response {path} { if {$path eq {}} { return {} } if {$path eq "/"} { set relative_segments [list index.html] } else { set relative_segments {} foreach segment [split [string trimleft $path /] /] { if {$segment eq {} || $segment eq "." || $segment eq ".."} { return {} } lappend relative_segments $segment } } set doc_root [::tclcurl::test::doc_root] set fs_path [file join $doc_root {*}$relative_segments] if {[file isdirectory $fs_path]} { set fs_path [file join $fs_path index.html] } if {![file exists $fs_path] || [file isdirectory $fs_path]} { return {} } set fh [open $fs_path rb] try { set body [read $fh] } finally { close $fh } return [dict create \ status 200 \ reason OK \ body $body \ headers [list "Content-Type: [my guess_content_type $fs_path]"]] } method byte_range_response {headers full_body} { set total_length [string length $full_body] set range_header [my header_value $headers range] if {$range_header eq {}} { return [dict create \ status 200 \ reason OK \ body $full_body \ headers [list "Accept-Ranges: bytes"]] } # Example matches: "bytes=16-47" and "bytes=16-47,102-134" if {![regexp {^bytes=\s*([0-9]+-[0-9]+)(\s*,\s*([0-9]+-[0-9]+))*$} $range_header]} { return [dict create \ status 416 \ reason "Range Not Satisfiable" \ body {} \ headers [list "Content-Range: bytes */$total_length"]] } set ranges {} foreach range_spec [split [string range $range_header 6 end] ,] { set range_spec [string trim $range_spec] lassign [split $range_spec -] start end if {$start > $end || $end >= $total_length} { return [dict create \ status 416 \ reason "Range Not Satisfiable" \ body {} \ headers [list "Content-Range: bytes */$total_length"]] } lappend ranges [list $start $end] } if {[llength $ranges] == 1} { lassign [lindex $ranges 0] start end set range_body [string range $full_body $start $end] return [dict create \ status 206 \ reason "Partial Content" \ body $range_body \ headers [list \ "Accept-Ranges: bytes" \ "Content-Range: bytes $start-$end/$total_length"]] } set boundary "tclcurl-boundary" set range_body {} foreach range $ranges { lassign $range start end append range_body "--$boundary\r\n" append range_body "Content-Type: text/plain\r\n" append range_body "Content-Range: bytes $start-$end/$total_length\r\n\r\n" append range_body [string range $full_body $start $end] append range_body "\r\n" } append range_body "--$boundary--\r\n" return [dict create \ status 206 \ reason "Partial Content" \ body $range_body \ headers [list \ "Accept-Ranges: bytes" \ "Content-Type: multipart/byteranges; boundary=$boundary"]] } # Map origin-server paths to the behavior expected by the test suite. method route_request {method path target version headers request} { # Example matches: "/redir_1" and "/redir_5" if {[regexp {^/redir_([0-9]+)$} $path -> redirect_step]} { if {$redirect_step < 5} { return [my redirect_response "/redir_[incr redirect_step]"] } set body "path=$path\nmethod=$method\n" return [dict create status 200 reason OK body $body headers {}] } # Example matches: "/wait-200ms" and "/wait-2s" if {[regexp {^/wait-([0-9]+)(ms|s)$} $path -> wait_amount wait_unit]} { set wait_time $wait_amount set close_only 0 if {$wait_unit eq "s"} { set wait_time [expr {$wait_time * 1000}] } set query_params [my parse_query $target] if {[dict exists $query_params reply] && [dict get $query_params reply] eq "none"} { set close_only 1 } return [dict create \ status 200 \ reason OK \ delay_ms $wait_time \ close_only $close_only \ body "waited=${wait_amount}${wait_unit}\n" \ headers {}] } # Example match: "/cookie-set/session_id/abc123" if {[regexp {^/cookie-set/([^/]+)/([^/]+)$} $path -> cookie_name cookie_value]} { set body "set-cookie=$cookie_name=$cookie_value\n" return [dict create status 200 \ reason OK \ body $body \ headers [list "Set-Cookie: $cookie_name=$cookie_value; Path=/"]] } switch -- $path { / { set static_response [my static_file_response /] if {$static_response ne {}} { return $static_response } set index_path [file join [::tclcurl::test::repo_root] testservers index.html] if {[file exists $index_path]} { set fh [open $index_path rb] try { set body [read $fh] } finally { close $fh } return [dict create \ status 200 \ reason OK \ body $body \ headers [list "Content-Type: text/html; charset=utf-8"]] } set body "tclcurl test server\n" return [dict create status 200 reason OK body $body headers {}] } /tclcurl-man { set static_response [my static_file_response /tclcurl-man.html] if {$static_response ne {}} { return $static_response } set manual_path [::tclcurl::testserver::manual_html_source] if {$manual_path ne {} && [file exists $manual_path]} { set fh [open $manual_path rb] try { set body [read $fh] } finally { close $fh } return [dict create \ status 200 \ reason OK \ body $body \ headers [list "Content-Type: text/html; charset=utf-8"]] } set body "path=$path\n" return [dict create status 404 reason "Not Found" body $body headers {}] } /tclcurl-http-root { set body "tclcurl test server\n" return [dict create status 200 reason OK body $body headers {}] } /tclcurl-http200alias { set body "http200aliases=matched\n" return [dict create \ status 200 \ reason OK \ body $body \ headers {} \ status_line "yummy/4.5 200 OK"] } /tclcurl-missing-resource { set body "not found\n" return [dict create status 404 reason "Not Found" body $body headers {}] } /autoreferer-start { return [my redirect_response "/autoreferer-target"] } /autoreferer-target { set referer {} if {[dict exists $headers referer]} { set referer [dict get $headers referer] } set body "method=$method\nreferer=$referer\n" return [dict create status 200 reason OK body $body headers {}] } /postredir-301 { if {$method eq "POST"} { return [dict create status 301 \ reason "Moved Permanently" \ body "redirect=/postredir-target\n" \ headers [list "Location: /postredir-target"]] } set body "method=$method\n" return [dict create status 200 reason OK body $body headers {}] } /postredir-target { set body "method=$method\n" return [dict create status 200 reason OK body $body headers {}] } /cookie-echo { set cookie_header {} if {[dict exists $headers cookie]} { set cookie_header [dict get $headers cookie] } set body "cookie=$cookie_header\n" return [dict create status 200 reason OK body $body headers {}] } /proxy-target { return [dict create status 200 reason OK body "proxy=ok\n" headers {}] } /proxy-auth-target { return [dict create status 200 reason OK body "proxy-auth=ok\n" headers {}] } /auth-basic { set expected_user "testuser" set expected_password "testpass" set authorization [my header_value $headers authorization] # Example match: "Basic dGVzdHVzZXI6dGVzdHBhc3M=" if {![regexp {^Basic\s+(.+)$} $authorization -> auth_blob]} { return [dict create \ status 401 \ reason "Unauthorized" \ body "auth=missing\n" \ headers [list "WWW-Authenticate: Basic realm=\"TclCurl Test\""]] } if {[catch {set decoded [::base64::decode $auth_blob]}]} { return [dict create \ status 401 \ reason "Unauthorized" \ body "auth=invalid\n" \ headers [list "WWW-Authenticate: Basic realm=\"TclCurl Test\""]] } # Example decoded value: "testuser:testpass" if {![regexp {^([^:]+):(.*)$} $decoded -> username password]} { return [dict create \ status 401 \ reason "Unauthorized" \ body "auth=invalid\n" \ headers [list "WWW-Authenticate: Basic realm=\"TclCurl Test\""]] } if {$username ne $expected_user || $password ne $expected_password} { return [dict create \ status 401 \ reason "Unauthorized" \ body "auth=denied\n" \ headers [list "WWW-Authenticate: Basic realm=\"TclCurl Test\""]] } set body "auth=ok\nuser=$username\n" return [dict create status 200 reason OK body $body headers {}] } /request-inspect { set request_body [my request_body $request] set body [join [list \ "method=[my escape_response_value $method]" \ "path=[my escape_response_value $path]" \ "target=[my escape_response_value $target]" \ "request-version=[my escape_response_value $version]" \ "content-type=[my escape_response_value [my header_value $headers content-type]]" \ "content-length=[my escape_response_value [my header_value $headers content-length]]" \ "accept-encoding=[my escape_response_value [my header_value $headers accept-encoding]]" \ "te=[my escape_response_value [my header_value $headers te]]" \ "connection=[my escape_response_value [my header_value $headers connection]]" \ "user-agent=[my escape_response_value [my header_value $headers user-agent]]" \ "referer=[my escape_response_value [my header_value $headers referer]]" \ "x-tclcurl-test=[my escape_response_value [my header_value $headers x-tclcurl-test]]" \ "body-length=[string length $request_body]" \ "body-hex=[binary encode hex $request_body]" \ "body-sha256=[::sha2::sha256 -hex $request_body]"] "\n"] append body "\n" return [dict create status 200 reason OK body $body headers {}] } /deflated-data { set body [::tclcurl::test::negotiation_payload] return [dict create \ status 200 \ reason OK \ body [zlib compress $body] \ headers [list "Content-Encoding: deflate"]] } /chunked-data { set body [::tclcurl::test::negotiation_payload] return [dict create \ status 200 \ reason OK \ body $body \ headers {} \ transfer_encoding chunked] } /slow-chunked-data { set body [::tclcurl::test::negotiation_payload] return [dict create \ status 200 \ reason OK \ body {} \ headers {} \ transfer_encoding chunked \ stream_chunks [list \ [list 0 [string range $body 0 9]] \ [list 50 [string range $body 10 end]]]] } /slow-body-1 { set body [::tclcurl::test::negotiation_payload] return [dict create \ status 200 \ reason OK \ body {} \ headers {} \ stream_chunks [list \ [list 0 [string range $body 0 9]] \ [list 6000 [string range $body 10 end]]]] } /slow-body-2 { set body [string range [::tclcurl::test::range_fixture] 0 191] set stream_chunks {} for {set offset 0} {$offset < [string length $body]} {incr offset 32} { lappend stream_chunks [list 1000 [string range $body $offset [expr {$offset + 31}]]] } return [dict create \ status 200 \ reason OK \ body {} \ headers {} \ stream_chunks $stream_chunks] } /range-data { return [my byte_range_response $headers [::tclcurl::test::range_fixture]] } /shutdown { # Let's also have a method to orderly stop operations set ::tclcurl::testserver::forever "no more" return [dict create status 200 reason OK body "server orderly shutdown\n" headers {}] } default { if {$method eq "GET" || $method eq "HEAD"} { set static_response [my static_file_response $path] if {$static_response ne {}} { return $static_response } } set body "path=$path\n" return [dict create status 200 reason OK body $body headers {}] } } } # Normalize partially specified route results into a complete response # dictionary so sending code can follow one path. method build_response_dict {response} { set completed_response [dict create \ status 200 \ reason OK \ body {} \ head_only 0 \ headers {} \ status_line {} \ transfer_encoding {} \ stream_chunks {}] dict for {key value} $response { dict set completed_response $key $value } return $completed_response } # Serialize a normalized response dictionary to the client socket, handling # HEAD requests, chunked transfers and delayed streaming responses. method send_response {chan response} { dict with response {} if {$status_line eq {}} { set status_line "HTTP/1.1 $status $reason" } ::tclcurl::test::msgoutput "send response chan=$chan status=$status reason=$reason body-length=[string length $body]" set response_headers [list $status_line "Connection: close"] if {![regexp -nocase {^Content-Type:} [join $headers "\n"]]} { lappend response_headers "Content-Type: text/plain" } if {$transfer_encoding eq "chunked"} { lappend response_headers "Transfer-Encoding: chunked" } elseif {[llength $stream_chunks] > 0} { lappend response_headers "Content-Length: [my streaming_payload_length $stream_chunks]" } else { lappend response_headers "Content-Length: [string length $body]" } set response_headers [concat $response_headers $headers] if {[llength $stream_chunks] > 0} { my stream_response_body $chan $response_headers $head_only $transfer_encoding $stream_chunks return } if {[catch { puts -nonewline $chan [join $response_headers "\r\n"] puts -nonewline $chan "\r\n\r\n" if {!$head_only} { if {$transfer_encoding eq "chunked"} { puts -nonewline $chan [my chunk_encode $body] } else { puts -nonewline $chan $body } } flush $chan } write_error]} { ::tclcurl::test::msgoutput "response write failed chan=$chan error=$write_error" my close_client $chan return } my close_client $chan } } ::tclcurl::testserver register_service_class http ::tclcurl::testserver::http_service tclcurl-ng-8.0.3/testservers/https_server.tcl000066400000000000000000000025131522613063100214210ustar00rootroot00000000000000# https_server.tcl -- Wrapping TLS around HTTP to have a simple HTTPS server # # Implementation of the HTTP server support used by the TclCurl extension. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. namespace eval ::tclcurl::testserver {} package require tls oo::class create ::tclcurl::testserver::https_service { superclass ::tclcurl::testserver::http_service method description {} { return "HTTPS origin test server" } method start {} { if {![::tclcurl::test::https_credentials_available]} { puts "https credentials not available, HTTPS tests will not run" return } set listener [::tls::socket -server [list [self] accept] \ -myaddr [my host] \ -certfile [::tclcurl::test::https_cert_file] \ -keyfile [::tclcurl::test::https_key_file] \ -ssl2 0 \ -ssl3 0 \ [my port]] my set_listener $listener my log [my listening_message] return $listener } } ::tclcurl::testserver register_service_class https ::tclcurl::testserver::https_service tclcurl-ng-8.0.3/testservers/index.html000066400000000000000000000566751522613063100202040ustar00rootroot00000000000000 Tclcurl tiny web server

Tclcurl tiny web server

TclCurl Test Suite

The repository now has two distinct kinds of files under tests/:

  • *.test: real tcltest test cases that are executed by tests/all.tcl
  • legacy/*.tcl: legacy example scripts that are useful as references, but are not part of the automated suite

Last update: 2026-05-16

Running the suite

tests/all.tcl tries to load TclCurl from the build tree first and falls back to an installed package if needed.

By default, tests/all.tcl enables tcltest’s start verbosity, so each test prints a line when it begins running. You can still override that from the command line with -verbose.

To run the server-backed suite from a normal working tree, use this sequence:

  1. Start the local test servers in one terminal:
tclsh testservers/testserver.tcl
  1. Run the suite in a second terminal from the repository root:
tclsh tests/all.tcl
  1. To run only one test file, add -file:
tclsh tests/all.tcl -file http.test
  1. If you want the test runner to shut down the HTTP test server when it finishes, add -exitserver:
tclsh tests/all.tcl -exitserver

If one of the configured protocol endpoints is not reachable, the corresponding server-backed tests are skipped.

testservers/testserver.tcl

The local server framework accepts the following general command form:

tclsh testservers/testserver.tcl \
                  ?--host host? \
                  ?--httpport port? ?--httpsport port? ?--ftpport port? ?--proxyport port? \
                  ?--certfile path? ?--keyfile path? \
                  ?--service protocol:port? ... \
                  ?--docroot path? ?--ftproot path? ?--keepdocroot? \
                  ?--logfile path? \
                  ?--startservers protocol[,protocol,...]|all? \
                  ?--quiet? ?--debug?

By default, testservers/testserver.tcl starts four services:

  • HTTP on 127.0.0.1:8990
  • HTTPS on 127.0.0.1:9443
  • FTP on 127.0.0.1:8991
  • HTTP proxy on 127.0.0.1:8992

The HTTP test server keeps its explicit dynamic routes for protocol behaviors such as redirects, request inspection, and authentication. For GET and HEAD requests that do not match one of those routes, it falls back to static file serving rooted at TCLCURL_TEST_DOC_ROOT or --docroot.

Unless --keepdocroot is given, the server removes the configured document root when it shuts down.

The server framework appends timestamped per-request log lines to /tmp/tclcurl.log by default. Override that path with --logfile when you want to keep the request log elsewhere.

tests/all.tcl

tests/all.tcl accepts a small set of TclCurl-specific options together with the usual tcltest command-line filters and output controls. The general form is:

tclsh tests/all.tcl \
                  ?--httpserver path/to/server.tcl? \
                  ?--httpport port? ?--httpsport port? ?--ftpport port? ?--proxyport port? \
                  ?--docroot path? ?--ftproot path? \
                  ?--certfile path? ?--keyfile path? \
                  ?--exitserver? ?--debug? \
                  ?--file pattern? ?--notfile pattern? ?--match pattern? ?--skip pattern? \
                  ?--verbose level...?

When the Tcl HTTP test server is wired in, the server script path precedence is:

  • --httpserver /path/to/server.tcl
  • TCLCURL_TEST_HTTP_SERVER_SCRIPT
  • testservers/testserver.tcl

testservers/testserver.tcl accepts --httpport, --httpsport, --ftpport, and --proxyport to override the default ports 8990, 9443, 8991, and 8992.

tests/all.tcl accepts the same double-dash options --httpport, --httpsport, --ftpport, and --proxyport. It also accepts --docroot, --ftproot, --certfile, and --keyfile, and maps them to the corresponding TCLCURL_TEST_* environment overrides used by the test support layer. When you need both entry points to target the same services, pass matching values to each script.

The Tcl test support layer uses protocol-specific base URLs. You can override them before running make test or tclsh tests/all.tcl:

  • TCLCURL_TEST_HTTP_BASE_URL: base URL for the running Tcl HTTP test server, default http://127.0.0.1:8990/
  • TCLCURL_TEST_HTTPS_BASE_URL: base URL for the running Tcl HTTPS test server, default https://127.0.0.1:9443/
  • TCLCURL_TEST_FTP_BASE_URL: base URL for the running Tcl FTP test server, default ftp://127.0.0.1:8991/
  • TCLCURL_TEST_PROXY_BASE_URL: base URL for the running Tcl HTTP proxy test server, default http://127.0.0.1:8992/
  • TCLCURL_TEST_DOC_ROOT: shared document root used by the Tcl test servers, default /tmp/tclcurl
  • TCLCURL_TEST_FTP_ROOT: root directory used by the Tcl FTP test server, default TCLCURL_TEST_DOC_ROOT
  • TCLCURL_TEST_HTTPS_CERT_FILE: path to the certificate file used by the Tcl HTTPS test server, default tests/certs/server.crt
  • TCLCURL_TEST_HTTPS_KEY_FILE: path to the private key file used by the Tcl HTTPS test server, default tests/certs/server.key
  • TCLCURL_TEST_HTTP_SERVER_SCRIPT: path to the Tcl test server framework script, used when no -httpserver CLI override is given; default testservers/testserver.tcl

Running secure protocol tests

In order to test the https series of tests you have to create a self-signed pair of key/certificate to be stored in tests/certs

If you want to keep the credentials elsewhere, either:

  • start testservers/testserver.tcl with --certfile /path/to/server.crt --keyfile /path/to/server.key
  • or run tests/all.tcl --certfile /path/to/server.crt --keyfile /path/to/server.key
  • or export TCLCURL_TEST_HTTPS_CERT_FILE and TCLCURL_TEST_HTTPS_KEY_FILE
 mkdir -p tests/certs

  openssl req   -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \
                -keyout tests/certs/server.key \
                -out tests/certs/server.crt \
                -subj "/CN=localhost" \
                -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

Shared transport scenarios

tests/http_common.tcl contains transport-oriented scenario helpers that are shared by http.test, https.test, redir.test, and cookies.test.

The common layer currently covers:

  • basic GET / HEAD requests
  • callback delivery through -writeproc
  • getinfo transfer metadata
  • redirect handling through -followlocation, -maxredirs, -autoreferer, and -postredir
  • request body handling through -post, -postfields, -postfieldsize, -upload, -readproc, and -range
  • timeout handling through -timeout and -timeoutms
  • cookie engine behaviors such as -cookiefile, -cookielist, -cookiejar, and -cookiesession

Tests that are primarily about easy-handle lifecycle or share-handle lifecycle stay in the protocol-specific files instead of being pulled into http_common.tcl.

Current server-backed coverage

tests/http.test focuses on TclCurl behaviors exercised over plain HTTP:

  • basic GET transfers with -bodyvar
  • HEAD requests with -headervar
  • callback delivery through -writeproc
  • getinfo transfer metadata
  • easy handle lifecycle operations such as reset and duphandle
  • HTTP error handling through -failonerror and -errorbuffer
  • share handle wiring for DNS sharing
  • request body handling through -post, -postfields, -postfieldsize, -upload, -readproc, and -range
  • timeout handling through -timeout and -timeoutms

tests/output.test covers output routing:

  • -file and resetting it to the default destination
  • -writeheader and resetting it to the default destination
  • -stderr and resetting it to the default destination

tests/progress.test covers transfer callbacks and related controls:

  • -command
  • -progressproc
  • pause / resume callback behavior
  • -buffersize

tests/negotiation.test covers HTTP negotiation-oriented options:

  • -httpversion
  • -encoding
  • -transferencoding
  • -contentdecoding
  • -transferdecoding

tests/https.test covers the TLS-specific aspects of the same HTTP behaviors:

  • HTTPS GET with certificate verification disabled
  • HTTPS GET with -cainfo pointing at the local self-signed certificate
  • expected verification failure when the certificate is not trusted
  • shared transport scenarios reused from tests/http_common.tcl

tests/ftp.test covers the local Tcl FTP server:

  • upload and download of text and binary files
  • directory listing via LIST / NLST
  • -dirlistonly
  • -quote / -postquote
  • -ftpcreatemissingdirs
  • -resumefrom

tests/redir.test and tests/cookies.test are thin wrappers around the shared transport scenarios, kept as separate files for readability and focused tcltest runs.

tests/mime.test currently covers multipart form submission through -httppost:

  • mixed textual parts
  • buffer-backed parts
  • file-backed parts

HTTPS setup

The HTTPS server requires:

  • the Tcl tls package
  • a local certificate and private key, by default at:
    • tests/certs/server.crt
    • tests/certs/server.key

You can override those paths:

  • for direct server runs, with --certfile /path/to/server.crt --keyfile /path/to/server.key
  • for the test suite, with TCLCURL_TEST_HTTPS_CERT_FILE and TCLCURL_TEST_HTTPS_KEY_FILE

These files are intentionally not required to live in the repository. When they are missing, HTTPS-backed tests are skipped.

One simple way to generate them locally is:

mkdir -p tests/certs

openssl req -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \
  -keyout tests/certs/server.key \
  -out tests/certs/server.crt \
  -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

Areas of Active Coverage Growth

The current suite already covers the core HTTP, HTTPS, and FTP behaviors used by TclCurl, but some areas are still being expanded. If you are looking for the parts of the option surface that are most likely to gain broader automated coverage next, the main groups are:

  • transfer controls such as -connecttimeout
  • name resolution and routing options such as -resolve, -ipresolve, -interface, -port, and -tcpnodelay
  • authentication options supported by the linked libcurl build, such as -userpwd, -username, -password, -httpauth, and -proxyauth

Other areas that are also expected to grow over time include:

  • callback diagnostics such as -debugproc
  • advanced multipart form handling through -httppost, including contentheader, overridden filename, and filecontent
  • broader metadata and utility APIs such as getinfo, curl::curlConfig, easystrerror, multistrerror, and sharestrerror

Current Limitations

Although the local test framework now covers a substantial part of TclCurl’s single-transfer behavior, some categories still have more limited automated coverage.

The main remaining limitations are:

  • scenarios that depend on more specialized server setups, such as proxy, SMTP, POP3, or authentication-specific environments
  • cases that require response scripts or fixtures derived from curl/tests/data
  • feature-conditional behaviors such as HTTP/2, HTTP/3, TLS auth, or compression variants that depend on how the local libcurl build was configured

In practice, this means that the absence of a test in one of those areas does not necessarily indicate lack of support in TclCurl. It more often means that the local test framework has not yet been extended to exercise that behavior in a reproducible way.

tclcurl-ng-8.0.3/testservers/proxy_server.tcl000066400000000000000000000343311522613063100214430ustar00rootroot00000000000000# proxy_server.tcl -- # # Implementation of a minimal HTTP proxy server for testing TclCurl. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. namespace eval ::tclcurl::testserver {} package require base64 if {[info commands ::tclcurl::testserver::http_endpoint_service] eq {}} { source [file join [file dirname [file normalize [info script]]] http_endpoint.tcl] } # HTTP proxy test service. The shared HTTP endpoint superclass owns the # listener/buffering/header-parsing mechanics; this class only implements proxy # target resolution, proxy authentication and upstream forwarding. oo::class create ::tclcurl::testserver::proxy_service { superclass ::tclcurl::testserver::http_endpoint_service variable tunnel_peer tunnel_root tunnel_pending constructor args { array set tunnel_peer {} array set tunnel_root {} array set tunnel_pending {} next {*}$args } destructor { foreach chan [array names tunnel_peer] { catch {close $chan} } next } method description {} { return "HTTP proxy test server" } # Convert either an absolute proxy target or an origin-form target plus # Host header into the upstream host/port/path tuple the proxy should use. method parse_target {target headers} { # Example match: "http://127.0.0.1:8990/proxy-target" if {[regexp {^http://([^/:]+)(?::([0-9]+))?(/.*)?$} $target -> host port path]} { if {$port eq {}} { set port 80 } if {$path eq {}} { set path / } return [dict create host $host port $port path $path] } set host_header [dict get $headers host] # Example matches: "127.0.0.1" and "127.0.0.1:8990" if {![regexp {^([^:]+)(?::([0-9]+))?$} $host_header -> host port]} { error "invalid Host header" } if {$port eq {}} { set port 80 } return [dict create host $host port $port path $target] } method auth_required {path} { return [expr {$path eq "/proxy-auth-target"}] } # Parse the host:port target used by HTTP CONNECT requests. method parse_connect_target {target} { if {![regexp {^([^:]+):([0-9]+)$} $target -> host port]} { error "invalid CONNECT target" } return [dict create host $host port $port] } # Validate the Proxy-Authorization header against the fixed credentials used # by the proxy authentication tests. method validate_proxy_auth {headers} { set authorization {} if {[dict exists $headers proxy-authorization]} { set authorization [dict get $headers proxy-authorization] } # Example match: "Basic cHJveHl1c2VyOnByb3h5cGFzcw==" if {![regexp {^Basic\s+(.+)$} $authorization -> auth_blob]} { return missing } if {[catch {set decoded [::base64::decode $auth_blob]}]} { return invalid } if {$decoded ne "proxyuser:proxypass"} { return denied } return ok } # Emit a simple proxy-generated response directly back to the client # without involving an upstream origin server. method proxy_response {chan status reason body headers} { set response_headers [concat [list \ "HTTP/1.1 $status $reason" \ "Content-Type: text/plain" \ "Content-Length: [string length $body]" \ "Connection: close"] $headers] catch { puts -nonewline $chan [join $response_headers "\r\n"] puts -nonewline $chan "\r\n\r\n" puts -nonewline $chan $body flush $chan } my close_client $chan } # Convert lower-cased header names from parse_headers back into the title # case form expected when forwarding headers upstream. method forwarded_header_name {name} { set parts {} foreach part [split $name -] { lappend parts [string totitle $part] } return [join $parts -] } # Extract the buffered request body so the proxy can forward it unchanged # once it has rewritten the request line and filtered the headers. method request_body {request} { set header_end [string first "\r\n\r\n" $request] if {$header_end < 0} { return {} } return [string range $request [expr {$header_end + 4}] end] } # Read the upstream response without blocking the event loop. The proxy and # origin services run in the same test server process, so a blocking read # would deadlock while the origin waits for the event loop to dispatch its # own readable callbacks. method read_upstream_response {upstream} { chan configure $upstream -blocking 0 -buffering none -translation binary set response {} set wait_var ::tclcurl::testserver::proxy_wait_[string map {: _} $upstream] while 1 { set chunk [chan read $upstream] if {$chunk ne {}} { append response $chunk } if {[chan eof $upstream]} { break } if {[chan blocked $upstream]} { set $wait_var 0 chan event $upstream readable [list set $wait_var 1] vwait $wait_var chan event $upstream readable {} catch {unset $wait_var} continue } break } catch {unset $wait_var} return $response } # Tear down both sides of an active CONNECT tunnel and discard the book- # keeping used by the asynchronous copy callbacks. method close_tunnel {root} { if {![info exists tunnel_peer($root)]} { return } set peer $tunnel_peer($root) catch {unset tunnel_pending($root)} catch {unset tunnel_root($root)} catch {unset tunnel_root($peer)} catch {unset tunnel_peer($root)} catch {unset tunnel_peer($peer)} catch {close $root} catch {close $peer} } # Complete one direction of an asynchronous CONNECT tunnel copy. The tunnel # is closed after both directions finish, or immediately if one direction # ends with an error. method tunnel_copy_done {src dst direction bytes {error {}}} { set root $tunnel_root($src) ::tclcurl::test::msgoutput \ "proxy tunnel copy done direction=$direction src=$src dst=$dst bytes=$bytes error=$error" if {$error ne {}} { my close_tunnel $root return } incr tunnel_pending($root) -1 if {$tunnel_pending($root) <= 0} { my close_tunnel $root } } # Establish a CONNECT tunnel to the requested upstream endpoint and bridge # bytes asynchronously in both directions. method start_tunnel {chan host port} { ::tclcurl::test::msgoutput \ "proxy tunnel connect chan=$chan host=$host port=$port" if {[catch {set upstream [socket $host $port]} socket_error]} { ::tclcurl::test::msgoutput \ "proxy tunnel connect failed chan=$chan error=$socket_error" my log_request "method=CONNECT status=502 target=[::tclcurl::testserver::log_value $host:$port]" my proxy_response $chan 502 "Bad Gateway" "proxy-error=$socket_error\n" {} return } chan configure $upstream -blocking 0 -buffering none -translation binary set tunnel_peer($chan) $upstream set tunnel_peer($upstream) $chan set tunnel_root($chan) $chan set tunnel_root($upstream) $chan set tunnel_pending($chan) 2 if {[catch { puts -nonewline $chan "HTTP/1.1 200 Connection Established\r\n\r\n" flush $chan } write_error]} { ::tclcurl::test::msgoutput \ "proxy tunnel establish failed chan=$chan error=$write_error" my close_tunnel $chan return } my log_request "method=CONNECT status=200 target=[::tclcurl::testserver::log_value $host:$port]" chan copy $chan $upstream -command \ [list [self] tunnel_copy_done $chan $upstream client_to_upstream] chan copy $upstream $chan -command \ [list [self] tunnel_copy_done $upstream $chan upstream_to_client] } # Build the standard proxy reply for malformed requests before any upstream # forwarding is attempted. method bad_request_response {} { return [dict create status 400 \ reason "Bad Request" \ body "bad proxy request\n" \ headers {}] } # Parse the proxy request, enforce proxy-specific policy and forward the # request upstream. The base class already guarantees that the request is # fully buffered before this method runs. method handle_request {chan request} { ::tclcurl::test::msgoutput \ "proxy handle_request chan=$chan request-bytes=[string length $request]" set request_info [my parse_request_line $request] if {$request_info eq {}} { ::tclcurl::test::msgoutput \ "proxy bad request chan=$chan reason=request-line-parse-failed" my log_request "method=? status=400 target=?" my proxy_response $chan 400 "Bad Request" "bad proxy request\n" {} return } dict with request_info {} ::tclcurl::test::msgoutput \ "proxy request-line chan=$chan method=$method target=$target version=$version" set headers [my parse_headers $request] if {$method eq "CONNECT"} { if {[catch {set connect_info [my parse_connect_target $target]} connect_error]} { ::tclcurl::test::msgoutput \ "proxy bad connect target chan=$chan target=$target error=$connect_error" my log_request "method=$method status=400 target=[::tclcurl::testserver::log_value $target]" my proxy_response $chan 400 "Bad Request" "bad proxy request\n" {} return } my start_tunnel $chan [dict get $connect_info host] [dict get $connect_info port] return } set target_info [my parse_target $target $headers] set path [dict get $target_info path] ::tclcurl::test::msgoutput \ "proxy target chan=$chan path=$path target-info=$target_info" if {[my auth_required $path]} { set auth_status [my validate_proxy_auth $headers] ::tclcurl::test::msgoutput \ "proxy auth chan=$chan path=$path status=$auth_status" if {$auth_status ne "ok"} { my log_request \ "method=$method status=407 target=[::tclcurl::testserver::log_value $path]" my proxy_response $chan 407 \ "Proxy Authentication Required" "proxy-auth=$auth_status\n" \ [list "Proxy-Authenticate: Basic realm=\"TclCurl Proxy Test\""] return } } set host [dict get $target_info host] set port [dict get $target_info port] set origin_path [dict get $target_info path] ::tclcurl::test::msgoutput \ "proxy connect chan=$chan host=$host port=$port origin-path=$origin_path" if {[catch {set upstream [socket $host $port]} socket_error]} { ::tclcurl::test::msgoutput \ "proxy connect failed chan=$chan error=$socket_error" my log_request \ "method=$method status=502 target=[::tclcurl::testserver::log_value $origin_path]" my proxy_response $chan 502 "Bad Gateway" "proxy-error=$socket_error\n" {} return } chan configure $upstream -blocking 1 -buffering none -translation binary set upstream_headers {} dict for {name value} $headers { if {$name in {proxy-authorization proxy-connection}} { continue } lappend upstream_headers "[my forwarded_header_name $name]: $value" } ::tclcurl::test::msgoutput \ "proxy forward headers chan=$chan count=[llength $upstream_headers]" set request_body [my request_body $request] ::tclcurl::test::msgoutput \ "proxy forward body chan=$chan bytes=[string length $request_body]" try { ::tclcurl::test::msgoutput \ "proxy upstream write start chan=$chan upstream=$upstream" puts -nonewline $upstream "$method $origin_path HTTP/$version\r\n" puts -nonewline $upstream "[join $upstream_headers "\r\n"]" puts -nonewline $upstream "\r\n\r\n" if {$request_body ne {}} { puts -nonewline $upstream $request_body } flush $upstream ::tclcurl::test::msgoutput \ "proxy upstream read start chan=$chan upstream=$upstream" set response [my read_upstream_response $upstream] ::tclcurl::test::msgoutput \ "proxy upstream read done chan=$chan response-bytes=[string length $response]" } finally { ::tclcurl::test::msgoutput \ "proxy upstream close chan=$chan upstream=$upstream" catch {close $upstream} } set upstream_status ? if {[regexp {^HTTP/[0-9.]+\s+([0-9]+)} $response -> parsed_status]} { set upstream_status $parsed_status } my log_request \ "method=$method status=$upstream_status target=[::tclcurl::testserver::log_value $origin_path]" catch { ::tclcurl::test::msgoutput \ "proxy client write chan=$chan response-bytes=[string length $response]" puts -nonewline $chan $response flush $chan } ::tclcurl::test::msgoutput "proxy complete chan=$chan" my close_client $chan } } ::tclcurl::testserver register_service_class proxy ::tclcurl::testserver::proxy_service tclcurl-ng-8.0.3/testservers/testserver.tcl000077500000000000000000000477571522613063100211250ustar00rootroot00000000000000#!/usr/bin/env tclsh # # testserver.tcl -- Start the server implementations needed by the test suite # # Implementation of the HTTP server support used by the TclCurl extension. # # Copyright (c) 2024-2026 Massimo Manghi # # SPDX-License-Identifier: TCL # # See the file "license.terms" at the top level of this distribution # for information on usage and redistribution of this file, and for the # complete disclaimer of warranties and limitation of liability. set tcl_conf_path [file join [file dirname [file dirname [file normalize [info script]]]] tests tcl_conf.tcl] if {[file exists $tcl_conf_path]} { source $tcl_conf_path set configured_tclsh $::tclcurl::test::conf::tclsh_prog if {$configured_tclsh ne {} && [file normalize [info nameofexecutable]] ne [file normalize $configured_tclsh]} { if {[info exists ::env(TCLCURL_TEST_REEXEC)] && $::env(TCLCURL_TEST_REEXEC) eq $configured_tclsh} { error "configured Tcl shell re-exec loop detected: $configured_tclsh" } set ::env(TCLCURL_TEST_REEXEC) $configured_tclsh set reexec_code [catch { exec $configured_tclsh [file normalize [info script]] {*}$argv >@ stdout 2>@ stderr } reexec_result reexec_options] if {$reexec_code == 0} { exit 0 } if {[dict get $reexec_options -errorcode] ni {{} NONE}} { set error_code [dict get $reexec_options -errorcode] if {[lindex $error_code 0] eq "CHILDSTATUS"} { exit [lindex $error_code 2] } } return -options $reexec_options $reexec_result } } unset -nocomplain tcl_conf_path configured_tclsh set ::argv_saved_for_testserver $argv set argv {} source [file join [file dirname [file dirname [file normalize [info script]]]] tests support.tcl] set argv $::argv_saved_for_testserver unset ::argv_saved_for_testserver namespace eval ::tclcurl::testserver { variable next_service_id 0 variable service_classes variable logger_logchan {} array set service_classes {} } oo::class create ::tclcurl::testserver::service { variable protocol host port quiet listener logfile constructor args { array set options { -protocol {} -host 127.0.0.1 -port {} -quiet 0 -logfile {} } foreach {name value} $args { if {![info exists options($name)]} { error "unknown option: $name" } set options($name) $value } if {$options(-protocol) eq {}} { error "missing -protocol" } if {$options(-port) eq {}} { error "missing -port" } set protocol $options(-protocol) set host $options(-host) set port $options(-port) set quiet $options(-quiet) set logfile $options(-logfile) set listener {} } destructor { my stop } method protocol {} { return $protocol } method host {} { return $host } method port {} { return $port } method endpoint {} { return "[my protocol]://[my host]:[my port]/" } method description {} { return "[string toupper [my protocol]] test server" } method listening_message {} { return "listening on [my endpoint] ([my description])" } method log {message} { if {!$quiet} { puts stderr $message } } method log_request {message} { if {$logfile eq {}} { return } if {[catch { ::tclcurl::testserver::write_log_line "[my protocol] $message" } log_error]} { ::tclcurl::test::msgoutput \ "request log failed protocol=$protocol error=$log_error" } } method set_listener {chan} { set listener $chan return $listener } method stop {} { if {$listener ne {}} { catch {close $listener} set listener {} } } method start {} { error "start must be implemented by subclasses" } } proc ::tclcurl::testserver::timestamp {} { return [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S"] } proc ::tclcurl::testserver::log_value {value} { return [string map [list "\\" "\\\\" "\n" "\\n" "\r" "\\r" "\t" "\\t"] $value] } proc ::tclcurl::testserver::write_log_line {line} { variable logger_logchan set stamped_line "[timestamp] $line" puts $logger_logchan $stamped_line flush $logger_logchan } proc ::tclcurl::testserver::start_logfile {config} { variable logger_logchan set logfile [dict get $config logfile] file mkdir [file dirname $logfile] set logger_logchan [open $logfile a] chan configure $logger_logchan -buffering line -translation lf -encoding utf-8 } proc ::tclcurl::testserver::stop_logfile {} { variable logger_logchan if {$logger_logchan ne {}} { catch {close $logger_logchan} set logger_logchan {} } } proc ::tclcurl::testserver::usage {} { set implemented_servers [join [implemented_protocols] ", "] puts stderr "Usage: tclsh testservers/testserver.tcl ?options?" puts stderr "" puts stderr "Options:" puts stderr " --help" puts stderr " Show this help message." puts stderr " --host
" puts stderr " Bind all selected servers to
. Default: 127.0.0.1" puts stderr " --startservers " puts stderr " Comma-separated list of servers to start. Use 'all' to start every" puts stderr " implemented server. Implemented servers: $implemented_servers" puts stderr " --httpport " puts stderr " Port for the default HTTP server. Default: 8990" puts stderr " --httpsport " puts stderr " Port for the default HTTPS server. Default: 9443" puts stderr " --ftpport " puts stderr " Port for the default FTP server. Default: 8991" puts stderr " --proxyport " puts stderr " Port for the default HTTP proxy server. Default: 8992" puts stderr " --certfile " puts stderr " TLS certificate file for HTTPS." puts stderr " --keyfile " puts stderr " TLS key file for HTTPS." puts stderr " --service " puts stderr " Add an explicit service entry. May be repeated." puts stderr " --docroot " puts stderr " Document root for HTTP/HTTPS test content." puts stderr " --ftproot " puts stderr " Root directory exposed by the FTP server." puts stderr " --keepdocroot" puts stderr " Leave the generated document root on disk after exit." puts stderr " --logfile " puts stderr " File where request log lines are appended." puts stderr " Default: /tmp/tclcurl.log" puts stderr " --quiet" puts stderr " Suppress listener startup messages." puts stderr " --debug" puts stderr " Enable verbose test debug output." } proc ::tclcurl::testserver::register_service_class {protocol class_name} { variable service_classes set service_classes($protocol) $class_name namespace ensemble configure ::tclcurl::testserver -map [command_map] return $class_name } proc ::tclcurl::testserver::service_class {protocol} { variable service_classes if {![info exists service_classes($protocol)]} { error "unsupported protocol: $protocol" } return $service_classes($protocol) } proc ::tclcurl::testserver::implemented_protocols {} { variable service_classes return [lsort [array names service_classes]] } proc ::tclcurl::testserver::parse_service_spec {spec} { if {![regexp {^([a-z0-9_+-]+):([0-9]+)$} $spec -> protocol port]} { error "invalid service spec: $spec" } if {$port < 1 || $port > 65535} { error "invalid port: $port" } return [dict create protocol $protocol port $port] } proc ::tclcurl::testserver::parse_port_value {name value} { if {![string is integer -strict $value] || $value < 1 || $value > 65535} { error "invalid value for $name: $value" } return $value } proc ::tclcurl::testserver::parse_startservers_value {value} { set normalized [string trim $value] if {$normalized eq {}} { error "invalid value for --startservers: empty list" } if {$normalized eq "all"} { return [implemented_protocols] } set selected {} foreach protocol [split $normalized ,] { set protocol [string trim $protocol] if {$protocol eq {}} { error "invalid value for --startservers: empty server name" } if {$protocol ni [implemented_protocols]} { error "unsupported server in --startservers: $protocol" } if {$protocol ni $selected} { lappend selected $protocol } } return $selected } proc ::tclcurl::testserver::parse_args {argv} { set host 127.0.0.1 set quiet 0 set debug 0 set docroot [::tclcurl::test::doc_root] set ftproot [::tclcurl::test::ftp_root] set certfile {} set keyfile {} set logfile [file normalize /tmp/tclcurl.log] set ftproot_follows_docroot [expr {$ftproot eq $docroot}] set keepdocroot 0 array set default_ports { http 8990 https 9443 ftp 8991 proxy 8992 } set startservers [implemented_protocols] set services {} set custom_services 0 for {set i 0} {$i < [llength $argv]} {incr i} { set arg [lindex $argv $i] switch -- $arg { --host { incr i if {$i >= [llength $argv]} { error "missing value after --host" } set host [lindex $argv $i] } --httpport { incr i if {$i >= [llength $argv]} { error "missing value after --httpport" } set default_ports(http) [parse_port_value --httpport [lindex $argv $i]] } --httpsport { incr i if {$i >= [llength $argv]} { error "missing value after --httpsport" } set default_ports(https) [parse_port_value --httpsport [lindex $argv $i]] } --ftpport { incr i if {$i >= [llength $argv]} { error "missing value after --ftpport" } set default_ports(ftp) [parse_port_value --ftpport [lindex $argv $i]] } --proxyport { incr i if {$i >= [llength $argv]} { error "missing value after --proxyport" } set default_ports(proxy) [parse_port_value --proxyport [lindex $argv $i]] } --startservers { incr i if {$i >= [llength $argv]} { error "missing value after --startservers" } set startservers [parse_startservers_value [lindex $argv $i]] } --certfile { incr i if {$i >= [llength $argv]} { error "missing value after --certfile" } set certfile [file normalize [lindex $argv $i]] } --keyfile { incr i if {$i >= [llength $argv]} { error "missing value after --keyfile" } set keyfile [file normalize [lindex $argv $i]] } --docroot { incr i if {$i >= [llength $argv]} { error "missing value after $arg" } set docroot [file normalize [lindex $argv $i]] if {$ftproot_follows_docroot} { set ftproot $docroot } } --ftproot { incr i if {$i >= [llength $argv]} { error "missing value after $arg" } set ftproot [file normalize [lindex $argv $i]] set ftproot_follows_docroot 0 } --keepdocroot { set keepdocroot 1 } --logfile { incr i if {$i >= [llength $argv]} { error "missing value after --logfile" } set logfile [file normalize [lindex $argv $i]] } --service { incr i if {$i >= [llength $argv]} { error "missing value after --service" } if {!$custom_services} { set services {} set custom_services 1 } lappend services [parse_service_spec [lindex $argv $i]] } --quiet { set quiet 1 } --debug { set debug 1 } --help { usage exit 0 } default { error "unknown argument: $arg" } } } if {!$custom_services} { set services {} foreach protocol $startservers { lappend services [dict create protocol $protocol port $default_ports($protocol)] } } else { set filtered_services {} foreach service_spec $services { if {[dict get $service_spec protocol] in $startservers} { lappend filtered_services $service_spec } } set services $filtered_services } return [dict create host $host quiet $quiet debug $debug \ docroot $docroot ftproot $ftproot \ certfile $certfile keyfile $keyfile \ keepdocroot $keepdocroot logfile $logfile \ services $services startservers $startservers] } proc ::tclcurl::testserver::configure_roots {config} { set docroot [dict get $config docroot] set ftproot [dict get $config ftproot] file mkdir $docroot file mkdir $ftproot ::tclcurl::test::set_doc_root $docroot ::tclcurl::test::set_ftp_root $ftproot seed_doc_root $docroot } proc ::tclcurl::testserver::configure_https_credentials {config} { set certfile [dict get $config certfile] set keyfile [dict get $config keyfile] if {$certfile ne {}} { ::tclcurl::test::set_https_cert_file $certfile } if {$keyfile ne {}} { ::tclcurl::test::set_https_key_file $keyfile } } proc ::tclcurl::testserver::manual_html_source {} { set repo_root [::tclcurl::test::repo_root] foreach candidate [list \ [file join $repo_root doc tclcurl.n.html] \ [file join $repo_root doc tclcurl.html]] { if {[file exists $candidate]} { return $candidate } } return {} } proc ::tclcurl::testserver::manual_html_files {} { set repo_root [::tclcurl::test::repo_root] set manuals {} foreach name [list tclcurl.html tclcurl_multi.html tclcurl_share.html] { set source_path [file join $repo_root doc $name] if {[file exists $source_path]} { dict set manuals $name $source_path } } return $manuals } proc ::tclcurl::testserver::seed_doc_root {docroot} { set index_source [file join [::tclcurl::test::repo_root] testservers index.html] set index_target [file join $docroot index.html] if {[file exists $index_source] && ![file exists $index_target]} { file copy $index_source $index_target } dict for {target_name source_path} [manual_html_files] { set target_path [file join $docroot $target_name] if {![file exists $target_path]} { file copy $source_path $target_path } } set manual_source [manual_html_source] if {$manual_source eq {}} { return } set manual_target [file join $docroot tclcurl-man.html] if {![file exists $manual_target]} { file copy $manual_source $manual_target } } proc ::tclcurl::testserver::cleanup_doc_root {config} { if {[dict get $config keepdocroot]} { return } set docroot [dict get $config docroot] if {$docroot eq {} || ![file exists $docroot]} { return } catch {file delete -force $docroot} } proc ::tclcurl::testserver::create_service {protocol host port quiet logfile} { variable next_service_id set class_name [service_class $protocol] set object_name ::tclcurl::testserver::service[incr next_service_id] return [$class_name create $object_name \ -protocol $protocol \ -host $host \ -port $port \ -quiet $quiet \ -logfile $logfile] } proc ::tclcurl::testserver::start_services {config} { set host [dict get $config host] set quiet [dict get $config quiet] set logfile [dict get $config logfile] set instances {} foreach service_spec [dict get $config services] { set protocol [dict get $service_spec protocol] set port [dict get $service_spec port] set service [create_service $protocol $host $port $quiet $logfile] $service start lappend instances $service } return $instances } proc ::tclcurl::testserver::stop_services {services} { foreach service $services { catch {$service destroy} } } proc ::tclcurl::testserver::run {argv} { set config [parse_args $argv] ::tclcurl::test::configure_debug_output [dict get $config debug] configure_roots $config configure_https_credentials $config start_logfile $config set services [start_services $config] try { vwait ::tclcurl::testserver::forever } finally { stop_services $services stop_logfile cleanup_doc_root $config } } proc ::tclcurl::testserver::command_map {} { return [dict create \ cleanup_doc_root ::tclcurl::testserver::cleanup_doc_root \ configure_https_credentials ::tclcurl::testserver::configure_https_credentials \ configure_roots ::tclcurl::testserver::configure_roots \ create_service ::tclcurl::testserver::create_service \ log_value ::tclcurl::testserver::log_value \ manual_html_files ::tclcurl::testserver::manual_html_files \ manual_html_source ::tclcurl::testserver::manual_html_source \ parse_args ::tclcurl::testserver::parse_args \ parse_service_spec ::tclcurl::testserver::parse_service_spec \ register_service_class ::tclcurl::testserver::register_service_class \ run ::tclcurl::testserver::run \ seed_doc_root ::tclcurl::testserver::seed_doc_root \ service_class ::tclcurl::testserver::service_class \ start_services ::tclcurl::testserver::start_services \ start_logfile ::tclcurl::testserver::start_logfile \ stop_services ::tclcurl::testserver::stop_services \ stop_logfile ::tclcurl::testserver::stop_logfile \ timestamp ::tclcurl::testserver::timestamp \ write_log_line ::tclcurl::testserver::write_log_line \ usage ::tclcurl::testserver::usage] } namespace ensemble create -command ::tclcurl::testserver -map [::tclcurl::testserver::command_map] source [file join [file dirname [file normalize [info script]]] http_endpoint.tcl] source [file join [file dirname [file normalize [info script]]] http_server.tcl] source [file join [file dirname [file normalize [info script]]] https_server.tcl] source [file join [file dirname [file normalize [info script]]] ftp_server.tcl] source [file join [file dirname [file normalize [info script]]] proxy_server.tcl] if {[file normalize $argv0] eq [file normalize [info script]]} { if {[catch {::tclcurl::testserver::run $argv} message]} { puts stderr $message ::tclcurl::testserver::usage exit 1 } puts stderr "Server exits..." } tclcurl-ng-8.0.3/win/000077500000000000000000000000001522613063100143705ustar00rootroot00000000000000tclcurl-ng-8.0.3/win/makefile.vc000066400000000000000000000047321522613063100165050ustar00rootroot00000000000000#------------------------------------------------------------- -*- makefile -*- # # Makefile for TclCurl # # Example build: # nmake /f makefile.vc INSTALLDIR=d:\tcl\debug\x64 CURLDIR=D:\src\curl-7.74.0\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-schannel CURLDEPSDIR=D:\src\curl-7.74.0\deps\x64 # nmake /f makefile.vc INSTALLDIR=d:\tcl\debug\x64 CURLDIR=D:\src\curl-7.74.0\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-schannel CURLDEPSDIR=D:\src\curl-7.74.0\deps\x64 install # # For other build options (debug, static etc.), # See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for # detailed documentation. # # # This makefile assumes static linking to the curl libraries #------------------------------------------------------------------------------ PROJECT = TclCurl !if "$(CURLDIR)" == "" !error Please define CURLDIR on command line to point to CURL distribution containing lib and include dirs. !endif # Curl dependencies directory. !if "$(CURLDEPSDIR)" == "" !error Please define CURLDEPDIR on command line to point to CURL dependencies containing lib and include dirs. !endif # Make package version same as Curl version for now !if [echo DOTVERSION = \> nmakehlp.out] \ || [for /f "tokens=3" %i in ('findstr /C:"define LIBCURL_VERSION " $(CURLDIR)\include\curl\curlver.h') do @echo %i >> nmakehlp.out] !error *** Could not retrieve PACKAGE_VERSION from Curl. !endif !include nmakehlp.out # Some Curls (from vcpkg e.g.) have -DEV in the middle of the version # string (eyeroll)). Remove it. DOTVERSION=$(DOTVERSION:-DEV=) # Remove the quotes from DOTVERSION DOTVERSION=$(DOTVERSION:"=) # " - Fix for Emacs highlighting to match quotes above # Script files (LIBDIR) are in same location as C generic files # NOTE: define this BEFORE including rules-ext.vc LIBDIR = $(GENERICDIR) !include "rules-ext.vc" PRJ_OBJS = \ $(TMP_DIR)\tclcurl.obj \ $(TMP_DIR)\multi.obj PRJ_DEFINES = -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE PRJ_INCLUDES = $(PRJ_INCLUDES) -I"$(CURLDIR)\include" -I"$(CURLDEPSDIR)\include" PRJ_LIBS = $(PRJ_LIBS) "$(CURLDIR)\lib\libcurl.lib" "$(CURLDEPSDIR)\lib\zlib.lib" ws2_32.lib crypt32.lib wldap32.lib Normaliz.lib !include "$(_RULESDIR)\targets.vc" install: default-install-docs-html default-install-libraries pkgindex: @type << >"$(OUT_DIR)\pkgIndex.tcl" package ifneeded $(PROJECT) $(DOTVERSION) "[list load [file join $$dir $(PRJLIBNAME)] TclCurl]; [list source [file join $$dir tclcurl.tcl]]" << tclcurl-ng-8.0.3/win/rules-ext.vc000066400000000000000000000071261522613063100166600ustar00rootroot00000000000000# This file should only be included in makefiles for Tcl extensions, # NOT in the makefile for Tcl itself. !ifndef _RULES_EXT_VC # We need to run from the directory the parent makefile is located in. # nmake does not tell us what makefile was used to invoke it so parent # makefile has to set the MAKEFILEVC macro or we just make a guess and # warn if we think that is not the case. !if "$(MAKEFILEVC)" == "" !if exist("$(PROJECT).vc") MAKEFILEVC = $(PROJECT).vc !elseif exist("makefile.vc") MAKEFILEVC = makefile.vc !endif !endif # "$(MAKEFILEVC)" == "" !if !exist("$(MAKEFILEVC)") MSG = ^ You must run nmake from the directory containing the project makefile.^ If you are doing that and getting this message, set the MAKEFILEVC^ macro to the name of the project makefile. !message WARNING: $(MSG) !endif !if "$(PROJECT)" == "tcl" !error The rules-ext.vc file is not intended for Tcl itself. !endif # We extract version numbers using the nmakehlp program. For now use # the local copy of nmakehlp. Once we locate Tcl, we will use that # one if it is newer. !if [$(CC) -nologo "nmakehlp.c" -link -subsystem:console > nul] !endif # First locate the Tcl directory that we are working with. !if "$(TCLDIR)" != "" _RULESDIR = $(TCLDIR:/=\) !else # If an installation path is specified, that is also the Tcl directory. # Also Tk never builds against an installed Tcl, it needs Tcl sources !if defined(INSTALLDIR) && "$(PROJECT)" != "tk" _RULESDIR=$(INSTALLDIR:/=\) !else # Locate Tcl sources !if [echo _RULESDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] _RULESDIR = ..\..\tcl !else !include nmakehlp.out !endif !endif # defined(INSTALLDIR).... !endif # ifndef TCLDIR # Now look for the targets.vc file under the Tcl root. Note we check this # file and not rules.vc because the latter also exists on older systems. !if exist("$(_RULESDIR)\lib\nmake\targets.vc") # Building against installed Tcl _RULESDIR = $(_RULESDIR)\lib\nmake !elseif exist("$(_RULESDIR)\win\targets.vc") # Building against Tcl sources _RULESDIR = $(_RULESDIR)\win !else # If we have not located Tcl's targets file, most likely we are compiling # against an older version of Tcl and so must use our own support files. _RULESDIR = . !endif !if "$(_RULESDIR)" != "." # Potentially using Tcl's support files. If this extension has its own # nmake support files, need to compare the versions and pick newer. !if exist("rules.vc") # The extension has its own copy !if [echo TCL_RULES_MAJOR = \> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo TCL_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !if [echo OUR_RULES_MAJOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo OUR_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !include versions.vc # We have a newer version of the support files, use them !if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR)) _RULESDIR = . !endif !endif # if exist("rules.vc") !endif # if $(_RULESDIR) != "." # Let rules.vc know what copy of nmakehlp.c to use. NMAKEHLPC = $(_RULESDIR)\nmakehlp.c # Get rid of our internal defines before calling rules.vc !undef TCL_RULES_MAJOR !undef TCL_RULES_MINOR !undef OUR_RULES_MAJOR !undef OUR_RULES_MINOR !if exist("$(_RULESDIR)\rules.vc") !message *** Using $(_RULESDIR)\rules.vc !include "$(_RULESDIR)\rules.vc" !else !error *** Could not locate rules.vc in $(_RULESDIR) !endif !endif # _RULES_EXT_VC