pax_global_header00006660000000000000000000000064151726427200014520gustar00rootroot0000000000000052 comment=f053a7e3dd636b7321a884f2416bfa9082987702 tclcurl-ng-8.0.1/000077500000000000000000000000001517264272000136005ustar00rootroot00000000000000tclcurl-ng-8.0.1/.github/000077500000000000000000000000001517264272000151405ustar00rootroot00000000000000tclcurl-ng-8.0.1/.github/workflows/000077500000000000000000000000001517264272000171755ustar00rootroot00000000000000tclcurl-ng-8.0.1/.github/workflows/linux-ci.yml000066400000000000000000000017431517264272000214550ustar00rootroot00000000000000# 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.1/.github/workflows/mac-ci.yml000066400000000000000000000010721517264272000210510ustar00rootroot00000000000000name: 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.1/.github/workflows/windows-ci.yml000066400000000000000000000036431517264272000220110ustar00rootroot00000000000000name: 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.1/.gitignore000066400000000000000000000002251517264272000155670ustar00rootroot00000000000000*~ config.h* Makefile config.log config.status libTclCurl*.so libtcl9TclCurl*.so *.o pkgIndex.tcl tags *.swp autom4te.cache .gdb_history tests/certs tclcurl-ng-8.0.1/ChangeLog000077500000000000000000001057751517264272000153740ustar00rootroot000000000000002026-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.1/Changes.txt000077500000000000000000001026771517264272000157310ustar00rootroot00000000000000Version 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 transfered by ftp, it should match the following prototype: ChunkBgnProc {remains} Where remains is the number of files still to be transfered (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 transfered (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 transfered. 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 cheksum 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 conecction 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.1/Makefile.in000077500000000000000000000434021517264272000156530ustar00rootroot00000000000000# 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 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.n: doc/tclcurl.n.md @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 @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 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.1/README.md000077500000000000000000000074251517264272000150720ustar00rootroot00000000000000# 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 the contitued as independed development effort since the upstream maintainers apparently stopped accepting or reacting to PR. 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 version of libcurl discontinued support for them 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. ## 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 set curlHandle [curl::init] $curlHandle perform $curlHandle getinfo curlinfo_option $curlHandle duphandle $curlHandle cleanup curl::transfer curl::version curl::escape $url curl::unescape $url curl::curlConfig option 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) ## License BSD like license, check 'license.terms' for details. tclcurl-ng-8.0.1/ReadMeW32.txt000077500000000000000000000073411517264272000160020ustar00rootroot00000000000000To 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.1/VERSION000066400000000000000000000000061517264272000146440ustar00rootroot000000000000008.0.1 tclcurl-ng-8.0.1/aclocal.m4000077500000000000000000000002231517264272000154400ustar00rootroot00000000000000# # 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.1/checkAutoPath.tcl000077500000000000000000000007111517264272000170310ustar00rootroot00000000000000# 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.1/configure000077500000000000000000011201271517264272000155130ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for TclCurl 8.0.1. # # 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.1' PACKAGE_STRING='TclCurl 8.0.1' 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.1 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.1:";; 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.1 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.1, 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 doc/tclcurl.n.md doc/tclcurl_share.n" 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.1, 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.1 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" ;; "doc/tclcurl.n.md") CONFIG_FILES="$CONFIG_FILES doc/tclcurl.n.md" ;; "doc/tclcurl_share.n") CONFIG_FILES="$CONFIG_FILES doc/tclcurl_share.n" ;; *) 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.1/configure.ac000066400000000000000000000361331517264272000160740ustar00rootroot00000000000000#!/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 doc/tclcurl.n.md doc/tclcurl_share.n]) AC_OUTPUT tclcurl-ng-8.0.1/doc/000077500000000000000000000000001517264272000143455ustar00rootroot00000000000000tclcurl-ng-8.0.1/doc/OpenSSL-LICENSE.txt000066400000000000000000000142071517264272000174550ustar00rootroot00000000000000 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.1/doc/aolserver.txt000066400000000000000000000050021517264272000171050ustar00rootroot00000000000000There 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.1/doc/tclcurl.html000066400000000000000000003324651517264272000167200ustar00rootroot00000000000000 TclCurl

NAME

TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.

SYNOPSIS

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

DESCRIPTION

The TclCurl extension gives Tcl programmers access to the libcurl library written by Daniel Stenberg, with it you can download urls, upload them and many other neat tricks, for more information check http://curl.haxx.se

curl::init

This procedure must be the first one to call, it returns a curlHandle that you need to use to invoke TclCurl procedures. The init calls intializes curl and this call MUST have a corresponding call to cleanup when the operation is completed. You should perform all your sequential file transfers using the same curlHandle. This enables TclCurl to use persistent connections when possible.

RETURN VALUE

curlHandle to use.

curlHandle configure ?options?

configure

is called to set the options for the transfer. Most operations in TclCurl have default actions, and by using the appropriate options you can make them behave differently (as documented). All options are set with the option followed by a parameter.

Notes:

the options set with this procedure are valid for the forthcoming data transfers that are 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 return code from the curl::init call.

OPTIONS

Behaviour options

-verbose

Set the parameter to 1 to get the library to display a lot of verbose information about its operations. Very useful for libcurl and/or protocol debugging and understanding.

You hardly ever want this set in production use, you will almost always want this when you debug/report problems. Another neat option for debugging is

-debugproc

-header

A 1 tells the extension to include the headers in the body output. This is only relevant for protocols that actually have headers preceding the data (like HTTP).

-noprogress

A 1 tells the extension to turn on the progress meter completely. It will also prevent the progessproc from getting called.

-nosignal

A 1 tells TclCurl not use any functions that install signal handlers or any functions that cause signals to be sent to the process. This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals.

If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals.

Setting nosignal to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire. In addition, using ntlm_Wb authentication could cause a SIGCHLD signal to be raised.

-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 option, using an fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name).

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

This feature is only supported by the FTP download for now.

A brief introduction of its syntax follows:

  • * - ASTERISK

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

Question mark matches any (exactly one) 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

Use it to set a Tcl procedure that will be invoked by TclCurl as soon as there is received data that needs to be saved. The procedure will receive a single parameter with the data to be saved.

NOTE: you will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be nothing if the file is empty or it may be thousands of bytes.

-file

File in which the transfered data will be saved.

-readproc

Sets a Tcl procedure to be called by TclCurl as soon as it needs to read data in order to send it to the peer. The procedure has to take one parameter, which will contain the maximun numbers 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 “pre-maturely” (i.e before the server expected it, like when you’ve said you will upload N bytes and you upload less than N bytes), you may experience that the server “hangs” waiting for the rest of the data that won’t come.

Bugs: when doing TFTP uploads, you must return the exact amount of data that the callback wants, or it will be considered the final packet by the server end and the transfer will end there.

-infile

File from which the data will be transfered.

-progressproc

Name of the Tcl procedure that will invoked by TclCurl with a frequent interval during operation (roughly once per second or sooner), no matter if data is being transfered or not. Unknown/unused argument values passed to the callback will be set to zero (like if you only download data, the upload size will remain 0), the prototype of the procedure must be:

proc ProgressCallback {dltotal dlnow ultotal ulnow}

In order to this option to work you have to set the noprogress option to ‘0’. Setting this option to the empty string will restore 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 a the file name to be used to write the header part of the received data to. The headers are guaranteed to be written one-by-one to this file and only complete lines are written. Parsing headers should be easy enough using this.

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

-debugproc

Name of the procedure that will receive the debug data produced by the -verbose option, it should match the following prototype:

debugProc {infoType data}

where infoType specifies what kind of information it is (0 text, 1 incoming header, 2 outgoing header, 3 incoming data, 4 outgoing data, 5 incoming SSL data, 6 outgoing SSL data).

-chunkbgnproc

Name of the procedure that will be called before a file will be transfered by ftp, it should match the following prototype:

ChunkBgnProc {remains}

Where remains is the number of files left to be transfered (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 of the file about to be transfered. 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.

-chunkendproc

Name of the procedure that will be called after a file is transfered (or skipped) by ftp, it should match the following prototype:

ChunkEndProc {}

It should return ‘0’ if everyhting is fine and ‘1’ if some error occurred.

-fnmatchProc

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.

Error Options

-errorbuffer

Pass a variable name where TclCurl may store human readable error messages in. This may be more helpful than just the return code from the command.

-stderr

Pass a file name as parameter. This is the stream to use internally instead of stderr when reporting errors.

-failonerror

A 1 parameter tells the extension to fail silently if the HTTP code returned is equal or larger than 400. The default action would be to return the page normally, ignoring that code.

This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407).

You might get some amounts of headers transferred before this situation is detected, like for when a “100-continue” is received as a response to a POST/PUT and a 401 or 407 is received immediately afterwards.

Network options

-url

The actual URL to deal with.

If the given URL lacks the protocol part (“ or “ftp://” etc), it will attempt to guess which protocol to use based on the given host name. If the given protocol of the set URL is not supported, TclCurl will return the unsupported protocol error when you call perform. Use curl::versioninfo for detailed info on which protocols are supported.

Starting with version 7.22.0, the fragment part of the URI will not be send as part of the path, which was the case previously.

NOTE: this is the one option required to be set before perform is called.

-protocols

Pass a list in lowecase of protocols to limit what protocols TclCurl may use in the transfer. This allows you to have a TclCurl built to support a wide range of protocols but still limit specific transfers to only be allowed to use 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 list in lowercase of accepted protocols to limit what protocols TclCurl may use in a transfer that it follows to in a redirect when -followlocation is enabled. This allows you to limit specific transfers to only be allowed to use a subset of protocols in redirections.

By default TclCurl will allow all protocols except for FILE and SCP. This is a difference compared to pre-7.19.4 versions which unconditionally would follow to all protocols supported.

-proxy

If you need to use a http proxy to access the outside world, set the proxy string with this option. To specify port number in this string, append :[port] to the end of the host name. The proxy string may be prefixed with [protocol]:// since any such prefix will be ignored.

When you tell the extension to use a HTTP proxy, TclCurl will transparently convert operations to HTTP even if you specify a FTP URL etc. This may have an impact on what other features of the library you can use, such as quote and similar FTP specifics that will not work unless you tunnel through the HTTP proxy. Such tunneling is activated with proxytunnel.

TclCurl respects the environment variables httpproxy, ftpproxy, all_proxy etc, if any of those are set. The use of this option does however override any possibly set environment variables.

Setting the proxy string to ““ (an empty string) will explicitly disable the use of a proxy, even if there is an environment variable set for it.

The proxy host string can be specified the exact same way as the proxy environment variables, include protocol prefix (http://) and embedded user + password.

Since 7.22.0, the proxy string may be specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or socks5h:// (the last one to enable socks5 and asking the proxy to do the resolving) to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be treated as HTTP proxies.

-proxyport

Use this option to set the proxy port to use unless it is specified in the proxy string by -proxy. If not specified, TclCurl will default to using port 1080 for proxies.

-proxytype

Pass the type of the proxy. Available options are ‘http’, ‘http1.0’, ‘socks4’, ‘socks4a’, ‘socks5’ and ‘socks5h’, with the HTTP one being the default.

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 “regular” HTTP requests is instead controled with httpversion.

-noproxy

Pass a string, a comma-separated list of hosts which do 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 as either a domain which contains the hostname, or the hostname itself. For example, local.com would match local.com, local.com:80, and http://www.local.com, but not http://www.notlocal.com.

-httpproxytunnel

Set the parameter to 1 to get the extension to tunnel all non-HTTP operations through the given HTTP proxy. Do note that there is a big difference between using a proxy and tunneling through it. If you don’t know what this means, you probably don’t want this tunnel option.

-socks5gssapiservice

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

-socks5gssapinec

Pass a 1 to enable or 0 to disable. As part of the gssapi negotiation a protection mode is negotiated. The rfc1961 says in section 4.3/4.4 it should be protected, but the NEC reference implementation does not. If enabled, this option allows the unprotected exchange of the protection mode negotiation.

-interface

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

-localport

This sets the local port number of the socket used for connection. This can be used in combination with -interface and you are recommended to use localportrange as well when this is set. Valid port numbers are 1 - 65535.

-localportrange

This is the 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. Setting this value to 1 or below will make TclCurl do only one try for each port number. Port numbers by nature are a scarce resource that will be busy at times so setting this value to something too low might cause unnecessary connection setup failures.

-dnscachetimeout

Pass the timeout in seconds. Name resolves will be kept in memory for this number of seconds. Set to ‘0’ to completely disable caching, or ‘-1’ to make the cached entries remain forever. By default, TclCurl caches this info for 60 seconds.

The name resolve functions of various libc implementations don’t re-read name server information unless explicitly told so (for example, by calling res_init(3)). This may cause TclCurl to keep using the older server even if DHCP has updated the server info, and this may look like a DNS cache issue.

-dnsuseglobalcache

If the value passed is 1, it tells TclCurl to use a global DNS cache that will survive between curl handles creations and deletions. This is not thread-safe as it uses a global varible. This option was deprecated in libcurl v7.11.1 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option

WARNING: this option is considered obsolete. Stop using it. Switch over to using the share interface instead! See tclcurl_share.

-buffersize

Pass your preferred size for the receive buffer in TclCurl. The main point of this would be that the write callback gets called more often and with smaller chunks. This is just treated as a request, not an order. You cannot be guaranteed to actually get the given size.

-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

Pass a number to specify whether the TCP_NODELAY option should be set or cleared (1 = set, 0 = clear). The option is cleared by default. This will have 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

A 1 parameter tells the extension to scan your ~/.netrc file to find user name and password for the remote site you are about to access. Do note that TclCurl does not verify that the file has the correct properties set (as the standard unix ftp client does), and that only machine name, user name and password is taken into account (init macros and similar things are not supported).

You can set it to the following values:

optional
The use of your ~/.netrc file is optional, and information in the URL is to be preferred. The file will be scanned with the host and user name (to find the password only) or with the host only, to find the first user name and password after that machine, which ever information is not specified in the URL.

Undefined values of the option will have this effect.

ignored
The extension will ignore the file and use only the information in the URL. This is the default.
required
This value tells the library that use of the file is required, to ignore the information in the URL, and to search the file with the host only.
-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.

-userpwd

Pass a string as parameter, which should be [username]:[password] to use for the connection. Use -httpauth to decide authentication method.

When using NTLM, you can set domain by prepending it to the user name and separating the domain and name with a forward (/) or backward slash (\). Like this: “domain/user:password” or “domain\user:password”. Some HTTP servers (on Windows) support this style even 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 as parameter, which should be [username]:[password] to use for the connection to the HTTP proxy.

-username

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

In order to specify the password to be used in conjunction with the user name use the -password option.

-password

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

It should be used in conjunction with the -username option.

-proxyusername

Pass a string with the user name to use for the transfer while connecting to Proxy.

It should be used in same way as the -proxyuserpwd is used, except that it allows the username to contain a colon, like in the following example: “sip:user@example.com”.

Note the -proxyusername option is an alternative way to set the user name while connecting to Proxy. It doesn’t make sense to use them together.

-proxypassword

Pass a string with the password to use for the transfer while connecting to Proxy. It is meant to use together with -proxyusername.

-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.
digestie
HTTP Digest authentication with an IE flavor. TclCurl will use a special “quirk” that IE is known to have used before version 7 and that some servers require the client to use.
gssnegotiate
HTTP GSS-Negotiate authentication. The GSS-Negotiate method, also known as plain “Negotiate”,was designed by Microsoft and is used in their web applications. It is primarily meant as a support for Kerberos5 authentication but may be also used along with another authentication methods.
ntlm
HTTP NTLM authentication. A proprietary protocol invented and used by Microsoft. It uses a challenge-response and hash concept similar to Digest, to prevent the password from being eavesdropped.
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.

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 will automatically select the one it finds most secure.
anysafe
It may use anything but basic, TclCurl will automatically select the one it finds most secure.
-tlsauthtype

Use it to tell TclCurl which authentication method(s) you want it to use for TLS authentication.

tlsauthsrp
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. To use TLS-SRP, you must also set the -tlsauthusername and -tlsauthpassword options.

You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this to work.

-tlsauthusername

Pass a string with the username to use for the TLS authentication method specified with the -tlsauthtype option. Requires that the -tlsauthpassword option also be set.

-tlsauthpassword

Pass a string with the password to use for the TLS authentication method specified with the -tlsauthtype option. Requires that the -tlsauthusername option also be set.

-proxyauth

Use it to tell TclCurl which authentication method(s) you want it to use for your proxy authentication. Note that for some methods, this will induce an extra network round-trip. Set the actual name and password with the proxyuserpwd option.

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

HTTP options

-autoreferer

Pass an 1 parameter to enable this. When enabled, TclCurl will automatically set the Referer: field in requests where it 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. Three encodings are supported: identity, which does nothing, deflate which requests the server to compress its response using the zlib algorithm, and gzip which requests the gzip algorithm. Use all to send an Accept-Encoding: header containing all supported encodings.

This is a request, not an order; the server may or may not do it. This option must be set or else any unsolicited encoding done by the server is ignored. See the special file lib/README.encoding in libcurl docs for details.

-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 response 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.

-followlocation

An 1 tells the library to follow any

Location: header

that the server sends as part of a HTTP header.

This means that the extension will re-send the same request on the new location and follow new Location: headers all the way until no more such headers are returned. -maxredirs can be used to limit the number of redirects TclCurl will follow.

Since 7.19.4, TclCurl can limit what protocols it will automatically follow. The accepted protocols are set with -redirprotocols and it excludes the FILE protocol by default.

-unrestrictedauth

An 1 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.

-maxredirs

Sets the redirection limit. If that many redirections have been followed, the next redirect will cause an error. This option only makes sense if the -followlocation option is used at the same time. Setting the limit to 0 will make libcurl refuse any redirect. Set it to -1 for an infinite number of redirects (which is the default)

-postredir

Controls how TclCurl acts on redirects after POSTs that get a 301, 302 or 303 response back. A “301” parameter tells TclCurl to keep POST requests as POST when following a 301 redirect. Passing a “302” makes TclCurl maintain the request method after a 302 redirect, while “303” does the same for a 303 redirect. “all” is a convenience string that activates all three behaviours.

The non-RFC behaviour is ubiquitous in web browsers, so the extension does the 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 setting -followlocation

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

-put

An 1 parameter tells the extension to use HTTP PUT a file. The file to put must be set with -infile and -infilesize.

This option is deprecated starting with version 0.12.1, you should 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

An 1 parameter tells the library to do a regular HTTP post. This is a normal application/x-www-form-urlencoded kind, which is the most commonly used one by HTML forms. See the -postfields option for how to specify the data to post and -postfieldsize about how to set the data size.

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

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 a “Expect: 100-continue” header. You can disable this header with -httpheader as usual.

If you use POST to a HTTP 1.1 server, you can send data without knowing the size before starting the POST 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 in the request.

When setting post to an 1 value, it will automatically set nobody to 0.

NOTE: if you have issued a POST request and want to make a HEAD or GET instead, you must explicitly pick the new request type using -nobody or -httpget or similar.

-postfields

Pass a string as parameter, which should be the full data to post in a HTTP POST operation. You must make sure that the data is formatted the way you want the server to receive it. TclCurl will not convert or encode it for you. Most web servers will assume this data to be url-encoded.

This is a normal application/x-www-form-urlencoded kind, 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, as simply setting -postfields to NULL or ““ just effectively disables the sending of the specified string. TclCurl will instead assume that the POST data will be sent using the read callback!

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

Note: to make multipart/formdata posts (aka rfc1867-posts), check out -httppost option.

-postfieldsize

If you want to post data to the server without letting TclCurl do a strlen() to measure the data size, this option must be used. Also, when this option is used, you can post fully binary data which otherwise is likely to fail. If this size is set to zero, the library will use strlen() to get the data size.

-httppost

Tells TclCurl you want a multipart/formdata HTTP POST to be made and you instruct what data to pass on to the server through a Tcl list.

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

First, there are some basics you need to understand about multipart/formdata posts. Each part consists of at least a NAME and a CONTENTS part. If the part is made for file upload, there are also a stored CONTENT-TYPE and a FILENAME. Below, we’ll discuss which options set these properties in the parts you want to add to your post.

The list must contain a ‘name’ tag with the name of the section followed by a string with the name, there are three tags to indicate the value of the section: ‘value’ followed by a string with the data to post, ‘file’ followed by the name of the file to post and ‘contenttype’ with the type of the data (text/plain, image/jpg, …), you can also indicate a false file name with ‘filename’, this is useful in case the server checks if the given file name is valid, for example, by testing if it starts with ‘c:\’ as any real file name does or if you want to include the full path of the file to post. You can also post the content of a variable as if it were a file with the options ‘bufferName’ and ‘buffer’ or use ‘filecontent’ followed by a file name to read that file and use the contents as data.

Should you need to specify extra headers for the form POST section, use ‘contentheader’ followed by a list with the headers to post.

Please see ‘httpPost.tcl’ and ‘httpBufferPost.tcl’ for examples.

If TclCurl can’t set the data to post an error will be returned:

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 the some form info is not complete (or error)
6
If an illegal option is used in an array.
7
TclCurl has no http support.
-referer

Pass a string as parameter. It will be used to set the referer header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with -httpheader.

-useragent

Pass a string as parameter. It will be used to set the user-agent: header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with -httpheader.

-httpheader

Pass a list with the HTTP headers to pass to the server in your request. If you add a header that is otherwise generated and used by TclCurl internally, your added one will be used instead. If you add a header with no contents as in ‘Accept:’, the internally used header will just get disabled. Thus, using this option you can add new headers, replace and remove internal headers.

The headers included in the linked list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. Failure to comply with this will result in strange bugs because the server will most likely ignore part of the headers you specified.

The first line in a request (containing the method, usually a GET or POST) is not a header and cannot be replaced using this option. Only the lines following the request-line are headers. Adding this method line in this list of headers will only cause your request to send an invalid header.

NOTE: The most commonly replaced headers have “shortcuts” in the options: cookie, useragent, and referer.

-http200aliases

Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers respond with a custom header response line. For example, IceCast servers respond with “ICY 200 OK”. By including this string in your list of aliases, the response will be treated as a valid HTTP header line such as “HTTP/1.0 200 OK”.

NOTE:The alias itself is not parsed for any version strings. Before version 7.16.3, TclCurl used the value set by option httpversion, but starting with 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matched.

-cookie

Pass a string as parameter. It will be used to set a cookie in the http request. The format of the string should be ‘[NAME]=[CONTENTS];’. Where NAME is the cookie name and CONTENTS is what the cookie should contain.

If you need to set mulitple cookies, you need to set them all using a single option and thus you need to concatenate them all in one single string. Set multiple cookies in one string like this: “name1=content1; name2=content2;” etc.

This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are done due to authentication, followed redirections or similar, they will all get this cookie passed on.

Using this option multiple times will only make the latest string override the previous ones.

-cookiefile

Pass a string as parameter. It should contain the name of your file holding cookie data. The cookie data may be in netscape cookie data format or just regular HTTP-style headers dumped to a file.

Given an empty or non-existing file, this option will enable cookies for this curl handle, making it understand and parse received cookies and then use matching cookies in future requests.

If you use this option multiple times, you add more files to read.

-cookiejar

Pass a file name in which TclCurl will dump all internally known cookies when curlHandle cleanup is called. If no cookies are known, no file will be created. Specify “-” to have the cookies written to stdout.

Using this option also enables cookies for this session, so if you, for example, follow a location it will make matching cookies get sent accordingly.

TclCurl will not and cannot report an error for this. Using ‘verbose’ will get a warning to display, but that is the only visible feedback you get about this possibly lethal situation.

-cookiesession

Pass an 1 to mark this as a new cookie “session”. It will force TclCurl to ignore all cookies it is about to load that are “session cookies” from the previous session. By default, TclCurl always stores and loads all cookies, independent of whether they are session cookies are not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this “session” only.

-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. If the cookie engine was not enabled it will be enabled. Passing a magic string “ALL” will erase all known cookies while “FLUSH” will write all cookies known by TclCurl to the file specified by -cookiejar.

-httpget

If set to 1 forces the HTTP request to get back to GET, usable if POST, PUT or a custom request have been used previously with the same handle.

When setting httpget to 1, nobody will automatically be set to 0.

-httpversion

Set to one of the values decribed below, they force TclCurl to use the specific http versions. It should only be used if you really MUST do that because of a silly remote server.

none
We do not care about what version the library uses. TclCurl will use whatever it thinks fit.
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.
2PRIORKNOWLEDGE
Enforce HTTP 2 requests without performing HTTP/1.1 Upgrade first.
-ignorecontentlength

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. If this option is used, TclCurl will not be able to accurately report progress, and will simply stop the download when the server ends the connection.

-httpcontentdecoding

Set to zero to disable content decoding. If set to 1 it is enabled. Note however that TclCurl has no default content decoding but requires you to use encoding for that.

-httptransferencoding

Set to zero to disable transfer decoding, if set to 1 it is enabled (default). TclCurl does chunked transfer decoding by default unless this option is set to zero.

SMTP options

-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.

Each recipient in SMTP lingo is specified with angle brackets (<>), but should you not use an angle bracket as first letter, TclCurl will assume you provide a single email address only and enclose that with angle brackets for you.

TFTP option

tftpblksize
Specify the block size to use for TFTP data transmission. Valid range as per RFC 2348 is 8-65464 bytes. The default of 512 bytes will be used if this option is not specified. The specified block size will only be used pending support by the remote server. If the server does not return an option acknowledgement or returns an option acknowledgement with no blksize, the default of 512 bytes will be used.

FTP options

-ftpport

Pass a string as parameter. It will be used to get the IP address to use for the ftp PORT instruction. The PORT instruction tells the remote server to connect to our specified IP address. The string may be a plain IP address, a host name, a network interface name (under unix) or just a ‘-’ to let the library use your systems default IP address. Default FTP operations are passive, and thus will not use PORT.

The address can be followed by a ‘:’ to specify a port, optionally followed by a ‘-’ o specify a port range. If the port specified is 0, the operating system will pick a free port. If a range is provided and all ports in the range are not available, libcurl will report CURLEFTPPORT_FAILED for the handle. Invalid port/range settings are ignored. IPv6 addresses followed by a port or portrange have to be in brackets. IPv6 addresses without port/range specifier can be in brackets.

Examples with specified ports:

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

You disable PORT again and go back to using the passive version by setting this option to an empty string.

-quote

Pass a list list with the FTP or SFTP commands to pass to the server prior to your ftp request. This will be done before any other FTP commands are issued (even before the CWD command).If you do not want to transfer any files, set nobody to ‘1’ and header to ‘0’.

Prefix the command with an asterisk (*) to make TclCurl continue even if the command fails as by default TclCurl will stop.

Disable this operation again by setting an empty string to this option.

Keep in mind the commands to send must be ‘raw’ ftp commands, for example, to create a directory you need to 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 with the FTP commands to pass to the server after your 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 pass to the server after the transfer type is set.

-dirlistonly

A 1 tells the library to just list the names of files in a directory, instead of doing a full directory listing that would include file sizes, dates etc. It works with both FTP and SFTP urls.

This causes an FTP NLST command to be sent. Beware that some FTP servers list only files in their response to NLST, they might not include subdirectories and symbolic links.

Setting this option to 1 also implies a directory listing even if the URL doesn’t end with a slash, which otherwise is necessary.

Do NOT use this option if you also use -wildcardmatch as it will effectively break that feature.

-append

A 1 parameter tells the extension to append to the remote file instead of overwriting it. This is only useful when uploading to a ftp site.

-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.

-ftpuseepvs

Set to one to tell TclCurl to use the EPSV command when doing passive FTP downloads (which it always does by default). Using EPSV means that it will first attempt to use EPSV before using PASV, but if you pass a zero to this option, it will not try using EPSV, only plain PASV.

-ftpusepret

Set to one to tell TclCurl to send a PRET command before PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard command for directory listings as well as up and downloads in PASV mode. Has no effect when using the active FTP transfers mode.

-ftpcreatemissingdirs

If set to 1, TclCurl will attempt to create any remote directory that it fails to CWD into. CWD is the command that changes working directory.

This setting also applies to SFTP-connections. TclCurl will attempt to create the remote directory if it can’t obtain a handle to the target-location. The creation will fail if a file of the same name as the directory to create already exists or lack of permissions prevents creation.

If set to 2, TclCurl will retry the CWD command again if the subsequent MKD command fails. This is especially useful if you’re doing many simultanoeus connections against the same server and they all have this option enabled, as then CWD may first fail but then another connection does MKD before this connection and thus MKD fails but trying CWD works

-ftpresponsetimeout

Causes TclCurl to set a timeout period (in seconds) 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. Note that while TclCurl is waiting for a response, this value overrides timeout. It is recommended that if used in conjunction with timeout, you set it to a value smaller than timeout.

-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.

-ftpskippasvip

If set to 1, 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.

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

-ftpsslauth

Pass TclCurl one of the values from below, to alter how TclCurl issues “AUTH TLS” or “AUTH SSL” when FTP over SSL is activated (see -ftpssl).

You may need this option because of servers like BSDFTPD-SSL from http://bsdftpd-ssl.sc.ru/ “which won’t work properly when “AUTH SSL” is issued (although the server responds fine and everything) but requires “AUTH TLS” instead.

default
Allows TclCurl to decide.
ssl
Try “AUTH SSL” first, and only if that fails try “AUTH TLS”.
tls
Try “AUTH TLS” first, and only if that fails try “AUTH SSL”.
-ftpsslccc

Set it to make TclCurl use CCC (Clear Command Channel). It shuts down the SSL/TLS layer after authenticating. The rest of the control channel communication will be unencrypted. This allows NAT routers to follow the FTP transaction. Possible values are:

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

Pass string (or ““ to disable). When an FTP server asks for “account data” after user name and password has been provided, this data is sent off using the ACCT command.

-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”. This is somewhat more standards compliant than ‘nocwd’ but without the full penalty of ‘multicwd’.

Protocol options

-transfertext

A 1 tells the extension to use ASCII mode for ftp transfers, instead of the default binary transfer. For win32 systems it does not set the stdout to binary mode. This option can be usable when transferring text data between systems with different views on certain characters, such as newlines or similar.

NOTE: TclCurl does not do a complete ASCII conversion when doing ASCII transfers over FTP. This is a known limitation/flaw that nobody has rectified. TclCurl simply sets the mode to ascii and performs a standard transfer.

-proxytransfermode

If set to 1, TclCurl sets 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 it being set to 0, the default, -transfertext has no effect when doing FTP via a proxy. Beware that not all proxies support this feature.

-crlf

If set to ‘1’, TclCurl converts Unix newlines to CRLF newlines on transfers. Disable this option again by setting the value to ‘0’.

-range

Pass a string as parameter, which should contain the specified range you want. It should be in the format “X-Y” , where X or Y may be left out. HTTP transfers also support several intervals, separated with commas as in “X-Y,N-M” Using this kind of multiple intervals will cause the HTTP server to send the response document in pieces (using standard MIME separation techniques).

Ranges only work on HTTP, FTP and FILE transfers.

-resumefrom

Pass the offset in number of bytes that you want the transfer to start from. Set this option to 0 to make the transfer start from the beginning (effectively disabling resume).

For FTP, set this option to -1 to make the transfer start from the end of the target file (useful to continue an interrupted upload).

When doing uploads with FTP, the resume position is where in the local/source file TclCurl should try to resume the upload from and it will then append the source file to the remote target file.

-customrequest

Pass a string as parameter. It will be used instead of GET or HEAD when doing the HTTP request. This is useful for doing DELETE or other more obscure HTTP requests. Do not do this at will, make sure your server supports the command first.

Note that TclCurl will still act and assume the keyword it would use if you do not set your custom and it will act according to that. Thus, changing this to a HEAD when TclCurl otherwise would do a GET might cause TclCurl to act funny, and similar. To switch to a proper HEAD, use -nobody, to switch to a proper POST, use -post or -postfields and so on.

-filetime

If you pass a 1, TclCurl will attempt to get the modification date of the remote document in this operation. This requires that the remote server sends the time or replies to a time querying command. The getinfo procedure with the filetime argument can be used after a transfer to extract the received time (if any).

-nobody

A 1 tells the library not to include the body-part in the output. This is only relevant for protocols that have a separate header and body part. On HTTP(S) servers, this will make TclCurl do a HEAD request.

To change request to GET, you should use httpget. Change request to POST with post etc.

-infilesize

When uploading a file to a remote site, this option should be used to tell TclCurl what the expected size of the infile is.

This option is mandatory for uploading using SCP.

-upload

A 1 tells the library to prepare for an upload. The -infile and -infilesize options are also interesting 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

This defines how the timevalue value is treated. You can set this parameter to ifmodsince or 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 you allow the TclCurl transfer operation to take. Do note that normally, name lookups may take a considerable time and that limiting the operation to less than a few minutes risks aborting perfectly normal operations. This option will cause libcurl to use the SIGALRM to enable time-outing system calls.

In unix-like systems, this might cause signals to be used unless -nosignal is used.

-timeoutms

Like timeout but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts.

-lowspeedlimit

Pass the speed in bytes per second that the transfer should be below during lowspeedtime seconds for the extension to consider it too slow and abort.

-lowspeedtime

Pass the time in seconds that the transfer should be below the lowspeedlimit for the extension to consider it too slow and abort.

-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. Defaults to unlimited speed.

-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. Defaults to unlimited speed.

-maxconnects

Sets the persistent connection cache size in all the protocols that support persistent conecctions. The set amount will be the maximum amount of simultaneous connections that TclCurl may cache in this easy handle. Default is 5, and there isn’t much point in changing this value unless you are perfectly aware of how this work and changes TclCurl’s behaviour.

When reaching the maximum limit, TclCurl closes the oldest connection in the cache to prevent the number of open connections to increase.

Note: if you have already performed transfers with this curl handle, setting a smaller maxconnects than before may cause open connections to unnecessarily get closed.

If you add this easy handle to a multi handle, this setting is not being acknowledged, instead you must configure the multi handle its own maxconnects option.

-connecttimeout

Maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once it has connected, this option is of no more use. Set to zero to disable connection timeout (it will then only timeout on the internal timeouts).

In unix-like systems, this might cause signals to be used unless -nosignal is set.

-connecttimeoutms

Like connecttimeout but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts.

-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. The allowed values are:

whatever

Default, resolves addresses to all IP versions that your system allows.

v4

Resolve to ipv4 addresses.

v6

Resolve to ipv6 addresses.

-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.

This option effectively pre-populates the DNS cache with entries for the host+port pair so redirects and everything that operations against the HOST+PORT will instead use your provided ADDRESS.

You can remove names from the DNS cache again, to stop providing these fake resolves, by including a string in the linked list that uses the format “-HOST:PORT”. The host name must be prefixed with a dash, and the host name and port number must exactly match what was already added previously.

-usessl

Pass a one of the values from below to make TclCurl use your desired level of SSL for the transfer. This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc.

You can use ftps:// URLs to explicitly switch on SSL/TSL for the control connection and the data connection.

Alternatively you can set the 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 conecction 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 as parameter. The string should be the file name of your certificate. The default format is “PEM” and can be changed with -sslcerttype.

With NSS this is the nickname of the certificate you wish to authenticate with. If you want to use a file from the current directory, please precede it with the “./” prefix, in order to avoid confusion with a nickname.

-sslcerttype

Pass a string as parameter. The string should be the format of your certificate. Supported formats are “PEM” and “DER”.

-sslkey

Pass a pointer to a zero terminated string as parameter. The string should be the file name of your private key. The default format is “PEM” and can be changed with -sslkeytype.

-sslkeytype

Pass a pointer to a zero terminated string as parameter. The string should be the format of your private key. Supported formats are “PEM”, “DER” and “ENG”

NOTE:The format “ENG” enables you to load the private key from a crypto engine. in this case -sslkey is used as an identifier passed to the engine. You have to set the crypto engine with -sslengine. The “DER” format key file currently does not work because of a bug in OpenSSL.

-keypasswd

Pass a string as parameter. It will be used as the password required to use the -sslkey or -sshprivatekeyfile private key.

You never need a pass phrase to load a certificate but you need one to load you private key.

This option used to be known as -sslkeypasswd and -sslcertpasswd.

-sslengine

Pass a string as parameter. It will be used as the identifier for the crypto engine you want to use for your private key.

NOTE:If the crypto device cannot be loaded, an error will be returned.

-sslenginedefault

Pass a 1 to set the actual crypto engine as the default for (asymmetric) crypto operations.

NOTE:If the crypto device cannot be set, an error will be returned.

-sslversion

Use it to set what version of SSL/TLS to use. The available options are:

default

The default action. This will attempt to figure out the remote SSL protocol version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled by default with 7.18.1).

tlsv1

Force TLSv1 or later

sslv2

Force SSLv2

sslv3

Force SSLv3

tlsv1_0

Force TLSv1.0 or later

tlsv1_1

Force TLSv1.1 or later

tlsv1_2

Force TLSv1.2 or later

tlsv1_3

Force TLSv1.3 or later

maxdefault

Use the maximum supported TLS version by libcurl or the default value from the SSL library.

maxtlsv1_0

Define maximum supported TLS version as TLSv1.0

maxtlsv1_1

Define maximum supported TLS version as TLSv1.1

maxtlsv1_2

Define maximum supported TLS version as TLSv1.2

maxtlsv1_3

Define maximum supported TLS version as TLSv1.3

-sslverifypeer

This option determines whether TclCurl verifies the authenticity of the peer’s certificate. A 1 means it verifies; zero means it doesn’t. The default is 1.

When negotiating an SSL connection, the server sends a certificate indicating its identity. TclCurl verifies whether the certificate is authentic, i.e. that you can trust that the server is who the certificate says it is. This trust is based on a chain of digital signatures, rooted in certification authority (CA) certificates you supply.

TclCurl uses a default bundle of CA certificates that comes with libcurl but you can specify alternate certificates with the -cainfo or the -capath options.

When -sslverifypeer is nonzero, and the verification fails to prove that the certificate is authentic, the connection fails. When the option is zero, the peer certificate verification succeeds regardless.

Authenticating the certificate is not by itself very useful. You typically want to ensure that the server, as authentically identified by its certificate, is the server you mean to be talking to, use -sslverifyhost to control that. The check that the host name in the certificate is valid for the host name you’re connecting to is done independently of this option.

-cainfo

Pass a file naming holding the certificate to verify the peer with. This only makes sense when used in combination with the -sslverifypeer option, if it is set to zero -cainfo need not even indicate an accessible file.

This option is by default set to the system path where libcurl’s cacert bundle is assumed to be stored, as established at build time.

When built against NSS this is the directory that the NSS certificate database resides in.

-issuercert

Pass a string naming a file holding a CA certificate in PEM format. If the option is set, an additional check against the peer certificate is performed to verify the issuer is indeed the one associated with the certificate provided by the option. This additional check is useful in multi-level PKI where one need to enforce the peer certificate is from a specific branch of the tree.

This option makes sense only when used in combination with the -sslverifypeer option. Otherwise, the result of the check is not considered as failure.

-capath

Pass the directory holding multiple CA certificates to verify the peer with. If libcurl is built against OpenSSL, the certificate directory must be prepared using the openssl c_rehash utility. This only makes sense when used in combination with the -sslverifypeer option, if it is set to zero, -capath need not even indicate an accessible path.

This option apparently does not work in Windows due to some limitation in openssl.

This option is OpenSSL-specific and does nothing if libcurl is built to use GnuTLS. NSS-powered libcurl provides the option only for backward compatibility.

-crlfile

Pass a string naming a file with the concatenation of CRL (in PEM format) to use in the certificate validation that occurs during the SSL exchange.

When libcurl is built to use NSS or GnuTLS, there is no way to influence the use of CRL passed to help in the verification process. When built with OpenSSL support, X509VFLAGCRLCHECK and X509VFLAGCRLCHECK_ALL are both set, requiring CRL check against all the elements of the certificate chain if a CRL file is passed.

This option makes sense only when used in combination with the -sslverifypeer option.

A specific error code (CURLESSLCRL_BADFILE) is defined with the option. It is returned when the SSL exchange fails because the CRL file cannot be loaded. A failure in certificate verification due to a revocation information found in the CRL does not trigger this specific error.

-sslverifyhost

This option determines whether TclCurl verifies that the server claims to be who you want it to be.

When negotiating an SSL connection, the server sends a certificate indicating its identity.

When -sslverifyhost is set to 2, that certificate must indicate that the server is the server to which you meant to connect, or the connection fails.

TclCurl considers the server the intended one when the Common Name field or a Subject Alternate Name field in the certificate matches the host name in the URL to which you told Curl to connect.

When set to 1, the certificate must contain a Common Name field, but it does not matter what name it says. (This is not ordinarily a useful setting).

When the value is 0, the connection succeeds regardless of the names in the certificate.

The default value for this option is 2.

This option controls the identity that the server claims. The server could be lying. To control lying, see -sslverifypeer. If libcurl is built against NSS and -verifypeer is zero, -verifyhost is ignored.

-certinfo

Set to ‘1’ to enable TclCurl’s certificate chain info gatherer. With this enabled, TclCurl (if built with OpenSSL) will extract lots of information and data about the certificates in the certificate chain used in the SSL connection. This data can then be to extracted after a transfer using the getinfo command and its option certinfo.

-randomfile

Pass a file name. The file will be used to read from to seed the random engine for SSL. The more random the specified file is, the more secure the SSL connection becomes. This option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option

-egdsocket

Pass a path name to the Entropy Gathering Daemon socket. It will be used to seed the random engine for SSL. This option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option

-sslcypherlist

Pass a string holding the ciphers to use for the SSL connection. The list must consists of one or more cipher strings separated by colons. Commas or spaces are also acceptable separators but colons are normally used, , - and

  • can be used as operators.

For OpenSSL and GnuTLS valid examples of cipher lists include ‘RC4-SHA’, ‘SHA1+DES’, ‘TLSv1’ and ‘DEFAULT’. The default list is normally set when you compile OpenSSL.

You will find more details about cipher lists on this URL: http://www.openssl.org/docs/apps/ciphers.html

For NSS valid examples of cipher lists include ‘rsarc4128md5’, ‘rsaaes128sha’, etc. With NSS you don’t add/remove ciphers. If you use this option then all known ciphers are disabled and only those passed in are enabled.

You’ll find more details about the NSS cipher lists on this URL: <http://directory.fedora.redhat.com/docs/mod_nss.html>

-sslsessionidcache

Pass a 0 to disable TclCurl’s use of SSL session-ID caching or a 1 to enable it. By default all transfers are done using the cache. While nothing ever should get hurt by attempting to reuse SSL session-IDs, there seem to be broken SSL implementations in the wild that may require you to disable this in order for you to succeed.

-krblevel

Set the kerberos security level for FTP, this also enables kerberos awareness. This is a string, ‘clear’, ‘safe’, ‘confidential’ or ‘private’. If the string is set but does not match one of these, ‘private’ will be used. Set the string to NULL to disable kerberos4. Set the string to ““ to disable kerberos support for FTP.

-gssapidelegation

Set the option to ‘flag’ to allow unconditional GSSAPI credential delegation. The delegation is disabled by default since 7.21.7. 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 GSSCDELEGPOLICYFLAG was available at compile-time.

SSH options

-sshauthtypes

The allowed types are:

publickey
Use public key authentication.
password
Use password authentication.
host
Use host-based authentication.
keyboard
Use keyboard-interactive authentication.
any
To let TclCurl pick one
-sshhostpublickeymd5

Pass a string containing 32 hexadecimal digits. The string should be the 128 bit MD5 cheksum of the remote host public key, and TclCurl will reject the connection to the host unless the md5sums match. This option is only for SCP and SFTP transfers.

-publickeyfile

Pass the file name for your public key. If not used, TclCurl defaults to using $HOME/.ssh/id_dsa.pub. HOME environment variable is set, and just id_dsa in the current directory if not.

-privatekeyfile

Pass the file name for your private key. If not used, TclCurl defaults to using $HOME/.ssh/id_dsa.pub. HOME environment variable is set, and just id_dsa in the current directory if not. If the file is password-protected, set the password with -keypasswd.

-sshknownhosts

Pass a string holding the file name of the knownhost file to use. The knownhosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, TclCurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use -sshkeyproc to alter the default behavior on host and key (mis)matching.

-sshkeyproc

Pass a the name of the procedure that will be called when the known_host matching has been done, to allow the application to act and decide for TclCurl how to proceed. The callback will only be called if -knownhosts is also set.

It gets passed a list with three elements, the first one is a list with the type of the key from the known_hosts file and the key itself, the second is another list with the type of the key from the remote site and the key itslef, the third tells you what TclCurl thinks about the matching status.

The known key types are: “rsa”, “rsa1” and “dss”, in any other case “unknown” is given.

TclCurl opinion about how they match may be: “match”, “mismatch”, “missing” or “error”.

The procedure must return:

0
The host+key is accepted and TclCurl will append it to the knownhosts file before continuing with the connection. This will also add the host+key combo to the knownhost pool kept in memory if it wasn’t already present there. The adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this.
1
The host+key is accepted, TclCurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn’t already present there.
2
The host+key is rejected. TclCurl will close the connection.
3
The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again.

Any other value will cause the connection to be closed.

Other options

-headervar
Name of the Tcl array variable where TclCurl will store the headers returned by the server.
-bodyvar
Name of the Tcl variable where TclCurl will store the file requested, the file may contain text or binary data.
-canceltransvar
Name of a Tcl variable, in case you have defined a procedure to call with -progressproc setting this variable to ‘1’ will cancel the transfer.
-command
Executes the given command after the transfer is done, since it only works with blocking transfers, it is pretty much useless.
-share
Pass a share handle as a parameter. The share handle must have been created by a previous call to curl::shareinit. Setting this option, will make this handle use the data from the shared handle instead of keeping the data to itself. See tclcurl_share for details.
-newfileperms
Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created files on the remote server. The default value is 0644, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://.
-newdirectoryperms
Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created directories on the remote server. The default value is 0755, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://.

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 transfered, 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 transfered. 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 successfull 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

Retuns 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.

SEE ALSO

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

tclcurl-ng-8.0.1/doc/tclcurl.n000066400000000000000000002764201517264272000162070ustar00rootroot00000000000000.\" -*- mode: troff; coding: utf-8 -*- .TH "TclCurl" "n" "12 April 2026" "TclCurl 8.0.1" "TclCurl Easy Interface" .SH NAME .LP TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. .SH SYNOPSIS .LP .EX curl::init .EE .LP .EX curlHandle configure ?options? .EE .LP .EX curlHandle perform .EE .LP .EX curlHandle getinfo curlinfo_option .EE .LP .EX curlhandle cleanup .EE .LP .EX curlhandle reset .EE .LP .EX curlHandle duphandle .EE .LP .EX curlHandle pause .EE .LP .EX curlHandle resume .EE .LP .EX curl::transfer ?options? .EE .LP .EX curl::version .EE .LP .EX curl::escape url .EE .LP .EX curl::unescape url .EE .LP .EX curl::curlConfig option .EE .LP .EX curl::versioninfo option .EE .LP .EX curl::easystrerror errorCode .EE .SH DESCRIPTION .LP The TclCurl extension gives Tcl programmers access to the libcurl library written by \fBDaniel Stenberg\fR, with it you can download urls, upload them and many other neat tricks, for more information check \c .UR http://curl.haxx.se .UE .SH curl::init .LP This procedure must be the first one to call, it returns a curlHandle that you need to use to invoke TclCurl procedures. The init calls intializes curl and this call MUST have a corresponding call to cleanup when the operation is completed. You should perform all your sequential file transfers using the same curlHandle. This enables TclCurl to use persistent connections when possible. .PP \fBRETURN VALUE\fR .PP curlHandle to use. .SH curlHandle configure ?options? .LP \fBconfigure\fR .PP is called to set the options for the transfer. Most operations in TclCurl have default actions, and by using the appropriate options you can make them behave differently (as documented). All options are set with the \fIoption\fR followed by a parameter. .PP \fBNotes:\fR .PP the options set with this procedure are valid for the forthcoming data transfers that are performed when you invoke perform .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 return code from the \f(CRcurl::init\fR call. .PP \fBOPTIONS\fR .SH Behaviour options .TP 3 -verbose Set the parameter to 1 to get the library to display a lot of verbose information about its operations. Very useful for libcurl and/or protocol debugging and understanding. .IP You hardly ever want this set in production use, you will almost always want this when you debug/report problems. Another neat option for debugging is .IP \fB-debugproc\fR .TP 3 -header A 1 tells the extension to include the headers in the body output. This is only relevant for protocols that actually have headers preceding the data (like HTTP). .TP 3 -noprogress A 1 tells the extension to turn on the progress meter completely. It will also prevent the \fIprogessproc\fR from getting called. .TP 3 -nosignal A 1 tells TclCurl not use any functions that install signal handlers or any functions that cause signals to be sent to the process. This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals. .IP If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals. .IP Setting \fInosignal\fR to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire. In addition, using \fIntlm_Wb\fR authentication could cause a SIGCHLD signal to be raised. .TP 3 -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 \fB-url\fR option, using an fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name). .IP By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function by the \fB-fnmatchproc\fR option. .IP This feature is only supported by the FTP download for now. .IP A brief introduction of its syntax follows: .RS .IP "\(bu" 3 * - ASTERISK .RE .IP .UR ftp://example.com/some/path/***.txt** .UE (for all txt\(cqs from the root directory) - ? - QUESTION MARK .IP Question mark matches any (exactly one) character. .IP .UR ftp://example.com/some/path/**photo?.jpeg** .UE - [ - 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 .UR ftp://example.com/some/path/**[a-z[:upper:]%5C%5C%5C%5C].jpeg** .UE .SH Callback options .TP 3 -writeproc Use it to set a Tcl procedure that will be invoked by TclCurl as soon as there is received data that needs to be saved. The procedure will receive a single parameter with the data to be saved. .IP NOTE: you will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be nothing if the file is empty or it may be thousands of bytes. .TP 3 -file File in which the transfered data will be saved. .TP 3 -readproc Sets a Tcl procedure to be called by TclCurl as soon as it needs to read data in order to send it to the peer. The procedure has to take one parameter, which will contain the maximun numbers of bytes to read. It should return the actual number of bytes read, or \(oq0\(cq if you want to stop the transfer. .IP If you stop the current transfer by returning 0 \(lqpre-maturely\(rq (i.e before the server expected it, like when you\(cqve said you will upload N bytes and you upload less than N bytes), you may experience that the server \(lqhangs\(rq waiting for the rest of the data that won\(cqt come. .IP Bugs: when doing TFTP uploads, you must return the exact amount of data that the callback wants, or it will be considered the final packet by the server end and the transfer will end there. .TP 3 -infile File from which the data will be transfered. .TP 3 -progressproc Name of the Tcl procedure that will invoked by TclCurl with a frequent interval during operation (roughly once per second or sooner), no matter if data is being transfered or not. Unknown/unused argument values passed to the callback will be set to zero (like if you only download data, the upload size will remain 0), the prototype of the procedure must be: .IP \fBproc ProgressCallback {dltotal dlnow ultotal ulnow}\fR .IP In order to this option to work you have to set the \fBnoprogress\fR option to \(oq0\(cq. Setting this option to the empty string will restore 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 -writeheader Pass a the file name to be used to write the header part of the received data to. The headers are guaranteed to be written one-by-one to this file and only complete lines are written. Parsing headers should be easy enough using this. .IP See also the \fB-headervar\fR option to get the headers into an array. .TP 3 -debugproc Name of the procedure that will receive the debug data produced by the \fB-verbose\fR option, it should match the following prototype: .IP \fBdebugProc {infoType data}\fR .IP where \fBinfoType\fR specifies what kind of information it is (0 text, 1 incoming header, 2 outgoing header, 3 incoming data, 4 outgoing data, 5 incoming SSL data, 6 outgoing SSL data). .TP 3 -chunkbgnproc Name of the procedure that will be called before a file will be transfered by ftp, it should match the following prototype: .IP \fBChunkBgnProc {remains}\fR .IP Where remains is the number of files left to be transfered (or skipped) .IP This callback makes sense only when using the \fB-wildcard\fR option. .TP 3 -chunkbgnvar Name of the variable in the global scope that will contain the data of the file about to be transfered. If you don\(cqt use this option \(oq::fileData\(cq will be used. .IP The available data is: filename, filetype (file, directory, symlink, device block, device char, named pipe, socket, door or error if it couldn\(cqt be identified), time, perm, uid, gid, size, hardlinks and flags. .TP 3 -chunkendproc Name of the procedure that will be called after a file is transfered (or skipped) by ftp, it should match the following prototype: .IP \fBChunkEndProc {}\fR .IP It should return \(oq0\(cq if everyhting is fine and \(oq1\(cq if some error occurred. .TP 3 -fnmatchProc Name of the procedure that will be called instead of the internal wildcard matching function, it should match the following prototype: .IP \fBFnMatchProc {pattern string}\fR .IP Returns \(oq0\(cq if it matches, \(oq1\(cq if it doesn\(cqt. .SH Error Options .TP 3 -errorbuffer Pass a variable name where TclCurl may store human readable error messages in. This may be more helpful than just the return code from the command. .TP 3 -stderr Pass a file name as parameter. This is the stream to use internally instead of stderr when reporting errors. .TP 3 -failonerror A 1 parameter tells the extension to fail silently if the HTTP code returned is equal or larger than 400. The default action would be to return the page normally, ignoring that code. .IP This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407). .IP You might get some amounts of headers transferred before this situation is detected, like for when a \(lq100-continue\(rq is received as a response to a POST/PUT and a 401 or 407 is received immediately afterwards. .SH Network options .TP 3 -url The actual URL to deal with. .IP If the given URL lacks the protocol part (\(lq or \(lqftp://\(rq etc), it will attempt to guess which protocol to use based on the given host name. If the given protocol of the set URL is not supported, TclCurl will return the \fBunsupported protocol\fR error when you call \fBperform\fR. Use \fBcurl::versioninfo\fR for detailed info on which protocols are supported. .IP Starting with version 7.22.0, the fragment part of the URI will not be send as part of the path, which was the case previously. .IP \fBNOTE\fR: this is the one option required to be set before \fBperform\fR is called. .TP 3 -protocols Pass a list in lowecase of protocols to limit what protocols TclCurl may use in the transfer. This allows you to have a TclCurl built to support a wide range of protocols but still limit specific transfers to only be allowed to use a subset of them. .IP Accepted protocols are \(oqhttp\(cq, \(oqhttps\(cq, \(oqftp\(cq, \(oqftps\(cq, \(oqscp\(cq, \(oqsftp\(cq, \(oqtelnet\(cq, \(oqldap\(cq, \(oqldaps\(cq, \(oqdict\(cq, \(oqfile\(cq,\(cqtftp\(cq, \(oqimap\(cq, \(oqimaps\(cq, \(oqpop\(cq, \(oqpop3\(cq, \(oqsmtp\(cq, \(oqsmtps\(cq, \(oqgopher\(cq and \(oqall\(cq. .TP 3 -redirprotocols Pass a list in lowercase of accepted protocols to limit what protocols TclCurl may use in a transfer that it follows to in a redirect when \fB-followlocation\fR is enabled. This allows you to limit specific transfers to only be allowed to use a subset of protocols in redirections. .IP By default TclCurl will allow all protocols except for FILE and SCP. This is a difference compared to pre-7.19.4 versions which unconditionally would follow to all protocols supported. .TP 3 -proxy If you need to use a http proxy to access the outside world, set the proxy string with this option. To specify port number in this string, append :[port] to the end of the host name. The proxy string may be prefixed with [protocol]:// since any such prefix will be ignored. .IP When you tell the extension to use a HTTP proxy, TclCurl will transparently convert operations to HTTP even if you specify a FTP URL etc. This may have an impact on what other features of the library you can use, such as \fBquote\fR and similar FTP specifics that will not work unless you tunnel through the HTTP proxy. Such tunneling is activated with \fBproxytunnel\fR. .IP TclCurl respects the environment variables http\fIproxy, ftp\fRproxy, all_proxy etc, if any of those are set. The use of this option does however override any possibly set environment variables. .IP Setting the proxy string to \(lq\(lq (an empty string) will explicitly disable the use of a proxy, even if there is an environment variable set for it. .IP The proxy host string can be specified the exact same way as the proxy environment variables, include protocol prefix (\c .UR http://) .UE and embedded user + password. .IP Since 7.22.0, the proxy string may be specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or socks5h:// (the last one to enable socks5 and asking the proxy to do the resolving) to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be treated as HTTP proxies. .TP 3 -proxyport Use this option to set the proxy port to use unless it is specified in the proxy string by \fB-proxy\fR. If not specified, TclCurl will default to using port 1080 for proxies. .TP 3 -proxytype Pass the type of the proxy. Available options are \(oqhttp\(cq, \(oqhttp1.0\(cq, \(oqsocks4\(cq, \(oqsocks4a\(cq, \(oqsocks5\(cq and \(oqsocks5h\(cq, with the HTTP one being the default. .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 \(lqregular\(rq HTTP requests is instead controled with \fIhttpversion\fR. .TP 3 -noproxy Pass a string, a comma-separated list of hosts which do 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 as either a domain which contains the hostname, or the hostname itself. For example, local.com would match local.com, local.com:80, and .UR http://www.local.com .UE \c , but not \c .UR http://www.notlocal.com .UE \c \&. .TP 3 -httpproxytunnel Set the parameter to 1 to get the extension to tunnel all non-HTTP operations through the given HTTP proxy. Do note that there is a big difference between using a proxy and tunneling through it. If you don\(cqt know what this means, you probably don\(cqt want this tunnel option. .TP 3 -socks5gssapiservice Pass the name of the service. The default service name for a SOCKS5 server is rcmd/server-fqdn. This option allows you to change it. .TP 3 -socks5gssapinec Pass a 1 to enable or 0 to disable. As part of the gssapi negotiation a protection mode is negotiated. The rfc1961 says in section 4.3/4.4 it should be protected, but the NEC reference implementation does not. If enabled, this option allows the unprotected exchange of the protection mode negotiation. .TP 3 -interface Pass the interface name to use as outgoing network interface. The name can be an interface name, an IP address or a host name. .TP 3 -localport This sets the local port number of the socket used for connection. This can be used in combination with \fB-interface\fR and you are recommended to use \fBlocalportrange\fR as well when this is set. Valid port numbers are 1 - 65535. .TP 3 -localportrange This is the number of attempts TclCurl should do to find a working local port number. It starts with the given \fB-localport\fR and adds one to the number for each retry. Setting this value to 1 or below will make TclCurl do only one try for each port number. Port numbers by nature are a scarce resource that will be busy at times so setting this value to something too low might cause unnecessary connection setup failures. .TP 3 -dnscachetimeout Pass the timeout in seconds. Name resolves will be kept in memory for this number of seconds. Set to \(oq0\(cq to completely disable caching, or \(oq-1\(cq to make the cached entries remain forever. By default, TclCurl caches this info for 60 seconds. .IP The name resolve functions of various libc implementations don\(cqt re-read name server information unless explicitly told so (for example, by calling \fIres_init(3)\fR). This may cause TclCurl to keep using the older server even if DHCP has updated the server info, and this may look like a DNS cache issue. .TP 3 -dnsuseglobalcache If the value passed is 1, it tells TclCurl to use a global DNS cache that will survive between curl handles creations and deletions. This is not thread-safe as it uses a global varible. \fIThis option was deprecated in libcurl v7.11.1 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option\fR .IP \fBWARNING:\fR this option is considered obsolete. Stop using it. Switch over to using the share interface instead! See \fItclcurl_share\fR. .TP 3 -buffersize Pass your preferred size for the receive buffer in TclCurl. The main point of this would be that the write callback gets called more often and with smaller chunks. This is just treated as a request, not an order. You cannot be guaranteed to actually get the given size. .TP 3 -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. .TP 3 -tcpnodelay Pass a number to specify whether the TCP_NODELAY option should be set or cleared (1 = set, 0 = clear). The option is cleared by default. This will have 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 -addressscope Pass a number specifying the scope_id value to use when connecting to IPv6 link-local or site-local addresses. .SH Names and Passwords options .TP 3 -netrc A 1 parameter tells the extension to scan your \fB\(ti/.netrc\fR file to find user name and password for the remote site you are about to access. Do note that TclCurl does not verify that the file has the correct properties set (as the standard unix ftp client does), and that only machine name, user name and password is taken into account (init macros and similar things are not supported). .IP You can set it to the following values: .RS .TP 3 optional The use of your \(ti/.netrc file is optional, and information in the URL is to be preferred. The file will be scanned with the host and user name (to find the password only) or with the host only, to find the first user name and password after that machine, which ever information is not specified in the URL. .RE .IP Undefined values of the option will have this effect. .RS .TP 3 ignored The extension will ignore the file and use only the information in the URL. This is the default. .TP 3 required This value tells the library that use of the file is required, to ignore the information in the URL, and to search the file with the host only. .RE .TP 3 -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 \fBnetrc\fR option to \fBrequired\fR. If this option is omitted, and \fBnetrc\fR is set, TclCurl will attempt to find the a .netrc file in the current user\(cqs home directory. .TP 3 -userpwd Pass a string as parameter, which should be [username]:[password] to use for the connection. Use \fB-httpauth\fR to decide authentication method. .IP When using NTLM, you can set domain by prepending it to the user name and separating the domain and name with a forward (/) or backward slash (\e). Like this: \(lqdomain/user:password\(rq or \(lqdomain\euser:password\(rq. Some HTTP servers (on Windows) support this style even 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 -proxyuserpwd Pass a string as parameter, which should be [username]:[password] to use for the connection to the HTTP proxy. .TP 3 -username Pass a string with the user name to use for the transfer. It sets the user name to be used in protocol authentication. You should not use this option together with the (older) \fB-userpwd\fR option. .IP In order to specify the password to be used in conjunction with the user name use the \fB-password\fR option. .TP 3 -password Pass a string with the password to use for the transfer. .IP It should be used in conjunction with the \fB-username\fR option. .TP 3 -proxyusername Pass a string with the user name to use for the transfer while connecting to Proxy. .IP It should be used in same way as the \fB-proxyuserpwd\fR is used, except that it allows the username to contain a colon, like in the following example: \(lqsip:\c .MT user@example.com .ME \c \(rq. .IP Note the \fB-proxyusername\fR option is an alternative way to set the user name while connecting to Proxy. It doesn\(cqt make sense to use them together. .TP 3 -proxypassword Pass a string with the password to use for the transfer while connecting to Proxy. It is meant to use together with \fB-proxyusername\fR. .TP 3 -httpauth Set to the authentication method you want, the available ones are: .RS .TP 3 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. .TP 3 digest HTTP Digest authentication. Digest authentication is a more secure way to do authentication over public networks than the regular old-fashioned Basic method. .TP 3 digestie HTTP Digest authentication with an IE flavor. TclCurl will use a special \(lqquirk\(rq that IE is known to have used before version 7 and that some servers require the client to use. .TP 3 gssnegotiate HTTP GSS-Negotiate authentication. The GSS-Negotiate method, also known as plain \(lqNegotiate\(rq,was designed by Microsoft and is used in their web applications. It is primarily meant as a support for Kerberos5 authentication but may be also used along with another authentication methods. .TP 3 ntlm HTTP NTLM authentication. A proprietary protocol invented and used by Microsoft. It uses a challenge-response and hash concept similar to Digest, to prevent the password from being eavesdropped. .TP 3 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\(cqs compile time but is typically /usr/bin/ntlm_auth. .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 any TclCurl will automatically select the one it finds most secure. .TP 3 anysafe It may use anything but basic, TclCurl will automatically select the one it finds most secure. .RE .TP 3 -tlsauthtype Use it to tell TclCurl which authentication method(s) you want it to use for TLS authentication. .RS .TP 3 tlsauthsrp 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. To use TLS-SRP, you must also set the \fB-tlsauthusername\fR and \fB-tlsauthpassword\fR options. .RE .IP You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this to work. .TP 3 -tlsauthusername Pass a string with the username to use for the TLS authentication method specified with the \fB-tlsauthtype\fR option. Requires that the \fB-tlsauthpassword\fR option also be set. .TP 3 -tlsauthpassword Pass a string with the password to use for the TLS authentication method specified with the \fB-tlsauthtype\fR option. Requires that the \fB-tlsauthusername\fR option also be set. .TP 3 -proxyauth Use it to tell TclCurl which authentication method(s) you want it to use for your proxy authentication. Note that for some methods, this will induce an extra network round-trip. Set the actual name and password with the \fBproxyuserpwd\fR option. .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 -autoreferer Pass an 1 parameter to enable this. When enabled, TclCurl will automatically set the Referer: field in requests where it follows a Location: redirect. .TP 3 -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. Three encodings are supported: \fIidentity\fR, which does nothing, \fIdeflate\fR which requests the server to compress its response using the zlib algorithm, and \fIgzip\fR which requests the gzip algorithm. Use \fIall\fR to send an Accept-Encoding: header containing all supported encodings. .IP This is a request, not an order; the server may or may not do it. This option must be set or else any unsolicited encoding done by the server is ignored. See the special file lib/README.encoding in libcurl docs for details. .TP 3 -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 response sent using a compressed Transfer-Encoding that will be automatically uncompressed by TclCurl on receival. .IP Transfer-Encoding differs slightly from the Content-Encoding you ask for with \fB-encoding\fR 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. .TP 3 -followlocation An 1 tells the library to follow any .IP \fBLocation: header\fR .IP that the server sends as part of a HTTP header. .IP This means that the extension will re-send the same request on the new location and follow new \fBLocation: headers\fR all the way until no more such headers are returned. \fB-maxredirs\fR can be used to limit the number of redirects TclCurl will follow. .IP Since 7.19.4, TclCurl can limit what protocols it will automatically follow. The accepted protocols are set with \fB-redirprotocols\fR and it excludes the FILE protocol by default. .TP 3 -unrestrictedauth An 1 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 \fB-followlocation\fR. .TP 3 -maxredirs Sets the redirection limit. If that many redirections have been followed, the next redirect will cause an error. This option only makes sense if the \fB-followlocation\fR option is used at the same time. Setting the limit to 0 will make libcurl refuse any redirect. Set it to -1 for an infinite number of redirects (which is the default) .TP 3 -postredir Controls how TclCurl acts on redirects after POSTs that get a 301, 302 or 303 response back. A \(lq301\(rq parameter tells TclCurl to keep POST requests as POST when following a 301 redirect. Passing a \(lq302\(rq makes TclCurl maintain the request method after a 302 redirect, while \(lq303\(rq does the same for a 303 redirect. \(lqall\(rq is a convenience string that activates all three behaviours. .IP The non-RFC behaviour is ubiquitous in web browsers, so the extension does the 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 setting \fB-followlocation\fR .IP The legacy alias \fB-post301\fR is accepted for compatibility and uses the same values. .TP 3 -put An 1 parameter tells the extension to use HTTP PUT a file. The file to put must be set with \fB-infile\fR and \fB-infilesize\fR. .IP This option is deprecated starting with version 0.12.1, you should 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 -post An 1 parameter tells the library to do a regular HTTP post. This is a normal application/x-www-form-urlencoded kind, which is the most commonly used one by HTML forms. See the \fB-postfields\fR option for how to specify the data to post and \fB-postfieldsize\fR about how to set the data 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 provide data to POST using the \fB-readproc\fR options. .IP You can override the default POST Content-Type: header by setting your own with \fB-httpheader\fR. .IP Using POST 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 POST to a HTTP 1.1 server, you can send data without knowing the size before starting the POST 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 in the request. .IP When setting \fBpost\fR to an 1 value, it will automatically set \fBnobody\fR to 0. .IP NOTE: if you have issued a POST request and want to make a HEAD or GET instead, you must explicitly pick the new request type using \fB-nobody\fR or \fB-httpget\fR or similar. .TP 3 -postfields Pass a string as parameter, which should be the full data to post in a HTTP POST operation. You must make sure that the data is formatted the way you want the server to receive it. TclCurl will not convert or encode it for you. Most web servers will assume this data to be url-encoded. .IP This is a normal application/x-www-form-urlencoded kind, 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, as simply setting \fB-postfields\fR to NULL or \(lq\(lq just effectively disables the sending of the specified string. TclCurl will instead assume that the POST data will be sent using the read callback! .IP Using POST 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 \fBNote\fR: to make multipart/formdata posts (aka rfc1867-posts), check out \fB-httppost\fR option. .TP 3 -postfieldsize If you want to post data to the server without letting TclCurl do a strlen() to measure the data size, this option must be used. Also, when this option is used, you can post fully binary data which otherwise is likely to fail. If this size is set to zero, the library will use strlen() to get the data size. .TP 3 -httppost Tells TclCurl you want a multipart/formdata HTTP POST to be made and you instruct what data to pass on to the server through a \fBTcl list\fR. .IP \fBThis is the only case where the data is reset after a transfer.\fR .IP First, there are some basics you need to understand about multipart/formdata posts. Each part consists of at least a \fBNAME\fR and a \fBCONTENTS\fR part. If the part is made for file upload, there are also a stored \fBCONTENT-TYPE\fR and a \fBFILENAME\fR. Below, we\(cqll discuss which options set these properties in the parts you want to add to your post. .IP The list must contain a \fB\(oqname\(cq\fR tag with the name of the section followed by a string with the name, there are three tags to indicate the value of the section: \fB\(oqvalue\(cq\fR followed by a string with the data to post, \fB\(oqfile\(cq\fR followed by the name of the file to post and \fB\(oqcontenttype\(cq\fR with the type of the data (text/plain, image/jpg, \[u2026]), you can also indicate a \fIfalse\fR file name with \fB\(oqfilename\(cq\fR, this is useful in case the server checks if the given file name is valid, for example, by testing if it starts with \(oqc:\e\(cq as any real file name does or if you want to include the full path of the file to post. You can also post the content of a variable as if it were a file with the options \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 the contents as data. .IP Should you need to specify extra headers for the form POST section, use \fB\(oqcontentheader\fR\(cq followed by a list with the headers to post. .IP Please see \(oqhttpPost.tcl\(cq and \(oqhttpBufferPost.tcl\(cq for examples. .IP If TclCurl can\(cqt set the data to post an error will be returned: .RS .TP 3 1 If the memory allocation fails. .TP 3 2 If one option is given twice for one form. .TP 3 3 If an empty string was given. .TP 3 4 If an unknown option was used. .TP 3 5 If the some form info is not complete (or error) .TP 3 6 If an illegal option is used in an array. .TP 3 7 TclCurl has no http support. .RE .TP 3 -referer Pass a string as parameter. It will be used to set the \fBreferer\fR header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with \fB-httpheader\fR. .TP 3 -useragent Pass a string as parameter. It will be used to set the \fBuser-agent:\fR header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with \fB-httpheader\fR. .TP 3 -httpheader Pass a \fBlist\fR with the HTTP headers to pass to the server in your request. If you add a header that is otherwise generated and used by TclCurl internally, your added one will be used instead. If you add a header with no contents as in \(oqAccept:\(cq, the internally used header will just get disabled. Thus, using this option you can add new headers, replace and remove internal headers. .IP The headers included in the linked list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. Failure to comply with this will result in strange bugs because the server will most likely ignore part of the headers you specified. .IP The first line in a request (containing the method, usually a GET or POST) is not a header and cannot be replaced using this option. Only the lines following the request-line are headers. Adding this method line in this list of headers will only cause your request to send an invalid header. .IP \fBNOTE\fR: The most commonly replaced headers have \(lqshortcuts\(rq in the options: \fBcookie\fR, \fBuseragent\fR, and \fBreferer\fR. .TP 3 -http200aliases Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers respond with a custom header response line. For example, IceCast servers respond with \(lqICY 200 OK\(rq. By including this string in your list of aliases, the response will be treated as a valid HTTP header line such as \(lqHTTP/1.0 200 OK\(rq. .IP \fBNOTE\fR:The alias itself is not parsed for any version strings. Before version 7.16.3, TclCurl used the value set by option \fBhttpversion\fR, but starting with 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matched. .TP 3 -cookie Pass a string as parameter. It will be used to set a cookie in the http request. The format of the string should be \(oq[NAME]=[CONTENTS];\(cq. Where NAME is the cookie name and CONTENTS is what the cookie should contain. .IP If you need to set mulitple cookies, you need to set them all using a single option and thus you need to concatenate them all in one single string. Set multiple cookies in one string like this: \(lqname1=content1; name2=content2;\(rq etc. .IP This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are done due to authentication, followed redirections or similar, they will all get this cookie passed on. .IP Using this option multiple times will only make the latest string override the previous ones. .TP 3 -cookiefile Pass a string as parameter. It should contain the name of your file holding cookie data. The cookie data may be in netscape cookie data format or just regular HTTP-style headers dumped to a file. .IP Given an empty or non-existing file, this option will enable cookies for this curl handle, making it understand and parse received cookies and then use matching cookies in future requests. .IP If you use this option multiple times, you add more files to read. .TP 3 -cookiejar Pass a file name in which TclCurl will dump all internally known cookies when \fBcurlHandle cleanup\fR is called. If no cookies are known, no file will be created. Specify \(lq-\(rq to have the cookies written to stdout. .IP Using this option also enables cookies for this session, so if you, for example, follow a location it will make matching cookies get sent accordingly. .IP TclCurl will not and cannot report an error for this. Using \(oq\fBverbose\fR\(cq will get a warning to display, but that is the only visible feedback you get about this possibly lethal situation. .TP 3 -cookiesession Pass an 1 to mark this as a new cookie \(lqsession\(rq. It will force TclCurl to ignore all cookies it is about to load that are \(lqsession cookies\(rq from the previous session. By default, TclCurl always stores and loads all cookies, independent of whether they are session cookies are not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this \(lqsession\(rq only. .TP 3 -cookielist Pass a string with a cookie. The cookie can be either in Netscape / Mozilla format or just regular HTTP-style header (Set-Cookie: \[u2026]) format. If the cookie engine was not enabled it will be enabled. Passing a magic string \(lqALL\(rq will erase all known cookies while \(lqFLUSH\(rq will write all cookies known by TclCurl to the file specified by \fB-cookiejar\fR. .TP 3 -httpget If set to 1 forces the HTTP request to get back to GET, usable if POST, PUT or a custom request have been used previously with the same handle. .IP When setting \fBhttpget\fR to 1, \fBnobody\fR will automatically be set to 0. .TP 3 -httpversion Set to one of the values decribed below, they force TclCurl to use the specific http versions. It should only be used if you really MUST do that because of a silly remote server. .RS .TP 3 none We do not care about what version the library uses. TclCurl will use whatever it thinks fit. .TP 3 1.0 Enforce HTTP 1.0 requests. .TP 3 1.1 Enforce HTTP 1.1 requests. .TP 3 2.0 Enforce HTTP version 2 requests. .TP 3 2TLS Enforce version 2 requests for HTTPS, version 1.1 for HTTP. .TP 3 2\fIPRIOR\fRKNOWLEDGE Enforce HTTP 2 requests without performing HTTP/1.1 Upgrade first. .RE .TP 3 -ignorecontentlength 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. If this option is used, TclCurl will not be able to accurately report progress, and will simply stop the download when the server ends the connection. .TP 3 -httpcontentdecoding Set to zero to disable content decoding. If set to 1 it is enabled. Note however that TclCurl has no default content decoding but requires you to use \fBencoding\fR for that. .TP 3 -httptransferencoding Set to zero to disable transfer decoding, if set to 1 it is enabled (default). TclCurl does chunked transfer decoding by default unless this option is set to zero. .SH SMTP options .TP 3 -mailfrom Pass a string to specify the sender address in a mail when sending an SMTP mail with TclCurl. .TP 3 -mailrcpt Pass a list of recipients to pass to the server in your SMTP mail request. .IP Each recipient in SMTP lingo is specified with angle brackets (<>), but should you not use an angle bracket as first letter, TclCurl will assume you provide a single email address only and enclose that with angle brackets for you. .SH TFTP option .TP 3 tftpblksize Specify the block size to use for TFTP data transmission. Valid range as per RFC 2348 is 8-65464 bytes. The default of 512 bytes will be used if this option is not specified. The specified block size will only be used pending support by the remote server. If the server does not return an option acknowledgement or returns an option acknowledgement with no blksize, the default of 512 bytes will be used. .SH FTP options .TP 3 -ftpport Pass a string as parameter. It will be used to get the IP address to use for the ftp PORT instruction. The PORT instruction tells the remote server to connect to our specified IP address. The string may be a plain IP address, a host name, a network interface name (under unix) or just a \(oq-\(cq to let the library use your systems default IP address. Default FTP operations are passive, and thus will not use PORT. .IP The address can be followed by a \(oq:\(cq to specify a port, optionally followed by a \(oq-\(cq o specify a port range. If the port specified is 0, the operating system will pick a free port. If a range is provided and all ports in the range are not available, libcurl will report CURLE\fIFTP\fRPORT_FAILED for the handle. Invalid port/range settings are ignored. IPv6 addresses followed by a port or portrange have to be in brackets. IPv6 addresses without port/range specifier can be in brackets. .IP Examples with specified ports: .IP eth0:0 192.168.1.2:32000-33000 curl.se:32123 [::1]:1234-4567 .IP You disable PORT again and go back to using the passive version by setting this option to an empty string. .TP 3 -quote Pass a \fBlist\fR list with the FTP or SFTP commands to pass to the server prior to your ftp request. This will be done before any other FTP commands are issued (even before the CWD command).If you do not want to transfer any files, set \fBnobody\fR to \(oq1\(cq and \fBheader\fR to \(oq0\(cq. .IP Prefix the command with an asterisk (*) to make TclCurl continue even if the command fails as by default TclCurl will stop. .IP Disable this operation again by setting an empty string to this option. .IP Keep in mind the commands to send must be \(oqraw\(cq ftp commands, for example, to create a directory you need to send \fBmkd Test\fR, not \fBmkdir Test\fR. .IP Valid SFTP commands are: chgrp, chmod, chown, ln, mkdir, pwd, rename, rm, rmdir and symlink. .TP 3 -postquote Pass a \fBlist\fR with the FTP commands to pass to the server after your ftp transfer request. If you do not want to transfer any files, set \fBnobody\fR to \(oq1\(cq and \fBheader\fR to \(oq0\(cq. .TP 3 -prequote Pass a \fBlist\fR of FTP or SFTP commands to pass to the server after the transfer type is set. .TP 3 -dirlistonly A 1 tells the library to just list the names of files in a directory, instead of doing a full directory listing that would include file sizes, dates etc. It works with both FTP and SFTP urls. .IP This causes an FTP NLST command to be sent. Beware that some FTP servers list only files in their response to NLST, they might not include subdirectories and symbolic links. .IP Setting this option to 1 also implies a directory listing even if the URL doesn\(cqt end with a slash, which otherwise is necessary. .IP Do NOT use this option if you also use \fB-wildcardmatch\fR as it will effectively break that feature. .TP 3 -append A 1 parameter tells the extension to append to the remote file instead of overwriting it. This is only useful when uploading to a ftp site. .TP 3 -ftpusepret Set to 1 to tell TclCurl to use the EPRT (and LPRT) command when doing active FTP downloads (which is enabled by \(oq\fBftpport\fR\(cq). 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. .TP 3 -ftpuseepvs Set to one to tell TclCurl to use the EPSV command when doing passive FTP downloads (which it always does by default). Using EPSV means that it will first attempt to use EPSV before using PASV, but if you pass a zero to this option, it will not try using EPSV, only plain PASV. .TP 3 -ftpusepret Set to one to tell TclCurl to send a PRET command before PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard command for directory listings as well as up and downloads in PASV mode. Has no effect when using the active FTP transfers mode. .TP 3 -ftpcreatemissingdirs If set to 1, TclCurl will attempt to create any remote directory that it fails to CWD into. CWD is the command that changes working directory. .IP This setting also applies to SFTP-connections. TclCurl will attempt to create the remote directory if it can\(cqt obtain a handle to the target-location. The creation will fail if a file of the same name as the directory to create already exists or lack of permissions prevents creation. .IP If set to 2, TclCurl will retry the CWD command again if the subsequent MKD command fails. This is especially useful if you\(cqre doing many simultanoeus connections against the same server and they all have this option enabled, as then CWD may first fail but then another connection does MKD before this connection and thus MKD fails but trying CWD works .TP 3 -ftpresponsetimeout Causes TclCurl to set a timeout period (in seconds) 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. Note that while TclCurl is waiting for a response, this value overrides \fBtimeout\fR. It is recommended that if used in conjunction with \fBtimeout\fR, you set it to a value smaller than \fBtimeout\fR. .TP 3 -ftpalternativetouser Pass a string which will be used to authenticate if the usual FTP \(lqUSER user\(rq and \(lqPASS password\(rq negotiation fails. This is currently only known to be required when connecting to Tumbleweed\(cqs Secure Transport FTPS server using client certificates for authentication. .TP 3 -ftpskippasvip If set to 1, it instructs TclCurl not to use the IP address the server suggests in its 227-response to TclCurl\(cqs 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. .IP This option has no effect if PORT, EPRT or EPSV is used instead of PASV. .TP 3 -ftpsslauth Pass TclCurl one of the values from below, to alter how TclCurl issues \(lqAUTH TLS\(rq or \(lqAUTH SSL\(rq when FTP over SSL is activated (see \fB-ftpssl\fR). .IP You may need this option because of servers like BSDFTPD-SSL from .UR http://bsdftpd-ssl.sc.ru/ .UE \(lqwhich won\(cqt work properly when \(lqAUTH SSL\(rq is issued (although the server responds fine and everything) but requires \(lqAUTH TLS\(rq instead. .RS .TP 3 default Allows TclCurl to decide. .TP 3 ssl Try \(lqAUTH SSL\(rq first, and only if that fails try \(lqAUTH TLS\(rq. .TP 3 tls Try \(lqAUTH TLS\(rq first, and only if that fails try \(lqAUTH SSL\(rq. .RE .TP 3 -ftpsslccc Set it to make TclCurl use CCC (Clear Command Channel). It shuts down the SSL/TLS layer after authenticating. The rest of the control channel communication will be unencrypted. This allows NAT routers to follow the FTP transaction. Possible values are: .RS .TP 3 none Do not attempt to use CCC. .TP 3 passive Do not initiate the shutdown, wait for the server to do it. Do not send a reply. .TP 3 active Initiate the shutdown and wait for a reply. .RE .TP 3 -ftpaccount Pass string (or \(lq\(lq to disable). When an FTP server asks for \(lqaccount data\(rq after user name and password has been provided, this data is sent off using the ACCT command. .TP 3 -ftpfilemethod It allows three values: .RS .TP 3 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. .TP 3 nocwd No CWD at all is done, TclCurl will do SIZE, RETR, STOR, etc and give a full path to the server. .TP 3 singlecwd Make one CWD with the full target directory and then operate on the file \(lqnormally\(rq. This is somewhat more standards compliant than \(oqnocwd\(cq but without the full penalty of \(oqmulticwd\(cq. .RE .SH Protocol options .TP 3 -transfertext A 1 tells the extension to use ASCII mode for ftp transfers, instead of the default binary transfer. For win32 systems it does not set the stdout to binary mode. This option can be usable when transferring text data between systems with different views on certain characters, such as newlines or similar. .IP \fBNOTE:\fR TclCurl does not do a complete ASCII conversion when doing ASCII transfers over FTP. This is a known limitation/flaw that nobody has rectified. TclCurl simply sets the mode to ascii and performs a standard transfer. .TP 3 -proxytransfermode If set to 1, TclCurl sets 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 it being set to 0, the default, \fB-transfertext\fR has no effect when doing FTP via a proxy. Beware that not all proxies support this feature. .TP 3 -crlf If set to \(oq1\(cq, TclCurl converts Unix newlines to CRLF newlines on transfers. Disable this option again by setting the value to \(oq0\(cq. .TP 3 -range Pass a string as parameter, which should contain the specified range you want. It should be in the format \(lqX-Y\(rq , where X or Y may be left out. HTTP transfers also support several intervals, separated with commas as in \(lqX-Y,N-M\(rq Using this kind of multiple intervals will cause the HTTP server to send the response document in pieces (using standard MIME separation techniques). .IP Ranges only work on HTTP, FTP and FILE transfers. .TP 3 -resumefrom Pass the offset in number of bytes that you want the transfer to start from. Set this option to 0 to make the transfer start from the beginning (effectively disabling resume). .IP For FTP, set this option to -1 to make the transfer start from the end of the target file (useful to continue an interrupted upload). .IP When doing uploads with FTP, the resume position is where in the local/source file TclCurl should try to resume the upload from and it will then append the source file to the remote target file. .TP 3 -customrequest Pass a string as parameter. It will be used instead of GET or HEAD when doing the HTTP request. This is useful for doing DELETE or other more obscure HTTP requests. Do not do this at will, make sure your server supports the command first. .IP Note that TclCurl will still act and assume the keyword it would use if you do not set your custom and it will act according to that. Thus, changing this to a HEAD when TclCurl otherwise would do a GET might cause TclCurl to act funny, and similar. To switch to a proper HEAD, use \fB-nobody\fR, to switch to a proper POST, use \fB-post\fR or \fB-postfields\fR and so on. .TP 3 -filetime If you pass a 1, TclCurl will attempt to get the modification date of the remote document in this operation. This requires that the remote server sends the time or replies to a time querying command. The getinfo procedure with the filetime argument can be used after a transfer to extract the received time (if any). .TP 3 -nobody A 1 tells the library not to include the body-part in the output. This is only relevant for protocols that have a separate header and body part. On HTTP(S) servers, this will make TclCurl do a HEAD request. .IP To change request to GET, you should use \fBhttpget\fR. Change request to POST with \fBpost\fR etc. .TP 3 -infilesize When uploading a file to a remote site, this option should be used to tell TclCurl what the expected size of the infile is. .IP This option is mandatory for uploading using SCP. .TP 3 -upload A 1 tells the library to prepare for an upload. The \fB-infile\fR and \fB-infilesize\fR options are also interesting 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 This defines how the \fBtimevalue\fR value is treated. You can set this parameter to \fBifmodsince\fR or \fBifunmodsince\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 -timeout Pass the maximum time in seconds that you allow the TclCurl transfer operation to take. Do note that normally, name lookups may take a considerable time and that limiting the operation to less than a few minutes risks aborting perfectly normal operations. This option will cause libcurl to use the SIGALRM to enable time-outing system calls. .IP In unix-like systems, this might cause signals to be used unless \fB-nosignal\fR is used. .TP 3 -timeoutms Like \fBtimeout\fR but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. .TP 3 -lowspeedlimit Pass the speed in bytes per second that the transfer should be below during \fBlowspeedtime\fR seconds for the extension to consider it too slow and abort. .TP 3 -lowspeedtime Pass the time in seconds that the transfer should be below the \fBlowspeedlimit\fR for the extension to consider it too slow and abort. .TP 3 -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. Defaults to unlimited speed. .TP 3 -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. Defaults to unlimited speed. .TP 3 -maxconnects Sets the persistent connection cache size in all the protocols that support persistent conecctions. The set amount will be the maximum amount of simultaneous connections that TclCurl may cache in this easy handle. Default is 5, and there isn\(cqt much point in changing this value unless you are perfectly aware of how this work and changes TclCurl\(cqs behaviour. .IP When reaching the maximum limit, TclCurl closes the oldest connection in the cache to prevent the number of open connections to increase. .IP \fBNote\fR: if you have already performed transfers with this curl handle, setting a smaller \fBmaxconnects\fR than before may cause open connections to unnecessarily get closed. .IP If you add this easy handle to a multi handle, this setting is not being acknowledged, instead you must configure the multi handle its own \fBmaxconnects\fR option. .TP 3 -connecttimeout Maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once it has connected, this option is of no more use. Set to zero to disable connection timeout (it will then only timeout on the internal timeouts). .IP In unix-like systems, this might cause signals to be used unless \fB-nosignal\fR is set. .TP 3 -connecttimeoutms Like \fBconnecttimeout\fR but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. .TP 3 -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. The allowed values are: .TP 3 whatever Default, resolves addresses to all IP versions that your system allows. .TP 3 v4 Resolve to ipv4 addresses. .TP 3 v6 Resolve to ipv6 addresses. .TP 3 -resolve Pass a list of strings with host name resolve information to use for requests with this handle. .IP 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. .IP This option effectively pre-populates the DNS cache with entries for the host+port pair so redirects and everything that operations against the HOST+PORT will instead use your provided ADDRESS. .IP You can remove names from the DNS cache again, to stop providing these fake resolves, by including a string in the linked list that uses the format \(lq-HOST:PORT\(rq. The host name must be prefixed with a dash, and the host name and port number must exactly match what was already added previously. .TP 3 -usessl Pass a one of the values from below to make TclCurl use your desired level of SSL for the transfer. This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc. .IP You can use ftps:// URLs to explicitly switch on SSL/TSL for the control connection and the data connection. .IP Alternatively you can set the option to one of these values: .TP 3 nope Do not attempt to use SSL .TP 3 try Try using SSL, proceed anyway otherwise. .TP 3 control Use SSL for the control conecction or fail with \(lquse ssl failed\(rq (64). .TP 3 all Use SSL for all communication or fail with \(lquse ssl failed\(rq (64). .SH SSL and security options .TP 3 -sslcert Pass a string as parameter. The string should be the file name of your certificate. The default format is \(lqPEM\(rq and can be changed with \fB-sslcerttype\fR. .IP With NSS this is the nickname of the certificate you wish to authenticate with. If you want to use a file from the current directory, please precede it with the \(lq./\(rq prefix, in order to avoid confusion with a nickname. .TP 3 -sslcerttype Pass a string as parameter. The string should be the format of your certificate. Supported formats are \(lqPEM\(rq and \(lqDER\(rq. .TP 3 -sslkey Pass a pointer to a zero terminated string as parameter. The string should be the file name of your private key. The default format is \(lqPEM\(rq and can be changed with \fB-sslkeytype\fR. .TP 3 -sslkeytype Pass a pointer to a zero terminated string as parameter. The string should be the format of your private key. Supported formats are \(lqPEM\(rq, \(lqDER\(rq and \(lqENG\(rq .IP \fBNOTE:\fRThe format \(lqENG\(rq enables you to load the private key from a crypto engine. in this case \fB-sslkey\fR is used as an identifier passed to the engine. You have to set the crypto engine with \fB-sslengine\fR. The \(lqDER\(rq format key file currently does not work because of a bug in OpenSSL. .TP 3 -keypasswd Pass a string as parameter. It will be used as the password required to use the \fB-sslkey\fR or \fB-sshprivatekeyfile\fR private key. .IP You never need a pass phrase to load a certificate but you need one to load you private key. .IP This option used to be known as \fB-sslkeypasswd\fR and \fB-sslcertpasswd\fR. .TP 3 -sslengine Pass a string as parameter. It will be used as the identifier for the crypto engine you want to use for your private key. .IP \fBNOTE:\fRIf the crypto device cannot be loaded, an error will be returned. .TP 3 -sslenginedefault Pass a 1 to set the actual crypto engine as the default for (asymmetric) crypto operations. .IP \fBNOTE:\fRIf the crypto device cannot be set, an error will be returned. .TP 3 -sslversion Use it to set what version of SSL/TLS to use. The available options are: .TP 3 default The default action. This will attempt to figure out the remote SSL protocol version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled by default with 7.18.1). .TP 3 tlsv1 Force TLSv1 or later .TP 3 sslv2 Force SSLv2 .TP 3 sslv3 Force SSLv3 .TP 3 tlsv1_0 Force TLSv1.0 or later .TP 3 tlsv1_1 Force TLSv1.1 or later .TP 3 tlsv1_2 Force TLSv1.2 or later .TP 3 tlsv1_3 Force TLSv1.3 or later .TP 3 maxdefault Use the maximum supported TLS version by libcurl or the default value from the SSL library. .TP 3 maxtlsv1_0 Define maximum supported TLS version as TLSv1.0 .TP 3 maxtlsv1_1 Define maximum supported TLS version as TLSv1.1 .TP 3 maxtlsv1_2 Define maximum supported TLS version as TLSv1.2 .TP 3 maxtlsv1_3 Define maximum supported TLS version as TLSv1.3 .TP 3 -sslverifypeer This option determines whether TclCurl verifies the authenticity of the peer\(cqs certificate. A 1 means it verifies; zero means it doesn\(cqt. The default is 1. .IP When negotiating an SSL connection, the server sends a certificate indicating its identity. TclCurl verifies whether the certificate is authentic, i.e. that you can trust that the server is who the certificate says it is. This trust is based on a chain of digital signatures, rooted in certification authority (CA) certificates you supply. .IP TclCurl uses a default bundle of CA certificates that comes with libcurl but you can specify alternate certificates with the \fB-cainfo\fR or the \fB-capath\fR options. .IP When \fB-sslverifypeer\fR is nonzero, and the verification fails to prove that the certificate is authentic, the connection fails. When the option is zero, the peer certificate verification succeeds regardless. .IP Authenticating the certificate is not by itself very useful. You typically want to ensure that the server, as authentically identified by its certificate, is the server you mean to be talking to, use \fB-sslverifyhost\fR to control that. The check that the host name in the certificate is valid for the host name you\(cqre connecting to is done independently of this option. .TP 3 -cainfo Pass a file naming holding the certificate to verify the peer with. This only makes sense when used in combination with the \fB-sslverifypeer\fR option, if it is set to zero \fB-cainfo\fR need not even indicate an accessible file. .IP This option is by default set to the system path where libcurl\(cqs cacert bundle is assumed to be stored, as established at build time. .IP When built against NSS this is the directory that the NSS certificate database resides in. .TP 3 -issuercert Pass a string naming a file holding a CA certificate in PEM format. If the option is set, an additional check against the peer certificate is performed to verify the issuer is indeed the one associated with the certificate provided by the option. This additional check is useful in multi-level PKI where one need to enforce the peer certificate is from a specific branch of the tree. .IP This option makes sense only when used in combination with the \fB-sslverifypeer\fR option. Otherwise, the result of the check is not considered as failure. .TP 3 -capath Pass the directory holding multiple CA certificates to verify the peer with. If libcurl is built against OpenSSL, the certificate directory must be prepared using the openssl c_rehash utility. This only makes sense when used in combination with the \fB-sslverifypeer\fR option, if it is set to zero, \fB-capath\fR need not even indicate an accessible path. .IP This option apparently does not work in Windows due to some limitation in openssl. .IP This option is OpenSSL-specific and does nothing if libcurl is built to use GnuTLS. NSS-powered libcurl provides the option only for backward compatibility. .TP 3 -crlfile Pass a string naming a file with the concatenation of CRL (in PEM format) to use in the certificate validation that occurs during the SSL exchange. .IP When libcurl is built to use NSS or GnuTLS, there is no way to influence the use of CRL passed to help in the verification process. When built with OpenSSL support, X509\fIV\fRFLAG\fICRL\fRCHECK and X509\fIV\fRFLAG\fICRL\fRCHECK_ALL are both set, requiring CRL check against all the elements of the certificate chain if a CRL file is passed. .IP This option makes sense only when used in combination with the \fB-sslverifypeer\fR option. .IP A specific error code (CURLE\fISSL\fRCRL_BADFILE) is defined with the option. It is returned when the SSL exchange fails because the CRL file cannot be loaded. A failure in certificate verification due to a revocation information found in the CRL does not trigger this specific error. .TP 3 -sslverifyhost This option determines whether TclCurl verifies that the server claims to be who you want it to be. .IP When negotiating an SSL connection, the server sends a certificate indicating its identity. .IP When \fB-sslverifyhost\fR is set to 2, that certificate must indicate that the server is the server to which you meant to connect, or the connection fails. .IP TclCurl considers the server the intended one when the Common Name field or a Subject Alternate Name field in the certificate matches the host name in the URL to which you told Curl to connect. .IP When set to 1, the certificate must contain a Common Name field, but it does not matter what name it says. (This is not ordinarily a useful setting). .IP When the value is 0, the connection succeeds regardless of the names in the certificate. .IP The default value for this option is 2. .IP This option controls the identity that the server \fIclaims\fR. The server could be lying. To control lying, see \fB-sslverifypeer\fR. If libcurl is built against NSS and \fB-verifypeer\fR is zero, \fB-verifyhost\fR is ignored. .TP 3 -certinfo Set to \(oq1\(cq to enable TclCurl\(cqs certificate chain info gatherer. With this enabled, TclCurl (if built with OpenSSL) will extract lots of information and data about the certificates in the certificate chain used in the SSL connection. This data can then be to extracted after a transfer using the \fBgetinfo\fR command and its option \fBcertinfo\fR. .TP 3 -randomfile Pass a file name. The file will be used to read from to seed the random engine for SSL. The more random the specified file is, the more secure the SSL connection becomes. \fIThis option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option\fR .TP 3 -egdsocket Pass a path name to the Entropy Gathering Daemon socket. It will be used to seed the random engine for SSL. \fIThis option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option\fR .TP 3 -sslcypherlist Pass a string holding the ciphers to use for the SSL connection. The list must consists of one or more cipher strings separated by colons. Commas or spaces are also acceptable separators but colons are normally used, , - and .RS .IP "\(bu" 3 can be used as operators. .RE .IP For OpenSSL and GnuTLS valid examples of cipher lists include \(oqRC4-SHA\(cq, \(oqSHA1+DES\(cq, \(oqTLSv1\(cq and \(oqDEFAULT\(cq. The default list is normally set when you compile OpenSSL. .IP You will find more details about cipher lists on this URL: .UR http://www.openssl.org/docs/apps/ciphers.html .UE .IP For NSS valid examples of cipher lists include \(oqrsa\fIrc4\fR128\fImd5\(cq, \(oqrsa\fRaes\fI128\fRsha\(cq, etc. With NSS you don\(cqt add/remove ciphers. If you use this option then all known ciphers are disabled and only those passed in are enabled. .IP You\(cqll find more details about the NSS cipher lists on this URL: <\c .UR http://directory.fedora.redhat.com/docs/mod_nss.html .UE \c > .TP 3 -sslsessionidcache Pass a 0 to disable TclCurl\(cqs use of SSL session-ID caching or a 1 to enable it. By default all transfers are done using the cache. While nothing ever should get hurt by attempting to reuse SSL session-IDs, there seem to be broken SSL implementations in the wild that may require you to disable this in order for you to succeed. .TP 3 -krblevel Set the kerberos security level for FTP, this also enables kerberos awareness. This is a string, \(oqclear\(cq, \(oqsafe\(cq, \(oqconfidential\(cq or \(oqprivate\(cq. If the string is set but does not match one of these, \(oqprivate\(cq will be used. Set the string to NULL to disable kerberos4. Set the string to \(lq\(lq to disable kerberos support for FTP. .TP 3 -gssapidelegation Set the option to \(oqflag\(cq to allow unconditional GSSAPI credential delegation. The delegation is disabled by default since 7.21.7. Set the parameter to \(oqpolicyflag\(cq 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\fIC\fRDELEG\fIPOLICY\fRFLAG was available at compile-time. .SH SSH options .TP 3 -sshauthtypes The allowed types are: .RS .TP 3 publickey Use public key authentication. .TP 3 password Use password authentication. .TP 3 host Use host-based authentication. .TP 3 keyboard Use keyboard-interactive authentication. .TP 3 any To let TclCurl pick one .RE .TP 3 -sshhostpublickeymd5 Pass a string containing 32 hexadecimal digits. The string should be the 128 bit MD5 cheksum of the remote host public key, and TclCurl will reject the connection to the host unless the md5sums match. This option is only for SCP and SFTP transfers. .TP 3 -publickeyfile Pass the file name for your public key. If not used, TclCurl defaults to using \fB$HOME/.ssh/id_dsa.pub\fR. HOME environment variable is set, and just \fBid_dsa\fR in the current directory if not. .TP 3 -privatekeyfile Pass the file name for your private key. If not used, TclCurl defaults to using \fB$HOME/.ssh/id_dsa.pub\fR. HOME environment variable is set, and just \fBid_dsa\fR in the current directory if not. If the file is password-protected, set the password with \fB-keypasswd\fR. .TP 3 -sshknownhosts Pass a string holding the file name of the known\fIhost file to use. The known\fRhosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, TclCurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use \fB-sshkeyproc\fR to alter the default behavior on host and key (mis)matching. .TP 3 -sshkeyproc Pass a the name of the procedure that will be called when the known_host matching has been done, to allow the application to act and decide for TclCurl how to proceed. The callback will only be called if \fB-knownhosts\fR is also set. .IP It gets passed a list with three elements, the first one is a list with the type of the key from the known_hosts file and the key itself, the second is another list with the type of the key from the remote site and the key itslef, the third tells you what TclCurl thinks about the matching status. .IP The known key types are: \(lqrsa\(rq, \(lqrsa1\(rq and \(lqdss\(rq, in any other case \(lqunknown\(rq is given. .IP TclCurl opinion about how they match may be: \(lqmatch\(rq, \(lqmismatch\(rq, \(lqmissing\(rq or \(lqerror\(rq. .IP The procedure must return: .RS .TP 3 0 The host+key is accepted and TclCurl will append it to the known\fIhosts file before continuing with the connection. This will also add the host+key combo to the known\fRhost pool kept in memory if it wasn\(cqt already present there. The adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this. .TP 3 1 The host+key is accepted, TclCurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn\(cqt already present there. .TP 3 2 The host+key is rejected. TclCurl will close the connection. .TP 3 3 The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again. .RE .IP Any other value will cause the connection to be closed. .SH Other options .TP 3 -headervar Name of the Tcl array variable where TclCurl will store the headers returned by the server. .TP 3 -bodyvar Name of the Tcl variable where TclCurl will store the file requested, the file may contain text or binary data. .TP 3 -canceltransvar Name of a Tcl variable, in case you have defined a procedure to call with \fB-progressproc\fR setting this variable to \(oq1\(cq will cancel the transfer. .TP 3 -command Executes the given command after the transfer is done, since it only works with blocking transfers, it is pretty much useless. .TP 3 -share Pass a share handle as a parameter. The share handle must have been created by a previous call to \fBcurl::shareinit\fR. Setting this option, will make this handle use the data from the shared handle instead of keeping the data to itself. See \fItclcurl_share\fR for details. .TP 3 -newfileperms Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created files on the remote server. The default value is 0644, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. .TP 3 -newdirectoryperms Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created directories on the remote server. The default value is 0755, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. .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 1 Unsupported protocol. This build of TclCurl has no support for this protocol. .TP 3 2 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 3 URL malformat. The syntax was not correct. .TP 3 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. .TP 3 5 Couldn\(cqt resolve proxy. The given proxy host could not be resolved. .TP 3 6 Couldn\(cqt resolve host. The given remote host was not resolved. .TP 3 7 Failed to connect to host or proxy. .TP 3 8 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 9 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 11 FTP weird PASS reply. TclCurl couldn\(cqt parse the reply sent to the PASS request. .TP 3 13 FTP weird PASV reply, TclCurl couldn\(cqt parse the reply sent to the PASV or EPSV request. .TP 3 14 FTP weird 227 format. TclCurl couldn\(cqt parse the 227-line the server sent. .TP 3 15 FTP can\(cqt get host. Couldn\(cqt resolve the host IP we got in the 227-line. .TP 3 17 FTP couldn\(cqt set type. Couldn\(cqt change transfer method to either binary or ascii. .TP 3 18 Partial file. Only a part of the file was transfered, this happens when the server first reports an expected transfer size and then delivers data that doesn\(cqt match the given size. .TP 3 19 FTP couldn\(cqt RETR file, we either got a weird reply to a \(oqRETR\(cq command or a zero byte transfer. .TP 3 21 Quote error. A custom \(oqQUOTE\(cq returned error code 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command. .TP 3 22 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 23 Write error. TclCurl couldn\(cqt write data to a local filesystem or an error was returned from a write callback. .TP 3 25 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 26 Read error. There was a problem reading from a local file or an error was returned from the read callback. .TP 3 27 Out of memory. A memory allocation request failed. This should never happen unless something weird is going on in your computer. .TP 3 28 Operation timeout. The specified time-out period was reached according to the conditions. .TP 3 30 The FTP PORT command failed, not all FTP servers support the PORT command, try doing a transfer using PASV instead!. .TP 3 31 FTP couldn\(cqt use REST. This command is used for resumed FTP transfers. .TP 3 33 Range error. The server doesn\(cqt support or accept range requests. .TP 3 34 HTTP post error. Internal post-request generation error. .TP 3 35 SSL connect error. The SSL handshaking failed, the error buffer may have a clue to the reason, could be certificates, passwords, \[u2026] .TP 3 36 The download could not be resumed because the specified offset was out of the file boundary. .TP 3 37 A file given with FILE:// couldn\(cqt be read. Did you checked the permissions? .TP 3 38 LDAP cannot bind. LDAP bind operation failed. .TP 3 39 LDAP search failed. .TP 3 41 A required zlib function was not found. .TP 3 42 Aborted by callback. An application told TclCurl to abort the operation. .TP 3 43 Internal error. A function was called with a bad parameter. .TP 3 45 Interface error. A specified outgoing interface could not be used. .TP 3 47 Too many redirects. When following redirects, TclCurl hit the maximum amount, set your limit with \(enmaxredirs .TP 3 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. .TP 3 49 A telnet option string was illegally formatted. .TP 3 51 The remote peer\(cqs SSL certificate or SSH md5 fingerprint wasn\(cqt ok .TP 3 52 The server didn\(cqt reply anything, which here is considered an error. .TP 3 53 The specified crypto engine wasn\(cqt found. .TP 3 54 Failed setting the selected SSL crypto engine as default! .TP 3 55 Failed sending network data. .TP 3 56 Failure with receiving network data. .TP 3 58 Problem with the local client certificate. .TP 3 59 Couldn\(cqt use specified SSL cipher. .TP 3 60 Peer certificate cannot be authenticated with known CA certificates. .TP 3 61 Unrecognized transfer encoding. .TP 3 62 Invalid LDAP URL. .TP 3 63 Maximum file size exceeded. .TP 3 64 SSL use failed. .TP 3 65 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 66 Failed to initialise ssl engine. .TP 3 67 Failed to login, user password or similar was not accepted. .TP 3 68 File not found on TFTP server. .TP 3 69 There is a permission problem with the TFTP request. .TP 3 70 The remote server has run out of space. .TP 3 71 Illegal TFTP operation. .TP 3 72 Unknown transfer ID. .TP 3 73 TFTP file already exists and will not be overwritten. .TP 3 74 No such user in the TFTP server and good behaving TFTP servers should never return this. .TP 3 75 Character conversion failed. .TP 3 77 Problem with reading the SSL CA cert (path? access rights?). .TP 3 78 Remote file not found .TP 3 79 Error from the SSH layer .TP 3 80 Failed to shut down the SSL connection .TP 3 82 Failed to load CRL file .TP 3 83 Issuer check failed .TP 3 84 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 85 Mismatch of RTSP CSeq numbers. .TP 3 86 Mismatch of RTSP Session Identifiers. .TP 3 87 Unable to parse FTP file list (during FTP wildcard downloading). .TP 3 88 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 transfered. 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 successfull 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 Retuns 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 SEE ALSO .LP curl, The art of HTTP scripting (at \c .UR http://curl.haxx.se) .UE \c , RFC 2396, tclcurl-ng-8.0.1/doc/tclcurl.n.in000066400000000000000000002721121517264272000166060ustar00rootroot00000000000000.\" You can view this file with: .\" nroff -man [file] .\" Adapted from libcurl docs by fandom@telefonica.net .TH TclCurl 3 "2 February 2026" "TclCurl @PACKAGE_VERSION@ "TclCurl Easy Interface" .SH NAME TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. .SH SYNOPSIS .BI "curl::init" .sp .IB curlHandle " configure " "?options?" .sp .IB curlHandle " perform" .sp .IB curlHandle " getinfo " curlinfo_option .sp .IB curlhandle " cleanup" .sp .IB curlhandle " reset" .sp .IB curlHandle " duphandle" .sp .IB curlHandle " pause" .sp .IB curlHandle " resume" .sp .BI curl::transfer " ?options?" .sp .BI curl::version .sp .BI "curl::escape " url .sp .BI "curl::unescape " url .sp .BI "curl::curlConfig " option .sp .BI "curl::versioninfo " option .sp .BI "curl::easystrerror " errorCode .SH DESCRIPTION The TclCurl extension gives Tcl programmers access to the libcurl library written by \fBDaniel Stenberg\fP, with it you can download urls, upload them and many other neat tricks, for more information check .I http://curl.haxx.se .SH curl::init This procedure must be the first one to call, it returns a .I curlHandle that you need to use to invoke TclCurl procedures. The init calls intializes curl and this call MUST have a corresponding call to .I cleanup when the operation is completed. You should perform all your sequential file transfers using the same curlHandle. This enables TclCurl to use persistent connections when possible. .sp .B RETURN VALUE .sp .I curlHandle to use. .SH curlHandle configure ?options? .sp .B configure is called to set the options for the transfer. Most operations in TclCurl have default actions, and by using the appropriate options you can make them behave differently (as documented). All options are set with the \fIoption\fP followed by a parameter. .sp .B Notes: the options set with this procedure are valid for the forthcoming data transfers that are performed when you invoke .I perform .sp 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\fP. .sp .I "curlHandle" is the return code from the .I "curl::init" call. .sp .B OPTIONS .sp .SH Behaviour options .TP .B -verbose Set the parameter to 1 to get the library to display a lot of verbose information about its operations. Very useful for libcurl and/or protocol debugging and understanding. You hardly ever want this set in production use, you will almost always want this when you debug/report problems. Another neat option for debugging is .B -debugproc .TP .B -header A 1 tells the extension to include the headers in the body output. This is only relevant for protocols that actually have headers preceding the data (like HTTP). .TP .B -noprogress A 1 tells the extension to turn on the progress meter completely. It will also prevent the \fIprogessproc\fP from getting called. .TP .B -nosignal A 1 tells TclCurl not use any functions that install signal handlers or any functions that cause signals to be sent to the process. This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals. If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals. Setting \fInosignal\fP to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire. In addition, using \fIntlm_Wb\fP authentication could cause a SIGCHLD signal to be raised. .TP .B -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 \fB-url\fP option, using an fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name). By default, TClCurl uses its internal wildcard matching implementation. You can provide your own matching function by the \fB-fnmatchproc\fP option. This feature is only supported by the FTP download for now. A brief introduction of its syntax follows: .RS .IP "* - ASTERISK" \&ftp://example.com/some/path/\fB*.txt\fP (for all txt's from the root directory) .RE .RS .IP "? - QUESTION MARK" Question mark matches any (exactly one) character. \&ftp://example.com/some/path/\fBphoto?.jpeg\fP .RE .RS .IP "[ - 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: \fB[a-zA-Z0\-9]\fP or \fB[f\-gF\-G]\fP \- character interval \fB[abc]\fP - character enumeration \fB[^abc]\fP or \fB[!abc]\fP - negation \fB[[:\fP\fIname\fP\fB:]]\fP class expression. Supported classes are \fBalnum\fP,\fBlower\fP, \fBspace\fP, \fBalpha\fP, \fBdigit\fP, \fBprint\fP, \fBupper\fP, \fBblank\fP, \fBgraph\fP, \fBxdigit\fP. \fB[][-!^]\fP - special case \- matches only '\-', ']', '[', '!' or '^'. These characters have no special purpose. \fB[\\[\\]\\\\]\fP - escape syntax. Matches '[', ']' or '\\'. Using the rules above, a file name pattern can be constructed: \&ftp://example.com/some/path/\fB[a-z[:upper:]\\\\].jpeg\fP .RE .PP .SH Callback options .TP .B -writeproc Use it to set a Tcl procedure that will be invoked by TclCurl as soon as there is received data that needs to be saved. The procedure will receive a single parameter with the data to be saved. NOTE: you will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be nothing if the file is empty or it may be thousands of bytes. .TP .B -file File in which the transfered data will be saved. .TP .B -readproc Sets a Tcl procedure to be called by TclCurl as soon as it needs to read data in order to send it to the peer. The procedure has to take one parameter, which will contain the maximun numbers 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 "pre-maturely" (i.e before the server expected it, like when you've said you will upload N bytes and you upload less than N bytes), you may experience that the server "hangs" waiting for the rest of the data that won't come. Bugs: when doing TFTP uploads, you must return the exact amount of data that the callback wants, or it will be considered the final packet by the server end and the transfer will end there. .TP .B -infile File from which the data will be transfered. .TP .B -progressproc Name of the Tcl procedure that will invoked by TclCurl with a frequent interval during operation (roughly once per second or sooner), no matter if data is being transfered or not. Unknown/unused argument values passed to the callback will be set to zero (like if you only download data, the upload size will remain 0), the prototype of the procedure must be: .sp .B proc ProgressCallback {dltotal dlnow ultotal ulnow} .sp In order to this option to work you have to set the \fBnoprogress\fP option to '0'. Setting this option to the empty string will restore 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 \fBpause\fP and \fBresume\fP commands. .TP .B -writeheader Pass a the file name to be used to write the header part of the received data to. The headers are guaranteed to be written one-by-one to this file and only complete lines are written. Parsing headers should be easy enough using this. See also the \f-headervar\fP option to get the headers into an array. .TP .B -debugproc Name of the procedure that will receive the debug data produced by the .B -verbose option, it should match the following prototype: .sp .B debugProc {infoType data} .sp where \fBinfoType\fP specifies what kind of information it is (0 text, 1 incoming header, 2 outgoing header, 3 incoming data, 4 outgoing data, 5 incoming SSL data, 6 outgoing SSL data). .TP .B -chunkbgnproc Name of the procedure that will be called before a file will be transfered by ftp, it should match the following prototype: .sp .B ChunkBgnProc {remains} .sp Where remains is the number of files left to be transfered (or skipped) This callback makes sense only when using the \fB-wildcard\fP option. .TP .B -chunkbgnvar Name of the variable in the global scope that will contain the data of the file about to be transfered. 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. .TP .B -chunkendproc Name of the procedure that will be called after a file is transfered (or skipped) by ftp, it should match the following prototype: .sp .B ChunkEndProc {} .sp It should return '0' if everyhting is fine and '1' if some error occurred. .TP .B -fnmatchProc Name of the procedure that will be called instead of the internal wildcard matching function, it should match the following prototype: .sp .B FnMatchProc {pattern string} .sp Returns '0' if it matches, '1' if it doesn't. .SH Error Options .TP .B -errorbuffer Pass a variable name where TclCurl may store human readable error messages in. This may be more helpful than just the return code from the command. .TP .B -stderr Pass a file name as parameter. This is the stream to use internally instead of stderr when reporting errors. .TP .B -failonerror A 1 parameter tells the extension to fail silently if the HTTP code returned is equal or larger than 400. The default action would be to return the page normally, ignoring that code. This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407). You might get some amounts of headers transferred before this situation is detected, like for when a "100-continue" is received as a response to a POST/PUT and a 401 or 407 is received immediately afterwards. .SH Network options .TP .B -url The actual URL to deal with. If the given URL lacks the protocol part ("http://" or "ftp://" etc), it will attempt to guess which protocol to use based on the given host name. If the given protocol of the set URL is not supported, TclCurl will return the \fBunsupported protocol\fP error when you call \fBperform\fP. Use \fBcurl::versioninfo\fP for detailed info on which protocols are supported. Starting with version 7.22.0, the fragment part of the URI will not be send as part of the path, which was the case previously. \fBNOTE\fP: this is the one option required to be set before \fBperform\fP is called. .TP .B -protocols Pass a list in lowecase of protocols to limit what protocols TclCurl may use in the transfer. This allows you to have a TclCurl built to support a wide range of protocols but still limit specific transfers to only be allowed to use 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'. .TP .B -redirprotocols Pass a list in lowercase of accepted protocols to limit what protocols TclCurl may use in a transfer that it follows to in a redirect when \fB-followlocation\fP is enabled. This allows you to limit specific transfers to only be allowed to use a subset of protocols in redirections. By default TclCurl will allow all protocols except for FILE and SCP. This is a difference compared to pre-7.19.4 versions which unconditionally would follow to all protocols supported. .TP .B -proxy If you need to use a http proxy to access the outside world, set the proxy string with this option. To specify port number in this string, append :[port] to the end of the host name. The proxy string may be prefixed with [protocol]:// since any such prefix will be ignored. When you tell the extension to use a HTTP proxy, TclCurl will transparently convert operations to HTTP even if you specify a FTP URL etc. This may have an impact on what other features of the library you can use, such as .B quote and similar FTP specifics that will not work unless you tunnel through the HTTP proxy. Such tunneling is activated with .B proxytunnel TclCurl respects the environment variables http_proxy, ftp_proxy, all_proxy etc, if any of those are set. The use of this option does however override any possibly set environment variables. Setting the proxy string to "" (an empty string) will explicitly disable the use of a proxy, even if there is an environment variable set for it. The proxy host string can be specified the exact same way as the proxy environment variables, include protocol prefix (http://) and embedded user + password. Since 7.22.0, the proxy string may be specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or socks5h:// (the last one to enable socks5 and asking the proxy to do the resolving) to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be treated as HTTP proxies. .TP .B -proxyport Use this option to set the proxy port to use unless it is specified in the proxy string by \fB-proxy\fP. If not specified, TclCurl will default to using port 1080 for proxies. .TP .B -proxytype Pass the type of the proxy. Available options are 'http', 'http1.0', 'socks4', 'socks4a', \&'socks5' and 'socks5h', with the HTTP one being the default. If you set it to \fIhttp1.0\fP, it will only affect how libcurl speaks to a proxy when CONNECT is used. The HTTP version used for "regular" HTTP requests is instead controled with \fIhttpversion\fP. .TP .B -noproxy Pass a string, a comma-separated list of hosts which do 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 as either a domain which contains the hostname, or the hostname itself. For example, local.com would match local.com, local.com:80, and www.local.com, but not www.notlocal.com. .TP .B -httpproxytunnel Set the parameter to 1 to get the extension to tunnel all non-HTTP operations through the given HTTP proxy. Do note that there is a big difference between using a proxy and tunneling through it. If you don't know what this means, you probably don't want this tunnel option. .TP .B -socks5gssapiservice Pass the name of the service. The default service name for a SOCKS5 server is rcmd/server-fqdn. This option allows you to change it. .TP .B -socks5gssapinec Pass a 1 to enable or 0 to disable. As part of the gssapi negotiation a protection mode is negotiated. The rfc1961 says in section 4.3/4.4 it should be protected, but the NEC reference implementation does not. If enabled, this option allows the unprotected exchange of the protection mode negotiation. .TP .B -interface Pass the interface name to use as outgoing network interface. The name can be an interface name, an IP address or a host name. .TP .B -localport This sets the local port number of the socket used for connection. This can be used in combination with \fB-interface\fP and you are recommended to use \fBlocalportrange\fP as well when this is set. Valid port numbers are 1 - 65535. .TP .B -localportrange This is the number of attempts TclCurl should do to find a working local port number. It starts with the given \fB-localport\fP and adds one to the number for each retry. Setting this value to 1 or below will make TclCurl do only one try for each port number. Port numbers by nature are a scarce resource that will be busy at times so setting this value to something too low might cause unnecessary connection setup failures. .TP .B -dnscachetimeout Pass the timeout in seconds. Name resolves will be kept in memory for this number of seconds. Set to '0' to completely disable caching, or '\-1' to make the cached entries remain forever. By default, TclCurl caches this info for 60 seconds. The name resolve functions of various libc implementations don't re-read name server information unless explicitly told so (for example, by calling \fIres_init(3)\fP). This may cause TclCurl to keep using the older server even if DHCP has updated the server info, and this may look like a DNS cache issue. .TP .B -dnsuseglobalcache If the value passed is 1, it tells TclCurl to use a global DNS cache that will survive between curl handles creations and deletions. This is not thread-safe as it uses a global varible. \fBWARNING:\fP this option is considered obsolete. Stop using it. Switch over to using the share interface instead! See \fItclcurl_share\fP. .TP .B -buffersize Pass your preferred size for the receive buffer in TclCurl. The main point of this would be that the write callback gets called more often and with smaller chunks. This is just treated as a request, not an order. You cannot be guaranteed to actually get the given size. .TP .B -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. .TP .B -tcpnodelay Pass a number to specify whether the TCP_NODELAY option should be set or cleared (1 = set, 0 = clear). The option is cleared by default. This will have 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. .TP .B -addressscope Pass a number specifying the scope_id value to use when connecting to IPv6 link-local or site-local addresses. .SH Names and Passwords options .TP .B -netrc A 1 parameter tells the extension to scan your .B ~/.netrc file to find user name and password for the remote site you are about to access. Do note that TclCurl does not verify that the file has the correct properties set (as the standard unix ftp client does), and that only machine name, user name and password is taken into account (init macros and similar things are not supported). You can set it to the following values: .RS .TP 5 .B optional The use of your ~/.netrc file is optional, and information in the URL is to be preferred. The file will be scanned with the host and user name (to find the password only) or with the host only, to find the first user name and password after that machine, which ever information is not specified in the URL. Undefined values of the option will have this effect. .TP .B ignored The extension will ignore the file and use only the information in the URL. This is the default. .TP .B required This value tells the library that use of the file is required, to ignore the information in the URL, and to search the file with the host only. .RE .TP .B -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 \fBnetrc\fP option to \fBrequired\fP. If this option is omitted, and \fBnetrc\fP is set, TclCurl will attempt to find the a .netrc file in the current user's home directory. .TP .B -userpwd Pass a string as parameter, which should be [username]:[password] to use for the connection. Use \fB-httpauth\fP to decide authentication method. When using NTLM, you can set domain by prepending it to the user name and separating the domain and name with a forward (/) or backward slash (\\). Like this: "domain/user:password" or "domain\\user:password". Some HTTP servers (on Windows) support this style even for Basic authentication. When using HTTP and \fB-followlocation\fP, 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\fP 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 .B -proxyuserpwd Pass a string as parameter, which should be [username]:[password] to use for the connection to the HTTP proxy. .TP .B -username Pass a string with the user name to use for the transfer. It sets the user name to be used in protocol authentication. You should not use this option together with the (older) \fB-userpwd\fP option. In order to specify the password to be used in conjunction with the user name use the \fB-password\fP option. .TP .B -password Pass a string with the password to use for the transfer. It should be used in conjunction with the \fB-username\fP option. .TP .B -proxyusername Pass a string with the user name to use for the transfer while connecting to Proxy. It should be used in same way as the \fB-proxyuserpwd\fP is used, except that it allows the username to contain a colon, like in the following example: "sip:user@example.com". Note the \fB-proxyusername\fP option is an alternative way to set the user name while connecting to Proxy. It doesn't make sense to use them together. .TP .B -proxypassword Pass a string with the password to use for the transfer while connecting to Proxy. It is meant to use together with \fB-proxyusername\fP. .TP .B -httpauth Set to the authentication method you want, the available ones are: .RS .TP 5 .B 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. .TP .B digest HTTP Digest authentication. Digest authentication is a more secure way to do authentication over public networks than the regular old-fashioned Basic method. .TP .B digestie HTTP Digest authentication with an IE flavor. TclCurl will use a special "quirk" that IE is known to have used before version 7 and that some servers require the client to use. .TP .B gssnegotiate HTTP GSS-Negotiate authentication. The GSS-Negotiate method, also known as plain "Negotiate",was designed by Microsoft and is used in their web applications. It is primarily meant as a support for Kerberos5 authentication but may be also used along with another authentication methods. .TP .B ntlm HTTP NTLM authentication. A proprietary protocol invented and used by Microsoft. It uses a challenge-response and hash concept similar to Digest, to prevent the password from being eavesdropped. .TP .B 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. 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\fP is set). This behavior is subject to change in future versions of libcurl. .TP .B any TclCurl will automatically select the one it finds most secure. .TP .B anysafe It may use anything but basic, TclCurl will automatically select the one it finds most secure. .RE .TP .B -tlsauthtype Use it to tell TclCurl which authentication method(s) you want it to use for TLS authentication. .RS .TP 5 .TP .B tlsauthsrp 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. To use TLS-SRP, you must also set the \fB-tlsauthusername\fP and \fB-tlsauthpassword\fP options. You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this to work. .RE .TP .B -tlsauthusername Pass a string with the username to use for the TLS authentication method specified with the \fB-tlsauthtype\fP option. Requires that the \fB-tlsauthpassword\fP option also be set. .TP .B -tlsauthpassword Pass a string with the password to use for the TLS authentication method specified with the \fB-tlsauthtype\fP option. Requires that the \fB-tlsauthusername\fP option also be set. .TP .B -proxyauth Use it to tell TclCurl which authentication method(s) you want it to use for your proxy authentication. Note that for some methods, this will induce an extra network round-trip. Set the actual name and password with the \fBproxyuserpwd\fP option. The methods are those listed above for the \fBhttpauth\fP option. As of this writing, only Basic and NTLM work. .SH HTTP options .TP .B -autoreferer Pass an 1 parameter to enable this. When enabled, TclCurl will automatically set the Referer: field in requests where it follows a Location: redirect. .TP .B -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. Three encodings are supported: \fIidentity\fP, which does nothing, \fIdeflate\fP which requests the server to compress its response using the zlib algorithm, and \fIgzip\fP which requests the gzip algorithm. Use \fIall\fP to send an Accept-Encoding: header containing all supported encodings. This is a request, not an order; the server may or may not do it. This option must be set or else any unsolicited encoding done by the server is ignored. See the special file lib/README.encoding in libcurl docs for details. .TP .B -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 response 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 \fB-encoding\fP 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. .TP .B -followlocation An 1 tells the library to follow any .B Location: header that the server sends as part of a HTTP header. This means that the extension will re-send the same request on the new location and follow new \fBLocation: headers\fP all the way until no more such headers are returned. \fB-maxredirs\fP can be used to limit the number of redirects TclCurl will follow. Since 7.19.4, TclCurl can limit what protocols it will automatically follow. The accepted protocols are set with \fB-redirprotocols\fP and it excludes the FILE protocol by default. .TP .B -unrestrictedauth An 1 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 \fB-followlocation\fP. .TP .B -maxredirs Sets the redirection limit. If that many redirections have been followed, the next redirect will cause an error. This option only makes sense if the \fB-followlocation\fP option is used at the same time. Setting the limit to 0 will make libcurl refuse any redirect. Set it to \-1 for an infinite number of redirects (which is the default) .TP .B -postredir Controls how TclCurl acts on redirects after POSTs that get a 301, 302 or 303 response back. A "301" parameter tells TclCurl to keep POST requests as POST when following a 301 redirect. Passing a "302" makes TclCurl maintain the request method after a 302 redirect, while "303" does the same for a 303 redirect. "all" is a convenience string that activates all three behaviours. The non-RFC behaviour is ubiquitous in web browsers, so the extension does the 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 setting \fB-followlocation\fP The legacy alias \fB-post301\fP is accepted for compatibility and uses the same values. .TP .B -put An 1 parameter tells the extension to use HTTP PUT a file. The file to put must be set with \fB-infile\fP and \fB-infilesize\fP. This option is deprecated starting with version 0.12.1, you should use \fB-upload\fP. This option does not limit how much data TclCurl will actually send, as that is controlled entirely by what the read callback returns. .TP .B -post An 1 parameter tells the library to do a regular HTTP post. This is a normal application/x-www-form-urlencoded kind, which is the most commonly used one by HTML forms. See the \fB-postfields\fP option for how to specify the data to post and \fB-postfieldsize\fP about how to set the data size. Use the \fB-postfields\fP option to specify what data to post and \fB-postfieldsize\fP to set the data size. Optionally, you can provide data to POST using the \fB-readproc\fP options. You can override the default POST Content-Type: header by setting your own with \fB-httpheader\fP. Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with \fB-httpheader\fP as usual. If you use POST to a HTTP 1.1 server, you can send data without knowing the size before starting the POST if you use chunked encoding. You enable this by adding a header like "Transfer-Encoding: chunked" with \fB-httpheader\fP. With HTTP 1.0 or without chunked transfer, you must specify the size in the request. When setting \fBpost\fP to an 1 value, it will automatically set \fBnobody\fP to 0. NOTE: if you have issued a POST request and want to make a HEAD or GET instead, you must explicitly pick the new request type using \fB-nobody\fP or \fB-httpget\fP or similar. .TP .B -postfields Pass a string as parameter, which should be the full data to post in a HTTP POST operation. You must make sure that the data is formatted the way you want the server to receive it. TclCurl will not convert or encode it for you. Most web servers will assume this data to be url-encoded. This is a normal application/x-www-form-urlencoded kind, which is the most commonly used one by HTML forms. If you want to do a zero-byte POST, you need to set \fB-postfieldsize\fP explicitly to zero, as simply setting \fB-postfields\fP to NULL or "" just effectively disables the sending of the specified string. TclCurl will instead assume that the POST data will be sent using the read callback! Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with \fB-httpheader\fP as usual. \fBNote\fP: to make multipart/formdata posts (aka rfc1867-posts), check out \fB-httppost\fP option. .TP .B -postfieldsize If you want to post data to the server without letting TclCurl do a strlen() to measure the data size, this option must be used. Also, when this option is used, you can post fully binary data which otherwise is likely to fail. If this size is set to zero, the library will use strlen() to get the data size. .TP .B -httppost Tells TclCurl you want a multipart/formdata HTTP POST to be made and you instruct what data to pass on to the server through a .B Tcl list. \fBThis is the only case where the data is reset after a transfer.\fP First, there are some basics you need to understand about multipart/formdata posts. Each part consists of at least a \fBNAME\fP and a \fBCONTENTS\fP part. If the part is made for file upload, there are also a stored \fBCONTENT-TYPE\fP and a \fBFILENAME\fP. Below, we'll discuss which options set these properties in the parts you want to add to your post. The list must contain a \fB'name'\fP tag with the name of the section followed by a string with the name, there are three tags to indicate the value of the section: \fB'value'\fP followed by a string with the data to post, \fB'file'\fP followed by the name of the file to post and \fB'contenttype'\fP with the type of the data (text/plain, image/jpg, ...), you can also indicate a \fIfalse\fP file name with \fB'filename'\fP, this is useful in case the server checks if the given file name is valid, for example, by testing if it starts with 'c:\\' as any real file name does or if you want to include the full path of the file to post. You can also post the content of a variable as if it were a file with the options \fB'bufferName'\fP and \fB'buffer'\fP or use \fB'filecontent'\fP followed by a file name to read that file and use the contents as data. Should you need to specify extra headers for the form POST section, use \fB'contentheader\fP' followed by a list with the headers to post. Please see 'httpPost.tcl' and 'httpBufferPost.tcl' for examples. If TclCurl can't set the data to post an error will be returned: .RS .TP 5 .B 1 If the memory allocation fails. .TP .B 2 If one option is given twice for one form. .TP .B 3 If an empty string was given. .TP .B 4 If an unknown option was used. .TP .B 5 If the some form info is not complete (or error) .TP .B 6 If an illegal option is used in an array. .TP .B 7 TclCurl has no http support. .RE .TP .B -referer Pass a string as parameter. It will be used to set the .B referer header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with .B -httpheader. .TP .B -useragent Pass a string as parameter. It will be used to set the .B user-agent: header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with .B -httpheader. .TP .B -httpheader Pass a .B list with the HTTP headers to pass to the server in your request. If you add a header that is otherwise generated and used by TclCurl internally, your added one will be used instead. If you add a header with no contents as in 'Accept:', the internally used header will just get disabled. Thus, using this option you can add new headers, replace and remove internal headers. The headers included in the linked list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. Failure to comply with this will result in strange bugs because the server will most likely ignore part of the headers you specified. The first line in a request (containing the method, usually a GET or POST) is not a header and cannot be replaced using this option. Only the lines following the request-line are headers. Adding this method line in this list of headers will only cause your request to send an invalid header. \fBNOTE\fP:The most commonly replaced headers have "shortcuts" in the options: .B cookie, useragent, and .B referer. .TP .B -http200aliases Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers respond with a custom header response line. For example, IceCast servers respond with "ICY 200 OK". By including this string in your list of aliases, the response will be treated as a valid HTTP header line such as "HTTP/1.0 200 OK". \fBNOTE\fP:The alias itself is not parsed for any version strings. Before version 7.16.3, TclCurl used the value set by option \fBhttpversion\fP, but starting with 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matched. .TP .B -cookie Pass a string as parameter. It will be used to set a cookie in the http request. The format of the string should be '[NAME]=[CONTENTS];'. Where NAME is the cookie name and CONTENTS is what the cookie should contain. If you need to set mulitple cookies, you need to set them all using a single option and thus you need to concatenate them all in one single string. Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc. This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are done due to authentication, followed redirections or similar, they will all get this cookie passed on. Using this option multiple times will only make the latest string override the previous ones. .TP .B -cookiefile Pass a string as parameter. It should contain the name of your file holding cookie data. The cookie data may be in netscape cookie data format or just regular HTTP-style headers dumped to a file. Given an empty or non-existing file, this option will enable cookies for this curl handle, making it understand and parse received cookies and then use matching cookies in future requests. If you use this option multiple times, you add more files to read. .TP .B -cookiejar Pass a file name in which TclCurl will dump all internally known cookies when .B curlHandle cleanup is called. If no cookies are known, no file will be created. Specify "-" to have the cookies written to stdout. Using this option also enables cookies for this session, so if you, for example, follow a location it will make matching cookies get sent accordingly. TclCurl will not and cannot report an error for this. Using '\fBverbose\fP' will get a warning to display, but that is the only visible feedback you get about this possibly lethal situation. .TP .B -cookiesession Pass an 1 to mark this as a new cookie "session". It will force TclCurl to ignore all cookies it is about to load that are "session cookies" from the previous session. By default, TclCurl always stores and loads all cookies, independent of whether they are session cookies are not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this "session" only. .TP .B -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. If the cookie engine was not enabled it will be enabled. Passing a magic string "ALL" will erase all known cookies while "FLUSH" will write all cookies known by TclCurl to the file specified by \fB-cookiejar\fP. .TP .B -httpget If set to 1 forces the HTTP request to get back to GET, usable if POST, PUT or a custom request have been used previously with the same handle. When setting \fBhttpget\fP to 1, \fBnobody\fP will automatically be set to 0. .TP .B -httpversion Set to one of the values decribed below, they force TclCurl to use the specific http versions. It should only be used if you really MUST do that because of a silly remote server. .RS .TP 5 .B none We do not care about what version the library uses. TclCurl will use whatever it thinks fit. .TP .B 1.0 Enforce HTTP 1.0 requests. .TP .B 1.1 Enforce HTTP 1.1 requests. .TP .B 2.0 Enforce HTTP version 2 requests. .TP .B 2TLS Enforce version 2 requests for HTTPS, version 1.1 for HTTP. .TP .B 2_PRIOR_KNOWLEDGE Enforce HTTP 2 requests without performing HTTP/1.1 Upgrade first. .RE .TP .B -ignorecontentlength 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. If this option is used, TclCurl will not be able to accurately report progress, and will simply stop the download when the server ends the connection. .TP .B -httpcontentdecoding Set to zero to disable content decoding. If set to 1 it is enabled. Note however that TclCurl has no default content decoding but requires you to use \fBencoding\fP for that. .TP .B -httptransferencoding Set to zero to disable transfer decoding, if set to 1 it is enabled (default). TclCurl does chunked transfer decoding by default unless this option is set to zero. .SH SMTP options .TP .B -mailfrom Pass a string to specify the sender address in a mail when sending an SMTP mail with TclCurl. .TP .B -mailrcpt Pass a list of recipients to pass to the server in your SMTP mail request. Each recipient in SMTP lingo is specified with angle brackets (<>), but should you not use an angle bracket as first letter, TclCurl will assume you provide a single email address only and enclose that with angle brackets for you. .SH TFTP option .TP .B tftpblksize Specify the block size to use for TFTP data transmission. Valid range as per RFC 2348 is 8-65464 bytes. The default of 512 bytes will be used if this option is not specified. The specified block size will only be used pending support by the remote server. If the server does not return an option acknowledgement or returns an option acknowledgement with no blksize, the default of 512 bytes will be used. .SH FTP options .TP .B -ftpport Pass a string as parameter. It will be used to get the IP address to use for the ftp PORT instruction. The PORT instruction tells the remote server to connect to our specified IP address. The string may be a plain IP address, a host name, a network interface name (under unix) or just a '-' to let the library use your systems default IP address. Default FTP operations are passive, and thus will not use PORT. The address can be followed by a ':' to specify a port, optionally followed by a '-' o specify a port range. If the port specified is 0, the operating system will pick a free port. If a range is provided and all ports in the range are not available, libcurl will report CURLE_FTP_PORT_FAILED for the handle. Invalid port/range settings are ignored. IPv6 addresses followed by a port or portrange have to be in brackets. IPv6 addresses without port/range specifier can be in brackets. Examples with specified ports: eth0:0 192.168.1.2:32000-33000 curl.se:32123 [::1]:1234-4567 You disable PORT again and go back to using the passive version by setting this option to an empty string. .TP .B -quote Pass a \fBlist\fP list with the FTP or SFTP commands to pass to the server prior to your ftp request. This will be done before any other FTP commands are issued (even before the CWD command).If you do not want to transfer any files, set \fBnobody\fP to '1' and \fBheader\fP to '0'. Prefix the command with an asterisk (*) to make TclCurl continue even if the command fails as by default TclCurl will stop. Disable this operation again by setting an empty string to this option. Keep in mind the commands to send must be 'raw' ftp commands, for example, to create a directory you need to send \fBmkd Test\fP, not \fBmkdir Test\fP. Valid SFTP commands are: chgrp, chmod, chown, ln, mkdir, pwd, rename, rm, rmdir and symlink. .TP .B -postquote Pass a \fBlist\fP with the FTP commands to pass to the server after your ftp transfer request. If you do not want to transfer any files, set \fBnobody\fP to '1' and \fBheader\fP to '0'. .TP .B -prequote Pass a \fBlist\fP of FTP or SFTP commands to pass to the server after the transfer type is set. .TP .B -dirlistonly A 1 tells the library to just list the names of files in a directory, instead of doing a full directory listing that would include file sizes, dates etc. It works with both FTP and SFTP urls. This causes an FTP NLST command to be sent. Beware that some FTP servers list only files in their response to NLST, they might not include subdirectories and symbolic links. Setting this option to 1 also implies a directory listing even if the URL doesn't end with a slash, which otherwise is necessary. Do NOT use this option if you also use \fB-wildcardmatch\fP as it will effectively break that feature. .TP .B -append A 1 parameter tells the extension to append to the remote file instead of overwriting it. This is only useful when uploading to a ftp site. .TP .B -ftpusepret Set to 1 to tell TclCurl to use the EPRT (and LPRT) command when doing active FTP downloads (which is enabled by '\fBftpport\fP'). 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. .TP .B -ftpuseepvs Set to one to tell TclCurl to use the EPSV command when doing passive FTP downloads (which it always does by default). Using EPSV means that it will first attempt to use EPSV before using PASV, but if you pass a zero to this option, it will not try using EPSV, only plain PASV. .TP .B -ftpusepret Set to one to tell TclCurl to send a PRET command before PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard command for directory listings as well as up and downloads in PASV mode. Has no effect when using the active FTP transfers mode. .TP .B -ftpcreatemissingdirs If set to 1, TclCurl will attempt to create any remote directory that it fails to CWD into. CWD is the command that changes working directory. This setting also applies to SFTP-connections. TclCurl will attempt to create the remote directory if it can't obtain a handle to the target-location. The creation will fail if a file of the same name as the directory to create already exists or lack of permissions prevents creation. If set to 2, TclCurl will retry the CWD command again if the subsequent MKD command fails. This is especially useful if you're doing many simultanoeus connections against the same server and they all have this option enabled, as then CWD may first fail but then another connection does MKD before this connection and thus MKD fails but trying CWD works .TP .B -ftpresponsetimeout Causes TclCurl to set a timeout period (in seconds) 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. Note that while TclCurl is waiting for a response, this value overrides \fBtimeout\fP. It is recommended that if used in conjunction with \fBtimeout\fP, you set it to a value smaller than \fBtimeout\fP. .TP .B -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. .TP .B -ftpskippasvip If set to 1, 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. This option has no effect if PORT, EPRT or EPSV is used instead of PASV. .TP .B -ftpsslauth Pass TclCurl one of the values from below, to alter how TclCurl issues "AUTH TLS" or "AUTH SSL" when FTP over SSL is activated (see \fB-ftpssl\fP). You may need this option because of servers like BSDFTPD-SSL from http://bsdftpd-ssl.sc.ru/ "which won't work properly when "AUTH SSL" is issued (although the server responds fine and everything) but requires "AUTH TLS" instead. .RS .TP 5 .B default Allows TclCurl to decide. .TP .B ssl Try "AUTH SSL" first, and only if that fails try "AUTH TLS". .TP .B tls Try "AUTH TLS" first, and only if that fails try "AUTH SSL". .RE .TP .B -ftpsslccc Set it to make TclCurl use CCC (Clear Command Channel). It shuts down the SSL/TLS layer after authenticating. The rest of the control channel communication will be unencrypted. This allows NAT routers to follow the FTP transaction. Possible values are: .RS .TP 5 .B none Do not attempt to use CCC. .TP .B passive Do not initiate the shutdown, wait for the server to do it. Do not send a reply. .TP .B active Initiate the shutdown and wait for a reply. .RE .TP .B -ftpaccount Pass string (or "" to disable). When an FTP server asks for "account data" after user name and password has been provided, this data is sent off using the ACCT command. .TP .B -ftpfilemethod It allows three values: .RS .TP 5 .B 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. .TP .B nocwd No CWD at all is done, TclCurl will do SIZE, RETR, STOR, etc and give a full path to the server. .TP .B singlecwd Make one CWD with the full target directory and then operate on the file "normally". This is somewhat more standards compliant than 'nocwd' but without the full penalty of 'multicwd'. .RE .SH Protocol options .TP .B -transfertext A 1 tells the extension to use ASCII mode for ftp transfers, instead of the default binary transfer. For win32 systems it does not set the stdout to binary mode. This option can be usable when transferring text data between systems with different views on certain characters, such as newlines or similar. \fBNOTE:\fP TclCurl does not do a complete ASCII conversion when doing ASCII transfers over FTP. This is a known limitation/flaw that nobody has rectified. TclCurl simply sets the mode to ascii and performs a standard transfer. .TP .B -proxytransfermode If set to 1, TclCurl sets 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 it being set to 0, the default, \fB-transfertext\fP has no effect when doing FTP via a proxy. Beware that not all proxies support this feature. .TP .B -crlf If set to '1', TclCurl converts Unix newlines to CRLF newlines on transfers. Disable this option again by setting the value to '0'. .TP .B -range Pass a string as parameter, which should contain the specified range you want. It should be in the format .I "X-Y" , where X or Y may be left out. HTTP transfers also support several intervals, separated with commas as in .I "X-Y,N-M" Using this kind of multiple intervals will cause the HTTP server to send the response document in pieces (using standard MIME separation techniques). Ranges only work on HTTP, FTP and FILE transfers. .TP .B -resumefrom Pass the offset in number of bytes that you want the transfer to start from. Set this option to 0 to make the transfer start from the beginning (effectively disabling resume). For FTP, set this option to \-1 to make the transfer start from the end of the target file (useful to continue an interrupted upload). When doing uploads with FTP, the resume position is where in the local/source file TclCurl should try to resume the upload from and it will then append the source file to the remote target file. .TP .B -customrequest Pass a string as parameter. It will be used instead of GET or HEAD when doing the HTTP request. This is useful for doing DELETE or other more obscure HTTP requests. Do not do this at will, make sure your server supports the command first. Note that TclCurl will still act and assume the keyword it would use if you do not set your custom and it will act according to that. Thus, changing this to a HEAD when TclCurl otherwise would do a GET might cause TclCurl to act funny, and similar. To switch to a proper HEAD, use \fB-nobody\fP, to switch to a proper POST, use \fB-post\fP or \fB-postfields\fP and so on. .TP .B -filetime If you pass a 1, TclCurl will attempt to get the modification date of the remote document in this operation. This requires that the remote server sends the time or replies to a time querying command. The getinfo procedure with the .I filetime argument can be used after a transfer to extract the received time (if any). .TP .B -nobody A 1 tells the library not to include the body-part in the output. This is only relevant for protocols that have a separate header and body part. On HTTP(S) servers, this will make TclCurl do a HEAD request. To change request to GET, you should use \fBhttpget\fP. Change request to POST with \fBpost\fP etc. .TP .B -infilesize When uploading a file to a remote site, this option should be used to tell TclCurl what the expected size of the infile is. This option is mandatory for uploading using SCP. .TP .B -upload A 1 tells the library to prepare for an upload. The \fB-infile\fP and \fB-infilesize\fP options are also interesting 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 \fB-httpheader\fP 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 \fB-httpheader\fP. With HTTP 1.0 or without chunked transfer, you must specify the size. .TP .B -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. .TP .B -timecondition This defines how the \fBtimevalue\fP value is treated. You can set this parameter to \fBifmodsince\fP or \fBifunmodsince\fP. This feature applies to HTTP, FTP and FILE. .TP .B -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\fP. .SH Connection options .TP .B -timeout Pass the maximum time in seconds that you allow the TclCurl transfer operation to take. Do note that normally, name lookups may take a considerable time and that limiting the operation to less than a few minutes risks aborting perfectly normal operations. This option will cause libcurl to use the SIGALRM to enable time-outing system calls. In unix-like systems, this might cause signals to be used unless \fB-nosignal\fP is used. .TP .B -timeoutms Like \fBtimeout\fP but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. .TP .B -lowspeedlimit Pass the speed in bytes per second that the transfer should be below during .B lowspeedtime seconds for the extension to consider it too slow and abort. .TP .B -lowspeedtime Pass the time in seconds that the transfer should be below the .B lowspeedlimit for the extension to consider it too slow and abort. .TP .B -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. Defaults to unlimited speed. .TP .B -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. Defaults to unlimited speed. .TP .B -maxconnects Sets the persistent connection cache size in all the protocols that support persistent conecctions. The set amount will be the maximum amount of simultaneous connections that TclCurl may cache in this easy handle. Default is 5, and there isn't much point in changing this value unless you are perfectly aware of how this work and changes TclCurl's behaviour. When reaching the maximum limit, TclCurl closes the oldest connection in the cache to prevent the number of open connections to increase. \fBNote\fP: if you have already performed transfers with this curl handle, setting a smaller .B maxconnects than before may cause open connections to unnecessarily get closed. If you add this easy handle to a multi handle, this setting is not being acknowledged, instead you must configure the multi handle its own \fBmaxconnects\fP option. .TP .B -connecttimeout Maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once it has connected, this option is of no more use. Set to zero to disable connection timeout (it will then only timeout on the internal timeouts). In unix-like systems, this might cause signals to be used unless \fB-nosignal\fP is set. .TP .B -connecttimeoutms Like \fBconnecttimeout\fP but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. .TP .B -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. The allowed values are: .RS .TP 5 .B whatever Default, resolves addresses to all IP versions that your system allows. .TP .B v4 Resolve to ipv4 addresses. .TP .B v6 Resolve to ipv6 addresses. .RE .TP .B -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. This option effectively pre-populates the DNS cache with entries for the host+port pair so redirects and everything that operations against the HOST+PORT will instead use your provided ADDRESS. You can remove names from the DNS cache again, to stop providing these fake resolves, by including a string in the linked list that uses the format "\-HOST:PORT". The host name must be prefixed with a dash, and the host name and port number must exactly match what was already added previously. .TP .B -usessl Pass a one of the values from below to make TclCurl use your desired level of SSL for the transfer. This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc. You can use ftps:// URLs to explicitly switch on SSL/TSL for the control connection and the data connection. Alternatively you can set the option to one of these values: .RS .TP 5 .B nope Do not attempt to use SSL .TP .B try Try using SSL, proceed anyway otherwise. .TP .B control Use SSL for the control conecction or fail with "use ssl failed" (64). .TP .B all Use SSL for all communication or fail with "use ssl failed" (64). .RE .SH SSL and security options .TP .B -sslcert Pass a string as parameter. The string should be the file name of your certificate. The default format is "PEM" and can be changed with \fB-sslcerttype\fP. With NSS this is the nickname of the certificate you wish to authenticate with. If you want to use a file from the current directory, please precede it with the "./" prefix, in order to avoid confusion with a nickname. .TP .B -sslcerttype Pass a string as parameter. The string should be the format of your certificate. Supported formats are "PEM" and "DER". .TP .B -sslkey Pass a pointer to a zero terminated string as parameter. The string should be the file name of your private key. The default format is "PEM" and can be changed with \fB-sslkeytype\fP. .TP .B -sslkeytype Pass a pointer to a zero terminated string as parameter. The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG" \fBNOTE:\fPThe format "ENG" enables you to load the private key from a crypto engine. in this case \fB-sslkey\fP is used as an identifier passed to the engine. You have to set the crypto engine with \fB-sslengine\fP. The "DER" format key file currently does not work because of a bug in OpenSSL. .TP .B -keypasswd Pass a string as parameter. It will be used as the password required to use the \fB-sslkey\fP or \fB-sshprivatekeyfile\fP private key. You never need a pass phrase to load a certificate but you need one to load you private key. This option used to be known as \fB-sslkeypasswd\fP and \fB-sslcertpasswd\fP. .TP .B -sslengine Pass a string as parameter. It will be used as the identifier for the crypto engine you want to use for your private key. \fBNOTE:\fPIf the crypto device cannot be loaded, an error will be returned. .TP .B -sslenginedefault Pass a 1 to set the actual crypto engine as the default for (asymmetric) crypto operations. \fBNOTE:\fPIf the crypto device cannot be set, an error will be returned. .TP .B -sslversion Use it to set what version of SSL/TLS to use. The available options are: .RS .TP 5 .B default The default action. This will attempt to figure out the remote SSL protocol version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled by default with 7.18.1). .TP .B tlsv1 Force TLSv1 or later .TP .B sslv2 Force SSLv2 .TP .B sslv3 Force SSLv3 .TP .B tlsv1_0 Force TLSv1.0 or later .TP .B tlsv1_1 Force TLSv1.1 or later .TP .B tlsv1_2 Force TLSv1.2 or later .TP .B tlsv1_3 Force TLSv1.3 or later .TP .B maxdefault Use the maximum supported TLS version by libcurl or the default value from the SSL library. .TP .B maxtlsv1_0 Define maximum supported TLS version as TLSv1.0 .TP .B maxtlsv1_1 Define maximum supported TLS version as TLSv1.1 .TP .B maxtlsv1_2 Define maximum supported TLS version as TLSv1.2 .TP .B maxtlsv1_3 Define maximum supported TLS version as TLSv1.3 .RE .TP .B -sslverifypeer This option determines whether TclCurl verifies the authenticity of the peer's certificate. A 1 means it verifies; zero means it doesn't. The default is 1. When negotiating an SSL connection, the server sends a certificate indicating its identity. TclCurl verifies whether the certificate is authentic, i.e. that you can trust that the server is who the certificate says it is. This trust is based on a chain of digital signatures, rooted in certification authority (CA) certificates you supply. TclCurl uses a default bundle of CA certificates that comes with libcurl but you can specify alternate certificates with the \fB-cainfo\fP or the \fB-capath\fP options. When \fB-sslverifypeer\fP is nonzero, and the verification fails to prove that the certificate is authentic, the connection fails. When the option is zero, the peer certificate verification succeeds regardless. Authenticating the certificate is not by itself very useful. You typically want to ensure that the server, as authentically identified by its certificate, is the server you mean to be talking to, use \fB-sslverifyhost\fP to control that. The check that the host name in the certificate is valid for the host name you're connecting to is done independently of this option. .TP .B -cainfo Pass a file naming holding the certificate to verify the peer with. This only makes sense when used in combination with the \fB-sslverifypeer\fP option, if it is set to zero \fB-cainfo\fP need not even indicate an accessible file. This option is by default set to the system path where libcurl's cacert bundle is assumed to be stored, as established at build time. When built against NSS this is the directory that the NSS certificate database resides in. .TP .B -issuercert Pass a string naming a file holding a CA certificate in PEM format. If the option is set, an additional check against the peer certificate is performed to verify the issuer is indeed the one associated with the certificate provided by the option. This additional check is useful in multi-level PKI where one need to enforce the peer certificate is from a specific branch of the tree. This option makes sense only when used in combination with the \fB-sslverifypeer\fP option. Otherwise, the result of the check is not considered as failure. .TP .B -capath Pass the directory holding multiple CA certificates to verify the peer with. If libcurl is built against OpenSSL, the certificate directory must be prepared using the openssl c_rehash utility. This only makes sense when used in combination with the \fB-sslverifypeer\fP option, if it is set to zero, \fB-capath\fP need not even indicate an accessible path. This option apparently does not work in Windows due to some limitation in openssl. This option is OpenSSL-specific and does nothing if libcurl is built to use GnuTLS. NSS-powered libcurl provides the option only for backward compatibility. .TP .B -crlfile Pass a string naming a file with the concatenation of CRL (in PEM format) to use in the certificate validation that occurs during the SSL exchange. When libcurl is built to use NSS or GnuTLS, there is no way to influence the use of CRL passed to help in the verification process. When built with OpenSSL support, X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are both set, requiring CRL check against all the elements of the certificate chain if a CRL file is passed. This option makes sense only when used in combination with the \fB-sslverifypeer\fP option. A specific error code (CURLE_SSL_CRL_BADFILE) is defined with the option. It is returned when the SSL exchange fails because the CRL file cannot be loaded. A failure in certificate verification due to a revocation information found in the CRL does not trigger this specific error. .TP .B -sslverifyhost This option determines whether TclCurl verifies that the server claims to be who you want it to be. When negotiating an SSL connection, the server sends a certificate indicating its identity. When \fB-sslverifyhost\fP is set to 2, that certificate must indicate that the server is the server to which you meant to connect, or the connection fails. TclCurl considers the server the intended one when the Common Name field or a Subject Alternate Name field in the certificate matches the host name in the URL to which you told Curl to connect. When set to 1, the certificate must contain a Common Name field, but it does not matter what name it says. (This is not ordinarily a useful setting). When the value is 0, the connection succeeds regardless of the names in the certificate. The default value for this option is 2. This option controls the identity that the server \fIclaims\fP. The server could be lying. To control lying, see \fB-sslverifypeer\fP. If libcurl is built against NSS and \fB-verifypeer\fP is zero, \fB-verifyhost\fP is ignored. .TP .B -certinfo Set to '1' to enable TclCurl's certificate chain info gatherer. With this enabled, TclCurl (if built with OpenSSL) will extract lots of information and data about the certificates in the certificate chain used in the SSL connection. This data can then be to extracted after a transfer using the \fBgetinfo\fP command and its option \fBcertinfo\fP. .TP .B -randomfile Pass a file name. The file will be used to read from to seed the random engine for SSL. The more random the specified file is, the more secure the SSL connection becomes. .TP .B -egdsocket Pass a path name to the Entropy Gathering Daemon socket. It will be used to seed the random engine for SSL. .TP .B -sslcypherlist Pass a string holding the ciphers to use for the SSL connection. The list must consists of one or more cipher strings separated by colons. Commas or spaces are also acceptable separators but colons are normally used, , - and + can be used as operators. For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA', 'SHA1+DES', \&'TLSv1' and 'DEFAULT'. The default list is normally set when you compile OpenSSL. You will find more details about cipher lists on this URL: http://www.openssl.org/docs/apps/ciphers.html For NSS valid examples of cipher lists include 'rsa_rc4_128_md5', 'rsa_aes_128_sha', etc. With NSS you don't add/remove ciphers. If you use this option then all known ciphers are disabled and only those passed in are enabled. You'll find more details about the NSS cipher lists on this URL: .TP .B -sslsessionidcache Pass a 0 to disable TclCurl's use of SSL session-ID caching or a 1 to enable it. By default all transfers are done using the cache. While nothing ever should get hurt by attempting to reuse SSL session-IDs, there seem to be broken SSL implementations in the wild that may require you to disable this in order for you to succeed. .TP .B -krblevel Set the kerberos security level for FTP, this also enables kerberos awareness. This is a string, 'clear', 'safe', 'confidential' or 'private'. If the string is set but does not match one of these, 'private' will be used. Set the string to NULL to disable kerberos4. Set the string to "" to disable kerberos support for FTP. .TP .B -gssapidelegation Set the option to 'flag' to allow unconditional GSSAPI credential delegation. The delegation is disabled by default since 7.21.7. 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. .SH SSH options .TP .B -sshauthtypes The allowed types are: .RS .TP 5 .B publickey .TP .B password .TP .B host .TP .B keyboard .TP .B any To let TclCurl pick one .RE .TP .B -sshhostpublickeymd5 Pass a string containing 32 hexadecimal digits. The string should be the 128 bit MD5 cheksum of the remote host public key, and TclCurl will reject the connection to the host unless the md5sums match. This option is only for SCP and SFTP transfers. .TP .B -publickeyfile Pass the file name for your public key. If not used, TclCurl defaults to using \fB$HOME/.ssh/id_dsa.pub\fP. HOME environment variable is set, and just \fBid_dsa\fP in the current directory if not. .TP .B -privatekeyfile Pass the file name for your private key. If not used, TclCurl defaults to using \fB$HOME/.ssh/id_dsa.pub\fP. HOME environment variable is set, and just \fBid_dsa\fP in the current directory if not. If the file is password-protected, set the password with \fB-keypasswd\fP. .TP .B -sshknownhosts Pass a string holding the file name of the known_host file to use. The known_hosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, TclCurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use \fB-sshkeyproc\fP to alter the default behavior on host and key (mis)matching. .TP .B -sshkeyproc Pass a the name of the procedure that will be called when the known_host matching has been done, to allow the application to act and decide for TclCurl how to proceed. The callback will only be called if \fB-knownhosts\fP is also set. It gets passed a list with three elements, the first one is a list with the type of the key from the known_hosts file and the key itself, the second is another list with the type of the key from the remote site and the key itslef, the third tells you what TclCurl thinks about the matching status. The known key types are: "rsa", "rsa1" and "dss", in any other case "unknown" is given. TclCurl opinion about how they match may be: "match", "mismatch", "missing" or "error". The procedure must return: .RS .TP 5 .B 0 The host+key is accepted and TclCurl will append it to the known_hosts file before continuing with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. The adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this. .TP .B 1 The host+key is accepted, TclCurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. .TP .B 2 The host+key is rejected. TclCurl will close the connection. .TP .B 3 The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again. .RE Any other value will cause the connection to be closed. .SH Other options .TP .B -headervar Name of the Tcl array variable where TclCurl will store the headers returned by the server. .TP .B -bodyvar Name of the Tcl variable where TclCurl will store the file requested, the file may contain text or binary data. .TP .B -canceltransvar Name of a Tcl variable, in case you have defined a procedure to call with \fB-progressproc\fP setting this variable to '1' will cancel the transfer. .TP .B -command Executes the given command after the transfer is done, since it only works with blocking transfers, it is pretty much useless. .TP .B -share Pass a share handle as a parameter. The share handle must have been created by a previous call to \fBcurl::shareinit\fP. Setting this option, will make this handle use the data from the shared handle instead of keeping the data to itself. See \fItclcurl_share\fP for details. .TP .B -newfileperms Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created files on the remote server. The default value is 0644, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. .TP .B -newdirectoryperms Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created directories on the remote server. The default value is 0755, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. .SH Telnet options .TP .B -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. .SH 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: .sp .B CURLOPT_FRESH_CONNECT, CURLOPT_FORBID_REUSE, CURLOPT_PRIVATE, .B CURLOPT_SSL_CTX_FUNCTION, CURLOPT_SSL_CTX_DATA, CURLOPT_SSL_CTX_FUNCTION and .B CURLOPT_CONNECT_ONLY, CURLOPT_OPENSOCKETFUNCTION, CURLOPT_OPENSOCKETDATA. .SH curlHandle perform This procedure is called after the .B init and all the .B configure calls are made, and will perform the transfer as described in the options. .sp It must be called with the same \fIcurlHandle\fP \fBcurl::init\fP 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 .I configure between the invokes to set options for the following perform. .sp 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 .B RETURN VALUE \&'0' if all went well, non-zero if it didn't. In case of error, if the .I errorbuffer was set with .I configure there will be a readable error message. The error codes are: .IP 1 Unsupported protocol. This build of TclCurl has no support for this protocol. .IP 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. .IP 3 URL malformat. The syntax was not correct. .IP 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. .IP 5 Couldn't resolve proxy. The given proxy host could not be resolved. .IP 6 Couldn't resolve host. The given remote host was not resolved. .IP 7 Failed to connect to host or proxy. .IP 8 FTP weird server reply. The server sent data TclCurl couldn't parse. The given remote server is probably not an OK FTP server. .IP 9 We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory. .IP 11 FTP weird PASS reply. TclCurl couldn't parse the reply sent to the PASS request. .IP 13 FTP weird PASV reply, TclCurl couldn't parse the reply sent to the PASV or EPSV request. .IP 14 FTP weird 227 format. TclCurl couldn't parse the 227-line the server sent. .IP 15 FTP can't get host. Couldn't resolve the host IP we got in the 227-line. .IP 17 FTP couldn't set type. Couldn't change transfer method to either binary or ascii. .IP 18 Partial file. Only a part of the file was transfered, this happens when the server first reports an expected transfer size and then delivers data that doesn't match the given size. .IP 19 FTP couldn't RETR file, we either got a weird reply to a 'RETR' command or a zero byte transfer. .IP 21 Quote error. A custom 'QUOTE' returned error code 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command. .IP 22 HTTP returned error. This return code only appears if \fB-failonerror\fP is used and the HTTP server returns an error code that is 400 or higher. .IP 23 Write error. TclCurl couldn't write data to a local filesystem or an error was returned from a write callback. .IP 25 Failed upload failed. For FTP, the server typcially denied the STOR command. The error buffer usually contains the server's explanation to this. .IP 26 Read error. There was a problem reading from a local file or an error was returned from the read callback. .IP 27 Out of memory. A memory allocation request failed. This should never happen unless something weird is going on in your computer. .IP 28 Operation timeout. The specified time-out period was reached according to the conditions. .IP 30 The FTP PORT command failed, not all FTP servers support the PORT command, try doing a transfer using PASV instead!. .IP 31 FTP couldn't use REST. This command is used for resumed FTP transfers. .IP 33 Range error. The server doesn't support or accept range requests. .IP 34 HTTP post error. Internal post-request generation error. .IP 35 SSL connect error. The SSL handshaking failed, the error buffer may have a clue to the reason, could be certificates, passwords, ... .IP 36 The download could not be resumed because the specified offset was out of the file boundary. .IP 37 A file given with FILE:// couldn't be read. Did you checked the permissions? .IP 38 LDAP cannot bind. LDAP bind operation failed. .IP 39 LDAP search failed. .IP 41 A required zlib function was not found. .IP 42 Aborted by callback. An application told TclCurl to abort the operation. .IP 43 Internal error. A function was called with a bad parameter. .IP 45 Interface error. A specified outgoing interface could not be used. .IP 47 Too many redirects. When following redirects, TclCurl hit the maximum amount, set your limit with \-\-maxredirs .IP 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. .IP 49 A telnet option string was illegally formatted. .IP 51 The remote peer's SSL certificate or SSH md5 fingerprint wasn't ok .IP 52 The server didn't reply anything, which here is considered an error. .IP 53 The specified crypto engine wasn't found. .IP 54 Failed setting the selected SSL crypto engine as default! .IP 55 Failed sending network data. .IP 56 Failure with receiving network data. .IP 58 Problem with the local client certificate. .IP 59 Couldn't use specified SSL cipher. .IP 60 Peer certificate cannot be authenticated with known CA certificates. .IP 61 Unrecognized transfer encoding. .IP 62 Invalid LDAP URL. .IP 63 Maximum file size exceeded. .IP 64 SSL use failed. .IP 65 Sending the data requires a rewind that failed, since TclCurl should take care of it for you, it means you found a bug. .IP 66 Failed to initialise ssl engine. .IP 67 Failed to login, user password or similar was not accepted. .IP 68 File not found on TFTP server. .IP 69 There is a permission problem with the TFTP request. .IP 70 The remote server has run out of space. .IP 71 Illegal TFTP operation. .IP 72 Unknown transfer ID. .IP 73 TFTP file already exists and will not be overwritten. .IP 74 No such user in the TFTP server and good behaving TFTP servers should never return this. .IP 75 Character conversion failed. .IP 77 Problem with reading the SSL CA cert (path? access rights?). .IP 78 Remote file not found .IP 79 Error from the SSH layer .IP 80 Failed to shut down the SSL connection .IP 82 Failed to load CRL file .IP 83 Issuer check failed .IP 84 The FTP server does not understand the PRET command at all or does not support the given argument. Be careful when using \fB-customrequest\fP, a custom LIST command will be sent with PRET CMD before PASV as well. .IP 85 Mismatch of RTSP CSeq numbers. .IP 86 Mismatch of RTSP Session Identifiers. .IP 87 Unable to parse FTP file list (during FTP wildcard downloading). .IP 88 Chunk callback reported error. .SH 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 \fBperform\fP returns 0. Use this function AFTER a performed transfer if you want to get transfer-oriented data. The following information can be extracted: .TP .B effectiveurl Returns the last used effective URL. .TP .B 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 \fBhttpconnectcode\fP and not this. .TP .B httpconnectcode Returns the last received proxy response code to a CONNECT request. .TP .B 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. .sp In order for this to work you have to set the \fB-filetime\fP option before the transfer. .TP .B namelookuptime Returns the time, in seconds, it took from the start until the name resolving was completed. .TP .B connecttime Returns the time, in seconds, it took from the start until the connect to the remote host (or proxy) was completed. .TP .B 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 .B 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 .B starttransfertime Returns the time, in seconds, it took from the start until the first byte is just about to be transfered. This includes the \fBpretransfertime\fP, and also the time the server needs to calculate the result. .TP .B totaltime Returns the total transaction time, in seconds, for the previous transfer, including name resolving, TCP connect etc. .TP .B redirecturl Returns the URL a redirect would take you to if you enable \fBfollowlocation\fP. 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. .TP .B 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 .B redirectcount Returns the total number of redirections that were actually followed. .TP .B numconnects Returns how many new connections TclCurl had to create to achieve the previous transfer (only the successful connects are counted). Combined with \fBredirectcount\fP you are able to know how many times TclCurl successfully reused existing connection(s) or not. See the Connection Options of \fBsetopt\fP to see how TclCurl tries to make persistent connections to save time. .TP .B primaryip Returns the IP address of the most recent connection done with this handle. This string may be IPv6 if that's enabled. .TP .B primaryport Returns the destination port of the most recent connection done with this handle. .TP .B 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. .TP .B localport Returns the local (source) port of the most recent connection done with this handle. .TP .B sizeupload Returns the total amount of bytes that were uploaded. .TP .B 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 .B speeddownload Returns the average download speed, measured in bytes/second, for the complete download. .TP .B speedupload Returns the average upload speed, measured in bytes/second, for the complete upload. .TP .B headersize Returns the total size in bytes of all the headers received. .TP .B 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 .B sslverifyresult Returns the result of the certification verification that was requested (using the \-sslverifypeer option to configure). .TP .B sslengines Returns a \fBlist\fP 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 .B contentlengthdownload Returns the content-length of the download. This is the value read from the .B Content-Length: field. If the size isn't known, it returns \-1. .TP .B contentlengthupload Returns the specified size of the upload. .TP .B 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. .TP .B httpauthavail Returns a list with the authentication method(s) available. .TP .B proxyauthavail Returns a list with the authentication method(s) available for your proxy athentication. .TP .B oserrno Returns the errno value from a connect failure. This value is only set on failure, it is no reset after a successfull operation. .TP .B 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 .B 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 .B certinfo Returns list with information about the certificate chain, assuming you had the \fB-certinfo\fP 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. .TP .B conditionunmet Returns the number 1 if the condition provided in the previous request didn't match (see \fItimecondition\fP), you will get a zero if the condition instead was met. .SH curlHandle cleanup This procedure must be the last one to call for a curl session. It is the opposite of the .I curl::init procedure and must be called with the same .I 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. .SH 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. .SH 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 .B cleanup. The new handle will not inherit any state information, connections, SSL sessions or cookies. .TP .B RETURN VALUE A new curl handle or an error message if the copy fails. .SH curlHandle pause You can use this command from within a progress callback procedure to pause the transfer. .SH curlHandle resume Resumes a transfer paused with \fBcurlhandle pause\fP .SH curl::transfer In case you do not want to use persistent connections you can use this command, it takes the same arguments as the \fIcurlHandle\fP \fBconfigure\fP and will init, configure, perform and cleanup a connection for you. You can also get the \fIgetinfo\fP information by using \fI-infooption variable\fP pairs, after the transfer \fIvariable\fP will contain the value that would have been returned by \fI$curlHandle getinfo option\fP. .TP .B RETURN VALUE The same error code \fBperform\fP would return. .SH curl::version Returns a string with the version number of tclcurl, libcurl and some of its important components (like OpenSSL version). .TP .B RETURN VALUE The string with the version info. .SH 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) .TP .B RETURN VALUE The converted string. .SH 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. .TP .B RETURN VALUE The string unencoded. .SH curl::curlConfig option Returns some information about how you have .B cURL installed. .TP .B -prefix Returns the directory root where you installed .B cURL .TP .B -feature Returns a list containing particular main features the installed .B libcurl was built with. The list may include SSL, KRB4 or IPv6, do not assume any particular order. .TP .B -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... .SH 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. .TP .B -version Returns the version of libcurl we are using. .TP .B -versionnum Retuns 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. .TP .B -host Returns a string with the host information as discovered by a configure script or set by the build environment. .TP .B -features Returns a list with the features compiled into libcurl, the possible elements are: .RS .TP 5 .B 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 .B CONV Libcurl was built with support for character conversions. .TP .B DEBUG Libcurl was built with extra debug capabilities built-in. This is mainly of interest for libcurl hackers. .TP .B GSSNEGOTIATE Supports HTTP GSS-Negotiate. .TP .B IDN Supports IDNA, domain names with international letters. .TP .B IPV6 Supports IPv6. .TP .B KERBEROS4 Supports kerberos4 (when using FTP). .TP .B LARGEFILE Libcurl was built with support for large files. .TP .B LIBZ Supports HTTP deflate using libz. .TP .B NTML Supports HTTP NTLM .TP .B SPNEGO Libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478) .TP .B SSL Supports SSL (HTTPS/FTPS) .TP .B 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. .TP .B TLSAUTH_SRP Libcurl was built with support for TLS-SRP. .B NTLM_WB Libcurl was built with support for NTLM delegation to a winbind helper. .RE Do not assume any particular order. .TP .B -sslversion Returns a string with the OpenSSL version used, like OpenSSL/0.9.6b. .TP .B -sslversionnum Returns the numerical OpenSSL version value as defined by the OpenSSL project. If libcurl has no SSL support, this is 0. .TP .B -libzversion Returns a string, there is no numerical version, for example: 1.1.3. .TP .B -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 This procedure returns a string describing the error code passed in the argument. .SH "SEE ALSO" .I curl, The art of HTTP scripting (at http://curl.haxx.se), RFC 2396, tclcurl-ng-8.0.1/doc/tclcurl.n.md000066400000000000000000003016761517264272000166100ustar00rootroot00000000000000--- title: TclCurl section: n date: 12 April 2026 source: TclCurl 8.0.1 volume: TclCurl Easy Interface --- # NAME TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. # SYNOPSIS ```tcl curl::init ``` ```tcl curlHandle configure ?options? ``` ```tcl curlHandle perform ``` ```tcl curlHandle getinfo curlinfo_option ``` ```tcl curlhandle cleanup ``` ```tcl curlhandle reset ``` ```tcl curlHandle duphandle ``` ```tcl curlHandle pause ``` ```tcl curlHandle resume ``` ```tcl curl::transfer ?options? ``` ```tcl curl::version ``` ```tcl curl::escape url ``` ```tcl curl::unescape url ``` ```tcl curl::curlConfig option ``` ```tcl curl::versioninfo option ``` ```tcl curl::easystrerror errorCode ``` # DESCRIPTION The TclCurl extension gives Tcl programmers access to the libcurl library written by **Daniel Stenberg**, with it you can download urls, upload them and many other neat tricks, for more information check # curl::init This procedure must be the first one to call, it returns a curlHandle that you need to use to invoke TclCurl procedures. The init calls intializes curl and this call MUST have a corresponding call to cleanup when the operation is completed. You should perform all your sequential file transfers using the same curlHandle. This enables TclCurl to use persistent connections when possible. **RETURN VALUE** curlHandle to use. # curlHandle configure ?options? **configure** is called to set the options for the transfer. Most operations in TclCurl have default actions, and by using the appropriate options you can make them behave differently (as documented). All options are set with the *option* followed by a parameter. **Notes:** the options set with this procedure are valid for the forthcoming data transfers that are 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 return code from the `curl::init` call. **OPTIONS** # Behaviour options -verbose : Set the parameter to 1 to get the library to display a lot of verbose information about its operations. Very useful for libcurl and/or protocol debugging and understanding. You hardly ever want this set in production use, you will almost always want this when you debug/report problems. Another neat option for debugging is **-debugproc** -header : A 1 tells the extension to include the headers in the body output. This is only relevant for protocols that actually have headers preceding the data (like HTTP). -noprogress : A 1 tells the extension to turn on the progress meter completely. It will also prevent the *progessproc* from getting called. -nosignal : A 1 tells TclCurl not use any functions that install signal handlers or any functions that cause signals to be sent to the process. This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals. If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals. Setting *nosignal* to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire. In addition, using *ntlm_Wb* authentication could cause a SIGCHLD signal to be raised. -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** option, using an fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name). By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function by the **-fnmatchproc** option. This feature is only supported by the FTP download for now. A brief introduction of its syntax follows: - * - ASTERISK ftp://example.com/some/path/***.txt** (for all txt's from the root directory) - ? - QUESTION MARK Question mark matches any (exactly one) 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 : Use it to set a Tcl procedure that will be invoked by TclCurl as soon as there is received data that needs to be saved. The procedure will receive a single parameter with the data to be saved. NOTE: you will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be nothing if the file is empty or it may be thousands of bytes. -file : File in which the transfered data will be saved. -readproc : Sets a Tcl procedure to be called by TclCurl as soon as it needs to read data in order to send it to the peer. The procedure has to take one parameter, which will contain the maximun numbers 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 "pre-maturely" (i.e before the server expected it, like when you've said you will upload N bytes and you upload less than N bytes), you may experience that the server "hangs" waiting for the rest of the data that won't come. Bugs: when doing TFTP uploads, you must return the exact amount of data that the callback wants, or it will be considered the final packet by the server end and the transfer will end there. -infile : File from which the data will be transfered. -progressproc : Name of the Tcl procedure that will invoked by TclCurl with a frequent interval during operation (roughly once per second or sooner), no matter if data is being transfered or not. Unknown/unused argument values passed to the callback will be set to zero (like if you only download data, the upload size will remain 0), the prototype of the procedure must be: **proc ProgressCallback {dltotal dlnow ultotal ulnow}** In order to this option to work you have to set the **noprogress** option to '0'. Setting this option to the empty string will restore 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 a the file name to be used to write the header part of the received data to. The headers are guaranteed to be written one-by-one to this file and only complete lines are written. Parsing headers should be easy enough using this. See also the **-headervar** option to get the headers into an array. -debugproc : Name of the procedure that will receive the debug data produced by the **-verbose** option, it should match the following prototype: **debugProc {infoType data}** where **infoType** specifies what kind of information it is (0 text, 1 incoming header, 2 outgoing header, 3 incoming data, 4 outgoing data, 5 incoming SSL data, 6 outgoing SSL data). -chunkbgnproc : Name of the procedure that will be called before a file will be transfered by ftp, it should match the following prototype: **ChunkBgnProc {remains}** Where remains is the number of files left to be transfered (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 of the file about to be transfered. 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. -chunkendproc : Name of the procedure that will be called after a file is transfered (or skipped) by ftp, it should match the following prototype: **ChunkEndProc {}** It should return '0' if everyhting is fine and '1' if some error occurred. -fnmatchProc : 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. # Error Options -errorbuffer : Pass a variable name where TclCurl may store human readable error messages in. This may be more helpful than just the return code from the command. -stderr : Pass a file name as parameter. This is the stream to use internally instead of stderr when reporting errors. -failonerror : A 1 parameter tells the extension to fail silently if the HTTP code returned is equal or larger than 400. The default action would be to return the page normally, ignoring that code. This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407). You might get some amounts of headers transferred before this situation is detected, like for when a "100-continue" is received as a response to a POST/PUT and a 401 or 407 is received immediately afterwards. # Network options -url : The actual URL to deal with. If the given URL lacks the protocol part (" or "ftp://" etc), it will attempt to guess which protocol to use based on the given host name. If the given protocol of the set URL is not supported, TclCurl will return the **unsupported protocol** error when you call **perform**. Use **curl::versioninfo** for detailed info on which protocols are supported. Starting with version 7.22.0, the fragment part of the URI will not be send as part of the path, which was the case previously. **NOTE**: this is the one option required to be set before **perform** is called. -protocols : Pass a list in lowecase of protocols to limit what protocols TclCurl may use in the transfer. This allows you to have a TclCurl built to support a wide range of protocols but still limit specific transfers to only be allowed to use 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 list in lowercase of accepted protocols to limit what protocols TclCurl may use in a transfer that it follows to in a redirect when **-followlocation** is enabled. This allows you to limit specific transfers to only be allowed to use a subset of protocols in redirections. By default TclCurl will allow all protocols except for FILE and SCP. This is a difference compared to pre-7.19.4 versions which unconditionally would follow to all protocols supported. -proxy : If you need to use a http proxy to access the outside world, set the proxy string with this option. To specify port number in this string, append :[port] to the end of the host name. The proxy string may be prefixed with [protocol]:// since any such prefix will be ignored. When you tell the extension to use a HTTP proxy, TclCurl will transparently convert operations to HTTP even if you specify a FTP URL etc. This may have an impact on what other features of the library you can use, such as **quote** and similar FTP specifics that will not work unless you tunnel through the HTTP proxy. Such tunneling is activated with **proxytunnel**. TclCurl respects the environment variables http_proxy, ftp_proxy, all_proxy etc, if any of those are set. The use of this option does however override any possibly set environment variables. Setting the proxy string to "" (an empty string) will explicitly disable the use of a proxy, even if there is an environment variable set for it. The proxy host string can be specified the exact same way as the proxy environment variables, include protocol prefix ( and embedded user + password. Since 7.22.0, the proxy string may be specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or socks5h:// (the last one to enable socks5 and asking the proxy to do the resolving) to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be treated as HTTP proxies. -proxyport : Use this option to set the proxy port to use unless it is specified in the proxy string by **-proxy**. If not specified, TclCurl will default to using port 1080 for proxies. -proxytype : Pass the type of the proxy. Available options are 'http', 'http1.0', 'socks4', 'socks4a', 'socks5' and 'socks5h', with the HTTP one being the default. 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 "regular" HTTP requests is instead controled with *httpversion*. -noproxy : Pass a string, a comma-separated list of hosts which do 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 as either a domain which contains the hostname, or the hostname itself. For example, local.com would match local.com, local.com:80, and www.local.com, but not www.notlocal.com. -httpproxytunnel : Set the parameter to 1 to get the extension to tunnel all non-HTTP operations through the given HTTP proxy. Do note that there is a big difference between using a proxy and tunneling through it. If you don't know what this means, you probably don't want this tunnel option. -socks5gssapiservice : Pass the name of the service. The default service name for a SOCKS5 server is rcmd/server-fqdn. This option allows you to change it. -socks5gssapinec : Pass a 1 to enable or 0 to disable. As part of the gssapi negotiation a protection mode is negotiated. The rfc1961 says in section 4.3/4.4 it should be protected, but the NEC reference implementation does not. If enabled, this option allows the unprotected exchange of the protection mode negotiation. -interface : Pass the interface name to use as outgoing network interface. The name can be an interface name, an IP address or a host name. -localport : This sets the local port number of the socket used for connection. This can be used in combination with **-interface** and you are recommended to use **localportrange** as well when this is set. Valid port numbers are 1 - 65535. -localportrange : This is the 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. Setting this value to 1 or below will make TclCurl do only one try for each port number. Port numbers by nature are a scarce resource that will be busy at times so setting this value to something too low might cause unnecessary connection setup failures. -dnscachetimeout : Pass the timeout in seconds. Name resolves will be kept in memory for this number of seconds. Set to '0' to completely disable caching, or '-1' to make the cached entries remain forever. By default, TclCurl caches this info for 60 seconds. The name resolve functions of various libc implementations don't re-read name server information unless explicitly told so (for example, by calling *res_init(3)*). This may cause TclCurl to keep using the older server even if DHCP has updated the server info, and this may look like a DNS cache issue. -dnsuseglobalcache : If the value passed is 1, it tells TclCurl to use a global DNS cache that will survive between curl handles creations and deletions. This is not thread-safe as it uses a global varible. *This option was deprecated in libcurl v7.11.1 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option* **WARNING:** this option is considered obsolete. Stop using it. Switch over to using the share interface instead! See *tclcurl_share*. -buffersize : Pass your preferred size for the receive buffer in TclCurl. The main point of this would be that the write callback gets called more often and with smaller chunks. This is just treated as a request, not an order. You cannot be guaranteed to actually get the given size. -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 : Pass a number to specify whether the TCP_NODELAY option should be set or cleared (1 = set, 0 = clear). The option is cleared by default. This will have 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 : A 1 parameter tells the extension to scan your **~/.netrc** file to find user name and password for the remote site you are about to access. Do note that TclCurl does not verify that the file has the correct properties set (as the standard unix ftp client does), and that only machine name, user name and password is taken into account (init macros and similar things are not supported). You can set it to the following values: optional : The use of your ~/.netrc file is optional, and information in the URL is to be preferred. The file will be scanned with the host and user name (to find the password only) or with the host only, to find the first user name and password after that machine, which ever information is not specified in the URL. Undefined values of the option will have this effect. ignored : The extension will ignore the file and use only the information in the URL. This is the default. required : This value tells the library that use of the file is required, to ignore the information in the URL, and to search the file with the host only. -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. -userpwd : Pass a string as parameter, which should be [username]:[password] to use for the connection. Use **-httpauth** to decide authentication method. When using NTLM, you can set domain by prepending it to the user name and separating the domain and name with a forward (/) or backward slash (\\). Like this: "domain/user:password" or "domain\\user:password". Some HTTP servers (on Windows) support this style even 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 as parameter, which should be [username]:[password] to use for the connection to the HTTP proxy. -username : Pass a string with the user name to use for the transfer. It sets the user name to be used in protocol authentication. You should not use this option together with the (older) **-userpwd** option. In order to specify the password to be used in conjunction with the user name use the **-password** option. -password : Pass a string with the password to use for the transfer. It should be used in conjunction with the **-username** option. -proxyusername : Pass a string with the user name to use for the transfer while connecting to Proxy. It should be used in same way as the **-proxyuserpwd** is used, except that it allows the username to contain a colon, like in the following example: "sip:user@example.com". Note the **-proxyusername** option is an alternative way to set the user name while connecting to Proxy. It doesn't make sense to use them together. -proxypassword : Pass a string with the password to use for the transfer while connecting to Proxy. It is meant to use together with **-proxyusername**. -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. digestie : HTTP Digest authentication with an IE flavor. TclCurl will use a special "quirk" that IE is known to have used before version 7 and that some servers require the client to use. gssnegotiate : HTTP GSS-Negotiate authentication. The GSS-Negotiate method, also known as plain "Negotiate",was designed by Microsoft and is used in their web applications. It is primarily meant as a support for Kerberos5 authentication but may be also used along with another authentication methods. ntlm : HTTP NTLM authentication. A proprietary protocol invented and used by Microsoft. It uses a challenge-response and hash concept similar to Digest, to prevent the password from being eavesdropped. 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. 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 will automatically select the one it finds most secure. anysafe : It may use anything but basic, TclCurl will automatically select the one it finds most secure. -tlsauthtype : Use it to tell TclCurl which authentication method(s) you want it to use for TLS authentication. tlsauthsrp : 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. To use TLS-SRP, you must also set the **-tlsauthusername** and **-tlsauthpassword** options. You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this to work. -tlsauthusername : Pass a string with the username to use for the TLS authentication method specified with the **-tlsauthtype** option. Requires that the **-tlsauthpassword** option also be set. -tlsauthpassword : Pass a string with the password to use for the TLS authentication method specified with the **-tlsauthtype** option. Requires that the **-tlsauthusername** option also be set. -proxyauth : Use it to tell TclCurl which authentication method(s) you want it to use for your proxy authentication. Note that for some methods, this will induce an extra network round-trip. Set the actual name and password with the **proxyuserpwd** option. The methods are those listed above for the **httpauth** option. As of this writing, only Basic and NTLM work. # HTTP options -autoreferer : Pass an 1 parameter to enable this. When enabled, TclCurl will automatically set the Referer: field in requests where it 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. Three encodings are supported: *identity*, which does nothing, *deflate* which requests the server to compress its response using the zlib algorithm, and *gzip* which requests the gzip algorithm. Use *all* to send an Accept-Encoding: header containing all supported encodings. This is a request, not an order; the server may or may not do it. This option must be set or else any unsolicited encoding done by the server is ignored. See the special file lib/README.encoding in libcurl docs for details. -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 response 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. -followlocation : An 1 tells the library to follow any **Location: header** that the server sends as part of a HTTP header. This means that the extension will re-send the same request on the new location and follow new **Location: headers** all the way until no more such headers are returned. **-maxredirs** can be used to limit the number of redirects TclCurl will follow. Since 7.19.4, TclCurl can limit what protocols it will automatically follow. The accepted protocols are set with **-redirprotocols** and it excludes the FILE protocol by default. -unrestrictedauth : An 1 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**. -maxredirs : Sets the redirection limit. If that many redirections have been followed, the next redirect will cause an error. This option only makes sense if the **-followlocation** option is used at the same time. Setting the limit to 0 will make libcurl refuse any redirect. Set it to -1 for an infinite number of redirects (which is the default) -postredir : Controls how TclCurl acts on redirects after POSTs that get a 301, 302 or 303 response back. A "301" parameter tells TclCurl to keep POST requests as POST when following a 301 redirect. Passing a "302" makes TclCurl maintain the request method after a 302 redirect, while "303" does the same for a 303 redirect. "all" is a convenience string that activates all three behaviours. The non-RFC behaviour is ubiquitous in web browsers, so the extension does the 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 setting **-followlocation** The legacy alias **-post301** is accepted for compatibility and uses the same values. -put : An 1 parameter tells the extension to use HTTP PUT a file. The file to put must be set with **-infile** and **-infilesize**. This option is deprecated starting with version 0.12.1, you should 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 : An 1 parameter tells the library to do a regular HTTP post. This is a normal application/x-www-form-urlencoded kind, which is the most commonly used one by HTML forms. See the **-postfields** option for how to specify the data to post and **-postfieldsize** about how to set the data size. Use the **-postfields** option to specify what data to post and **-postfieldsize** to set the data size. Optionally, you can provide data to POST using the **-readproc** options. 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 a "Expect: 100-continue" header. You can disable this header with **-httpheader** as usual. If you use POST to a HTTP 1.1 server, you can send data without knowing the size before starting the POST 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 in the request. When setting **post** to an 1 value, it will automatically set **nobody** to 0. NOTE: if you have issued a POST request and want to make a HEAD or GET instead, you must explicitly pick the new request type using **-nobody** or **-httpget** or similar. -postfields : Pass a string as parameter, which should be the full data to post in a HTTP POST operation. You must make sure that the data is formatted the way you want the server to receive it. TclCurl will not convert or encode it for you. Most web servers will assume this data to be url-encoded. This is a normal application/x-www-form-urlencoded kind, 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, as simply setting **-postfields** to NULL or "" just effectively disables the sending of the specified string. TclCurl will instead assume that the POST data will be sent using the read callback! Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with **-httpheader** as usual. **Note**: to make multipart/formdata posts (aka rfc1867-posts), check out **-httppost** option. -postfieldsize : If you want to post data to the server without letting TclCurl do a strlen() to measure the data size, this option must be used. Also, when this option is used, you can post fully binary data which otherwise is likely to fail. If this size is set to zero, the library will use strlen() to get the data size. -httppost : Tells TclCurl you want a multipart/formdata HTTP POST to be made and you instruct what data to pass on to the server through a **Tcl list**. **This is the only case where the data is reset after a transfer.** First, there are some basics you need to understand about multipart/formdata posts. Each part consists of at least a **NAME** and a **CONTENTS** part. If the part is made for file upload, there are also a stored **CONTENT-TYPE** and a **FILENAME**. Below, we'll discuss which options set these properties in the parts you want to add to your post. The list must contain a **'name'** tag with the name of the section followed by a string with the name, there are three tags to indicate the value of the section: **'value'** followed by a string with the data to post, **'file'** followed by the name of the file to post and **'contenttype'** with the type of the data (text/plain, image/jpg, ...), you can also indicate a *false* file name with **'filename'**, this is useful in case the server checks if the given file name is valid, for example, by testing if it starts with 'c:\\' as any real file name does or if you want to include the full path of the file to post. You can also post the content of a variable as if it were a file with the options **'bufferName'** and **'buffer'** or use **'filecontent'** followed by a file name to read that file and use the contents as data. Should you need to specify extra headers for the form POST section, use **'contentheader**' followed by a list with the headers to post. Please see 'httpPost.tcl' and 'httpBufferPost.tcl' for examples. If TclCurl can't set the data to post an error will be returned: 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 the some form info is not complete (or error) 6 : If an illegal option is used in an array. 7 : TclCurl has no http support. -referer : Pass a string as parameter. It will be used to set the **referer** header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with **-httpheader**. -useragent : Pass a string as parameter. It will be used to set the **user-agent:** header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with **-httpheader**. -httpheader : Pass a **list** with the HTTP headers to pass to the server in your request. If you add a header that is otherwise generated and used by TclCurl internally, your added one will be used instead. If you add a header with no contents as in 'Accept:', the internally used header will just get disabled. Thus, using this option you can add new headers, replace and remove internal headers. The headers included in the linked list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. Failure to comply with this will result in strange bugs because the server will most likely ignore part of the headers you specified. The first line in a request (containing the method, usually a GET or POST) is not a header and cannot be replaced using this option. Only the lines following the request-line are headers. Adding this method line in this list of headers will only cause your request to send an invalid header. **NOTE**: The most commonly replaced headers have "shortcuts" in the options: **cookie**, **useragent**, and **referer**. -http200aliases : Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers respond with a custom header response line. For example, IceCast servers respond with "ICY 200 OK". By including this string in your list of aliases, the response will be treated as a valid HTTP header line such as "HTTP/1.0 200 OK". **NOTE**:The alias itself is not parsed for any version strings. Before version 7.16.3, TclCurl used the value set by option **httpversion**, but starting with 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matched. -cookie : Pass a string as parameter. It will be used to set a cookie in the http request. The format of the string should be '[NAME]=[CONTENTS];'. Where NAME is the cookie name and CONTENTS is what the cookie should contain. If you need to set mulitple cookies, you need to set them all using a single option and thus you need to concatenate them all in one single string. Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc. This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are done due to authentication, followed redirections or similar, they will all get this cookie passed on. Using this option multiple times will only make the latest string override the previous ones. -cookiefile : Pass a string as parameter. It should contain the name of your file holding cookie data. The cookie data may be in netscape cookie data format or just regular HTTP-style headers dumped to a file. Given an empty or non-existing file, this option will enable cookies for this curl handle, making it understand and parse received cookies and then use matching cookies in future requests. If you use this option multiple times, you add more files to read. -cookiejar : Pass a file name in which TclCurl will dump all internally known cookies when **curlHandle cleanup** is called. If no cookies are known, no file will be created. Specify "-" to have the cookies written to stdout. Using this option also enables cookies for this session, so if you, for example, follow a location it will make matching cookies get sent accordingly. TclCurl will not and cannot report an error for this. Using '**verbose**' will get a warning to display, but that is the only visible feedback you get about this possibly lethal situation. -cookiesession : Pass an 1 to mark this as a new cookie "session". It will force TclCurl to ignore all cookies it is about to load that are "session cookies" from the previous session. By default, TclCurl always stores and loads all cookies, independent of whether they are session cookies are not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this "session" only. -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. If the cookie engine was not enabled it will be enabled. Passing a magic string "ALL" will erase all known cookies while "FLUSH" will write all cookies known by TclCurl to the file specified by **-cookiejar**. -httpget : If set to 1 forces the HTTP request to get back to GET, usable if POST, PUT or a custom request have been used previously with the same handle. When setting **httpget** to 1, **nobody** will automatically be set to 0. -httpversion : Set to one of the values decribed below, they force TclCurl to use the specific http versions. It should only be used if you really MUST do that because of a silly remote server. none : We do not care about what version the library uses. TclCurl will use whatever it thinks fit. 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 HTTP/1.1 Upgrade first. -ignorecontentlength : 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. If this option is used, TclCurl will not be able to accurately report progress, and will simply stop the download when the server ends the connection. -httpcontentdecoding : Set to zero to disable content decoding. If set to 1 it is enabled. Note however that TclCurl has no default content decoding but requires you to use **encoding** for that. -httptransferencoding : Set to zero to disable transfer decoding, if set to 1 it is enabled (default). TclCurl does chunked transfer decoding by default unless this option is set to zero. # SMTP options -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. Each recipient in SMTP lingo is specified with angle brackets (<>), but should you not use an angle bracket as first letter, TclCurl will assume you provide a single email address only and enclose that with angle brackets for you. # TFTP option tftpblksize : Specify the block size to use for TFTP data transmission. Valid range as per RFC 2348 is 8-65464 bytes. The default of 512 bytes will be used if this option is not specified. The specified block size will only be used pending support by the remote server. If the server does not return an option acknowledgement or returns an option acknowledgement with no blksize, the default of 512 bytes will be used. # FTP options -ftpport : Pass a string as parameter. It will be used to get the IP address to use for the ftp PORT instruction. The PORT instruction tells the remote server to connect to our specified IP address. The string may be a plain IP address, a host name, a network interface name (under unix) or just a '-' to let the library use your systems default IP address. Default FTP operations are passive, and thus will not use PORT. The address can be followed by a ':' to specify a port, optionally followed by a '-' o specify a port range. If the port specified is 0, the operating system will pick a free port. If a range is provided and all ports in the range are not available, libcurl will report CURLE_FTP_PORT_FAILED for the handle. Invalid port/range settings are ignored. IPv6 addresses followed by a port or portrange have to be in brackets. IPv6 addresses without port/range specifier can be in brackets. Examples with specified ports: eth0:0 192.168.1.2:32000-33000 curl.se:32123 [::1]:1234-4567 You disable PORT again and go back to using the passive version by setting this option to an empty string. -quote : Pass a **list** list with the FTP or SFTP commands to pass to the server prior to your ftp request. This will be done before any other FTP commands are issued (even before the CWD command).If you do not want to transfer any files, set **nobody** to '1' and **header** to '0'. Prefix the command with an asterisk (*) to make TclCurl continue even if the command fails as by default TclCurl will stop. Disable this operation again by setting an empty string to this option. Keep in mind the commands to send must be 'raw' ftp commands, for example, to create a directory you need to 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** with the FTP commands to pass to the server after your 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 pass to the server after the transfer type is set. -dirlistonly : A 1 tells the library to just list the names of files in a directory, instead of doing a full directory listing that would include file sizes, dates etc. It works with both FTP and SFTP urls. This causes an FTP NLST command to be sent. Beware that some FTP servers list only files in their response to NLST, they might not include subdirectories and symbolic links. Setting this option to 1 also implies a directory listing even if the URL doesn't end with a slash, which otherwise is necessary. Do NOT use this option if you also use **-wildcardmatch** as it will effectively break that feature. -append : A 1 parameter tells the extension to append to the remote file instead of overwriting it. This is only useful when uploading to a ftp site. -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. -ftpuseepvs : Set to one to tell TclCurl to use the EPSV command when doing passive FTP downloads (which it always does by default). Using EPSV means that it will first attempt to use EPSV before using PASV, but if you pass a zero to this option, it will not try using EPSV, only plain PASV. -ftpusepret : Set to one to tell TclCurl to send a PRET command before PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard command for directory listings as well as up and downloads in PASV mode. Has no effect when using the active FTP transfers mode. -ftpcreatemissingdirs : If set to 1, TclCurl will attempt to create any remote directory that it fails to CWD into. CWD is the command that changes working directory. This setting also applies to SFTP-connections. TclCurl will attempt to create the remote directory if it can't obtain a handle to the target-location. The creation will fail if a file of the same name as the directory to create already exists or lack of permissions prevents creation. If set to 2, TclCurl will retry the CWD command again if the subsequent MKD command fails. This is especially useful if you're doing many simultanoeus connections against the same server and they all have this option enabled, as then CWD may first fail but then another connection does MKD before this connection and thus MKD fails but trying CWD works -ftpresponsetimeout : Causes TclCurl to set a timeout period (in seconds) 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. Note that while TclCurl is waiting for a response, this value overrides **timeout**. It is recommended that if used in conjunction with **timeout**, you set it to a value smaller than **timeout**. -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. -ftpskippasvip : If set to 1, 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. This option has no effect if PORT, EPRT or EPSV is used instead of PASV. -ftpsslauth : Pass TclCurl one of the values from below, to alter how TclCurl issues "AUTH TLS" or "AUTH SSL" when FTP over SSL is activated (see **-ftpssl**). You may need this option because of servers like BSDFTPD-SSL from "which won't work properly when "AUTH SSL" is issued (although the server responds fine and everything) but requires "AUTH TLS" instead. default : Allows TclCurl to decide. ssl : Try "AUTH SSL" first, and only if that fails try "AUTH TLS". tls : Try "AUTH TLS" first, and only if that fails try "AUTH SSL". -ftpsslccc : Set it to make TclCurl use CCC (Clear Command Channel). It shuts down the SSL/TLS layer after authenticating. The rest of the control channel communication will be unencrypted. This allows NAT routers to follow the FTP transaction. Possible values are: none : Do not attempt to use CCC. passive : Do not initiate the shutdown, wait for the server to do it. Do not send a reply. active : Initiate the shutdown and wait for a reply. -ftpaccount : Pass string (or "" to disable). When an FTP server asks for "account data" after user name and password has been provided, this data is sent off using the ACCT command. -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". This is somewhat more standards compliant than 'nocwd' but without the full penalty of 'multicwd'. # Protocol options -transfertext : A 1 tells the extension to use ASCII mode for ftp transfers, instead of the default binary transfer. For win32 systems it does not set the stdout to binary mode. This option can be usable when transferring text data between systems with different views on certain characters, such as newlines or similar. **NOTE:** TclCurl does not do a complete ASCII conversion when doing ASCII transfers over FTP. This is a known limitation/flaw that nobody has rectified. TclCurl simply sets the mode to ascii and performs a standard transfer. -proxytransfermode : If set to 1, TclCurl sets 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 it being set to 0, the default, **-transfertext** has no effect when doing FTP via a proxy. Beware that not all proxies support this feature. -crlf : If set to '1', TclCurl converts Unix newlines to CRLF newlines on transfers. Disable this option again by setting the value to '0'. -range : Pass a string as parameter, which should contain the specified range you want. It should be in the format "X-Y" , where X or Y may be left out. HTTP transfers also support several intervals, separated with commas as in "X-Y,N-M" Using this kind of multiple intervals will cause the HTTP server to send the response document in pieces (using standard MIME separation techniques). Ranges only work on HTTP, FTP and FILE transfers. -resumefrom : Pass the offset in number of bytes that you want the transfer to start from. Set this option to 0 to make the transfer start from the beginning (effectively disabling resume). For FTP, set this option to -1 to make the transfer start from the end of the target file (useful to continue an interrupted upload). When doing uploads with FTP, the resume position is where in the local/source file TclCurl should try to resume the upload from and it will then append the source file to the remote target file. -customrequest : Pass a string as parameter. It will be used instead of GET or HEAD when doing the HTTP request. This is useful for doing DELETE or other more obscure HTTP requests. Do not do this at will, make sure your server supports the command first. Note that TclCurl will still act and assume the keyword it would use if you do not set your custom and it will act according to that. Thus, changing this to a HEAD when TclCurl otherwise would do a GET might cause TclCurl to act funny, and similar. To switch to a proper HEAD, use **-nobody**, to switch to a proper POST, use **-post** or **-postfields** and so on. -filetime : If you pass a 1, TclCurl will attempt to get the modification date of the remote document in this operation. This requires that the remote server sends the time or replies to a time querying command. The getinfo procedure with the filetime argument can be used after a transfer to extract the received time (if any). -nobody : A 1 tells the library not to include the body-part in the output. This is only relevant for protocols that have a separate header and body part. On HTTP(S) servers, this will make TclCurl do a HEAD request. To change request to GET, you should use **httpget**. Change request to POST with **post** etc. -infilesize : When uploading a file to a remote site, this option should be used to tell TclCurl what the expected size of the infile is. This option is mandatory for uploading using SCP. -upload : A 1 tells the library to prepare for an upload. The **-infile** and **-infilesize** options are also interesting 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 : This defines how the **timevalue** value is treated. You can set this parameter to **ifmodsince** or **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 you allow the TclCurl transfer operation to take. Do note that normally, name lookups may take a considerable time and that limiting the operation to less than a few minutes risks aborting perfectly normal operations. This option will cause libcurl to use the SIGALRM to enable time-outing system calls. In unix-like systems, this might cause signals to be used unless **-nosignal** is used. -timeoutms : Like **timeout** but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. -lowspeedlimit : Pass the speed in bytes per second that the transfer should be below during **lowspeedtime** seconds for the extension to consider it too slow and abort. -lowspeedtime : Pass the time in seconds that the transfer should be below the **lowspeedlimit** for the extension to consider it too slow and abort. -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. Defaults to unlimited speed. -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. Defaults to unlimited speed. -maxconnects : Sets the persistent connection cache size in all the protocols that support persistent conecctions. The set amount will be the maximum amount of simultaneous connections that TclCurl may cache in this easy handle. Default is 5, and there isn't much point in changing this value unless you are perfectly aware of how this work and changes TclCurl's behaviour. When reaching the maximum limit, TclCurl closes the oldest connection in the cache to prevent the number of open connections to increase. **Note**: if you have already performed transfers with this curl handle, setting a smaller **maxconnects** than before may cause open connections to unnecessarily get closed. If you add this easy handle to a multi handle, this setting is not being acknowledged, instead you must configure the multi handle its own **maxconnects** option. -connecttimeout : Maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once it has connected, this option is of no more use. Set to zero to disable connection timeout (it will then only timeout on the internal timeouts). In unix-like systems, this might cause signals to be used unless **-nosignal** is set. -connecttimeoutms : Like **connecttimeout** but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. -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. The allowed values are: whatever : Default, resolves addresses to all IP versions that your system allows. v4 : Resolve to ipv4 addresses. v6 : Resolve to ipv6 addresses. -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. This option effectively pre-populates the DNS cache with entries for the host+port pair so redirects and everything that operations against the HOST+PORT will instead use your provided ADDRESS. You can remove names from the DNS cache again, to stop providing these fake resolves, by including a string in the linked list that uses the format "-HOST:PORT". The host name must be prefixed with a dash, and the host name and port number must exactly match what was already added previously. -usessl : Pass a one of the values from below to make TclCurl use your desired level of SSL for the transfer. This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc. You can use ftps:// URLs to explicitly switch on SSL/TSL for the control connection and the data connection. Alternatively you can set the 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 conecction 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 as parameter. The string should be the file name of your certificate. The default format is "PEM" and can be changed with **-sslcerttype**. With NSS this is the nickname of the certificate you wish to authenticate with. If you want to use a file from the current directory, please precede it with the "./" prefix, in order to avoid confusion with a nickname. -sslcerttype : Pass a string as parameter. The string should be the format of your certificate. Supported formats are "PEM" and "DER". -sslkey : Pass a pointer to a zero terminated string as parameter. The string should be the file name of your private key. The default format is "PEM" and can be changed with **-sslkeytype**. -sslkeytype : Pass a pointer to a zero terminated string as parameter. The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG" **NOTE:**The format "ENG" enables you to load the private key from a crypto engine. in this case **-sslkey** is used as an identifier passed to the engine. You have to set the crypto engine with **-sslengine**. The "DER" format key file currently does not work because of a bug in OpenSSL. -keypasswd : Pass a string as parameter. It will be used as the password required to use the **-sslkey** or **-sshprivatekeyfile** private key. You never need a pass phrase to load a certificate but you need one to load you private key. This option used to be known as **-sslkeypasswd** and **-sslcertpasswd**. -sslengine : Pass a string as parameter. It will be used as the identifier for the crypto engine you want to use for your private key. **NOTE:**If the crypto device cannot be loaded, an error will be returned. -sslenginedefault : Pass a 1 to set the actual crypto engine as the default for (asymmetric) crypto operations. **NOTE:**If the crypto device cannot be set, an error will be returned. -sslversion : Use it to set what version of SSL/TLS to use. The available options are: default : The default action. This will attempt to figure out the remote SSL protocol version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled by default with 7.18.1). tlsv1 : Force TLSv1 or later sslv2 : Force SSLv2 sslv3 : Force SSLv3 tlsv1_0 : Force TLSv1.0 or later tlsv1_1 : Force TLSv1.1 or later tlsv1_2 : Force TLSv1.2 or later tlsv1_3 : Force TLSv1.3 or later maxdefault : Use the maximum supported TLS version by libcurl or the default value from the SSL library. maxtlsv1_0 : Define maximum supported TLS version as TLSv1.0 maxtlsv1_1 : Define maximum supported TLS version as TLSv1.1 maxtlsv1_2 : Define maximum supported TLS version as TLSv1.2 maxtlsv1_3 : Define maximum supported TLS version as TLSv1.3 -sslverifypeer : This option determines whether TclCurl verifies the authenticity of the peer's certificate. A 1 means it verifies; zero means it doesn't. The default is 1. When negotiating an SSL connection, the server sends a certificate indicating its identity. TclCurl verifies whether the certificate is authentic, i.e. that you can trust that the server is who the certificate says it is. This trust is based on a chain of digital signatures, rooted in certification authority (CA) certificates you supply. TclCurl uses a default bundle of CA certificates that comes with libcurl but you can specify alternate certificates with the **-cainfo** or the **-capath** options. When **-sslverifypeer** is nonzero, and the verification fails to prove that the certificate is authentic, the connection fails. When the option is zero, the peer certificate verification succeeds regardless. Authenticating the certificate is not by itself very useful. You typically want to ensure that the server, as authentically identified by its certificate, is the server you mean to be talking to, use **-sslverifyhost** to control that. The check that the host name in the certificate is valid for the host name you're connecting to is done independently of this option. -cainfo : Pass a file naming holding the certificate to verify the peer with. This only makes sense when used in combination with the **-sslverifypeer** option, if it is set to zero **-cainfo** need not even indicate an accessible file. This option is by default set to the system path where libcurl's cacert bundle is assumed to be stored, as established at build time. When built against NSS this is the directory that the NSS certificate database resides in. -issuercert : Pass a string naming a file holding a CA certificate in PEM format. If the option is set, an additional check against the peer certificate is performed to verify the issuer is indeed the one associated with the certificate provided by the option. This additional check is useful in multi-level PKI where one need to enforce the peer certificate is from a specific branch of the tree. This option makes sense only when used in combination with the **-sslverifypeer** option. Otherwise, the result of the check is not considered as failure. -capath : Pass the directory holding multiple CA certificates to verify the peer with. If libcurl is built against OpenSSL, the certificate directory must be prepared using the openssl c_rehash utility. This only makes sense when used in combination with the **-sslverifypeer** option, if it is set to zero, **-capath** need not even indicate an accessible path. This option apparently does not work in Windows due to some limitation in openssl. This option is OpenSSL-specific and does nothing if libcurl is built to use GnuTLS. NSS-powered libcurl provides the option only for backward compatibility. -crlfile : Pass a string naming a file with the concatenation of CRL (in PEM format) to use in the certificate validation that occurs during the SSL exchange. When libcurl is built to use NSS or GnuTLS, there is no way to influence the use of CRL passed to help in the verification process. When built with OpenSSL support, X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are both set, requiring CRL check against all the elements of the certificate chain if a CRL file is passed. This option makes sense only when used in combination with the **-sslverifypeer** option. A specific error code (CURLE_SSL_CRL_BADFILE) is defined with the option. It is returned when the SSL exchange fails because the CRL file cannot be loaded. A failure in certificate verification due to a revocation information found in the CRL does not trigger this specific error. -sslverifyhost : This option determines whether TclCurl verifies that the server claims to be who you want it to be. When negotiating an SSL connection, the server sends a certificate indicating its identity. When **-sslverifyhost** is set to 2, that certificate must indicate that the server is the server to which you meant to connect, or the connection fails. TclCurl considers the server the intended one when the Common Name field or a Subject Alternate Name field in the certificate matches the host name in the URL to which you told Curl to connect. When set to 1, the certificate must contain a Common Name field, but it does not matter what name it says. (This is not ordinarily a useful setting). When the value is 0, the connection succeeds regardless of the names in the certificate. The default value for this option is 2. This option controls the identity that the server *claims*. The server could be lying. To control lying, see **-sslverifypeer**. If libcurl is built against NSS and **-verifypeer** is zero, **-verifyhost** is ignored. -certinfo : Set to '1' to enable TclCurl's certificate chain info gatherer. With this enabled, TclCurl (if built with OpenSSL) will extract lots of information and data about the certificates in the certificate chain used in the SSL connection. This data can then be to extracted after a transfer using the **getinfo** command and its option **certinfo**. -randomfile : Pass a file name. The file will be used to read from to seed the random engine for SSL. The more random the specified file is, the more secure the SSL connection becomes. *This option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option* -egdsocket : Pass a path name to the Entropy Gathering Daemon socket. It will be used to seed the random engine for SSL. *This option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option* -sslcypherlist : Pass a string holding the ciphers to use for the SSL connection. The list must consists of one or more cipher strings separated by colons. Commas or spaces are also acceptable separators but colons are normally used, , - and + can be used as operators. For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA', 'SHA1+DES', 'TLSv1' and 'DEFAULT'. The default list is normally set when you compile OpenSSL. You will find more details about cipher lists on this URL: For NSS valid examples of cipher lists include 'rsa_rc4_128_md5', 'rsa_aes_128_sha', etc. With NSS you don't add/remove ciphers. If you use this option then all known ciphers are disabled and only those passed in are enabled. You'll find more details about the NSS cipher lists on this URL: <> -sslsessionidcache : Pass a 0 to disable TclCurl's use of SSL session-ID caching or a 1 to enable it. By default all transfers are done using the cache. While nothing ever should get hurt by attempting to reuse SSL session-IDs, there seem to be broken SSL implementations in the wild that may require you to disable this in order for you to succeed. -krblevel : Set the kerberos security level for FTP, this also enables kerberos awareness. This is a string, 'clear', 'safe', 'confidential' or 'private'. If the string is set but does not match one of these, 'private' will be used. Set the string to NULL to disable kerberos4. Set the string to "" to disable kerberos support for FTP. -gssapidelegation : Set the option to 'flag' to allow unconditional GSSAPI credential delegation. The delegation is disabled by default since 7.21.7. 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. # SSH options -sshauthtypes : The allowed types are: publickey : Use public key authentication. password : Use password authentication. host : Use host-based authentication. keyboard : Use keyboard-interactive authentication. any : To let TclCurl pick one -sshhostpublickeymd5 : Pass a string containing 32 hexadecimal digits. The string should be the 128 bit MD5 cheksum of the remote host public key, and TclCurl will reject the connection to the host unless the md5sums match. This option is only for SCP and SFTP transfers. -publickeyfile : Pass the file name for your public key. If not used, TclCurl defaults to using **$HOME/.ssh/id_dsa.pub**. HOME environment variable is set, and just **id_dsa** in the current directory if not. -privatekeyfile : Pass the file name for your private key. If not used, TclCurl defaults to using **$HOME/.ssh/id_dsa.pub**. HOME environment variable is set, and just **id_dsa** in the current directory if not. If the file is password-protected, set the password with **-keypasswd**. -sshknownhosts : Pass a string holding the file name of the known_host file to use. The known_hosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, TclCurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use **-sshkeyproc** to alter the default behavior on host and key (mis)matching. -sshkeyproc : Pass a the name of the procedure that will be called when the known_host matching has been done, to allow the application to act and decide for TclCurl how to proceed. The callback will only be called if **-knownhosts** is also set. It gets passed a list with three elements, the first one is a list with the type of the key from the known_hosts file and the key itself, the second is another list with the type of the key from the remote site and the key itslef, the third tells you what TclCurl thinks about the matching status. The known key types are: "rsa", "rsa1" and "dss", in any other case "unknown" is given. TclCurl opinion about how they match may be: "match", "mismatch", "missing" or "error". The procedure must return: 0 : The host+key is accepted and TclCurl will append it to the known_hosts file before continuing with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. The adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this. 1 : The host+key is accepted, TclCurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. 2 : The host+key is rejected. TclCurl will close the connection. 3 : The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again. Any other value will cause the connection to be closed. # Other options -headervar : Name of the Tcl array variable where TclCurl will store the headers returned by the server. -bodyvar : Name of the Tcl variable where TclCurl will store the file requested, the file may contain text or binary data. -canceltransvar : Name of a Tcl variable, in case you have defined a procedure to call with **-progressproc** setting this variable to '1' will cancel the transfer. -command : Executes the given command after the transfer is done, since it only works with blocking transfers, it is pretty much useless. -share : Pass a share handle as a parameter. The share handle must have been created by a previous call to **curl::shareinit**. Setting this option, will make this handle use the data from the shared handle instead of keeping the data to itself. See *tclcurl_share* for details. -newfileperms : Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created files on the remote server. The default value is 0644, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. -newdirectoryperms : Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created directories on the remote server. The default value is 0755, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. # 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 transfered, 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 transfered. 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 successfull 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 : Retuns 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. # SEE ALSO curl, The art of HTTP scripting (at , RFC 2396, tclcurl-ng-8.0.1/doc/tclcurl.n.md.in000066400000000000000000003017121517264272000172040ustar00rootroot00000000000000--- title: TclCurl section: n date: 12 April 2026 source: TclCurl @PACKAGE_VERSION@ volume: TclCurl Easy Interface --- # NAME TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. # SYNOPSIS ```tcl curl::init ``` ```tcl curlHandle configure ?options? ``` ```tcl curlHandle perform ``` ```tcl curlHandle getinfo curlinfo_option ``` ```tcl curlhandle cleanup ``` ```tcl curlhandle reset ``` ```tcl curlHandle duphandle ``` ```tcl curlHandle pause ``` ```tcl curlHandle resume ``` ```tcl curl::transfer ?options? ``` ```tcl curl::version ``` ```tcl curl::escape url ``` ```tcl curl::unescape url ``` ```tcl curl::curlConfig option ``` ```tcl curl::versioninfo option ``` ```tcl curl::easystrerror errorCode ``` # DESCRIPTION The TclCurl extension gives Tcl programmers access to the libcurl library written by **Daniel Stenberg**, with it you can download urls, upload them and many other neat tricks, for more information check # curl::init This procedure must be the first one to call, it returns a curlHandle that you need to use to invoke TclCurl procedures. The init calls intializes curl and this call MUST have a corresponding call to cleanup when the operation is completed. You should perform all your sequential file transfers using the same curlHandle. This enables TclCurl to use persistent connections when possible. **RETURN VALUE** curlHandle to use. # curlHandle configure ?options? **configure** is called to set the options for the transfer. Most operations in TclCurl have default actions, and by using the appropriate options you can make them behave differently (as documented). All options are set with the *option* followed by a parameter. **Notes:** the options set with this procedure are valid for the forthcoming data transfers that are 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 return code from the `curl::init` call. **OPTIONS** # Behaviour options -verbose : Set the parameter to 1 to get the library to display a lot of verbose information about its operations. Very useful for libcurl and/or protocol debugging and understanding. You hardly ever want this set in production use, you will almost always want this when you debug/report problems. Another neat option for debugging is **-debugproc** -header : A 1 tells the extension to include the headers in the body output. This is only relevant for protocols that actually have headers preceding the data (like HTTP). -noprogress : A 1 tells the extension to turn on the progress meter completely. It will also prevent the *progessproc* from getting called. -nosignal : A 1 tells TclCurl not use any functions that install signal handlers or any functions that cause signals to be sent to the process. This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals. If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals. Setting *nosignal* to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire. In addition, using *ntlm_Wb* authentication could cause a SIGCHLD signal to be raised. -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** option, using an fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name). By default, TclCurl uses its internal wildcard matching implementation. You can provide your own matching function by the **-fnmatchproc** option. This feature is only supported by the FTP download for now. A brief introduction of its syntax follows: - * - ASTERISK ftp://example.com/some/path/***.txt** (for all txt's from the root directory) - ? - QUESTION MARK Question mark matches any (exactly one) 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 : Use it to set a Tcl procedure that will be invoked by TclCurl as soon as there is received data that needs to be saved. The procedure will receive a single parameter with the data to be saved. NOTE: you will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be nothing if the file is empty or it may be thousands of bytes. -file : File in which the transfered data will be saved. -readproc : Sets a Tcl procedure to be called by TclCurl as soon as it needs to read data in order to send it to the peer. The procedure has to take one parameter, which will contain the maximun numbers 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 "pre-maturely" (i.e before the server expected it, like when you've said you will upload N bytes and you upload less than N bytes), you may experience that the server "hangs" waiting for the rest of the data that won't come. Bugs: when doing TFTP uploads, you must return the exact amount of data that the callback wants, or it will be considered the final packet by the server end and the transfer will end there. -infile : File from which the data will be transfered. -progressproc : Name of the Tcl procedure that will invoked by TclCurl with a frequent interval during operation (roughly once per second or sooner), no matter if data is being transfered or not. Unknown/unused argument values passed to the callback will be set to zero (like if you only download data, the upload size will remain 0), the prototype of the procedure must be: **proc ProgressCallback {dltotal dlnow ultotal ulnow}** In order to this option to work you have to set the **noprogress** option to '0'. Setting this option to the empty string will restore 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 a the file name to be used to write the header part of the received data to. The headers are guaranteed to be written one-by-one to this file and only complete lines are written. Parsing headers should be easy enough using this. See also the **-headervar** option to get the headers into an array. -debugproc : Name of the procedure that will receive the debug data produced by the **-verbose** option, it should match the following prototype: **debugProc {infoType data}** where **infoType** specifies what kind of information it is (0 text, 1 incoming header, 2 outgoing header, 3 incoming data, 4 outgoing data, 5 incoming SSL data, 6 outgoing SSL data). -chunkbgnproc : Name of the procedure that will be called before a file will be transfered by ftp, it should match the following prototype: **ChunkBgnProc {remains}** Where remains is the number of files left to be transfered (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 of the file about to be transfered. 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. -chunkendproc : Name of the procedure that will be called after a file is transfered (or skipped) by ftp, it should match the following prototype: **ChunkEndProc {}** It should return '0' if everyhting is fine and '1' if some error occurred. -fnmatchProc : 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. # Error Options -errorbuffer : Pass a variable name where TclCurl may store human readable error messages in. This may be more helpful than just the return code from the command. -stderr : Pass a file name as parameter. This is the stream to use internally instead of stderr when reporting errors. -failonerror : A 1 parameter tells the extension to fail silently if the HTTP code returned is equal or larger than 400. The default action would be to return the page normally, ignoring that code. This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407). You might get some amounts of headers transferred before this situation is detected, like for when a "100-continue" is received as a response to a POST/PUT and a 401 or 407 is received immediately afterwards. # Network options -url : The actual URL to deal with. If the given URL lacks the protocol part (" or "ftp://" etc), it will attempt to guess which protocol to use based on the given host name. If the given protocol of the set URL is not supported, TclCurl will return the **unsupported protocol** error when you call **perform**. Use **curl::versioninfo** for detailed info on which protocols are supported. Starting with version 7.22.0, the fragment part of the URI will not be send as part of the path, which was the case previously. **NOTE**: this is the one option required to be set before **perform** is called. -protocols : Pass a list in lowecase of protocols to limit what protocols TclCurl may use in the transfer. This allows you to have a TclCurl built to support a wide range of protocols but still limit specific transfers to only be allowed to use 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 list in lowercase of accepted protocols to limit what protocols TclCurl may use in a transfer that it follows to in a redirect when **-followlocation** is enabled. This allows you to limit specific transfers to only be allowed to use a subset of protocols in redirections. By default TclCurl will allow all protocols except for FILE and SCP. This is a difference compared to pre-7.19.4 versions which unconditionally would follow to all protocols supported. -proxy : If you need to use a http proxy to access the outside world, set the proxy string with this option. To specify port number in this string, append :[port] to the end of the host name. The proxy string may be prefixed with [protocol]:// since any such prefix will be ignored. When you tell the extension to use a HTTP proxy, TclCurl will transparently convert operations to HTTP even if you specify a FTP URL etc. This may have an impact on what other features of the library you can use, such as **quote** and similar FTP specifics that will not work unless you tunnel through the HTTP proxy. Such tunneling is activated with **proxytunnel**. TclCurl respects the environment variables http_proxy, ftp_proxy, all_proxy etc, if any of those are set. The use of this option does however override any possibly set environment variables. Setting the proxy string to "" (an empty string) will explicitly disable the use of a proxy, even if there is an environment variable set for it. The proxy host string can be specified the exact same way as the proxy environment variables, include protocol prefix ( and embedded user + password. Since 7.22.0, the proxy string may be specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or socks5h:// (the last one to enable socks5 and asking the proxy to do the resolving) to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be treated as HTTP proxies. -proxyport : Use this option to set the proxy port to use unless it is specified in the proxy string by **-proxy**. If not specified, TclCurl will default to using port 1080 for proxies. -proxytype : Pass the type of the proxy. Available options are 'http', 'http1.0', 'socks4', 'socks4a', 'socks5' and 'socks5h', with the HTTP one being the default. 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 "regular" HTTP requests is instead controled with *httpversion*. -noproxy : Pass a string, a comma-separated list of hosts which do 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 as either a domain which contains the hostname, or the hostname itself. For example, local.com would match local.com, local.com:80, and www.local.com, but not www.notlocal.com. -httpproxytunnel : Set the parameter to 1 to get the extension to tunnel all non-HTTP operations through the given HTTP proxy. Do note that there is a big difference between using a proxy and tunneling through it. If you don't know what this means, you probably don't want this tunnel option. -socks5gssapiservice : Pass the name of the service. The default service name for a SOCKS5 server is rcmd/server-fqdn. This option allows you to change it. -socks5gssapinec : Pass a 1 to enable or 0 to disable. As part of the gssapi negotiation a protection mode is negotiated. The rfc1961 says in section 4.3/4.4 it should be protected, but the NEC reference implementation does not. If enabled, this option allows the unprotected exchange of the protection mode negotiation. -interface : Pass the interface name to use as outgoing network interface. The name can be an interface name, an IP address or a host name. -localport : This sets the local port number of the socket used for connection. This can be used in combination with **-interface** and you are recommended to use **localportrange** as well when this is set. Valid port numbers are 1 - 65535. -localportrange : This is the 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. Setting this value to 1 or below will make TclCurl do only one try for each port number. Port numbers by nature are a scarce resource that will be busy at times so setting this value to something too low might cause unnecessary connection setup failures. -dnscachetimeout : Pass the timeout in seconds. Name resolves will be kept in memory for this number of seconds. Set to '0' to completely disable caching, or '-1' to make the cached entries remain forever. By default, TclCurl caches this info for 60 seconds. The name resolve functions of various libc implementations don't re-read name server information unless explicitly told so (for example, by calling *res_init(3)*). This may cause TclCurl to keep using the older server even if DHCP has updated the server info, and this may look like a DNS cache issue. -dnsuseglobalcache : If the value passed is 1, it tells TclCurl to use a global DNS cache that will survive between curl handles creations and deletions. This is not thread-safe as it uses a global varible. *This option was deprecated in libcurl v7.11.1 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option* **WARNING:** this option is considered obsolete. Stop using it. Switch over to using the share interface instead! See *tclcurl_share*. -buffersize : Pass your preferred size for the receive buffer in TclCurl. The main point of this would be that the write callback gets called more often and with smaller chunks. This is just treated as a request, not an order. You cannot be guaranteed to actually get the given size. -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 : Pass a number to specify whether the TCP_NODELAY option should be set or cleared (1 = set, 0 = clear). The option is cleared by default. This will have 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 : A 1 parameter tells the extension to scan your **~/.netrc** file to find user name and password for the remote site you are about to access. Do note that TclCurl does not verify that the file has the correct properties set (as the standard unix ftp client does), and that only machine name, user name and password is taken into account (init macros and similar things are not supported). You can set it to the following values: optional : The use of your ~/.netrc file is optional, and information in the URL is to be preferred. The file will be scanned with the host and user name (to find the password only) or with the host only, to find the first user name and password after that machine, which ever information is not specified in the URL. Undefined values of the option will have this effect. ignored : The extension will ignore the file and use only the information in the URL. This is the default. required : This value tells the library that use of the file is required, to ignore the information in the URL, and to search the file with the host only. -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. -userpwd : Pass a string as parameter, which should be [username]:[password] to use for the connection. Use **-httpauth** to decide authentication method. When using NTLM, you can set domain by prepending it to the user name and separating the domain and name with a forward (/) or backward slash (\\). Like this: "domain/user:password" or "domain\\user:password". Some HTTP servers (on Windows) support this style even 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 as parameter, which should be [username]:[password] to use for the connection to the HTTP proxy. -username : Pass a string with the user name to use for the transfer. It sets the user name to be used in protocol authentication. You should not use this option together with the (older) **-userpwd** option. In order to specify the password to be used in conjunction with the user name use the **-password** option. -password : Pass a string with the password to use for the transfer. It should be used in conjunction with the **-username** option. -proxyusername : Pass a string with the user name to use for the transfer while connecting to Proxy. It should be used in same way as the **-proxyuserpwd** is used, except that it allows the username to contain a colon, like in the following example: "sip:user@example.com". Note the **-proxyusername** option is an alternative way to set the user name while connecting to Proxy. It doesn't make sense to use them together. -proxypassword : Pass a string with the password to use for the transfer while connecting to Proxy. It is meant to use together with **-proxyusername**. -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. digestie : HTTP Digest authentication with an IE flavor. TclCurl will use a special "quirk" that IE is known to have used before version 7 and that some servers require the client to use. gssnegotiate : HTTP GSS-Negotiate authentication. The GSS-Negotiate method, also known as plain "Negotiate",was designed by Microsoft and is used in their web applications. It is primarily meant as a support for Kerberos5 authentication but may be also used along with another authentication methods. ntlm : HTTP NTLM authentication. A proprietary protocol invented and used by Microsoft. It uses a challenge-response and hash concept similar to Digest, to prevent the password from being eavesdropped. 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. 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 will automatically select the one it finds most secure. anysafe : It may use anything but basic, TclCurl will automatically select the one it finds most secure. -tlsauthtype : Use it to tell TclCurl which authentication method(s) you want it to use for TLS authentication. tlsauthsrp : 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. To use TLS-SRP, you must also set the **-tlsauthusername** and **-tlsauthpassword** options. You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this to work. -tlsauthusername : Pass a string with the username to use for the TLS authentication method specified with the **-tlsauthtype** option. Requires that the **-tlsauthpassword** option also be set. -tlsauthpassword : Pass a string with the password to use for the TLS authentication method specified with the **-tlsauthtype** option. Requires that the **-tlsauthusername** option also be set. -proxyauth : Use it to tell TclCurl which authentication method(s) you want it to use for your proxy authentication. Note that for some methods, this will induce an extra network round-trip. Set the actual name and password with the **proxyuserpwd** option. The methods are those listed above for the **httpauth** option. As of this writing, only Basic and NTLM work. # HTTP options -autoreferer : Pass an 1 parameter to enable this. When enabled, TclCurl will automatically set the Referer: field in requests where it 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. Three encodings are supported: *identity*, which does nothing, *deflate* which requests the server to compress its response using the zlib algorithm, and *gzip* which requests the gzip algorithm. Use *all* to send an Accept-Encoding: header containing all supported encodings. This is a request, not an order; the server may or may not do it. This option must be set or else any unsolicited encoding done by the server is ignored. See the special file lib/README.encoding in libcurl docs for details. -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 response 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. -followlocation : An 1 tells the library to follow any **Location: header** that the server sends as part of a HTTP header. This means that the extension will re-send the same request on the new location and follow new **Location: headers** all the way until no more such headers are returned. **-maxredirs** can be used to limit the number of redirects TclCurl will follow. Since 7.19.4, TclCurl can limit what protocols it will automatically follow. The accepted protocols are set with **-redirprotocols** and it excludes the FILE protocol by default. -unrestrictedauth : An 1 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**. -maxredirs : Sets the redirection limit. If that many redirections have been followed, the next redirect will cause an error. This option only makes sense if the **-followlocation** option is used at the same time. Setting the limit to 0 will make libcurl refuse any redirect. Set it to -1 for an infinite number of redirects (which is the default) -postredir : Controls how TclCurl acts on redirects after POSTs that get a 301, 302 or 303 response back. A "301" parameter tells TclCurl to keep POST requests as POST when following a 301 redirect. Passing a "302" makes TclCurl maintain the request method after a 302 redirect, while "303" does the same for a 303 redirect. "all" is a convenience string that activates all three behaviours. The non-RFC behaviour is ubiquitous in web browsers, so the extension does the 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 setting **-followlocation** The legacy alias **-post301** is accepted for compatibility and uses the same values. -put : An 1 parameter tells the extension to use HTTP PUT a file. The file to put must be set with **-infile** and **-infilesize**. This option is deprecated starting with version 0.12.1, you should 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 : An 1 parameter tells the library to do a regular HTTP post. This is a normal application/x-www-form-urlencoded kind, which is the most commonly used one by HTML forms. See the **-postfields** option for how to specify the data to post and **-postfieldsize** about how to set the data size. Use the **-postfields** option to specify what data to post and **-postfieldsize** to set the data size. Optionally, you can provide data to POST using the **-readproc** options. 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 a "Expect: 100-continue" header. You can disable this header with **-httpheader** as usual. If you use POST to a HTTP 1.1 server, you can send data without knowing the size before starting the POST 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 in the request. When setting **post** to an 1 value, it will automatically set **nobody** to 0. NOTE: if you have issued a POST request and want to make a HEAD or GET instead, you must explicitly pick the new request type using **-nobody** or **-httpget** or similar. -postfields : Pass a string as parameter, which should be the full data to post in a HTTP POST operation. You must make sure that the data is formatted the way you want the server to receive it. TclCurl will not convert or encode it for you. Most web servers will assume this data to be url-encoded. This is a normal application/x-www-form-urlencoded kind, 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, as simply setting **-postfields** to NULL or "" just effectively disables the sending of the specified string. TclCurl will instead assume that the POST data will be sent using the read callback! Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with **-httpheader** as usual. **Note**: to make multipart/formdata posts (aka rfc1867-posts), check out **-httppost** option. -postfieldsize : If you want to post data to the server without letting TclCurl do a strlen() to measure the data size, this option must be used. Also, when this option is used, you can post fully binary data which otherwise is likely to fail. If this size is set to zero, the library will use strlen() to get the data size. -httppost : Tells TclCurl you want a multipart/formdata HTTP POST to be made and you instruct what data to pass on to the server through a **Tcl list**. **This is the only case where the data is reset after a transfer.** First, there are some basics you need to understand about multipart/formdata posts. Each part consists of at least a **NAME** and a **CONTENTS** part. If the part is made for file upload, there are also a stored **CONTENT-TYPE** and a **FILENAME**. Below, we'll discuss which options set these properties in the parts you want to add to your post. The list must contain a **'name'** tag with the name of the section followed by a string with the name, there are three tags to indicate the value of the section: **'value'** followed by a string with the data to post, **'file'** followed by the name of the file to post and **'contenttype'** with the type of the data (text/plain, image/jpg, ...), you can also indicate a *false* file name with **'filename'**, this is useful in case the server checks if the given file name is valid, for example, by testing if it starts with 'c:\\' as any real file name does or if you want to include the full path of the file to post. You can also post the content of a variable as if it were a file with the options **'bufferName'** and **'buffer'** or use **'filecontent'** followed by a file name to read that file and use the contents as data. Should you need to specify extra headers for the form POST section, use **'contentheader**' followed by a list with the headers to post. Please see 'httpPost.tcl' and 'httpBufferPost.tcl' for examples. If TclCurl can't set the data to post an error will be returned: 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 the some form info is not complete (or error) 6 : If an illegal option is used in an array. 7 : TclCurl has no http support. -referer : Pass a string as parameter. It will be used to set the **referer** header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with **-httpheader**. -useragent : Pass a string as parameter. It will be used to set the **user-agent:** header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with **-httpheader**. -httpheader : Pass a **list** with the HTTP headers to pass to the server in your request. If you add a header that is otherwise generated and used by TclCurl internally, your added one will be used instead. If you add a header with no contents as in 'Accept:', the internally used header will just get disabled. Thus, using this option you can add new headers, replace and remove internal headers. The headers included in the linked list must not be CRLF-terminated, because TclCurl adds CRLF after each header item. Failure to comply with this will result in strange bugs because the server will most likely ignore part of the headers you specified. The first line in a request (containing the method, usually a GET or POST) is not a header and cannot be replaced using this option. Only the lines following the request-line are headers. Adding this method line in this list of headers will only cause your request to send an invalid header. **NOTE**: The most commonly replaced headers have "shortcuts" in the options: **cookie**, **useragent**, and **referer**. -http200aliases : Pass a list of aliases to be treated as valid HTTP 200 responses. Some servers respond with a custom header response line. For example, IceCast servers respond with "ICY 200 OK". By including this string in your list of aliases, the response will be treated as a valid HTTP header line such as "HTTP/1.0 200 OK". **NOTE**:The alias itself is not parsed for any version strings. Before version 7.16.3, TclCurl used the value set by option **httpversion**, but starting with 7.16.3 the protocol is assumed to match HTTP 1.0 when an alias matched. -cookie : Pass a string as parameter. It will be used to set a cookie in the http request. The format of the string should be '[NAME]=[CONTENTS];'. Where NAME is the cookie name and CONTENTS is what the cookie should contain. If you need to set mulitple cookies, you need to set them all using a single option and thus you need to concatenate them all in one single string. Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc. This option sets the cookie header explicitly in the outgoing request(s). If multiple requests are done due to authentication, followed redirections or similar, they will all get this cookie passed on. Using this option multiple times will only make the latest string override the previous ones. -cookiefile : Pass a string as parameter. It should contain the name of your file holding cookie data. The cookie data may be in netscape cookie data format or just regular HTTP-style headers dumped to a file. Given an empty or non-existing file, this option will enable cookies for this curl handle, making it understand and parse received cookies and then use matching cookies in future requests. If you use this option multiple times, you add more files to read. -cookiejar : Pass a file name in which TclCurl will dump all internally known cookies when **curlHandle cleanup** is called. If no cookies are known, no file will be created. Specify "-" to have the cookies written to stdout. Using this option also enables cookies for this session, so if you, for example, follow a location it will make matching cookies get sent accordingly. TclCurl will not and cannot report an error for this. Using '**verbose**' will get a warning to display, but that is the only visible feedback you get about this possibly lethal situation. -cookiesession : Pass an 1 to mark this as a new cookie "session". It will force TclCurl to ignore all cookies it is about to load that are "session cookies" from the previous session. By default, TclCurl always stores and loads all cookies, independent of whether they are session cookies are not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this "session" only. -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. If the cookie engine was not enabled it will be enabled. Passing a magic string "ALL" will erase all known cookies while "FLUSH" will write all cookies known by TclCurl to the file specified by **-cookiejar**. -httpget : If set to 1 forces the HTTP request to get back to GET, usable if POST, PUT or a custom request have been used previously with the same handle. When setting **httpget** to 1, **nobody** will automatically be set to 0. -httpversion : Set to one of the values decribed below, they force TclCurl to use the specific http versions. It should only be used if you really MUST do that because of a silly remote server. none : We do not care about what version the library uses. TclCurl will use whatever it thinks fit. 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 HTTP/1.1 Upgrade first. -ignorecontentlength : 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. If this option is used, TclCurl will not be able to accurately report progress, and will simply stop the download when the server ends the connection. -httpcontentdecoding : Set to zero to disable content decoding. If set to 1 it is enabled. Note however that TclCurl has no default content decoding but requires you to use **encoding** for that. -httptransferencoding : Set to zero to disable transfer decoding, if set to 1 it is enabled (default). TclCurl does chunked transfer decoding by default unless this option is set to zero. # SMTP options -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. Each recipient in SMTP lingo is specified with angle brackets (<>), but should you not use an angle bracket as first letter, TclCurl will assume you provide a single email address only and enclose that with angle brackets for you. # TFTP option tftpblksize : Specify the block size to use for TFTP data transmission. Valid range as per RFC 2348 is 8-65464 bytes. The default of 512 bytes will be used if this option is not specified. The specified block size will only be used pending support by the remote server. If the server does not return an option acknowledgement or returns an option acknowledgement with no blksize, the default of 512 bytes will be used. # FTP options -ftpport : Pass a string as parameter. It will be used to get the IP address to use for the ftp PORT instruction. The PORT instruction tells the remote server to connect to our specified IP address. The string may be a plain IP address, a host name, a network interface name (under unix) or just a '-' to let the library use your systems default IP address. Default FTP operations are passive, and thus will not use PORT. The address can be followed by a ':' to specify a port, optionally followed by a '-' o specify a port range. If the port specified is 0, the operating system will pick a free port. If a range is provided and all ports in the range are not available, libcurl will report CURLE_FTP_PORT_FAILED for the handle. Invalid port/range settings are ignored. IPv6 addresses followed by a port or portrange have to be in brackets. IPv6 addresses without port/range specifier can be in brackets. Examples with specified ports: eth0:0 192.168.1.2:32000-33000 curl.se:32123 [::1]:1234-4567 You disable PORT again and go back to using the passive version by setting this option to an empty string. -quote : Pass a **list** list with the FTP or SFTP commands to pass to the server prior to your ftp request. This will be done before any other FTP commands are issued (even before the CWD command).If you do not want to transfer any files, set **nobody** to '1' and **header** to '0'. Prefix the command with an asterisk (*) to make TclCurl continue even if the command fails as by default TclCurl will stop. Disable this operation again by setting an empty string to this option. Keep in mind the commands to send must be 'raw' ftp commands, for example, to create a directory you need to 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** with the FTP commands to pass to the server after your 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 pass to the server after the transfer type is set. -dirlistonly : A 1 tells the library to just list the names of files in a directory, instead of doing a full directory listing that would include file sizes, dates etc. It works with both FTP and SFTP urls. This causes an FTP NLST command to be sent. Beware that some FTP servers list only files in their response to NLST, they might not include subdirectories and symbolic links. Setting this option to 1 also implies a directory listing even if the URL doesn't end with a slash, which otherwise is necessary. Do NOT use this option if you also use **-wildcardmatch** as it will effectively break that feature. -append : A 1 parameter tells the extension to append to the remote file instead of overwriting it. This is only useful when uploading to a ftp site. -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. -ftpuseepvs : Set to one to tell TclCurl to use the EPSV command when doing passive FTP downloads (which it always does by default). Using EPSV means that it will first attempt to use EPSV before using PASV, but if you pass a zero to this option, it will not try using EPSV, only plain PASV. -ftpusepret : Set to one to tell TclCurl to send a PRET command before PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard command for directory listings as well as up and downloads in PASV mode. Has no effect when using the active FTP transfers mode. -ftpcreatemissingdirs : If set to 1, TclCurl will attempt to create any remote directory that it fails to CWD into. CWD is the command that changes working directory. This setting also applies to SFTP-connections. TclCurl will attempt to create the remote directory if it can't obtain a handle to the target-location. The creation will fail if a file of the same name as the directory to create already exists or lack of permissions prevents creation. If set to 2, TclCurl will retry the CWD command again if the subsequent MKD command fails. This is especially useful if you're doing many simultanoeus connections against the same server and they all have this option enabled, as then CWD may first fail but then another connection does MKD before this connection and thus MKD fails but trying CWD works -ftpresponsetimeout : Causes TclCurl to set a timeout period (in seconds) 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. Note that while TclCurl is waiting for a response, this value overrides **timeout**. It is recommended that if used in conjunction with **timeout**, you set it to a value smaller than **timeout**. -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. -ftpskippasvip : If set to 1, 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. This option has no effect if PORT, EPRT or EPSV is used instead of PASV. -ftpsslauth : Pass TclCurl one of the values from below, to alter how TclCurl issues "AUTH TLS" or "AUTH SSL" when FTP over SSL is activated (see **-ftpssl**). You may need this option because of servers like BSDFTPD-SSL from "which won't work properly when "AUTH SSL" is issued (although the server responds fine and everything) but requires "AUTH TLS" instead. default : Allows TclCurl to decide. ssl : Try "AUTH SSL" first, and only if that fails try "AUTH TLS". tls : Try "AUTH TLS" first, and only if that fails try "AUTH SSL". -ftpsslccc : Set it to make TclCurl use CCC (Clear Command Channel). It shuts down the SSL/TLS layer after authenticating. The rest of the control channel communication will be unencrypted. This allows NAT routers to follow the FTP transaction. Possible values are: none : Do not attempt to use CCC. passive : Do not initiate the shutdown, wait for the server to do it. Do not send a reply. active : Initiate the shutdown and wait for a reply. -ftpaccount : Pass string (or "" to disable). When an FTP server asks for "account data" after user name and password has been provided, this data is sent off using the ACCT command. -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". This is somewhat more standards compliant than 'nocwd' but without the full penalty of 'multicwd'. # Protocol options -transfertext : A 1 tells the extension to use ASCII mode for ftp transfers, instead of the default binary transfer. For win32 systems it does not set the stdout to binary mode. This option can be usable when transferring text data between systems with different views on certain characters, such as newlines or similar. **NOTE:** TclCurl does not do a complete ASCII conversion when doing ASCII transfers over FTP. This is a known limitation/flaw that nobody has rectified. TclCurl simply sets the mode to ascii and performs a standard transfer. -proxytransfermode : If set to 1, TclCurl sets 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 it being set to 0, the default, **-transfertext** has no effect when doing FTP via a proxy. Beware that not all proxies support this feature. -crlf : If set to '1', TclCurl converts Unix newlines to CRLF newlines on transfers. Disable this option again by setting the value to '0'. -range : Pass a string as parameter, which should contain the specified range you want. It should be in the format "X-Y" , where X or Y may be left out. HTTP transfers also support several intervals, separated with commas as in "X-Y,N-M" Using this kind of multiple intervals will cause the HTTP server to send the response document in pieces (using standard MIME separation techniques). Ranges only work on HTTP, FTP and FILE transfers. -resumefrom : Pass the offset in number of bytes that you want the transfer to start from. Set this option to 0 to make the transfer start from the beginning (effectively disabling resume). For FTP, set this option to -1 to make the transfer start from the end of the target file (useful to continue an interrupted upload). When doing uploads with FTP, the resume position is where in the local/source file TclCurl should try to resume the upload from and it will then append the source file to the remote target file. -customrequest : Pass a string as parameter. It will be used instead of GET or HEAD when doing the HTTP request. This is useful for doing DELETE or other more obscure HTTP requests. Do not do this at will, make sure your server supports the command first. Note that TclCurl will still act and assume the keyword it would use if you do not set your custom and it will act according to that. Thus, changing this to a HEAD when TclCurl otherwise would do a GET might cause TclCurl to act funny, and similar. To switch to a proper HEAD, use **-nobody**, to switch to a proper POST, use **-post** or **-postfields** and so on. -filetime : If you pass a 1, TclCurl will attempt to get the modification date of the remote document in this operation. This requires that the remote server sends the time or replies to a time querying command. The getinfo procedure with the filetime argument can be used after a transfer to extract the received time (if any). -nobody : A 1 tells the library not to include the body-part in the output. This is only relevant for protocols that have a separate header and body part. On HTTP(S) servers, this will make TclCurl do a HEAD request. To change request to GET, you should use **httpget**. Change request to POST with **post** etc. -infilesize : When uploading a file to a remote site, this option should be used to tell TclCurl what the expected size of the infile is. This option is mandatory for uploading using SCP. -upload : A 1 tells the library to prepare for an upload. The **-infile** and **-infilesize** options are also interesting 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 : This defines how the **timevalue** value is treated. You can set this parameter to **ifmodsince** or **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 you allow the TclCurl transfer operation to take. Do note that normally, name lookups may take a considerable time and that limiting the operation to less than a few minutes risks aborting perfectly normal operations. This option will cause libcurl to use the SIGALRM to enable time-outing system calls. In unix-like systems, this might cause signals to be used unless **-nosignal** is used. -timeoutms : Like **timeout** but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. -lowspeedlimit : Pass the speed in bytes per second that the transfer should be below during **lowspeedtime** seconds for the extension to consider it too slow and abort. -lowspeedtime : Pass the time in seconds that the transfer should be below the **lowspeedlimit** for the extension to consider it too slow and abort. -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. Defaults to unlimited speed. -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. Defaults to unlimited speed. -maxconnects : Sets the persistent connection cache size in all the protocols that support persistent conecctions. The set amount will be the maximum amount of simultaneous connections that TclCurl may cache in this easy handle. Default is 5, and there isn't much point in changing this value unless you are perfectly aware of how this work and changes TclCurl's behaviour. When reaching the maximum limit, TclCurl closes the oldest connection in the cache to prevent the number of open connections to increase. **Note**: if you have already performed transfers with this curl handle, setting a smaller **maxconnects** than before may cause open connections to unnecessarily get closed. If you add this easy handle to a multi handle, this setting is not being acknowledged, instead you must configure the multi handle its own **maxconnects** option. -connecttimeout : Maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once it has connected, this option is of no more use. Set to zero to disable connection timeout (it will then only timeout on the internal timeouts). In unix-like systems, this might cause signals to be used unless **-nosignal** is set. -connecttimeoutms : Like **connecttimeout** but takes a number of milliseconds instead. If libcurl is built to use the standard system name resolver, that part will still use full-second resolution for timeouts. -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. The allowed values are: whatever : Default, resolves addresses to all IP versions that your system allows. v4 : Resolve to ipv4 addresses. v6 : Resolve to ipv6 addresses. -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. This option effectively pre-populates the DNS cache with entries for the host+port pair so redirects and everything that operations against the HOST+PORT will instead use your provided ADDRESS. You can remove names from the DNS cache again, to stop providing these fake resolves, by including a string in the linked list that uses the format "-HOST:PORT". The host name must be prefixed with a dash, and the host name and port number must exactly match what was already added previously. -usessl : Pass a one of the values from below to make TclCurl use your desired level of SSL for the transfer. This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc. You can use ftps:// URLs to explicitly switch on SSL/TSL for the control connection and the data connection. Alternatively you can set the 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 conecction 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 as parameter. The string should be the file name of your certificate. The default format is "PEM" and can be changed with **-sslcerttype**. With NSS this is the nickname of the certificate you wish to authenticate with. If you want to use a file from the current directory, please precede it with the "./" prefix, in order to avoid confusion with a nickname. -sslcerttype : Pass a string as parameter. The string should be the format of your certificate. Supported formats are "PEM" and "DER". -sslkey : Pass a pointer to a zero terminated string as parameter. The string should be the file name of your private key. The default format is "PEM" and can be changed with **-sslkeytype**. -sslkeytype : Pass a pointer to a zero terminated string as parameter. The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG" **NOTE:**The format "ENG" enables you to load the private key from a crypto engine. in this case **-sslkey** is used as an identifier passed to the engine. You have to set the crypto engine with **-sslengine**. The "DER" format key file currently does not work because of a bug in OpenSSL. -keypasswd : Pass a string as parameter. It will be used as the password required to use the **-sslkey** or **-sshprivatekeyfile** private key. You never need a pass phrase to load a certificate but you need one to load you private key. This option used to be known as **-sslkeypasswd** and **-sslcertpasswd**. -sslengine : Pass a string as parameter. It will be used as the identifier for the crypto engine you want to use for your private key. **NOTE:**If the crypto device cannot be loaded, an error will be returned. -sslenginedefault : Pass a 1 to set the actual crypto engine as the default for (asymmetric) crypto operations. **NOTE:**If the crypto device cannot be set, an error will be returned. -sslversion : Use it to set what version of SSL/TLS to use. The available options are: default : The default action. This will attempt to figure out the remote SSL protocol version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled by default with 7.18.1). tlsv1 : Force TLSv1 or later sslv2 : Force SSLv2 sslv3 : Force SSLv3 tlsv1_0 : Force TLSv1.0 or later tlsv1_1 : Force TLSv1.1 or later tlsv1_2 : Force TLSv1.2 or later tlsv1_3 : Force TLSv1.3 or later maxdefault : Use the maximum supported TLS version by libcurl or the default value from the SSL library. maxtlsv1_0 : Define maximum supported TLS version as TLSv1.0 maxtlsv1_1 : Define maximum supported TLS version as TLSv1.1 maxtlsv1_2 : Define maximum supported TLS version as TLSv1.2 maxtlsv1_3 : Define maximum supported TLS version as TLSv1.3 -sslverifypeer : This option determines whether TclCurl verifies the authenticity of the peer's certificate. A 1 means it verifies; zero means it doesn't. The default is 1. When negotiating an SSL connection, the server sends a certificate indicating its identity. TclCurl verifies whether the certificate is authentic, i.e. that you can trust that the server is who the certificate says it is. This trust is based on a chain of digital signatures, rooted in certification authority (CA) certificates you supply. TclCurl uses a default bundle of CA certificates that comes with libcurl but you can specify alternate certificates with the **-cainfo** or the **-capath** options. When **-sslverifypeer** is nonzero, and the verification fails to prove that the certificate is authentic, the connection fails. When the option is zero, the peer certificate verification succeeds regardless. Authenticating the certificate is not by itself very useful. You typically want to ensure that the server, as authentically identified by its certificate, is the server you mean to be talking to, use **-sslverifyhost** to control that. The check that the host name in the certificate is valid for the host name you're connecting to is done independently of this option. -cainfo : Pass a file naming holding the certificate to verify the peer with. This only makes sense when used in combination with the **-sslverifypeer** option, if it is set to zero **-cainfo** need not even indicate an accessible file. This option is by default set to the system path where libcurl's cacert bundle is assumed to be stored, as established at build time. When built against NSS this is the directory that the NSS certificate database resides in. -issuercert : Pass a string naming a file holding a CA certificate in PEM format. If the option is set, an additional check against the peer certificate is performed to verify the issuer is indeed the one associated with the certificate provided by the option. This additional check is useful in multi-level PKI where one need to enforce the peer certificate is from a specific branch of the tree. This option makes sense only when used in combination with the **-sslverifypeer** option. Otherwise, the result of the check is not considered as failure. -capath : Pass the directory holding multiple CA certificates to verify the peer with. If libcurl is built against OpenSSL, the certificate directory must be prepared using the openssl c_rehash utility. This only makes sense when used in combination with the **-sslverifypeer** option, if it is set to zero, **-capath** need not even indicate an accessible path. This option apparently does not work in Windows due to some limitation in openssl. This option is OpenSSL-specific and does nothing if libcurl is built to use GnuTLS. NSS-powered libcurl provides the option only for backward compatibility. -crlfile : Pass a string naming a file with the concatenation of CRL (in PEM format) to use in the certificate validation that occurs during the SSL exchange. When libcurl is built to use NSS or GnuTLS, there is no way to influence the use of CRL passed to help in the verification process. When built with OpenSSL support, X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are both set, requiring CRL check against all the elements of the certificate chain if a CRL file is passed. This option makes sense only when used in combination with the **-sslverifypeer** option. A specific error code (CURLE_SSL_CRL_BADFILE) is defined with the option. It is returned when the SSL exchange fails because the CRL file cannot be loaded. A failure in certificate verification due to a revocation information found in the CRL does not trigger this specific error. -sslverifyhost : This option determines whether TclCurl verifies that the server claims to be who you want it to be. When negotiating an SSL connection, the server sends a certificate indicating its identity. When **-sslverifyhost** is set to 2, that certificate must indicate that the server is the server to which you meant to connect, or the connection fails. TclCurl considers the server the intended one when the Common Name field or a Subject Alternate Name field in the certificate matches the host name in the URL to which you told Curl to connect. When set to 1, the certificate must contain a Common Name field, but it does not matter what name it says. (This is not ordinarily a useful setting). When the value is 0, the connection succeeds regardless of the names in the certificate. The default value for this option is 2. This option controls the identity that the server *claims*. The server could be lying. To control lying, see **-sslverifypeer**. If libcurl is built against NSS and **-verifypeer** is zero, **-verifyhost** is ignored. -certinfo : Set to '1' to enable TclCurl's certificate chain info gatherer. With this enabled, TclCurl (if built with OpenSSL) will extract lots of information and data about the certificates in the certificate chain used in the SSL connection. This data can then be to extracted after a transfer using the **getinfo** command and its option **certinfo**. -randomfile : Pass a file name. The file will be used to read from to seed the random engine for SSL. The more random the specified file is, the more secure the SSL connection becomes. *This option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option* -egdsocket : Pass a path name to the Entropy Gathering Daemon socket. It will be used to seed the random engine for SSL. *This option was deprecated in libcurl v7.84 and removed by default in tclcurl build. See README.md for instructions on how to re-enable this option* -sslcypherlist : Pass a string holding the ciphers to use for the SSL connection. The list must consists of one or more cipher strings separated by colons. Commas or spaces are also acceptable separators but colons are normally used, , - and + can be used as operators. For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA', 'SHA1+DES', 'TLSv1' and 'DEFAULT'. The default list is normally set when you compile OpenSSL. You will find more details about cipher lists on this URL: For NSS valid examples of cipher lists include 'rsa_rc4_128_md5', 'rsa_aes_128_sha', etc. With NSS you don't add/remove ciphers. If you use this option then all known ciphers are disabled and only those passed in are enabled. You'll find more details about the NSS cipher lists on this URL: <> -sslsessionidcache : Pass a 0 to disable TclCurl's use of SSL session-ID caching or a 1 to enable it. By default all transfers are done using the cache. While nothing ever should get hurt by attempting to reuse SSL session-IDs, there seem to be broken SSL implementations in the wild that may require you to disable this in order for you to succeed. -krblevel : Set the kerberos security level for FTP, this also enables kerberos awareness. This is a string, 'clear', 'safe', 'confidential' or 'private'. If the string is set but does not match one of these, 'private' will be used. Set the string to NULL to disable kerberos4. Set the string to "" to disable kerberos support for FTP. -gssapidelegation : Set the option to 'flag' to allow unconditional GSSAPI credential delegation. The delegation is disabled by default since 7.21.7. 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. # SSH options -sshauthtypes : The allowed types are: publickey : Use public key authentication. password : Use password authentication. host : Use host-based authentication. keyboard : Use keyboard-interactive authentication. any : To let TclCurl pick one -sshhostpublickeymd5 : Pass a string containing 32 hexadecimal digits. The string should be the 128 bit MD5 cheksum of the remote host public key, and TclCurl will reject the connection to the host unless the md5sums match. This option is only for SCP and SFTP transfers. -publickeyfile : Pass the file name for your public key. If not used, TclCurl defaults to using **$HOME/.ssh/id_dsa.pub**. HOME environment variable is set, and just **id_dsa** in the current directory if not. -privatekeyfile : Pass the file name for your private key. If not used, TclCurl defaults to using **$HOME/.ssh/id_dsa.pub**. HOME environment variable is set, and just **id_dsa** in the current directory if not. If the file is password-protected, set the password with **-keypasswd**. -sshknownhosts : Pass a string holding the file name of the known_host file to use. The known_hosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, TclCurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use **-sshkeyproc** to alter the default behavior on host and key (mis)matching. -sshkeyproc : Pass a the name of the procedure that will be called when the known_host matching has been done, to allow the application to act and decide for TclCurl how to proceed. The callback will only be called if **-knownhosts** is also set. It gets passed a list with three elements, the first one is a list with the type of the key from the known_hosts file and the key itself, the second is another list with the type of the key from the remote site and the key itslef, the third tells you what TclCurl thinks about the matching status. The known key types are: "rsa", "rsa1" and "dss", in any other case "unknown" is given. TclCurl opinion about how they match may be: "match", "mismatch", "missing" or "error". The procedure must return: 0 : The host+key is accepted and TclCurl will append it to the known_hosts file before continuing with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. The adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this. 1 : The host+key is accepted, TclCurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. 2 : The host+key is rejected. TclCurl will close the connection. 3 : The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again. Any other value will cause the connection to be closed. # Other options -headervar : Name of the Tcl array variable where TclCurl will store the headers returned by the server. -bodyvar : Name of the Tcl variable where TclCurl will store the file requested, the file may contain text or binary data. -canceltransvar : Name of a Tcl variable, in case you have defined a procedure to call with **-progressproc** setting this variable to '1' will cancel the transfer. -command : Executes the given command after the transfer is done, since it only works with blocking transfers, it is pretty much useless. -share : Pass a share handle as a parameter. The share handle must have been created by a previous call to **curl::shareinit**. Setting this option, will make this handle use the data from the shared handle instead of keeping the data to itself. See *tclcurl_share* for details. -newfileperms : Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created files on the remote server. The default value is 0644, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. -newdirectoryperms : Pass a number as a parameter, containing the value of the permissions that will be assigned to newly created directories on the remote server. The default value is 0755, but any valid value can be used. The only protocols that can use this are sftp://, scp:// and file://. # 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 transfered, 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 transfered. 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 successfull 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 : Retuns 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. # SEE ALSO curl, The art of HTTP scripting (at , RFC 2396, tclcurl-ng-8.0.1/doc/tclcurl_multi.html000066400000000000000000000224211517264272000201160ustar00rootroot00000000000000Manpage of TclCurl

TclCurl

Section: TclCurl Multi Interface (3)
Updated: 03 September 2011

 

NAME

TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.  

SYNOPSIS

curl::multiinit

multiHandle addhandle

multiHandle removehandle

multiHandle configure

multiHandle perform

multiHandle active

multiHandle getinfo

multihandle cleanup

multihandle auto

curl::multistrerror errorCode

 

DESCRIPTION

TclCurl's multi interface introduces several new abilities that the easy interface refuses to offer. They are mainly:
  • 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.

 

Blocking

A few areas in the code are still using blocking code, even when used from the multi interface. While we certainly want and intend for these to get fixed in the future, you should be aware of the following current restrictions:
  • Name resolves on non-windows unless c-ares is used.
  • GnuTLS SSL connections.
  • Active FTP connections.
  • HTTP proxy CONNECT operations.
  • SCP and SFTP connections.
  • SFTP transfers.
  • TFTP transfers
  • file:// transfers.

 

curl::multiinit

This procedure must be the first one to call, it returns a multiHandle that you need to use to invoke TclCurl procedures. The init MUST have a corresponding call to cleanup when the operation is completed.

RETURN VALUE

multiHandle to use.

 

multiHandle addhandle ?easyHandle?

Each single transfer is built up with an 'easy' handle, the kind we have been using so far with TclCurl, you must create them and setup the appropriate options for each of them. Then we add them to the 'multi stack' using the addhandle command.

If the easy handle is not set to use a shared or global DNS cache, it will be made to use the DNS cache that is shared between all easy handles within the multi handle.

When an easy handle has been added to a multi stack, you can not and you must not use perform on that handle!

multiHandle is the return code from the curl::multiinit call.

RETURN VALUE The possible return values are:

-1
Handle added to the multi stack, please call perform soon
0
Handle added ok.
1
Invalid multi handle.
2
Invalid 'easy' handle. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle.
3
Out of memory, you should never get this.
4
You found a bug in TclCurl.

 

multiHandle removehandle ?easyHandle?

When a transfer is done or if we want to stop a transfer before it is completed, we can use the removehandle command. Once removed from the multi handle, we can again use other easy interface functions on it.

Please note that when a single transfer is completed, the easy handle is still left added to the multi stack. You need to remove it and then close or, possibly, set new options to it and add it again to the multi handle to start another transfer.

RETURN VALUE The possible return values are:

0
Handle removed ok.
1
Invalid multi handle.
2
Invalid 'easy' handle.
3
Out of memory, you should never get this.
4
You found a bug in TclCurl.

 

multiHandle configure

So far the only option is:
-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.
-maxconnects
Pass a number which will be used as the maximum amount of simultaneously open connections that TclCurl may cache. Default is 10, and TclCurl will enlarge the size for each added easy handle to make it fit 4 times the number of added easy handles.

By setting this option, you can prevent the cache size to grow 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 to increase.

This option is for the multi handle's use only, when using the easy interface you should instead use it's own maxconnects option.

 

multiHandle perform

Adding the easy handles to the multi stack does not start any transfer. Remember that one of the main ideas with this interface is to let your application drive. You drive the transfers by invoking perform. TclCurl will then transfer data if there is anything available to transfer. It'll use the callbacks and everything else we have setup in the individual easy handles. It'll transfer data on all current transfers in the multi stack that are ready to transfer anything. It may be all, it may be none.

When you call perform and the amount of Irunning handles is changed from the previous call (or is less than the amount of easy handles you added to the multi handle), you know that there is one or more transfers less "running". You can then call getinfo to get information about each individual completed transfer.

RETURN VALUE If everything goes well, it returns the number of running handles, '0' if all are done. In case of error, it will return the error code.

 

multiHandle active

In order to know if any of the easy handles are ready to transfer data before invoking perform you can use the active command, it will return the number of transfers currently active.

RETURN VALUE The number of active transfers or '-1' in case of error.

 

multiHandle getinfo

This procedure returns very simple information about the transfers, you can get more detail information using the getinfo command on each of the easy handles.

RETURN VALUE A list with the following elements:

easyHandle about which the info is about.
state of the transfer, '1' if it is done.
exit code of the transfer, '0' if there was no error,...
Number of messages still in the info queue.
In case there are no messages in the queue it will return {"" 0 0 0}.

 

multiHandle cleanup

This procedure must be the last one to call for a multi stack, it is the opposite of the curl::multiinit procedure and must be called with the same multiHandle as input as the curl::multiinit call returned.

 

multiHandle auto ?-command command?

Using this command Tcl's event loop will take care of periodically invoking perform for you, before using it, you must have already added at least one easy handle to the multi handle.

The command option allows you to specify a command to invoke after all the easy handles have finished their transfers, even though I say it is an option, the truth is you must use this command to cleanup all the handles, otherwise the transfered files may not be complete.

This support is still in a very experimental state, it may still change without warning. Any and all comments are welcome.

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.


 

Index

NAME
SYNOPSIS
DESCRIPTION
Blocking
curl::multiinit
multiHandle addhandle ?easyHandle?
multiHandle removehandle ?easyHandle?
multiHandle configure
multiHandle perform
multiHandle active
multiHandle getinfo
multiHandle cleanup
multiHandle auto ?-command command?
curl::multistrerror errorCode
SEE ALSO

This document was created by man2html, using the manual pages.
tclcurl-ng-8.0.1/doc/tclcurl_multi.n000066400000000000000000000174101517264272000174110ustar00rootroot00000000000000.\" You can view this file with: .\" nroff -man [file] .\" Adapted from libcurl docs by fandom@telefonica.net .TH TclCurl 3 "3 October 2011" "TclCurl 7.22.0 "TclCurl Easy Interface" .SH NAME TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. .SH SYNOPSIS .BI "curl::multiinit" .sp .IB multiHandle " addhandle" .sp .IB multiHandle " removehandle" .sp .IB multiHandle " configure" .sp .IB multiHandle " perform" .sp .IB multiHandle " active" .sp .IB multiHandle " getinfo " .sp .IB multihandle " cleanup" .sp .IB multihandle " auto" .sp .BI "curl::multistrerror " errorCode .sp .SH DESCRIPTION TclCurl's multi interface introduces several new abilities that the easy interface refuses to offer. They are mainly: .TP Enable a "pull" interface. The application that uses TclCurl decides where and when to get/send data. .TP Enable multiple simultaneous transfers in the same thread without making it complicated for the application. .TP Keep Tk GUIs 'alive' while transfers are taking place. .SH Blocking A few areas in the code are still using blocking code, even when used from the multi interface. While we certainly want and intend for these to get fixed in the future, you should be aware of the following current restrictions: .RS .TP 5 .B Name resolves on non-windows unless c-ares is used. .TP .B GnuTLS SSL connections. .TP .B GnuTLS SSL connections .TP .B Active FTP connections. .TP .B HTTP proxy CONNECT operations. .TP .B SOCKS proxy handshakes .TP .B file:// transfers. .TP .B TELNET transfers .RE .SH curl::multiinit This procedure must be the first one to call, it returns a \fImultiHandle\fP that you need to use to invoke TclCurl procedures. The init MUST have a corresponding call to \fIcleanup\fP when the operation is completed. .sp .B RETURN VALUE .sp .I multiHandle to use. .sp .SH multiHandle addhandle ?easyHandle? .sp Each single transfer is built up with an 'easy' handle, the kind we have been using so far with TclCurl, you must create them and setup the appropriate options for each of them. Then we add them to the 'multi stack' using the \fIaddhandle\fP command. If the easy handle is not set to use a shared or global DNS cache, it will be made to use the DNS cache that is shared between all easy handles within the multi handle. When an easy handle has been added to a multi stack, you can not and you must not use \fIperform\fP on that handle! .sp .I "multiHandle" is the return code from the \fIcurl::multiinit\fP call. .sp .B RETURN VALUE The possible return values are: .IP -1 Handle added to the multi stack, please call .I perform soon .IP 0 Handle added ok. .IP 1 Invalid multi handle. .IP 2 Invalid 'easy' handle. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle. .IP 3 Out of memory, you should never get this. .IP 4 You found a bug in TclCurl. .sp .SH multiHandle removehandle ?easyHandle? .sp When a transfer is done or if we want to stop a transfer before it is completed, we can use the \fIremovehandle\fP command. Once removed from the multi handle, we can again use other easy interface functions on it. Please note that when a single transfer is completed, the easy handle is still left added to the multi stack. You need to remove it and then close or, possibly, set new options to it and add it again to the multi handle to start another transfer. .sp .B RETURN VALUE The possible return values are: .IP 0 Handle removed ok. .IP 1 Invalid multi handle. .IP 2 Invalid 'easy' handle. .IP 3 Out of memory, you should never get this. .IP 4 You found a bug in TclCurl. .sp .SH multiHandle configure So far the only options are: .TP .B -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. .TP .B -maxconnects Pass a number which will be used as the maximum amount of simultaneously open connections that TclCurl may cache. Default is 10, and TclCurl will enlarge the size for each added easy handle to make it fit 4 times the number of added easy handles. By setting this option, you can prevent the cache size to grow 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 to increase. This option is for the multi handle's use only, when using the easy interface you should instead use it's own \fBmaxconnects\fP option. .sp .SH multiHandle perform Adding the easy handles to the multi stack does not start any transfer. Remember that one of the main ideas with this interface is to let your application drive. You drive the transfers by invoking .I perform. TclCurl will then transfer data if there is anything available to transfer. It'll use the callbacks and everything else we have setup in the individual easy handles. It'll transfer data on all current transfers in the multi stack that are ready to transfer anything. It may be all, it may be none. When you call \fBperform\fP and the amount of running handles is changed from the previous call (or is less than the amount of easy handles you added to the multi handle), you know that there is one or more transfers less "running". You can then call \fIgetinfo\fP to get information about each individual completed transfer. If an added handle fails very quickly, it may never be counted as a running handle. .sp .B RETURN VALUE If everything goes well, it returns the number of running handles, '0' if all are done. In case of error, it will return the error code. This function only returns errors etc regarding the whole multi stack. Problems still might have occurred on individual transfers even when this function returns ok. .sp .SH multiHandle active In order to know if any of the easy handles are ready to transfer data before invoking .I perform you can use the .I active command, it will return the number of transfers currently active. .sp .B RETURN VALUE The number of active transfers or '\-1' in case of error. .SH multiHandle getinfo This procedure returns very simple information about the transfers, you can get more detail information using the \fIgetinfo\fP command on each of the easy handles. .sp .B RETURN VALUE A list with the following elements: .TP easyHandle about which the info is about. .TP state of the transfer, '1' if it is done. .TP exit code of the transfer, '0' if there was no error,... .TP Number of messages still in the info queue. .TP In case there are no messages in the queue it will return {"" 0 0 0}. .SH multiHandle cleanup This procedure must be the last one to call for a multi stack, it is the opposite of the .I curl::multiinit procedure and must be called with the same .I multiHandle as input as the .B curl::multiinit call returned. .SH multiHandle auto ?-command \fIcommand\fP? Using this command Tcl's event loop will take care of periodically invoking \fBperform\fP for you, before using it, you must have already added at least one easy handle to the multi handle. The \fBcommand\fP option allows you to specify a command to invoke after all the easy handles have finished their transfers, even though I say it is an option, the truth is you must use this command to cleanup all the handles, otherwise the transfered files may not be complete. This support is still in a very experimental state, it may still change without warning. Any and all comments are welcome. You can find a couple of examples at \fBtests/multi\fP. .SH curl::multistrerror errorCode This procedure returns a string describing the error code passed in the argument. .SH "SEE ALSO" .I tclcurl, curl. tclcurl-ng-8.0.1/doc/tclcurl_share.html000066400000000000000000000053441517264272000200730ustar00rootroot00000000000000Manpage of TclCurl

TclCurl

Section: TclCurl share data api (3)
Updated: 03 October 2011

 

NAME

TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.  

SYNOPSIS

curl::shareinit

shareHandle share ?data?

shareHandle unshare ?data?

shareHandle cleanup

curl::sharestrerror errorCode

 

DESCRIPTION

With the share API, you can have two or more 'easy' handles sharing data among them, so far they can only share cookies and DNS data.

 

curl::shareinit

This procedure must be the first one to call, it returns a shareHandle that you need to use to share data among handles using the -share option to the configure command. The init MUST have a corresponding call to cleanup when the operation is completed.

RETURN VALUE

shareHandle to use.

 

shareHandle share ?data?

The parameter specifies a type of data that should be shared. This may be set to one of the values described below:

cookies
Cookie data will be shared across the easy handles using this shared object.

dns
Cached DNS hosts will be shared across the easy handles using this shared object.

 

shareHandle unshare ?data?

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

 

sharehandle cleanup

Deletes a shared object. The share handle cannot be used anymore after this function has been called.

 

curl::sharestrerror errorCode

Returns a string describing the error code passed in the argument.

 

SEE ALSO

curl, TclCurl


 

Index

NAME
SYNOPSIS
DESCRIPTION
curl::shareinit
shareHandle share ?data?
shareHandle unshare ?data?
sharehandle cleanup
curl::sharestrerror errorCode
SEE ALSO

This document was created by man2html, using the manual pages.
tclcurl-ng-8.0.1/doc/tclcurl_share.n000066400000000000000000000037621517264272000173660ustar00rootroot00000000000000.\" You can view this file with: .\" nroff -man [file] .\" Adapted from libcurl docs by fandom@telefonica.net .\" Reworked and refactored by massimo.manghi@rivetweb.org .TH TclCurl 3 "1 April 2026" "TclCurl 8.0.1 "TclCurl Easy Interface" .SH NAME TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. .SH SYNOPSIS .BI "curl::shareinit" .sp .IB shareHandle " share " "?data?" .sp .IB shareHandle " unshare " "?data?" .sp .IB shareHandle " cleanup" .sp .BI "curl::sharestrerror " errorCode .SH DESCRIPTION With the share API, you can have two or more 'easy' handles sharing data among them, so far they can only share cookies and DNS data. .SH curl::shareinit This procedure must be the first one to call, it returns a \fBshareHandle\fP that you need to use to share data among handles using the \fB-share\fP option to the \fBconfigure\fP command. The init MUST have a corresponding call to \fBcleanup\fP when the operation is completed. .B RETURN VALUE .sp \fBshareHandle\fP to use. .SH shareHandle share ?data? The parameter specifies a type of data that should be shared. This may be set to one of the values described below: .RS .TP 5 .B cookies Cookie data will be shared across the easy handles using this shared object. .TP .B dns Cached DNS hosts will be shared across the easy handles using this shared object. Note that when you use the multi interface, all easy handles added to the same multi handle will share DNS cache by default without this having to be used! .RE .SH shareHandle unshare ?data? This command does the opposite of \fBshare\fP. The specified parameter will no longer be shared. Valid values are the same as those for \fBshare\fP. .SH sharehandle cleanup Deletes a shared object. The share handle cannot be used anymore after this function has been called. .SH curl::sharestrerror errorCode Returns a string describing the error code passed in the argument. .SH "SEE ALSO" .I curl, TclCurl tclcurl-ng-8.0.1/doc/tclcurl_share.n.in000066400000000000000000000037761517264272000200000ustar00rootroot00000000000000.\" You can view this file with: .\" nroff -man [file] .\" Adapted from libcurl docs by fandom@telefonica.net .\" Reworked and refactored by massimo.manghi@rivetweb.org .TH TclCurl 3 "1 April 2026" "TclCurl @PACKAGE_VERSION@ "TclCurl Easy Interface" .SH NAME TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP, LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax. .SH SYNOPSIS .BI "curl::shareinit" .sp .IB shareHandle " share " "?data?" .sp .IB shareHandle " unshare " "?data?" .sp .IB shareHandle " cleanup" .sp .BI "curl::sharestrerror " errorCode .SH DESCRIPTION With the share API, you can have two or more 'easy' handles sharing data among them, so far they can only share cookies and DNS data. .SH curl::shareinit This procedure must be the first one to call, it returns a \fBshareHandle\fP that you need to use to share data among handles using the \fB-share\fP option to the \fBconfigure\fP command. The init MUST have a corresponding call to \fBcleanup\fP when the operation is completed. .B RETURN VALUE .sp \fBshareHandle\fP to use. .SH shareHandle share ?data? The parameter specifies a type of data that should be shared. This may be set to one of the values described below: .RS .TP 5 .B cookies Cookie data will be shared across the easy handles using this shared object. .TP .B dns Cached DNS hosts will be shared across the easy handles using this shared object. Note that when you use the multi interface, all easy handles added to the same multi handle will share DNS cache by default without this having to be used! .RE .SH shareHandle unshare ?data? This command does the opposite of \fBshare\fP. The specified parameter will no longer be shared. Valid values are the same as those for \fBshare\fP. .SH sharehandle cleanup Deletes a shared object. The share handle cannot be used anymore after this function has been called. .SH curl::sharestrerror errorCode Returns a string describing the error code passed in the argument. .SH "SEE ALSO" .I curl, TclCurl tclcurl-ng-8.0.1/generic/000077500000000000000000000000001517264272000152145ustar00rootroot00000000000000tclcurl-ng-8.0.1/generic/curl_getinfo.c000066400000000000000000000342201517264272000200410ustar00rootroot00000000000000/* * 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.1/generic/curl_mime.c000066400000000000000000000375241517264272000173470ustar00rootroot00000000000000/* * 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.1/generic/curl_mime.h000066400000000000000000000016761517264272000173530ustar00rootroot00000000000000/* * 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.1/generic/curl_setopts.c000066400000000000000000001451321517264272000201140ustar00rootroot00000000000000/* * 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.1/generic/curl_setopts.h000066400000000000000000000551431517264272000201230ustar00rootroot00000000000000/* * 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.1/generic/curl_utils.c000066400000000000000000000210541517264272000175470ustar00rootroot00000000000000/* * 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.1/generic/ftp.c000066400000000000000000000024711517264272000161550ustar00rootroot00000000000000/* * */ #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.1/generic/multi.c000066400000000000000000000656151517264272000165270ustar00rootroot00000000000000/* * 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 /* *---------------------------------------------------------------------- * * 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; CURLMcode errorCode; 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; } switch(tableIndex) { case 0: /* fprintf(stdout,"Multi add handle\n"); */ errorCode=curlAddMultiHandle(interp,curlMultiData->mcurl,objv[2]); return curlReturnCURLMcode(interp,errorCode); break; case 1: /* fprintf(stdout,"Multi remove handle\n"); */ errorCode=curlRemoveMultiHandle(interp,curlMultiData->mcurl,objv[2]); return curlReturnCURLMcode(interp,errorCode); break; case 2: /* fprintf(stdout,"Multi perform\n"); */ errorCode=curlMultiPerform(interp,curlMultiData->mcurl); return errorCode; break; case 3: /* fprintf(stdout,"Multi cleanup\n"); */ Tcl_DeleteCommandFromToken(interp,curlMultiData->token); break; case 4: /* fprintf(stdout,"Multi getInfo\n"); */ curlMultiGetInfo(interp,curlMultiData->mcurl); break; case 5: /* fprintf(stdout,"Multi activeTransfers\n"); */ curlMultiActiveTransfers(interp,curlMultiData); break; case 6: /* fprintf(stdout,"Multi auto transfer\n");*/ curlMultiAutoTransfer(interp,curlMultiData,objc,objv); break; case 7: /* fprintf(stdout,"Multi configure\n");*/ curlMultiConfigTransfer(interp,curlMultiData,objc,objv); break; } 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, CURLMOPT_PIPELINING,tableIndex,objv)) { return TCL_ERROR; } break; case 1: if (SetMultiOptLong(interp,curlMultiData->mcurl, CURLMOPT_MAXCONNECTS,tableIndex,objv)) { return TCL_ERROR; } break; } 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.1/generic/multi.h000066400000000000000000000066101517264272000165220ustar00rootroot00000000000000/* * 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; }; const static char *multiCommandTable[] = { "addhandle", "removehandle", "perform", "cleanup", "getinfo", "active", "auto", "configure", (char *) NULL }; const static char *multiConfigTable[] = { "-pipelining", "-maxconnects", (char *)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.1/generic/tcl_size.c000066400000000000000000000012301517264272000171700ustar00rootroot00000000000000/* * 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.1/generic/tclcompat.h000066400000000000000000000020241517264272000173510ustar00rootroot00000000000000#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.1/generic/tclcurl.c000066400000000000000000002121561517264272000170370ustar00rootroot00000000000000/* * 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.1/generic/tclcurl.h000066400000000000000000000234031517264272000170370ustar00rootroot00000000000000/* * 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.1/generic/tclcurl.tcl000077500000000000000000000111101517264272000173650ustar00rootroot00000000000000################################################################################ ################################################################################ #### 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.1/license.terms000077500000000000000000000041611517264272000163030ustar00rootroot00000000000000This 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.1/packages/000077500000000000000000000000001517264272000153565ustar00rootroot00000000000000tclcurl-ng-8.0.1/packages/Linux/000077500000000000000000000000001517264272000164555ustar00rootroot00000000000000tclcurl-ng-8.0.1/packages/Linux/tclcurl-7.22.0.spec000077500000000000000000000024101517264272000215250ustar00rootroot00000000000000Name: 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.1/packages/Windows/000077500000000000000000000000001517264272000170105ustar00rootroot00000000000000tclcurl-ng-8.0.1/packages/Windows/SetUp.tcl000077500000000000000000000022621517264272000205610ustar00rootroot00000000000000# 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.1/packages/Windows/tclcurl.mk000077500000000000000000000072321517264272000210200ustar00rootroot00000000000000TCL_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.1/pkgIndex.tcl.in000066400000000000000000000007611517264272000164660ustar00rootroot00000000000000# -*- 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.1/tclconfig/000077500000000000000000000000001517264272000155505ustar00rootroot00000000000000tclcurl-ng-8.0.1/tclconfig/install-sh000077500000000000000000000357761517264272000175760ustar00rootroot00000000000000#!/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.1/tclconfig/tcl.m4000077500000000000000000004064051517264272000166100ustar00rootroot00000000000000# 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.1/tests/000077500000000000000000000000001517264272000147425ustar00rootroot00000000000000tclcurl-ng-8.0.1/tests/TESTING.md000066400000000000000000000167041517264272000164110ustar00rootroot00000000000000# 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-04-08* ## 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 only one test file directly through `tcltest`, use `tests/all.tcl` and the `-file` filter: - `tclsh tests/all.tcl -file http.test` - `tclsh tests/all.tcl -file https.test` - `tclsh tests/all.tcl -file ftp.test` - `make test TESTFLAGS='-file http.test'` 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 curl HTTP 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_FTP_ROOT`: root directory used by the Tcl FTP test server, default `/tmp/ftp` - `TCLCURL_TEST_HTTP_SERVER_SCRIPT`: path to the Tcl test server framework script, used when no `-httpserver` CLI override is given; default `tests/testserver.tcl` You can run the default Tcl test server framework directly with: - `tclsh tests/testserver.tcl` - `tclsh tests/testserver.tcl -host 127.0.0.1 -service http:8990` - `tclsh tests/testserver.tcl -host 127.0.0.1 -service https:9443 -service ftp:8991` By default, `tests/testserver.tcl` starts three services: - HTTP on `127.0.0.1:8990` - HTTPS on `127.0.0.1:9443` - FTP on `127.0.0.1:8991` 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` - `tests/testserver.tcl` If the configured server for a protocol is not reachable, the corresponding server-backed cases are skipped. ## 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 ``` 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 at: - `tests/certs/server.crt` - `tests/certs/server.key` 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" ``` ## Migration candidates from `curl/tests/http` Based on the current TclCurl option surface in `generic/curl_setopts.h`, the strongest next targets for migration are: - transfer controls: `-connecttimeout` - name resolution and routing: `-resolve`, `-ipresolve`, `-interface`, `-port`, `-tcpnodelay` - auth paths supported by the linked libcurl build: `-userpwd`, `-username`, `-password`, `-httpauth`, `-proxyauth` Useful follow-on areas not listed above but still worth covering are: - callback diagnostics such as `-debugproc` - advanced multipart forms through `-httppost` (`contentheader`, overridden `filename`, `filecontent`) - broader metadata and utility APIs such as `getinfo`, `curl::curlConfig`, `easystrerror`, `multistrerror`, and `sharestrerror` ## Gaps still worth planning The curl Perl tests include scenarios that need more than a single HTTP base URL. The bigger remaining gaps are: - tests that depend on proxy, SMTP, POP3, or authentication-specific server setups - cases that need specific response scripts from `curl/tests/data` - feature-conditional cases such as HTTP/2, HTTP/3, TLS auth, or compression variants that depend on the local libcurl build Those are good candidates for a second support layer that can map named curl test assets from `CURL_ROOT/tests/http` or `tests/data` into Tcl fixtures instead of hard-coding endpoint paths in each test. tclcurl-ng-8.0.1/tests/all.tcl000077500000000000000000000056741517264272000162350ustar00rootroot00000000000000#!/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 ::argv_saved_for_all_tests $argv set argv {} package require tcltest set argv $::argv_saved_for_all_tests unset ::argv_saved_for_all_tests ::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} } } set tcltestArgv {} set exitServer 0 set debug 0 for {set i 0} {$i < [llength $argv]} {incr i} { set arg [lindex $argv $i] if {$arg eq "-httpserver"} { incr i if {$i >= [llength $argv]} { error "missing path after -httpserver" } ::tclcurl::test::server::set_http_server_script [lindex $argv $i] continue } if {$arg eq "-exitserver"} { set exitServer 1 continue } if {$arg eq "-debug"} { set debug 1 continue } lappend tcltestArgv $arg } ::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.1/tests/auth.test000066400000000000000000000075521517264272000166150ustar00rootroot00000000000000# 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.1/tests/config.test000066400000000000000000000033601517264272000171120ustar00rootroot00000000000000# 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.1/tests/cookies.test000066400000000000000000000034671517264272000173110ustar00rootroot00000000000000# 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.1/tests/debug.test000066400000000000000000000054641517264272000167420ustar00rootroot00000000000000# 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.1/tests/escape.test000077500000000000000000000016411517264272000171100ustar00rootroot00000000000000#!/usr/local/bin/tclsh # 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.1/tests/ftp.test000066400000000000000000000316531517264272000164440ustar00rootroot00000000000000# 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-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.1/tests/ftp_server.tcl000066400000000000000000000403041517264272000176260ustar00rootroot00000000000000# 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 {}] 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]] 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 "211 End" flush $chan } 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] } 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 } } 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.1/tests/getinfo.test000066400000000000000000000130641517264272000173020ustar00rootroot00000000000000# 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] $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.1/tests/http.test000066400000000000000000000234041517264272000166250ustar00rootroot00000000000000# 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-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.1/tests/http_common.tcl000066400000000000000000000552321517264272000200040ustar00rootroot00000000000000package 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.1/tests/http_server.tcl000066400000000000000000000727401517264272000200250ustar00rootroot00000000000000# 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 package require zlib package require base64 proc ::tclcurl::testserver::http_header_lines {header_block} { return [regexp -all -inline {[^\r\n]+} $header_block] } proc ::tclcurl::testserver::escape_response_value {value} { return [string map [list "\\" "\\\\" "\n" "\\n" "\r" "\\r"] $value] } proc ::tclcurl::testserver::parse_query {target} { set query_start [string first ? $target] if {$query_start < 0} { return [dict create] } set params [dict create] foreach pair [split [string range $target [expr {$query_start + 1}] end] &] { if {$pair eq {}} { continue } set separator [string first = $pair] if {$separator < 0} { dict set params $pair {} continue } dict set params \ [string range $pair 0 [expr {$separator - 1}]] \ [string range $pair [expr {$separator + 1}] end] } return $params } # 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}]] } # 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 [::tclcurl::testserver::http_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} } } # 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 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 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] 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 [format %X [string length $chunk]] "\r\n" $chunk "\r\n" } append encoded "0\r\n\r\n" return $encoded } 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]} { 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_encode $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 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 [::tclcurl::testserver::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 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=[::tclcurl::testserver::escape_response_value $method]" \ "path=[::tclcurl::testserver::escape_response_value $path]" \ "request-version=[::tclcurl::testserver::escape_response_value $version]" \ "content-type=[::tclcurl::testserver::escape_response_value [my header_value $headers content-type]]" \ "content-length=[::tclcurl::testserver::escape_response_value [my header_value $headers content-length]]" \ "accept-encoding=[::tclcurl::testserver::escape_response_value [my header_value $headers accept-encoding]]" \ "te=[::tclcurl::testserver::escape_response_value [my header_value $headers te]]" \ "connection=[::tclcurl::testserver::escape_response_value [my header_value $headers connection]]" \ "user-agent=[::tclcurl::testserver::escape_response_value [my header_value $headers user-agent]]" \ "referer=[::tclcurl::testserver::escape_response_value [my header_value $headers referer]]" \ "x-tclcurl-test=[::tclcurl::testserver::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-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 { 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 \ "Content-Type: text/plain" \ "Connection: close"] if {[llength $stream_chunks] > 0} { lappend response_headers "Content-Length: [my streaming_payload_length $stream_chunks]" } elseif {$transfer_encoding eq "chunked"} { lappend response_headers "Transfer-Encoding: chunked" } 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.1/tests/https.test000066400000000000000000000071571517264272000170170ustar00rootroot00000000000000# 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] \ -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] \ -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.1/tests/https_server.tcl000066400000000000000000000025131517264272000201770ustar00rootroot00000000000000# 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.1/tests/legacy/000077500000000000000000000000001517264272000162065ustar00rootroot00000000000000tclcurl-ng-8.0.1/tests/legacy/basic.tcl000077500000000000000000000000761517264272000200010ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" tclcurl-ng-8.0.1/tests/legacy/bodyVar.tcl000077500000000000000000000013741517264272000203300ustar00rootroot00000000000000package 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.1/tests/legacy/bufferSize.tcl000077500000000000000000000012421517264272000210200ustar00rootroot00000000000000package 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.1/tests/legacy/command.tcl000077500000000000000000000001521517264272000203310ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -command "puts \"\nTransfer complete\n\"" tclcurl-ng-8.0.1/tests/legacy/cookie.tcl000077500000000000000000000001401517264272000201610ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -cookie "name=andres;" -verbose 1 tclcurl-ng-8.0.1/tests/legacy/cookieFile.tcl000077500000000000000000000003431517264272000207660ustar00rootroot00000000000000package 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.1/tests/legacy/curlConfig.tcl000077500000000000000000000005531517264272000210130ustar00rootroot00000000000000package 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.1/tests/legacy/debugProc.tcl000077500000000000000000000013171517264272000206310ustar00rootroot00000000000000package 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.1/tests/legacy/dict.tcl000077500000000000000000000001121517264272000176320ustar00rootroot00000000000000package require TclCurl curl::transfer -url "dict://dict.org/m:curl" tclcurl-ng-8.0.1/tests/legacy/dupHandle.tcl000077500000000000000000000003721517264272000206230ustar00rootroot00000000000000package 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.1/tests/legacy/encoding.tcl000077500000000000000000000002501517264272000205000ustar00rootroot00000000000000package 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.1/tests/legacy/errorBuffer.tcl000077500000000000000000000007501517264272000212020ustar00rootroot00000000000000package 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.1/tests/legacy/failOnError.tcl000077500000000000000000000005431517264272000211410ustar00rootroot00000000000000package 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.1/tests/legacy/file.tcl000077500000000000000000000004051517264272000176330ustar00rootroot00000000000000package 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.1/tests/legacy/fileNoFile.tcl000077500000000000000000000004411517264272000207300ustar00rootroot00000000000000package 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.1/tests/legacy/formGet.tcl000077500000000000000000000005271517264272000203240ustar00rootroot00000000000000package 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.1/tests/legacy/ftp.tcl000077500000000000000000000006361517264272000175130ustar00rootroot00000000000000package 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.1/tests/legacy/ftpList.tcl000077500000000000000000000001311517264272000203350ustar00rootroot00000000000000package require TclCurl curl::transfer -url "ftp://127.0.0.1/pub/" -ftplistonly 1 tclcurl-ng-8.0.1/tests/legacy/ftpUpload.tcl000077500000000000000000000007061517264272000206560ustar00rootroot00000000000000package 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.1/tests/legacy/ftpWildcard.tcl000077500000000000000000000027701517264272000211660ustar00rootroot00000000000000package 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.1/tests/legacy/getInfo.tcl000077500000000000000000000047131517264272000203150ustar00rootroot00000000000000package 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.1/tests/legacy/headNoHead.tcl000077500000000000000000000005361517264272000207010ustar00rootroot00000000000000package 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.1/tests/legacy/header.tcl000077500000000000000000000001221517264272000201400ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -header 1 -nobody 1 tclcurl-ng-8.0.1/tests/legacy/headerVar.tcl000077500000000000000000000003211517264272000206120ustar00rootroot00000000000000package 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.1/tests/legacy/http200Aliases.tcl000077500000000000000000000002471517264272000214230ustar00rootroot00000000000000package 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.1/tests/legacy/httpBufferPost.tcl000077500000000000000000000012371517264272000216770ustar00rootroot00000000000000package 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.1/tests/legacy/httpHeader.tcl000077500000000000000000000002221517264272000210010ustar00rootroot00000000000000package require TclCurl curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 \ -httpheader [list "hola: hello" "adios: goodbye"] tclcurl-ng-8.0.1/tests/legacy/httpPost.tcl000077500000000000000000000011041517264272000205360ustar00rootroot00000000000000package 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.1/tests/legacy/httpVersion.tcl000077500000000000000000000003661517264272000212470ustar00rootroot00000000000000package 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.1/tests/legacy/https.tcl000077500000000000000000000005321517264272000200570ustar00rootroot00000000000000package 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.1/tests/legacy/interface.tcl000077500000000000000000000001511517264272000206520ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -verbose 1 -interface 127.0.0.1 -nobody 1 tclcurl-ng-8.0.1/tests/legacy/ipresolve.tcl000077500000000000000000000003131517264272000207220ustar00rootroot00000000000000package 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.1/tests/legacy/netrcfile.tcl000077500000000000000000000002421517264272000206660ustar00rootroot00000000000000package require TclCurl curl::transfer -url "ftp://Strider.Asturias.es" -verbose 1 \ -netrc required -netrcfile "/home/andres/testnetrc" tclcurl-ng-8.0.1/tests/legacy/noProgress.tcl000077500000000000000000000001761517264272000210620ustar00rootroot00000000000000package require TclCurl # The default is not to show the progress meter. curl::transfer -url 127.0.0.1 -noprogress 1 tclcurl-ng-8.0.1/tests/legacy/nobody.tcl000077500000000000000000000001201517264272000202000ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -header 1 -nobody 1 tclcurl-ng-8.0.1/tests/legacy/ntlm.tcl000077500000000000000000000010311517264272000176620ustar00rootroot00000000000000# 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.1/tests/legacy/pop3.tcl000077500000000000000000000010441517264272000175750ustar00rootroot00000000000000package 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.1/tests/legacy/postdebug.tcl000066400000000000000000000004311517264272000207040ustar00rootroot00000000000000::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.1/tests/legacy/progressProc.tcl000077500000000000000000000010021517264272000213760ustar00rootroot00000000000000package 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.1/tests/legacy/progressProcPause.tcl000077500000000000000000000013101517264272000223760ustar00rootroot00000000000000package 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.1/tests/legacy/proxy.tcl000077500000000000000000000001521517264272000200740ustar00rootroot00000000000000package require TclCurl curl::transfer -url http://curl.haxx.se -verbose 1 -proxy "192.168.0.0" tclcurl-ng-8.0.1/tests/legacy/proxyPort.tcl000077500000000000000000000002031517264272000207360ustar00rootroot00000000000000package require TclCurl curl::transfer -url http://curl.haxx.com -verbose 1 \ -proxy 192.168.0.0 -proxyport 8080 tclcurl-ng-8.0.1/tests/legacy/proxyTunnel.tcl000077500000000000000000000002121517264272000212570ustar00rootroot00000000000000package require TclCurl curl::transfer -url http://curl.haxx.se -verbose 1 \ -proxy "192.168.0.0:8080" -httpproxytunnel 1 tclcurl-ng-8.0.1/tests/legacy/range.tcl000077500000000000000000000001151517264272000200060ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -range "100-500" tclcurl-ng-8.0.1/tests/legacy/readProc.tcl000077500000000000000000000005661517264272000204630ustar00rootroot00000000000000package 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.1/tests/legacy/referer.tcl000077500000000000000000000001731517264272000203500ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -referer "127.0.0.1/cosa.html" \ -verbose 1 -nobody 1 tclcurl-ng-8.0.1/tests/legacy/reset.tcl000077500000000000000000000005031517264272000200350ustar00rootroot00000000000000package 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.1/tests/legacy/resume.tcl000077500000000000000000000001141517264272000202110ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -resumefrom 500 tclcurl-ng-8.0.1/tests/legacy/share.tcl000077500000000000000000000007761517264272000200310ustar00rootroot00000000000000# 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.1/tests/legacy/smtp.tcl000077500000000000000000000021031517264272000176740ustar00rootroot00000000000000package 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.1/tests/legacy/stderrNoStderr.tcl000077500000000000000000000005371517264272000217060ustar00rootroot00000000000000package 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.1/tests/legacy/strerror.tcl000077500000000000000000000007421517264272000206020ustar00rootroot00000000000000package 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.1/tests/legacy/timeout.tcl000077500000000000000000000001071517264272000204010ustar00rootroot00000000000000package require TclCurl curl::transfer -timeout 0 -url 127.0.0.1 tclcurl-ng-8.0.1/tests/legacy/transfer.tcl000077500000000000000000000037041517264272000205450ustar00rootroot00000000000000package 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.1/tests/legacy/upload.tcl000077500000000000000000000003151517264272000202000ustar00rootroot00000000000000package 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.1/tests/legacy/userAgent.tcl000077500000000000000000000002251517264272000206510ustar00rootroot00000000000000package 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.1/tests/legacy/verbose.tcl000077500000000000000000000004161517264272000203630ustar00rootroot00000000000000package 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.1/tests/legacy/writeHeader.tcl000077500000000000000000000001621517264272000211570ustar00rootroot00000000000000package require TclCurl curl::transfer -url 127.0.0.1 -header 1 -nobody 1 \ -writeheader header.txt tclcurl-ng-8.0.1/tests/legacy/writeProc.tcl000077500000000000000000000005721517264272000206770ustar00rootroot00000000000000package 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.1/tests/mime.test000066400000000000000000000253731517264272000166040ustar00rootroot00000000000000# 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.1/tests/multi/000077500000000000000000000000001517264272000160745ustar00rootroot00000000000000tclcurl-ng-8.0.1/tests/multi/auto.tcl000077500000000000000000000010521517264272000175510ustar00rootroot00000000000000#!/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.1/tests/multi/autoGUI.tcl000077500000000000000000000013451517264272000201230ustar00rootroot00000000000000#!/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.1/tests/multi/cancelTrans.tcl000077500000000000000000000033511517264272000210420ustar00rootroot00000000000000#!/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.1/tests/multi/double.tcl000077500000000000000000000024021517264272000200530ustar00rootroot00000000000000package 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.1/tests/multi/single.tcl000077500000000000000000000022171517264272000200660ustar00rootroot00000000000000package 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.1/tests/negotiation.test000066400000000000000000000216641517264272000201740ustar00rootroot00000000000000# 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 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 } 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} cleanupTests tclcurl-ng-8.0.1/tests/output.test000066400000000000000000000221561517264272000172110ustar00rootroot00000000000000# 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] \ -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] \ -file $bodyPath \ -noprogress 1 set firstRc [$handle perform] file delete -force $bodyPath $handle configure -url [::tclcurl::test::server::base_url] \ -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.1/tests/progress.test000066400000000000000000000144021517264272000175100ustar00rootroot00000000000000# 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} { 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 expectedSize [string length [::tclcurl::test::range_fixture]] 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 range-data] \ -progressproc ::tclcurl::test::progress_probe \ -bodyvar body \ -noprogress 0 set rc [$handle perform] list $rc \ [$handle getinfo responsecode] \ [expr {$::tclcurl::test::progress_calls > 0}] \ $::tclcurl::test::progress_max_dltotal \ $::tclcurl::test::progress_max_dlnow \ [string length $body] } } -result [list 0 200 1 131072 131072 131072] 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 [string length [::tclcurl::test::range_fixture]] 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 range-data] \ -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}] \ [expr {$::tclcurl::test::resume_seen_dlnow >= $::tclcurl::test::pause_start_dlnow}] \ [string length $body] } } -result [list 0 200 1 1 1 1 1 131072] cleanupTests tclcurl-ng-8.0.1/tests/proxy.test000066400000000000000000000111251517264272000170240ustar00rootroot00000000000000# 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.1/tests/proxy_server.tcl000066400000000000000000000323351517264272000202230ustar00rootroot00000000000000# 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 # 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 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 } 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" dict with [my bad_request_response] {} my proxy_response $chan $status $reason $body $headers 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" dict with [my bad_request_response] {} my proxy_response $chan $status $reason $body $headers 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 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 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} } 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.1/tests/redir.test000066400000000000000000000033451517264272000167550ustar00rootroot00000000000000# 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.1/tests/repro_share.tcl000066400000000000000000000012201517264272000177520ustar00rootroot00000000000000source [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.1/tests/request_headers.test000066400000000000000000000053271517264272000210350ustar00rootroot00000000000000# 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.1/tests/support.tcl000066400000000000000000000227751517264272000171770ustar00rootroot00000000000000# --support.tcl # # package require tcltest namespace eval ::tclcurl::test { variable debug 0 } 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 } proc ::tclcurl::test::repo_root {} { return [file dirname [file dirname [file normalize [info script]]]] } 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 if {$tcl_major == 8} { return [glob -nocomplain [file join $root lib*TclCurl*.so]] } elseif {$tcl_major == 9} { 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::load_package {} { foreach libraryPath [build_library_candidates] { if {![catch {load $libraryPath Tclcurl}]} { 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 } } if {![catch {package require TclCurl}]} { return } error "unable to load TclCurl from the installed packages or the build tree" } 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] tests 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 {} { return [file join [::tclcurl::test::repo_root] tests certs server.crt] } proc ::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::tls_package_available {} { return [expr {![catch {package require tls}]}] } proc ::tclcurl::test::ftp_root {} { return [env_or_default TCLCURL_TEST_FTP_ROOT "/tmp/ftp"] } 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.1/tests/tcl9.png000066400000000000000000000463621517264272000163360ustar00rootroot00000000000000PNG  IHDRWN pHYsodtEXtSoftwarewww.inkscape.org< IDATx{|?sf@ 7% jQ+xCHVVBZ~bV_mUlH6x*lP&cU*jp"dw#regvfgvsޯ잙'3s!f((M8((S ]QEQҀJ芢(TBWEQ4(EQ% ((i@%tEQEI*+(JP ]QEQҀJ芢(TBWEQ4(EQ% ((i@%tEQEI*+(JP ]QEQҀJ芢(TBWEQ4(EQ% ((i@%tEQEI*+(JP ]QEQҀJ芢(TBWEQ4(EQ% x@Q幯/kGL2C{X|#ܜwld)$%a+|}=bBg1 0! ЫD Xz5c7(TBWRJ=='2'tN8G j.ay֍r̞EQz Y} =5AÙpG<8ah}B |A V[k ZdIﶿ<ѣS4Npíhɷt޵-YQ1*XW="D,NbI8[u2{Bnd]';gt.Zxfbvd*J.'j^LdoL2$BK F<5n>Gal"߷%?tkW;Q AyZ4|'s`7?E:?5q:+Q]䓥hq07}/A:Z6r( OQ%%d˗6QJ|)CO*V I"'I[poxBj7G~E%qEQГfIo,3f`2Nc7fl j!%Z-Ҏt(ʁTBQ__c*N+^|ĜkGQŭܶ*-Ԭ2 ӕt:TD3*t<(n-TX8LfB67  v:EQT-ЖogNǒZT/p9(J*R =5 Ǒt,5|zr(2Mxq0 CM #ǚFQ%gԯ4j{.st0(D%86.0cIALǠo|t0(HMwah.t: ?"@EQҙJ蝨k]|p:@7,z@EQbr] XRP 0mIr:EQB=C?K pӱ2ք`EQN&5 _ %*,=lEQѶK\t,)Ӌ&N(ҝu^fJt%$9y8(5N;,0XR̿.8j*QEQZug5)r)T27"G|,EQܥ[ޡ5L?Aa7b`SmM%M>雑ї2s_u媪NǨ%ƩNǑJb&xrӱ(9@_M !헔_!D_)Dԏ9 < `B~#%^(6󯝎$0ږK7I`EX00NӴ^L:1SO7IDS9t$)& ;Ӂ(9KӴsx>3f9sEBo3W<^%I#5:(]xy<3䤂o9bŘU)p]0|E&Ph;Q8HR7QPyB$ksϐ%3wOwik8R6`RnNJ%tH)!73HqH/*<;G ,YZާ9Gh4 %drh.埡׭D ~m$yF-@{ !NЫ7 V[Whp1󿈨C瞈YN[m8nR5a1p8`K~ԩNrMIt gZ{X!ܒA0н^_SRR"6lؐ% MD뜧t; 21&]~ w9W85 „+DIʀ>)SVVY"^MN793%m|?B":d,(ԐW])}$I6y#*w/$~''́-K+zyfzZ$t"kbLZ.ezLʠw[ɢ`DI?7H) Yevw/`f/+qœ9s2$v tfYeee235!x wBHt1zNJyu!5 DX7~d`̷.}РA]Vd#⊊UL??OrҮ~ Yf̘1>+//Žx{ jsÅtQOnI Gm-Nb__9Bq_'o9aÆ $+t]y˛6mcRiȺ%={ [1AM't0܉k;yZL9ٳGDd! l.kTi'O`)2'!z uEm}20^G>Cm\K?gZҮ+|=ya YS}N`08%^V35vu۳+\Q.L^`9~1Srʩڵ_DQ ]'}4^Z{Ү.~٢ބt .R5Nzd]'[ϋ<37ud*))455?I0Ӯ\KHQQQbˊAMsMrԂ>Q/_A_A&;!às< ɤcEudp%Np:7!cv.D{CYG=ME9T Gmذa K +bJTZ(Si###ԐGEcXk,m]A@ tHBCs[Ur;t<τ/`kVM%4>R#1Ν DD`J")A">,BH)z< N-RK`g#S6lؚgm:4d)**:οWUUێx|߻m `uh`ˌL10{cx\4~tVs]B_鲮}ëmvTrʩ$? 8͗gGl_MoP(0!qف@,.++GDf$p_3Z X8 y"$3Ĩi;w JęW20Wļ8)'e/vJ.o9lkN.Cϗ+`CWվ1$K8Jv}/ ,1}s܌C?Q33}ֻT8ݤmI+LD(3@D'81aD@_Zw6SfPzEX!3%+|}=0c_*{ƌꬲx|p/3##4LqAbG.4p]B'6.H5 ǿlw*YDxM .~Kϙ,P'8׈S?.dM{DDgɺn"z 8p<3_?!a1P` [iiݟ3kbm-4FK/q\|wT2v"S l0vUaĻm]y̹U <xqsuȈF߹ <A/5eWX}d(**yYQ8F1LU2;Ȑ ނc<3㪄Gi묬Bf t"J`WUUڊ4hCUUU_[ 6LpNG0貂%"s]5+?z0R㔳RaU[4@pMhTm n733>݊~  !CɼYUUU~wu{CY@} ZN rMV|KL=[.j o1ę X)ΰS~0'x~}Dg;W%t"t &d/ƋhCEgGf4gΜP(tU0|]>Z;| x<GUqeVٳgg{GuW`0xl0|_%KJj~];~f.,ND {5JxΝ4"bNcD8ZblδH֬.G'nG1~8/:5M;wn;w^(?FW;,j/hvZ,̃NC}ZKK=Mw˜9s2e/X&lȐ![c~?KӴDt":>`08>o3LC!e %̆) Q.8&dUi|S=/$c=/i(Ql ,A6£R9*:ڒUN$p87Qv[WqQ[?8@ebo~1@Dw_7;,>fJ B70p8/ɶ5DtWKK ,;1!>4M.^VTTdYU[.]?Q^O8Wj12RIJ F<Ѯ;tҴs9&ZuO}'~2_#LqS2|ڠANu 4M;=oZ#D{3:@N,0^`WB{F1 }>y XHDSri%LB3QˬJu|3O૓ {ѳ 8=1 F,"35 DgjZ8ڒ[fJ QCoY/3fz8/++k'+7xDTiӦ6 ~b>9sds=)],"@ `!7Lڗ둕9d3+**y# f1s{k=s̙3ZVV4dj`MCEDtQ Tw >1XJ؂ Ν]v%̶bۈhLٳgcrBߧgKK8I;P(GJ9X"JZCsz@+**>Rʱ7/35fTC5؉:onNfl~^l00צLsEBޔitk1r[0_W]]yt]wA?i{|6oRN@7MRJ*( r5>Ҳ Dddqyܹsg}6VRR"`B\={j \ _ǣ0Y#9R7ptq`8M_7rUilWl[=\\8ӉƟ.c;ZI}Dϓ*Mho~\]PfܹMr;V&Yf ޖkΝ=͛`tJ,9o[8DΛ8~Ġ--;]W A?p:1ݖhnY ρeQ9;s@ SK3lju=®]v=g̟?C+u0w2X,f!KB[kLa h('X !mMiH t{/?7b"(AGwZaG݉M(:0{vq3ߟfkwC 6ȝᰥڞ_mrҭ " 5MKR" `a~NDkßJ#\5슄`#3ݞ\{KG>U"Hf:RJ,&3St{ J|-O9]c{jqP:a݅Y{jVO;_{㧒ٳgŞ`bjQ\4=6demn5S(R'23~3̖E03#, B[IbC'AÝ!˄vKW")_@ǽ`>pb/W;d^N,B=?uv0ᒙߊsFql,//o08P1z8 f/0<Ů;HCpb찈uk|}u?|C yZR&K 23e":%q[ЃF>wǬef6=/w#u%4dY} /$g+S@ƞ;t +'ZX4R¬Y$w &/IjE6tOm0nS9;nFc3se`rLȍ7sN;bsHq͢n:/=: ax'Z[uX`ebK~0X]z ȅ{,Pdte.lMV 2q#"pGXRG5/lU kA tO t&l-4q}G? oBijջ@{jN"v4dR nahG9u)L#ڶylܸТ;xf%pqLIYc|BW&e/ȀdYNy̼ 5 dq~]fp lM!655ɶߎD"F/6S8!H2 |Rf2*V'nzv^U5':/CUEf`^jNlv`TVƢi0]fiTTTjz["<e&M-%",/cNg`lㆄ? F{=?ngNB\(0yWdimSͿ0:NӴ!p>]׏k0xf梌 =7O ʀb3kH隆WA7J cGnt:>{3fXrƍyd g(++hVҥiRl*ˌd> X_j,iwf->VR =ytOL_ANʦMN08f Ln!45S‚Mo3f:%V{[횭nHy`QW߯r3~`0xmNǒniLz';lْn; /kh6LM2|<\c%WSkv1B ~\ 7y <7/{bnVRRٸq-n;.2M#Nz9j&O#@ a_͟?j|s v.aw>vq<%vR"Ջ?pEUy9ˬy~ vr fчK$ҐŲ~߫i:̼ʪ܀π,;!(C3{^;Dcgj0~ M7]DL>g(YӴvMH[Cw}+EqL!"sB]̌L#͎ؕ h88~΀kہtF` vz?o_Y3?1pAZ`08͖]fV1!NJڪ܀ ??gfse'=ȕ Ƙ\|'tFS:?C|7ø6r=aqhI5w;w*\`ȵ sXC7Z|>etdСC7{N!x4'/!0%rNDa'd/è0 @@`8Zɭ2dȗFݙu!+I%gimrzůzϞ=[אEC]k/@%Q1`suUt|;H^x{b5P FtNon[t)//uCG 3uݕiY0wWXSo6mv!15MKJS>HTB?&k_^H7qz̘qup8|ijE݈h1U#^'4޽T2 K 8 g)? ?#%0% SM48[O[[U!ϴiǁ퓲;zr_;+**rcКܗJЎ-Na.@;ú[}'cvqeBctU ɫ=+NVđcl][yF\^8:pW< -]?Ocȇy-ѯӶ\VVn83Ox<}tx R;25d1MlUEE фf[]SgǤ?ck`.Y=+b1kIo, k5Vc+Ѻ::=oǭS|Z'#[HUɞjWiii3άYRÙy ]LΒR bdkv5B6{ڰ@/>Ǜ-_?׉Fߕhar1 x,㊄§`J,Vj("q[ IU W^ St++O")3j)k9,##D>+//ªo÷} T2n~mUL][+u Okn!Cؒ FD鶄ĸ@'mzg;7e4kVkzf:N:ZF̌Kw,[_t mnD*T"tHL _8:իO޳gϞ鄈LWr;YvH$|v8fƌikqۊKύw2 ㆺi)Y (=}ЗH fLW#13𨉺ۣwWҸ8C@@J"q]@#233b; lHCw-@f1>UCi^wM(,W{'\&Gs r"Eך8^ͷ<2&SeFJoѹun,KC_oKF\v(**;0s&0ȑm̦S,ϧi8\}}63:fejRL_4}2q 2-Oˍ|C`M:ZI,ocxz*mm~΢Ǔ~itد@S]"Z38v o%*j)ʃ8k֬#a|֊fb4cȞE?gup ܸG6(ȉWǢ񪇺ֆhw%t^t:ͺĬdeӧ4iM+DU4}3:ۖnX `B`(mŌA϶m 6%;@ljT."7.έk-g 6qBs#>3#/>tVY5|2>+cH0<ߠ>0̞=X, m"P^^c̙3's޽;a|VuKEEt܅>Q/Vdd}6e M`p*NwVx'X33㨒*i{$vg7ҪXlx^ ?X 8%9}x.,]`&ƥh 9;ⱓ+zcp0#7U;)~ Tᘎxˆk0p:bxeBX yYNL<pc9_ Bϝ;كP㒤5D4!B]C`Og6z=~Vu.sb(Y] j q$~Z(e|9[-0f2%?+** Z]2sXӴG"@ PS9V3/h8r̙3>V1'.M~ߔiܹwڵ DeDy;dddd>!Pf`4S\S>Hmca!"F#>q+&tS0r4DÈW0<BC͘ Wvٳ3t]?VJ9"s$ D* ֥-8e6Dt3ADd ffrEj`?N2:.2##cyI9-Q7$Ň0Iկ\m! џ$bQ0 .tݵ[cf]8:Җ y03B bf0bߖ$^|%455 B@J@DMD'{\{gdd3׾?3vUTT,03HnB(9Dƒ9|[*'siAj6BEިȇN?4ԵPɼ Djݮ] '<ngh> ->sTEE̟? M1j+Y5L.FJ&/߽s:8}]_v>!čOVe86ѭ)9fϞžA݈*//̮Dt352px]')))455$ ^_Z#ME룥xIT?iW\ɖ_1a&l6 6CD"zQ !W1f1---vsڮ]zddd\yaR^ '<$kN53?m˖-يfVqqq @!o9!>"t]_XYY2G:R1.o0AĿNd:6cqt@b@`gUUU9cݍOikju]JSeH8p:Z.|]/ }wwup!|z&op2^4L-%,#c+/'h1"I^Qo#M">//ފc͚5]ן Hf~B|ߢxG_(=OmE `9=*)*))7oP"`^{lR~QUU05\#c)荗LBƩ\$<}5MELDmp8巴(J:mzo24tL@ r.t jA{< Tc4͛t:EQZUç6M >?{ ́K腣#-`8X~N};]ZZqlKۥDR뒢ݯO)ddVŮ":F"b;OP^^^CDvC93^YYq(,];2b$ˮNFAǥĶ gIDATu:+',^;~WӴ !I)wxWQ)yk< Pxix 4"`d 'u]&*pJcx'XSgojz=|Zf~ٳSsϞECR"Tm (i>_t3 (2&q##]M')KP"5|:Z^:J r~?KӴ.[nem# ߁VVTTkť(X-?r)FHG{;z1i?555{֬YǴzA*pJf}쐺g>\Ӵ:un{-[{W9G^7%(JY;F/k%蚉9-좸5N;Ylbc.Ȏl:@ ]mv 4i[@D_2sa8~X;kr X5xHcGU:e/|7Gl=dS9z/G<qR{***T2WDm\q!gD`fr sR3ե>fZR?jϘ1c@ݕp8|Ӂ(Jw*]HY^2t6wXqNȁ'0<͠%sz}0S 3e˖kCQ͒OJMˡd~F7?~ˇPvwH*,'v @Wg⊊uN( fW`YdWU27'-Յ?!Iz?=Q0rC~J $\TVVӁ(~\ױrNP0zYM <>f pZ)I^J9%Qnl =PmX't(YU @x[ŏ w!wt|e*bpxӱ(J7Le\+3/{{NκEBk+^/О|̙3p)\qt:E3 !Mɴ {z.?]N]t#wd<C>~)dC)\;S4MUYYYӱ(J` k1?"'<_ℴ܇ޕVċ@l̙K)?jevWpb7etʡvZg&4z8w:yn=C]oJnfXO%s l=\o <8it=Pd"3t\Q&t(8]rp)3>R~)mPwn-u]/(--U-Ev34^D yTBw"_EQTC_ANs |2*+ݩ;<Ž.^̙3's޽_8Д.f~px(8[CEC}sdN(*ǁr:݄Qq=3ķzR" DDlAPjB`EiJ@(BRUzBRڊԚ,F !}XI:0>>ÇՀ9ؿZI{%=³肻z߾}y Q*WIk;6O ޡ˝?[,~ޓwhf'$}gyWx63۞$ɁS fsܲ{ffg%}EQmxxj3jFQT>w7y4}``,5>i5I(:'CCCy! s(Jq<&q3MdtV[Vw[K:rEҏY}h4N= ϡ\.PǦb^?rݹs QTSBwEyI ǚ!sT*_{Kf}XefϒNYz+W5Gg)Jq<*̬glU,$,yI,؟.(<:22{C݆RTvgoizt%^)ovfIa>i:fvݿ$I~▬/>K7^t^G%dYz}l@!隻_Ԍbe'tͥ>&kHp;=\Z-j6JZ:w25y>ISff~Z~̮I:+F1/Xn!˲ ^c.IwnIm8qÓM4M= zZI,{3^IoybqE$IN=UK@: @: @: @: @: @: @: oҩIENDB`tclcurl-ng-8.0.1/tests/testserver.tcl000066400000000000000000000167461517264272000176720ustar00rootroot00000000000000#!/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 ::argv_saved_for_testserver $argv set argv {} source [file join [file dirname [file normalize [info script]]] 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 array set service_classes {} } oo::class create ::tclcurl::testserver::service { variable protocol host port quiet listener constructor args { array set options { -protocol {} -host 127.0.0.1 -port {} -quiet 0 } 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 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 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::usage {} { puts stderr "usage: tclsh tests/testserver.tcl ?-host 127.0.0.1? ?-service protocol:port? ... ?-quiet? ?-debug?" } 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::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_args {argv} { set host 127.0.0.1 set quiet 0 set debug 0 set services [list [dict create protocol http port 8990] \ [dict create protocol https port 9443] \ [dict create protocol ftp port 8991] \ [dict create protocol proxy port 8992]] 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] } -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 } -h - -help - --help { usage exit 0 } default { error "unknown argument: $arg" } } } return [dict create host $host quiet $quiet debug $debug services $services] } proc ::tclcurl::testserver::create_service {protocol host port quiet} { 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] } proc ::tclcurl::testserver::start_services {config} { set host [dict get $config host] set quiet [dict get $config quiet] 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] $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] set services [start_services $config] try { vwait ::tclcurl::testserver::forever } finally { stop_services $services } } proc ::tclcurl::testserver::command_map {} { return [dict create \ create_service ::tclcurl::testserver::create_service \ 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 \ service_class ::tclcurl::testserver::service_class \ start_services ::tclcurl::testserver::start_services \ stop_services ::tclcurl::testserver::stop_services \ 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_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.1/tests/version.test000077500000000000000000000015731517264272000173410ustar00rootroot00000000000000# 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.1/tests/version_info.test000077500000000000000000000040201517264272000203420ustar00rootroot00000000000000#!/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.1/win/000077500000000000000000000000001517264272000143755ustar00rootroot00000000000000tclcurl-ng-8.0.1/win/makefile.vc000066400000000000000000000047321517264272000165120ustar00rootroot00000000000000#------------------------------------------------------------- -*- 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.1/win/rules-ext.vc000066400000000000000000000071261517264272000166650ustar00rootroot00000000000000# 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