Compare commits
33 Commits
pre-host-c
...
curl-7_9_3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ea9a88a9b8 | ||
![]() |
aec7358ca4 | ||
![]() |
3c334b2bb6 | ||
![]() |
75bba0da92 | ||
![]() |
c0bfe7be15 | ||
![]() |
22ac08e06d | ||
![]() |
87037136ef | ||
![]() |
2182e37433 | ||
![]() |
1de82b220d | ||
![]() |
bd878756fc | ||
![]() |
8d7f402efb | ||
![]() |
d3299beec7 | ||
![]() |
f9192db358 | ||
![]() |
c69c0c0446 | ||
![]() |
deb2911c0e | ||
![]() |
e31a306a38 | ||
![]() |
d9a7773011 | ||
![]() |
2b14916813 | ||
![]() |
1d1530e14c | ||
![]() |
b4fdc025a8 | ||
![]() |
f1c14fe0b4 | ||
![]() |
38306cda54 | ||
![]() |
5a0f0023cf | ||
![]() |
6dcdb8b821 | ||
![]() |
781f52a287 | ||
![]() |
f75ff58b4b | ||
![]() |
ae9bf16dee | ||
![]() |
17a8bf212f | ||
![]() |
4fc76afef4 | ||
![]() |
a31155a72a | ||
![]() |
75601f7924 | ||
![]() |
8b6314ccfb | ||
![]() |
6de7dc5879 |
52
CHANGES
52
CHANGES
@@ -6,7 +6,59 @@
|
||||
|
||||
History of Changes
|
||||
|
||||
|
||||
Daniel (7 January 2002)
|
||||
- I made the 'bool' typedef use an "unsigned char". It makes it the same on
|
||||
all platforms, no matter what the platform thinks the default format for
|
||||
char is. This was noticed since we made a silly comparison involving such a
|
||||
bool variable, and only one compiler/platform combination (on Debian Linux)
|
||||
complained about it (that happened to have its char unsigned by default).
|
||||
|
||||
- Bug report #495290 identified a cookie parsing problem that was corrected.
|
||||
When a Set-Cookie: line is received without a trailing semicolon, libcurl
|
||||
didn't read the last "name=value" pair of the line, leading to confusions...
|
||||
|
||||
- Sterling committed his updated DNS cache code.
|
||||
|
||||
- I worked with Georg Horn and comments from G<>tz Babin-Ebell and switched
|
||||
curl's socket operations completely over to non-blocking for the entire
|
||||
operation (previously we used non-blocking only for the connection phase).
|
||||
We had to do this to make the SSL connection phase timeout properly without
|
||||
the use of signals. A little extra code to deal with this was added.
|
||||
|
||||
- T. Bharath pointed out a slightly obscure cookie engine flaw.
|
||||
|
||||
- Pete Su pointed out that libcurl didn't treat HTTP code 204 as it should.
|
||||
204-replies never provides a response-body. This resulted in bad persistant
|
||||
behavior when 204 was received.
|
||||
|
||||
Daniel (5 January 2002)
|
||||
- SM updated the VC++ library Makefiles for the new source files.
|
||||
|
||||
Daniel (4 January 2002)
|
||||
- I discovered that we wrongly used inet_ntoa() (instead of inet_ntoa_r() in
|
||||
two places in the source code). One happened with VERBOSE set on connects,
|
||||
and the other when VERBOSE was on and krb4 over nat was used... I honestly
|
||||
don't think anyone has suffered from these mistakes.
|
||||
|
||||
- I replaced a lot of silly occurances of printf() to instead use the more
|
||||
appropriate Curl_infof() or Curl_failf(). The krb4 and telnet code were
|
||||
affected.
|
||||
|
||||
- Philip Gladstone found a few more problems with 64-bit archs (the 64-bit
|
||||
sparc on solaris 8).
|
||||
|
||||
- After discussions on the libcurl list with Raoul Cridlig, I just made FTP
|
||||
response lines get passed to the header callback if such a one is
|
||||
registered. It'll make it possible for any application to get all the
|
||||
responses an FTP server sends to libcurl.
|
||||
|
||||
Daniel (3 January 2002)
|
||||
- Sterling Hughes brought a few buckets of code. Now, libcurl will
|
||||
automatically cache DNS lookups and re-use the previous results first if any
|
||||
such is available. It greatly improves speed when doing many repeated
|
||||
operations to the same host.
|
||||
|
||||
- As the test case uses --include and then --head, I had to modify src/main.c
|
||||
to deal with this situation slightly better than previously. When done, we
|
||||
have 100% good tests again in the main branch.
|
||||
|
@@ -11,7 +11,7 @@ EXTRA_DIST = \
|
||||
|
||||
bin_SCRIPTS = curl-config
|
||||
|
||||
SUBDIRS = docs lib src include tests packages
|
||||
SUBDIRS = docs lib src include tests packages multi
|
||||
|
||||
# create a root makefile in the distribution:
|
||||
dist-hook:
|
||||
|
@@ -597,6 +597,7 @@ AC_CONFIG_FILES([Makefile \
|
||||
include/Makefile \
|
||||
include/curl/Makefile \
|
||||
src/Makefile \
|
||||
multi/Makefile \
|
||||
lib/Makefile \
|
||||
tests/Makefile \
|
||||
tests/data/Makefile \
|
||||
|
24
docs/INSTALL
24
docs/INSTALL
@@ -178,9 +178,9 @@ Win32
|
||||
For VC++ 6, there's an included Makefile.vc6 that should be possible
|
||||
to use out-of-the-box.
|
||||
|
||||
Microsoft note: add /Zm200 to the compiler options to increase the
|
||||
compiler's memory allocation limit, as the hugehelp.c won't compile
|
||||
due to "too long puts string".
|
||||
Microsoft note: add /Zm200 to the compiler options to increase the
|
||||
compiler's memory allocation limit, as the hugehelp.c won't compile
|
||||
due to "too long puts string".
|
||||
|
||||
|
||||
With SSL:
|
||||
@@ -322,6 +322,24 @@ VMS
|
||||
13-jul-2001
|
||||
N. Baggus
|
||||
|
||||
QNX
|
||||
===
|
||||
(This section was graciously brought to us by David Bentham)
|
||||
|
||||
By setting FD_SETSIZE early in connect.c we override the QNX default value
|
||||
and thus avoid a crash.
|
||||
|
||||
Fortunately in the QNX headers its defined as
|
||||
|
||||
#ifndef FD_SETSIZE
|
||||
#define FD_SETSIZE 32
|
||||
#endif
|
||||
|
||||
so its relatively easy to override without changing the original
|
||||
definition. QNX claim posix compliance so this definition style could be
|
||||
standard in other o/s's. Eg Microsoft Visual C++ 6 defines it similarly,
|
||||
but its set to 64.
|
||||
|
||||
CROSS COMPILE
|
||||
=============
|
||||
|
||||
|
@@ -601,15 +601,15 @@ RESUMING FILE TRANSFERS
|
||||
|
||||
Continue downloading a document:
|
||||
|
||||
curl -c -o file ftp://ftp.server.com/path/file
|
||||
curl -C - -o file ftp://ftp.server.com/path/file
|
||||
|
||||
Continue uploading a document(*1):
|
||||
|
||||
curl -c -T file ftp://ftp.server.com/path/file
|
||||
curl -C - -T file ftp://ftp.server.com/path/file
|
||||
|
||||
Continue downloading a document from a web server(*2):
|
||||
|
||||
curl -c -o file http://www.server.com/
|
||||
curl -C - -o file http://www.server.com/
|
||||
|
||||
(*1) = This requires that the ftp server supports the non-standard command
|
||||
SIZE. If it doesn't, curl will say so.
|
||||
|
@@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \
|
||||
win32sockets.c persistant.c ftpget.c Makefile.example \
|
||||
multithread.c getinmemory.c ftpupload.c httpput.c \
|
||||
simplessl.c
|
||||
simplessl.c ftpgetresp.c
|
||||
|
||||
all:
|
||||
@echo "done"
|
||||
|
61
docs/examples/ftpgetresp.c
Normal file
61
docs/examples/ftpgetresp.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/types.h>
|
||||
#include <curl/easy.h>
|
||||
|
||||
/*
|
||||
* Similar to ftpget.c but this also stores the received response-lines
|
||||
* in a separate file using our own callback!
|
||||
*
|
||||
* This functionality was introduced in libcurl 7.9.3.
|
||||
*/
|
||||
|
||||
size_t
|
||||
write_response(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
{
|
||||
FILE *writehere = (FILE *)data;
|
||||
return fwrite(ptr, size, nmemb, writehere);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
FILE *ftpfile;
|
||||
FILE *respfile;
|
||||
|
||||
/* local file name to store the file as */
|
||||
ftpfile = fopen("ftp-list", "wb"); /* b is binary, needed on win32 */
|
||||
|
||||
/* local file name to store the FTP server's response lines in */
|
||||
respfile = fopen("ftp-responses", "wb"); /* b is binary, needed on win32 */
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
/* Get a file listing from sunet */
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.sunet.se/");
|
||||
curl_easy_setopt(curl, CURLOPT_FILE, ftpfile);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_response);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile);
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
fclose(ftpfile); /* close the local file */
|
||||
fclose(respfile); /* close the response file */
|
||||
|
||||
return 0;
|
||||
}
|
@@ -488,6 +488,12 @@ typedef enum {
|
||||
*/
|
||||
CINIT(SSLENGINE_DEFAULT, LONG, 90),
|
||||
|
||||
/* Non-zero value means to use the global dns cache */
|
||||
CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91),
|
||||
|
||||
/* DNS cache timeout */
|
||||
CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unusued */
|
||||
} CURLoption;
|
||||
|
||||
@@ -607,8 +613,8 @@ CURLcode curl_global_init(long flags);
|
||||
void curl_global_cleanup(void);
|
||||
|
||||
/* This is the version number */
|
||||
#define LIBCURL_VERSION "7.9.2"
|
||||
#define LIBCURL_VERSION_NUM 0x070902
|
||||
#define LIBCURL_VERSION "7.9.3-pre1"
|
||||
#define LIBCURL_VERSION_NUM 0x070903
|
||||
|
||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||
struct curl_slist {
|
||||
|
@@ -56,7 +56,9 @@ escape.c mprintf.c telnet.c \
|
||||
escape.h getpass.c netrc.c telnet.h \
|
||||
getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
|
||||
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
|
||||
http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h
|
||||
http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h \
|
||||
llist.c llist.h hash.c hash.h multi.c multi.h
|
||||
|
||||
|
||||
noinst_HEADERS = setup.h transfer.h
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
# Usage: see usage message below
|
||||
# Should be invoked from \lib directory
|
||||
# Edit the paths and desired library name
|
||||
# SSL path is only required if you intend compiling
|
||||
# SSL path is only required if you intend compiling
|
||||
# with SSL.
|
||||
#
|
||||
# This make file leaves the result either a .lib or .dll file
|
||||
@@ -17,13 +17,13 @@
|
||||
#
|
||||
# Another option would have been to leave the .lib and .dll
|
||||
# files in the "cfg" directory, but then the make file
|
||||
# in \src would need to be changed.
|
||||
#
|
||||
# in \src would need to be changed.
|
||||
#
|
||||
##############################################################
|
||||
# CHANGE LOG
|
||||
# CHANGE LOG
|
||||
# ------------------------------------------------------------
|
||||
# 05.11.2001 John Lask Initial Release
|
||||
#
|
||||
#
|
||||
#
|
||||
##############################################################
|
||||
|
||||
@@ -50,7 +50,7 @@ CFGSET = FALSE
|
||||
######################
|
||||
# release
|
||||
|
||||
!IF "$(CFG)" == "release"
|
||||
!IF "$(CFG)" == "release"
|
||||
TARGET =$(LIB_NAME).lib
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKLIB) /out:$(TARGET)
|
||||
@@ -61,7 +61,7 @@ CFGSET = TRUE
|
||||
######################
|
||||
# release-dll
|
||||
|
||||
!IF "$(CFG)" == "release-dll"
|
||||
!IF "$(CFG)" == "release-dll"
|
||||
TARGET =$(LIB_NAME).dll
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
|
||||
@@ -72,25 +72,25 @@ CFGSET = TRUE
|
||||
######################
|
||||
# release-ssl
|
||||
|
||||
!IF "$(CFG)" == "release-ssl"
|
||||
!IF "$(CFG)" == "release-ssl"
|
||||
TARGET =$(LIB_NAME).lib
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)
|
||||
LINKLIBS = $(LINKLIBS) $(SSLLIBS)
|
||||
CC = $(CCNODBG) $(CFLAGSSSL)
|
||||
CFGSET = TRUE
|
||||
CFGSET = TRUE
|
||||
!ENDIF
|
||||
|
||||
######################
|
||||
# release-ssl-dll
|
||||
|
||||
!IF "$(CFG)" == "release-ssl-dll"
|
||||
!IF "$(CFG)" == "release-ssl-dll"
|
||||
TARGET =$(LIB_NAME).dll
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
|
||||
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
|
||||
LINKLIBS = $(LINKLIBS) $(SSLLIBS)
|
||||
CC = $(CCNODBG) $(CFLAGSSSL)
|
||||
CFGSET = TRUE
|
||||
CFGSET = TRUE
|
||||
!ENDIF
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ CFGSET = TRUE
|
||||
######################
|
||||
# debug
|
||||
|
||||
!IF "$(CFG)" == "debug"
|
||||
!IF "$(CFG)" == "debug"
|
||||
TARGET =$(LIB_NAME_DEBUG).lib
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKLIB) /out:$(TARGET)
|
||||
@@ -110,7 +110,7 @@ CFGSET = TRUE
|
||||
######################
|
||||
# debug-dll
|
||||
|
||||
!IF "$(CFG)" == "debug-dll"
|
||||
!IF "$(CFG)" == "debug-dll"
|
||||
TARGET =$(LIB_NAME_DEBUG).dll
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib"
|
||||
@@ -121,7 +121,7 @@ CFGSET = TRUE
|
||||
######################
|
||||
# debug-ssl
|
||||
#todo
|
||||
!IF "$(CFG)" == "debug-ssl"
|
||||
!IF "$(CFG)" == "debug-ssl"
|
||||
TARGET = $(LIB_NAME_DEBUG).lib
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)
|
||||
@@ -133,10 +133,10 @@ CFGSET = TRUE
|
||||
######################
|
||||
# debug-ssl-dll
|
||||
|
||||
!IF "$(CFG)" == "debug-ssl-dll"
|
||||
!IF "$(CFG)" == "debug-ssl-dll"
|
||||
TARGET =$(LIB_NAME_DEBUG).dll
|
||||
DIROBJ =.\$(CFG)
|
||||
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib"
|
||||
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib"
|
||||
LINKLIBS = $(LINKLIBS) $(SSLLIBS)
|
||||
CC = $(CCDEBUG) $(CFLAGSSSL)
|
||||
CFGSET = TRUE
|
||||
@@ -193,8 +193,9 @@ X_OBJS= \
|
||||
$(DIROBJ)\easy.obj \
|
||||
$(DIROBJ)\strequal.obj \
|
||||
$(DIROBJ)\strtok.obj \
|
||||
$(DIROBJ)\connect.obj
|
||||
|
||||
$(DIROBJ)\connect.obj \
|
||||
$(DIROBJ)\hash.obj \
|
||||
$(DIROBJ)\llist.obj
|
||||
|
||||
all : $(TARGET)
|
||||
|
||||
|
@@ -210,11 +210,11 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
in_addr_t in;
|
||||
|
||||
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
|
||||
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr);
|
||||
h = Curl_resolv(data, myhost, 0, &hostdataptr);
|
||||
}
|
||||
else {
|
||||
if(strlen(data->set.device)>1) {
|
||||
h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr);
|
||||
h = Curl_resolv(data, data->set.device, 0, &hostdataptr);
|
||||
}
|
||||
if(h) {
|
||||
/* we know data->set.device is shorter than the myhost array */
|
||||
@@ -229,8 +229,6 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
hostent_buf,
|
||||
sizeof(hostent_buf));
|
||||
*/
|
||||
if(hostdataptr)
|
||||
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
|
||||
return CURLE_HTTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
@@ -304,9 +302,6 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
return CURLE_HTTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
if(hostdataptr)
|
||||
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
|
||||
|
||||
return CURLE_OK;
|
||||
|
||||
} /* end of device selection support */
|
||||
@@ -453,8 +448,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* now disable the non-blocking mode again */
|
||||
Curl_nonblock(sockfd, FALSE);
|
||||
/* leave the socket in non-blocking mode */
|
||||
|
||||
if(addr)
|
||||
*addr = ai; /* the address we ended up connected to */
|
||||
@@ -559,9 +553,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
failf(data, "Couldn't connect to host");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* now disable the non-blocking mode again */
|
||||
Curl_nonblock(sockfd, FALSE);
|
||||
|
||||
/* leave the socket in non-blocking mode */
|
||||
|
||||
if(addr)
|
||||
/* this is the address we've connected to */
|
||||
|
14
lib/cookie.c
14
lib/cookie.c
@@ -194,6 +194,11 @@ Curl_cookie_add(struct CookieInfo *c,
|
||||
while(ptr && *ptr && isspace((int)*ptr))
|
||||
ptr++;
|
||||
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
|
||||
|
||||
if(!semiptr && *ptr)
|
||||
/* There are no more semicolons, but there's a final name=value pair
|
||||
coming up */
|
||||
semiptr=ptr;
|
||||
} while(semiptr);
|
||||
|
||||
if(NULL == co->domain)
|
||||
@@ -377,8 +382,15 @@ Curl_cookie_add(struct CookieInfo *c,
|
||||
|
||||
free(co); /* free the newly alloced memory */
|
||||
co = clist; /* point to the previous struct instead */
|
||||
}
|
||||
|
||||
/* We have replaced a cookie, now skip the rest of the list but
|
||||
make sure the 'lastc' pointer is properly set */
|
||||
do {
|
||||
lastc = clist;
|
||||
clist = clist->next;
|
||||
} while(clist);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastc = clist;
|
||||
clist = clist->next;
|
||||
|
@@ -151,6 +151,10 @@ SOURCE=.\getpass.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hostip.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -179,6 +183,10 @@ SOURCE=.\libcurl.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\llist.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\memdebug.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
17
lib/easy.c
17
lib/easy.c
@@ -76,6 +76,7 @@
|
||||
#include "ssluse.h"
|
||||
#include "url.h"
|
||||
#include "getinfo.h"
|
||||
#include "hostip.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -139,7 +140,7 @@ CURLcode curl_global_init(long flags)
|
||||
{
|
||||
if (initialized)
|
||||
return CURLE_OK;
|
||||
|
||||
|
||||
if (flags & CURL_GLOBAL_SSL)
|
||||
Curl_SSL_init();
|
||||
|
||||
@@ -162,6 +163,8 @@ void curl_global_cleanup(void)
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
Curl_global_host_cache_dtor();
|
||||
|
||||
if (init_flags & CURL_GLOBAL_SSL)
|
||||
Curl_SSL_cleanup();
|
||||
|
||||
@@ -230,12 +233,24 @@ CURLcode curl_easy_perform(CURL *curl)
|
||||
{
|
||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||
|
||||
if (!data->hostcache) {
|
||||
if (Curl_global_host_cache_use(data)) {
|
||||
data->hostcache = Curl_global_host_cache_get();
|
||||
}
|
||||
else {
|
||||
data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
|
||||
}
|
||||
}
|
||||
|
||||
return Curl_perform(data);
|
||||
}
|
||||
|
||||
void curl_easy_cleanup(CURL *curl)
|
||||
{
|
||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||
if (!Curl_global_host_cache_use(data)) {
|
||||
curl_hash_destroy(data->hostcache);
|
||||
}
|
||||
Curl_close(data);
|
||||
}
|
||||
|
||||
|
52
lib/ftp.c
52
lib/ftp.c
@@ -84,6 +84,10 @@
|
||||
#include "ssluse.h"
|
||||
#include "connect.h"
|
||||
|
||||
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||
#include "inet_ntoa_r.h"
|
||||
#endif
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
@@ -192,9 +196,12 @@ int Curl_GetFTPResponse(char *buf,
|
||||
char *line_start;
|
||||
int code=0; /* default "error code" to return */
|
||||
|
||||
#define SELECT_OK 0
|
||||
#define SELECT_ERROR 1
|
||||
#define SELECT_TIMEOUT 2
|
||||
#define SELECT_OK 0
|
||||
#define SELECT_ERROR 1 /* select() problems */
|
||||
#define SELECT_TIMEOUT 2 /* took too long */
|
||||
#define SELECT_MEMORY 3 /* no available memory */
|
||||
#define SELECT_CALLBACK 4 /* aborted by callback */
|
||||
|
||||
int error = SELECT_OK;
|
||||
|
||||
struct FTP *ftp = conn->proto.ftp;
|
||||
@@ -283,6 +290,7 @@ int Curl_GetFTPResponse(char *buf,
|
||||
if(*ptr=='\n') {
|
||||
/* a newline is CRLF in ftp-talk, so the CR is ignored as
|
||||
the line isn't really terminated until the LF comes */
|
||||
CURLcode result;
|
||||
|
||||
/* output debug output if that is requested */
|
||||
if(data->set.verbose) {
|
||||
@@ -291,6 +299,16 @@ int Curl_GetFTPResponse(char *buf,
|
||||
/* no need to output LF here, it is part of the data */
|
||||
}
|
||||
|
||||
/*
|
||||
* We pass all response-lines to the callback function registered
|
||||
* for "headers". The response lines can be seen as a kind of
|
||||
* headers.
|
||||
*/
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER,
|
||||
line_start, perline);
|
||||
if(result)
|
||||
return -SELECT_CALLBACK;
|
||||
|
||||
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
|
||||
isdigit((int)line[2]) && (' ' == line[3]))
|
||||
|
||||
@@ -324,7 +342,7 @@ int Curl_GetFTPResponse(char *buf,
|
||||
if(ftp->cache)
|
||||
memcpy(ftp->cache, line_start, ftp->cache_size);
|
||||
else
|
||||
return CURLE_OUT_OF_MEMORY; /**BANG**/
|
||||
return -SELECT_MEMORY; /**BANG**/
|
||||
}
|
||||
} /* there was data */
|
||||
} /* if(no error) */
|
||||
@@ -847,13 +865,17 @@ ftp_pasv_verbose(struct connectdata *conn,
|
||||
#ifdef HAVE_INET_NTOA_R
|
||||
char ntoa_buf[64];
|
||||
#endif
|
||||
char hostent_buf[9000];
|
||||
/* The array size trick below is to make this a large chunk of memory
|
||||
suitably 8-byte aligned on 64-bit platforms. This was thoughtfully
|
||||
suggested by Philip Gladstone. */
|
||||
long bigbuf[9000 / sizeof(long)];
|
||||
|
||||
#if defined(HAVE_INET_ADDR)
|
||||
in_addr_t address;
|
||||
# if defined(HAVE_GETHOSTBYADDR_R)
|
||||
int h_errnop;
|
||||
# endif
|
||||
char *hostent_buf = (char *)bigbuf; /* get a char * to the buffer */
|
||||
|
||||
address = inet_addr(newhost);
|
||||
# ifdef HAVE_GETHOSTBYADDR_R
|
||||
@@ -1174,19 +1196,19 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
||||
|
||||
if(data->set.ftpport) {
|
||||
if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
|
||||
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr);
|
||||
h = Curl_resolv(data, myhost, 0, &hostdataptr);
|
||||
}
|
||||
else {
|
||||
if(strlen(data->set.ftpport)>1)
|
||||
h = Curl_getaddrinfo(data, data->set.ftpport, 0, &hostdataptr);
|
||||
int len = strlen(data->set.ftpport);
|
||||
if(len>1)
|
||||
h = Curl_resolv(data, data->set.ftpport, 0, &hostdataptr);
|
||||
if(h)
|
||||
strcpy(myhost, data->set.ftpport); /* buffer overflow risk */
|
||||
}
|
||||
}
|
||||
if(! *myhost) {
|
||||
h=Curl_getaddrinfo(data,
|
||||
getmyhost(myhost, sizeof(myhost)),
|
||||
0, &hostdataptr);
|
||||
char *tmp_host = getmyhost(myhost, sizeof(myhost));
|
||||
h=Curl_resolv(data, tmp_host, 0, &hostdataptr);
|
||||
}
|
||||
infof(data, "We connect from %s\n", myhost);
|
||||
|
||||
@@ -1237,9 +1259,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
||||
free(hostdataptr);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
if(hostdataptr)
|
||||
/* free the memory used for name lookup */
|
||||
Curl_freeaddrinfo(hostdataptr);
|
||||
}
|
||||
else {
|
||||
failf(data, "could't find my own IP address (%s)", myhost);
|
||||
@@ -1431,7 +1450,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||
}
|
||||
else {
|
||||
/* normal, direct, ftp connection */
|
||||
addr = Curl_getaddrinfo(data, newhostp, newport, &hostdataptr);
|
||||
addr = Curl_resolv(data, newhostp, newport, &hostdataptr);
|
||||
if(!addr) {
|
||||
failf(data, "Can't resolve new host %s", newhost);
|
||||
return CURLE_FTP_CANT_GET_HOST;
|
||||
@@ -1450,9 +1469,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||
/* this just dumps information about this second connection */
|
||||
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
||||
|
||||
if(hostdataptr)
|
||||
Curl_freeaddrinfo(hostdataptr);
|
||||
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
|
||||
|
@@ -55,7 +55,6 @@ char *GetEnv(const char *variable)
|
||||
if (env && strcmp("HOME",variable) == 0) {
|
||||
env = decc$translate_vms(env);
|
||||
}
|
||||
/* printf ("Getenv: %s=%s\n",variable,env); */
|
||||
#else
|
||||
/* no length control */
|
||||
char *env = getenv(variable);
|
||||
|
282
lib/hash.c
Normal file
282
lib/hash.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al
|
||||
*
|
||||
* In order to be useful for every potential user, curl and libcurl are
|
||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||
* licenses. You may pick one of these licenses.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hash.h"
|
||||
#include "llist.h"
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
/* this must be the last include file */
|
||||
#include "memdebug.h"
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned long
|
||||
curl_hash_str(const char *key, unsigned int key_length)
|
||||
{
|
||||
register unsigned long h = 0;
|
||||
register unsigned long g;
|
||||
register char *p = (char *) key;
|
||||
register char *end = (char *) key + key_length;
|
||||
|
||||
while (p < end) {
|
||||
h = (h << 4) + *p++;
|
||||
if ((g = (h & 0xF0000000))) {
|
||||
h = h ^ (g >> 24);
|
||||
h = h ^ g;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
curl_hash_num(unsigned long key)
|
||||
{
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += (key << 11);
|
||||
key ^= (key >> 16);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
hash_element_dtor(void *u, void *ele)
|
||||
{
|
||||
curl_hash_element *e = (curl_hash_element *) ele;
|
||||
curl_hash *h = (curl_hash *) u;
|
||||
|
||||
if (e->key.type == CURL_HASH_KEY_IS_STRING) {
|
||||
free(e->key.value.str.val);
|
||||
}
|
||||
h->dtor(e->ptr);
|
||||
|
||||
free(e);
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
|
||||
{
|
||||
int i;
|
||||
|
||||
h->dtor = dtor;
|
||||
h->size = 0;
|
||||
h->slots = slots;
|
||||
|
||||
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
|
||||
for (i = 0; i < h->slots; ++i) {
|
||||
h->table[i] = curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
|
||||
}
|
||||
}
|
||||
|
||||
curl_hash *
|
||||
curl_hash_alloc(int slots, curl_hash_dtor dtor)
|
||||
{
|
||||
curl_hash *h;
|
||||
|
||||
h = malloc(sizeof(curl_hash));
|
||||
curl_hash_init(h, slots, dtor);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
#define FIND_SLOT(__h, __s_key, __s_key_len, __n_key) \
|
||||
((__s_key ? curl_hash_str(__s_key, __s_key_len) : curl_hash_num(__n_key)) % (__h)->slots)
|
||||
|
||||
#define KEY_CREATE(__k, __s_key, __s_key_len, __n_key, __dup) \
|
||||
if (__s_key) { \
|
||||
if (__dup) { \
|
||||
(__k)->value.str.val = (char *) malloc(__s_key_len); \
|
||||
memcpy((__k)->value.str.val, __s_key, __s_key_len); \
|
||||
} else { \
|
||||
(__k)->value.str.val = __s_key; \
|
||||
} \
|
||||
(__k)->value.str.len = __s_key_len; \
|
||||
(__k)->type = CURL_HASH_KEY_IS_STRING; \
|
||||
} else { \
|
||||
(__k)->value.num = __n_key; \
|
||||
(__k)->type = CURL_HASH_KEY_IS_NUM; \
|
||||
}
|
||||
|
||||
#define MIN(a, b) (a > b ? b : a)
|
||||
|
||||
static int
|
||||
curl_hash_key_compare(curl_hash_key *key1, curl_hash_key *key2)
|
||||
{
|
||||
if (key1->type == CURL_HASH_KEY_IS_NUM) {
|
||||
if (key2->type == CURL_HASH_KEY_IS_STRING)
|
||||
return 0;
|
||||
|
||||
if (key1->value.num == key2->value.num)
|
||||
return 1;
|
||||
} else {
|
||||
if (key2->type == CURL_HASH_KEY_IS_NUM)
|
||||
return 0;
|
||||
|
||||
if (memcmp(key1->value.str.val, key2->value.str.val,
|
||||
MIN(key1->value.str.len, key2->value.str.len)) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||
unsigned long num_key, const void *p)
|
||||
{
|
||||
curl_hash_element *e;
|
||||
curl_hash_key tmp;
|
||||
curl_llist *l;
|
||||
curl_llist_element *le;
|
||||
int slot;
|
||||
|
||||
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
|
||||
l = h->table[slot];
|
||||
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
|
||||
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
|
||||
curl_hash_element *to_update = CURL_LLIST_VALP(le);
|
||||
h->dtor(to_update->ptr);
|
||||
to_update->ptr = (void *) p;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
e = (curl_hash_element *) malloc(sizeof(curl_hash_element));
|
||||
KEY_CREATE(&e->key, str_key, str_key_len, num_key, 1);
|
||||
e->ptr = (void *) p;
|
||||
|
||||
if (curl_llist_insert_next(l, CURL_LLIST_TAIL(l), e)) {
|
||||
++h->size;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||
unsigned long num_key)
|
||||
{
|
||||
curl_llist *l;
|
||||
curl_llist_element *le;
|
||||
curl_hash_key tmp;
|
||||
int slot;
|
||||
|
||||
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
|
||||
l = h->table[slot];
|
||||
|
||||
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
|
||||
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
|
||||
curl_llist_remove(l, le, (void *) h);
|
||||
--h->size;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||
unsigned long num_key, void **p)
|
||||
{
|
||||
curl_llist *l;
|
||||
curl_llist_element *le;
|
||||
curl_hash_key tmp;
|
||||
int slot;
|
||||
|
||||
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
|
||||
l = h->table[slot];
|
||||
|
||||
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
|
||||
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
|
||||
*p = ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *))
|
||||
{
|
||||
curl_llist_element *le;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < h->slots; ++i) {
|
||||
for (le = CURL_LLIST_HEAD(h->table[i]); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||
cb(user, (curl_hash_element *) CURL_LLIST_VALP(le));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
curl_hash_clean(curl_hash *h)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < h->slots; ++i) {
|
||||
curl_llist_destroy(h->table[i], (void *) h);
|
||||
}
|
||||
|
||||
free(h->table);
|
||||
h->table = NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
curl_hash_count(curl_hash *h)
|
||||
{
|
||||
return h->size;
|
||||
}
|
||||
|
||||
void
|
||||
curl_hash_destroy(curl_hash *h)
|
||||
{
|
||||
if (!h) {
|
||||
return;
|
||||
}
|
||||
|
||||
curl_hash_clean(h);
|
||||
free(h);
|
||||
h = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* local variables:
|
||||
* eval: (load-file "../curl-mode.el")
|
||||
* end:
|
||||
* vim600: fdm=marker
|
||||
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||
*/
|
87
lib/hash.h
Normal file
87
lib/hash.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef __HASH_H
|
||||
#define __HASH_H
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* In order to be useful for every potential user, curl and libcurl are
|
||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||
* licenses. You may pick one of these licenses.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "llist.h"
|
||||
|
||||
#define CURL_HASH_KEY_IS_STRING 0
|
||||
#define CURL_HASH_KEY_IS_NUM 1
|
||||
|
||||
typedef void (*curl_hash_dtor)(void *);
|
||||
|
||||
typedef struct _curl_hash {
|
||||
curl_llist **table;
|
||||
curl_hash_dtor dtor;
|
||||
int slots;
|
||||
size_t size;
|
||||
} curl_hash;
|
||||
|
||||
typedef struct _curl_hash_key {
|
||||
union {
|
||||
struct {
|
||||
char *val;
|
||||
unsigned int len;
|
||||
} str;
|
||||
|
||||
unsigned long num;
|
||||
} value;
|
||||
|
||||
int type;
|
||||
} curl_hash_key;
|
||||
|
||||
typedef struct _curl_hash_element {
|
||||
curl_hash_key key;
|
||||
void *ptr;
|
||||
} curl_hash_element;
|
||||
|
||||
|
||||
void curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor);
|
||||
curl_hash *curl_hash_alloc(int slots, curl_hash_dtor dtor);
|
||||
int curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||
unsigned long num_key, const void *p);
|
||||
int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||
unsigned long num_key);
|
||||
int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||
unsigned long num_key, void **p);
|
||||
void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
|
||||
size_t curl_hash_count(curl_hash *h);
|
||||
void curl_hash_clean(curl_hash *h);
|
||||
void curl_hash_destroy(curl_hash *h);
|
||||
|
||||
#define curl_hash_find(h, key, key_len, p) curl_hash_extended_find(h, key, key_len, 0, p)
|
||||
#define curl_hash_delete(h, key, key_len) curl_hash_extended_delete(h, key, key_len, 0)
|
||||
#define curl_hash_add(h, key, key_len, p) curl_hash_add_or_update(h, key, key_len, 0, p)
|
||||
#define curl_hash_update curl_hash_add
|
||||
#define curl_hash_index_find(h, key, p) curl_hash_extended_find(h, NULL, 0, key, p)
|
||||
#define curl_hash_index_delete(h, key) curl_hash_extended_delete(h, NULL, 0, key)
|
||||
#define curl_hash_index_add(h, key, p) curl_hash_add_or_update(h, NULL, 0, key, p)
|
||||
#define curl_hash_index_update curl_hash_index_add
|
||||
|
||||
#endif
|
93
lib/hostip.c
93
lib/hostip.c
@@ -58,6 +58,7 @@
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "hostip.h"
|
||||
#include "hash.h"
|
||||
|
||||
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||
#include "inet_ntoa_r.h"
|
||||
@@ -68,6 +69,85 @@
|
||||
#include "memdebug.h"
|
||||
#endif
|
||||
|
||||
static curl_hash hostname_cache;
|
||||
static int host_cache_initialized;
|
||||
|
||||
void Curl_global_host_cache_init(void)
|
||||
{
|
||||
if (!host_cache_initialized) {
|
||||
curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
|
||||
host_cache_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
curl_hash *Curl_global_host_cache_get(void)
|
||||
{
|
||||
return &hostname_cache;
|
||||
}
|
||||
|
||||
void Curl_global_host_cache_dtor(void)
|
||||
{
|
||||
if (host_cache_initialized) {
|
||||
curl_hash_clean(&hostname_cache);
|
||||
host_cache_initialized = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct curl_dns_cache_entry {
|
||||
Curl_addrinfo *addr;
|
||||
time_t timestamp;
|
||||
};
|
||||
|
||||
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
|
||||
char *hostname,
|
||||
int port,
|
||||
char **bufp)
|
||||
{
|
||||
struct curl_dns_cache_entry *p = NULL;
|
||||
size_t hostname_len;
|
||||
time_t now;
|
||||
|
||||
/* If the host cache timeout is 0, we don't do DNS cach'ing
|
||||
so fall through */
|
||||
if (data->set.dns_cache_timeout == 0) {
|
||||
return Curl_getaddrinfo(data, hostname, port, bufp);
|
||||
}
|
||||
|
||||
hostname_len = strlen(hostname)+1;
|
||||
|
||||
time(&now);
|
||||
/* See if its already in our dns cache */
|
||||
if (curl_hash_find(data->hostcache, hostname, hostname_len, (void **) &p)) {
|
||||
/* Do we need to check for a cache timeout? */
|
||||
if (data->set.dns_cache_timeout != -1) {
|
||||
/* Return if the entry has not timed out */
|
||||
if ((now - p->timestamp) < data->set.dns_cache_timeout) {
|
||||
return p->addr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return p->addr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new cache entry */
|
||||
p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry));
|
||||
if (!p) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->addr = Curl_getaddrinfo(data, hostname, port, bufp);
|
||||
if (!p->addr) {
|
||||
return NULL;
|
||||
}
|
||||
p->timestamp = now;
|
||||
|
||||
/* Save it in our host cache */
|
||||
curl_hash_update(data->hostcache, hostname, hostname_len, (const void *) p);
|
||||
|
||||
return p->addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a wrapper function for freeing name information in a protocol
|
||||
* independent way. This takes care of using the appropriate underlaying
|
||||
@@ -75,11 +155,15 @@
|
||||
*/
|
||||
void Curl_freeaddrinfo(void *freethis)
|
||||
{
|
||||
struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
freeaddrinfo(freethis);
|
||||
freeaddrinfo(p->addr);
|
||||
#else
|
||||
free(freethis);
|
||||
free(p->addr);
|
||||
#endif
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
/* --- resolve name or IP-number --- */
|
||||
@@ -102,7 +186,7 @@ int curl_getaddrinfo(char *hostname, char *service,
|
||||
/* success */
|
||||
if(logfile)
|
||||
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
|
||||
source, line, *result);
|
||||
source, line, (void *)*result);
|
||||
}
|
||||
else {
|
||||
if(logfile)
|
||||
@@ -118,7 +202,7 @@ void curl_freeaddrinfo(struct addrinfo *freethis,
|
||||
(freeaddrinfo)(freethis);
|
||||
if(logfile)
|
||||
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
|
||||
source, line, freethis);
|
||||
source, line, (void *)freethis);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -372,3 +456,4 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||
* vim600: fdm=marker
|
||||
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||
*/
|
||||
|
||||
|
13
lib/hostip.h
13
lib/hostip.h
@@ -23,10 +23,23 @@
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
struct addrinfo;
|
||||
struct hostent;
|
||||
struct SessionHandle;
|
||||
|
||||
void Curl_global_host_cache_init(void);
|
||||
void Curl_global_host_cache_dtor(void);
|
||||
curl_hash *Curl_global_host_cache_get(void);
|
||||
|
||||
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
|
||||
|
||||
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
|
||||
char *hostname,
|
||||
int port,
|
||||
char **bufp);
|
||||
|
||||
/* Get name info */
|
||||
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||
char *hostname,
|
||||
|
69
lib/krb4.c
69
lib/krb4.c
@@ -57,6 +57,10 @@
|
||||
#include "ftp.h"
|
||||
#include "sendf.h"
|
||||
|
||||
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||
#include "inet_ntoa_r.h"
|
||||
#endif
|
||||
|
||||
/* The last #include file should be: */
|
||||
#ifdef MALLOCDEBUG
|
||||
#include "memdebug.h"
|
||||
@@ -193,10 +197,10 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
||||
int checksum;
|
||||
u_int32_t cs;
|
||||
struct krb4_data *d = app_data;
|
||||
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
||||
char *host = conn->hostaddr->h_name;
|
||||
ssize_t nread;
|
||||
int l = sizeof(conn->local_addr);
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
if(getsockname(conn->firstsocket,
|
||||
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
|
||||
@@ -207,80 +211,76 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
||||
if(ret == KDC_PR_UNKNOWN)
|
||||
ret = mk_auth(d, &adat, "rcmd", host, checksum);
|
||||
if(ret) {
|
||||
printf("%s\n", krb_get_err_text(ret));
|
||||
Curl_infof(data, "%s\n", krb_get_err_text(ret));
|
||||
return AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
|
||||
if (krb_get_config_bool("nat_in_use")) {
|
||||
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
||||
struct in_addr natAddr;
|
||||
|
||||
if (krb_get_our_ip_for_realm(krb_realmofhost(host),
|
||||
&natAddr) != KSUCCESS
|
||||
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
|
||||
printf("Can't get address for realm %s\n",
|
||||
krb_realmofhost(host));
|
||||
Curl_infof(data, "Can't get address for realm %s\n",
|
||||
krb_realmofhost(host));
|
||||
else {
|
||||
if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
|
||||
printf("Using NAT IP address (%s) for kerberos 4\n",
|
||||
(char *)inet_ntoa(natAddr));
|
||||
#ifdef HAVE_INET_NTOA_R
|
||||
char ntoa_buf[64];
|
||||
char *ip = (char *)inet_ntoa_r(natAddr, ntoa_buf, sizeof(ntoa_buf));
|
||||
#else
|
||||
char *ip = (char *)inet_ntoa(natAddr);
|
||||
#endif
|
||||
Curl_infof(data, "Using NAT IP address (%s) for kerberos 4\n", ip);
|
||||
localaddr->sin_addr = natAddr;
|
||||
|
||||
/*
|
||||
* This not the best place to do this, but it is here we know that
|
||||
* (probably) NAT is in use! */
|
||||
|
||||
/*passivemode = 1;***/
|
||||
/*printf("Setting: Passive mode on.\n");***/
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));***/
|
||||
/*printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));***/
|
||||
|
||||
if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) {
|
||||
printf("Out of memory base64-encoding.\n");
|
||||
Curl_failf(data, "Out of memory base64-encoding");
|
||||
return AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
if(Curl_ftpsendf(conn, "ADAT %s", p))
|
||||
return -2;
|
||||
|
||||
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
|
||||
nread = Curl_GetFTPResponse(data->state.buffer, conn, NULL);
|
||||
if(nread < 0)
|
||||
return -1;
|
||||
free(p);
|
||||
|
||||
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
|
||||
printf("Server didn't accept auth data.\n");
|
||||
if(data->state.buffer[0] != '2'){
|
||||
Curl_failf(data, "Server didn't accept auth data");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
|
||||
p = strstr(conn->data->state.buffer, "ADAT=");
|
||||
if(!p){
|
||||
printf("Remote host didn't send adat reply.\n");
|
||||
p = strstr(data->state.buffer, "ADAT=");
|
||||
if(!p) {
|
||||
Curl_failf(data, "Remote host didn't send adat reply");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
p += 5;
|
||||
len = Curl_base64_decode(p, adat.dat);
|
||||
if(len < 0){
|
||||
printf("Failed to decode base64 from server.\n");
|
||||
if(len < 0) {
|
||||
Curl_failf(data, "Failed to decode base64 from server");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
adat.length = len;
|
||||
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
|
||||
(struct sockaddr_in *)hisctladdr,
|
||||
(struct sockaddr_in *)myctladdr, &msg_data);
|
||||
if(ret){
|
||||
printf("Error reading reply from server: %s.\n",
|
||||
krb_get_err_text(ret));
|
||||
if(ret) {
|
||||
Curl_failf(data, "Error reading reply from server: %s",
|
||||
krb_get_err_text(ret));
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
krb_get_int(msg_data.app_data, &cs, 4, 0);
|
||||
if(cs - checksum != 1){
|
||||
printf("Bad checksum returned from server.\n");
|
||||
if(cs - checksum != 1) {
|
||||
Curl_failf(data, "Bad checksum returned from server");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
return AUTH_OK;
|
||||
@@ -321,15 +321,14 @@ void Curl_krb_kauth(struct connectdata *conn)
|
||||
if(nread < 0)
|
||||
return /*CURLE_OPERATION_TIMEOUTED*/;
|
||||
|
||||
if(/*ret != CONTINUE*/conn->data->state.buffer[0] != '3'){
|
||||
if(conn->data->state.buffer[0] != '3'){
|
||||
Curl_set_command_prot(conn, save);
|
||||
/*code = -1;***/
|
||||
return;
|
||||
}
|
||||
|
||||
p = strstr(conn->data->state.buffer, "T=");
|
||||
if(!p) {
|
||||
printf("Bad reply from server.\n");
|
||||
Curl_failf(conn->data, "Bad reply from server");
|
||||
Curl_set_command_prot(conn, save);
|
||||
return;
|
||||
}
|
||||
@@ -337,7 +336,7 @@ void Curl_krb_kauth(struct connectdata *conn)
|
||||
p += 2;
|
||||
tmp = Curl_base64_decode(p, &tkt.dat);
|
||||
if(tmp < 0) {
|
||||
printf("Failed to decode base64 in reply.\n");
|
||||
Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
|
||||
Curl_set_command_prot(conn, save);
|
||||
return;
|
||||
}
|
||||
@@ -346,7 +345,7 @@ void Curl_krb_kauth(struct connectdata *conn)
|
||||
|
||||
p = strstr(conn->data->state.buffer, "P=");
|
||||
if(!p) {
|
||||
printf("Bad reply from server.\n");
|
||||
Curl_failf(conn->data, "Bad reply from server");
|
||||
Curl_set_command_prot(conn, save);
|
||||
return;
|
||||
}
|
||||
|
165
lib/llist.c
Normal file
165
lib/llist.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al
|
||||
*
|
||||
* In order to be useful for every potential user, curl and libcurl are
|
||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||
* licenses. You may pick one of these licenses.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "llist.h"
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
/* this must be the last include file */
|
||||
#include "memdebug.h"
|
||||
#endif
|
||||
void
|
||||
curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
|
||||
{
|
||||
l->size = 0;
|
||||
l->dtor = dtor;
|
||||
l->head = NULL;
|
||||
l->tail = NULL;
|
||||
}
|
||||
|
||||
curl_llist *
|
||||
curl_llist_alloc(curl_llist_dtor dtor)
|
||||
{
|
||||
curl_llist *list;
|
||||
|
||||
list = malloc(sizeof(curl_llist));
|
||||
curl_llist_init(list, dtor);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
int
|
||||
curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
|
||||
{
|
||||
curl_llist_element *ne;
|
||||
|
||||
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
|
||||
ne->ptr = (void *) p;
|
||||
if (list->size == 0) {
|
||||
list->head = ne;
|
||||
list->head->prev = NULL;
|
||||
list->head->next = NULL;
|
||||
list->tail = ne;
|
||||
} else {
|
||||
ne->next = e->next;
|
||||
ne->prev = e;
|
||||
if (e->next) {
|
||||
e->next->prev = ne;
|
||||
} else {
|
||||
list->tail = ne;
|
||||
}
|
||||
e->next = ne;
|
||||
}
|
||||
|
||||
++list->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
|
||||
{
|
||||
curl_llist_element *ne;
|
||||
|
||||
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
|
||||
ne->ptr = (void *) p;
|
||||
if (list->size == 0) {
|
||||
list->head = ne;
|
||||
list->head->prev = NULL;
|
||||
list->head->next = NULL;
|
||||
list->tail = ne;
|
||||
} else {
|
||||
ne->next = e;
|
||||
ne->prev = e->prev;
|
||||
if (e->prev)
|
||||
e->prev->next = ne;
|
||||
else
|
||||
list->head = ne;
|
||||
e->prev = ne;
|
||||
}
|
||||
|
||||
++list->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
|
||||
{
|
||||
if (e == NULL || list->size == 0)
|
||||
return 1;
|
||||
|
||||
if (e == list->head) {
|
||||
list->head = e->next;
|
||||
|
||||
if (list->head == NULL)
|
||||
list->tail = NULL;
|
||||
else
|
||||
e->next->prev = NULL;
|
||||
} else {
|
||||
e->prev->next = e->next;
|
||||
if (!e->next)
|
||||
list->tail = e->prev;
|
||||
else
|
||||
e->next->prev = e->prev;
|
||||
}
|
||||
|
||||
list->dtor(user, e->ptr);
|
||||
free(e);
|
||||
--list->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user)
|
||||
{
|
||||
return curl_llist_remove(list, e->next, user);
|
||||
}
|
||||
|
||||
int
|
||||
curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user)
|
||||
{
|
||||
return curl_llist_remove(list, e->prev, user);
|
||||
}
|
||||
|
||||
size_t
|
||||
curl_llist_count(curl_llist *list)
|
||||
{
|
||||
return list->size;
|
||||
}
|
||||
|
||||
void
|
||||
curl_llist_destroy(curl_llist *list, void *user)
|
||||
{
|
||||
while (list->size > 0) {
|
||||
curl_llist_remove(list, CURL_LLIST_TAIL(list), user);
|
||||
}
|
||||
|
||||
free(list);
|
||||
list = NULL;
|
||||
}
|
64
lib/llist.h
Normal file
64
lib/llist.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef __LLIST_H
|
||||
#define __LLIST_H
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al
|
||||
*
|
||||
* In order to be useful for every potential user, curl and libcurl are
|
||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||
* licenses. You may pick one of these licenses.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
#include <stddef.h>
|
||||
|
||||
typedef void (*curl_llist_dtor)(void *, void *);
|
||||
|
||||
typedef struct _curl_llist_element {
|
||||
void *ptr;
|
||||
|
||||
struct _curl_llist_element *prev;
|
||||
struct _curl_llist_element *next;
|
||||
} curl_llist_element;
|
||||
|
||||
typedef struct _curl_llist {
|
||||
curl_llist_element *head;
|
||||
curl_llist_element *tail;
|
||||
|
||||
curl_llist_dtor dtor;
|
||||
|
||||
size_t size;
|
||||
} curl_llist;
|
||||
|
||||
void curl_llist_init(curl_llist *, curl_llist_dtor);
|
||||
curl_llist *curl_llist_alloc(curl_llist_dtor);
|
||||
int curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *);
|
||||
int curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *);
|
||||
int curl_llist_remove(curl_llist *, curl_llist_element *, void *);
|
||||
int curl_llist_remove_next(curl_llist *, curl_llist_element *, void *);
|
||||
size_t curl_llist_count(curl_llist *);
|
||||
void curl_llist_destroy(curl_llist *, void *);
|
||||
|
||||
#define CURL_LLIST_HEAD(__l) ((__l)->head)
|
||||
#define CURL_LLIST_TAIL(__l) ((__l)->tail)
|
||||
#define CURL_LLIST_NEXT(__e) ((__e)->next)
|
||||
#define CURL_LLIST_PREV(__e) ((__e)->prev)
|
||||
#define CURL_LLIST_VALP(__e) ((__e)->ptr)
|
||||
#define CURL_LLIST_IS_TAIL(__e) ((__e)->next ? 0 : 1)
|
||||
#define CURL_LLIST_IS_HEAD(__e) ((__e)->prev ? 0 : 1)
|
||||
|
||||
#endif
|
82
lib/multi.c
82
lib/multi.c
@@ -22,10 +22,16 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "multi.h" /* will become <curl/multi.h> soon */
|
||||
|
||||
#include "urldata.h"
|
||||
#include "transfer.h"
|
||||
#include "url.h"
|
||||
|
||||
struct Curl_message {
|
||||
/* the 'CURLMsg' is the part that is visible to the external user */
|
||||
struct CURLMsg extmsg;
|
||||
@@ -48,7 +54,9 @@ struct Curl_one_easy {
|
||||
struct Curl_one_easy *next;
|
||||
struct Curl_one_easy *prev;
|
||||
|
||||
CURL *easy_handle; /* this is the easy handle for this unit */
|
||||
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
||||
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||
|
||||
CURLMstate state; /* the handle's state */
|
||||
CURLcode result; /* previous result */
|
||||
};
|
||||
@@ -74,7 +82,8 @@ struct Curl_multi {
|
||||
struct Curl_message *msgs;
|
||||
/* amount of messages in the queue */
|
||||
int num_msgs;
|
||||
|
||||
/* Hostname cache */
|
||||
curl_hash *hostcache;
|
||||
};
|
||||
|
||||
|
||||
@@ -134,7 +143,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
/* increase the node-counter */
|
||||
multi->num_easy++;
|
||||
|
||||
return CURLM_OK;
|
||||
return CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
@@ -190,23 +199,30 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
and then we must make sure that is done. */
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
int this_max_fd=-1;
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
*max_fd = -1; /* so far none! */
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy) {
|
||||
switch(easy->state) {
|
||||
case CURLM_STATE_INIT:
|
||||
case CURLM_STATE_CONNECT:
|
||||
case CURLM_STATE_DO:
|
||||
case CURLM_STATE_DONE:
|
||||
/* we want curl_multi_perform() to get called, but we don't have any
|
||||
file descriptors to set */
|
||||
default:
|
||||
break;
|
||||
case CURLM_STATE_PERFORM:
|
||||
/* This should have a set of file descriptors for us to set. */
|
||||
/* after the transfer is done, go DONE */
|
||||
|
||||
Curl_single_fdset(easy->easy_conn,
|
||||
read_fd_set, write_fd_set,
|
||||
exc_fd_set, &this_max_fd);
|
||||
|
||||
/* remember the maximum file descriptor */
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
|
||||
break;
|
||||
}
|
||||
easy = easy->next; /* check next handle */
|
||||
@@ -222,12 +238,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
bool done;
|
||||
CURLMcode result=CURLM_OK;
|
||||
|
||||
*running_handles = 0; /* bump this once for every living handle */
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy) {
|
||||
|
||||
switch(easy->state) {
|
||||
case CURLM_STATE_INIT:
|
||||
/* init this transfer. */
|
||||
@@ -239,8 +256,20 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
}
|
||||
break;
|
||||
case CURLM_STATE_CONNECT:
|
||||
/* connect */
|
||||
easy->result = Curl_connect(easy->easy_handle);
|
||||
if (Curl_global_host_cache_use(easy->easy_handle)) {
|
||||
easy->easy_handle->hostcache = Curl_global_host_cache_get();
|
||||
}
|
||||
else {
|
||||
if (multi->hostcache == NULL) {
|
||||
multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
|
||||
}
|
||||
|
||||
easy->easy_handle->hostcache = multi->hostcache;
|
||||
}
|
||||
|
||||
/* Connect. We get a connection identifier filled in. */
|
||||
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
|
||||
|
||||
/* after connect, go DO */
|
||||
if(CURLE_OK == easy->result) {
|
||||
easy->state = CURLM_STATE_DO;
|
||||
@@ -249,15 +278,18 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
break;
|
||||
case CURLM_STATE_DO:
|
||||
/* Do the fetch or put request */
|
||||
easy->result = Curl_do(easy->easy_handle);
|
||||
easy->result = Curl_do(&easy->easy_conn);
|
||||
/* after do, go PERFORM */
|
||||
if(CURLE_OK == easy->result) {
|
||||
easy->state = CURLM_STATE_PERFORM;
|
||||
if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) {
|
||||
easy->state = CURLM_STATE_PERFORM;
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CURLM_STATE_PERFORM:
|
||||
/* read/write data if it is ready to do so */
|
||||
easy->result = Curl_readwrite(easy->easy_handle, &done);
|
||||
easy->result = Curl_readwrite(easy->easy_conn, &done);
|
||||
/* hm, when we follow redirects, we may need to go back to the CONNECT
|
||||
state */
|
||||
/* after the transfer is done, go DONE */
|
||||
@@ -265,11 +297,12 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
/* call this even if the readwrite function returned error */
|
||||
easy->result = Curl_posttransfer(easy->easy_handle);
|
||||
easy->state = CURLM_STATE_DONE;
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
break;
|
||||
case CURLM_STATE_DONE:
|
||||
/* post-transfer command */
|
||||
easy->result = Curl_done(easy->easy_handle);
|
||||
easy->result = Curl_done(easy->easy_conn);
|
||||
/* after we have DONE what we're supposed to do, go COMPLETED */
|
||||
if(CURLE_OK == easy->result)
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
@@ -280,7 +313,10 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
/* This node should be delinked from the list now and we should post
|
||||
an information message that we are complete. */
|
||||
break;
|
||||
default:
|
||||
return CURLM_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if((CURLM_STATE_COMPLETED != easy->state) &&
|
||||
(CURLE_OK != easy->result)) {
|
||||
/*
|
||||
@@ -289,10 +325,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
*/
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
}
|
||||
else if(CURLM_STATE_COMPLETED != easy->state)
|
||||
/* this one still lives! */
|
||||
(*running_handles)++;
|
||||
|
||||
easy = easy->next; /* operate on next handle */
|
||||
}
|
||||
return CURLM_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
@@ -300,7 +339,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
if(GOOD_MULTI_HANDLE(multi)) {
|
||||
multi->type = 0; /* not good anymore */
|
||||
|
||||
curl_hash_destroy(multi->hostcache);
|
||||
/* remove all easy handles */
|
||||
|
||||
free(multi);
|
||||
@@ -313,3 +352,10 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
|
||||
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
|
||||
|
||||
/*
|
||||
* local variables:
|
||||
* eval: (load-file "../curl-mode.el")
|
||||
* end:
|
||||
* vim600: fdm=marker
|
||||
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||
*/
|
||||
|
@@ -50,7 +50,7 @@
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <curl/types.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
typedef void CURLM;
|
||||
|
||||
@@ -60,6 +60,7 @@ typedef enum {
|
||||
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
|
@@ -52,7 +52,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus /* (rabe) */
|
||||
typedef char bool;
|
||||
typedef unsigned char bool;
|
||||
#define typedef_bool
|
||||
#endif /* (rabe) */
|
||||
|
||||
|
74
lib/ssluse.c
74
lib/ssluse.c
@@ -736,8 +736,78 @@ Curl_SSLConnect(struct connectdata *conn)
|
||||
}
|
||||
|
||||
/* pass the raw socket into the SSL layers */
|
||||
SSL_set_fd (conn->ssl.handle, conn->firstsocket);
|
||||
err = SSL_connect (conn->ssl.handle);
|
||||
SSL_set_fd(conn->ssl.handle, conn->firstsocket);
|
||||
|
||||
do {
|
||||
int what;
|
||||
fd_set writefd;
|
||||
fd_set readfd;
|
||||
struct timeval interval;
|
||||
long timeout_ms;
|
||||
|
||||
err = SSL_connect(conn->ssl.handle);
|
||||
|
||||
what = SSL_get_error(conn->ssl.handle, err);
|
||||
|
||||
FD_ZERO(&writefd);
|
||||
FD_ZERO(&readfd);
|
||||
|
||||
if(SSL_ERROR_WANT_READ == what)
|
||||
FD_SET(conn->firstsocket, &readfd);
|
||||
else if(SSL_ERROR_WANT_WRITE == what)
|
||||
FD_SET(conn->firstsocket, &writefd);
|
||||
else
|
||||
break; /* untreated error */
|
||||
|
||||
/* Find out if any timeout is set. If not, use 300 seconds.
|
||||
Otherwise, figure out the most strict timeout of the two possible one
|
||||
and then how much time that has elapsed to know how much time we
|
||||
allow for the connect call */
|
||||
if(data->set.timeout || data->set.connecttimeout) {
|
||||
double has_passed;
|
||||
|
||||
/* Evaluate in milliseconds how much time that has passed */
|
||||
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* get the most strict timeout of the ones converted to milliseconds */
|
||||
if(data->set.timeout &&
|
||||
(data->set.timeout>data->set.connecttimeout))
|
||||
timeout_ms = data->set.timeout*1000;
|
||||
else
|
||||
timeout_ms = data->set.connecttimeout*1000;
|
||||
|
||||
/* subtract the passed time */
|
||||
timeout_ms -= (long)has_passed;
|
||||
|
||||
if(timeout_ms < 0)
|
||||
/* a precaution, no need to continue if time already is up */
|
||||
return CURLE_OPERATION_TIMEOUTED;
|
||||
}
|
||||
else
|
||||
/* no particular time-out has been set */
|
||||
timeout_ms=300000; /* milliseconds, default to five minutes */
|
||||
|
||||
interval.tv_sec = timeout_ms/1000;
|
||||
timeout_ms -= interval.tv_sec*1000;
|
||||
|
||||
interval.tv_usec = timeout_ms*1000;
|
||||
|
||||
what = select(conn->firstsocket+1, &readfd, &writefd, NULL, &interval);
|
||||
if(what > 0)
|
||||
/* reabable or writable, go loop yourself */
|
||||
continue;
|
||||
else if(0 == what) {
|
||||
/* timeout */
|
||||
failf(data, "SSL connection timeout");
|
||||
return CURLE_OPERATION_TIMEOUTED;
|
||||
}
|
||||
else
|
||||
break; /* get out of loop */
|
||||
} while(1);
|
||||
|
||||
/* 1 is fine
|
||||
0 is "not successful but was shut down controlled"
|
||||
|
58
lib/telnet.c
58
lib/telnet.c
@@ -226,9 +226,9 @@ static void printoption(struct SessionHandle *data,
|
||||
if (cmd == IAC)
|
||||
{
|
||||
if (TELCMD_OK(option))
|
||||
printf("%s IAC %s\n", direction, TELCMD(option));
|
||||
Curl_infof(data, "%s IAC %s\n", direction, TELCMD(option));
|
||||
else
|
||||
printf("%s IAC %d\n", direction, option);
|
||||
Curl_infof(data, "%s IAC %d\n", direction, option);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -244,12 +244,12 @@ static void printoption(struct SessionHandle *data,
|
||||
opt = NULL;
|
||||
|
||||
if(opt)
|
||||
printf("%s %s %s\n", direction, fmt, opt);
|
||||
Curl_infof(data, "%s %s %s\n", direction, fmt, opt);
|
||||
else
|
||||
printf("%s %s %d\n", direction, fmt, option);
|
||||
Curl_infof(data, "%s %s %d\n", direction, fmt, option);
|
||||
}
|
||||
else
|
||||
printf("%s %d %d\n", direction, cmd, option);
|
||||
Curl_infof(data, "%s %d %d\n", direction, cmd, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,7 +638,7 @@ static void printsub(struct SessionHandle *data,
|
||||
{
|
||||
if (direction)
|
||||
{
|
||||
printf("%s IAC SB ", (direction == '<')? "RCVD":"SENT");
|
||||
Curl_infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
|
||||
if (length >= 3)
|
||||
{
|
||||
int j;
|
||||
@@ -648,27 +648,27 @@ static void printsub(struct SessionHandle *data,
|
||||
|
||||
if (i != IAC || j != SE)
|
||||
{
|
||||
printf("(terminated by ");
|
||||
Curl_infof(data, "(terminated by ");
|
||||
if (TELOPT_OK(i))
|
||||
printf("%s ", TELOPT(i));
|
||||
Curl_infof(data, "%s ", TELOPT(i));
|
||||
else if (TELCMD_OK(i))
|
||||
printf("%s ", TELCMD(i));
|
||||
Curl_infof(data, "%s ", TELCMD(i));
|
||||
else
|
||||
printf("%d ", i);
|
||||
Curl_infof(data, "%d ", i);
|
||||
if (TELOPT_OK(j))
|
||||
printf("%s", TELOPT(j));
|
||||
Curl_infof(data, "%s", TELOPT(j));
|
||||
else if (TELCMD_OK(j))
|
||||
printf("%s", TELCMD(j));
|
||||
Curl_infof(data, "%s", TELCMD(j));
|
||||
else
|
||||
printf("%d", j);
|
||||
printf(", not IAC SE!) ");
|
||||
Curl_infof(data, "%d", j);
|
||||
Curl_infof(data, ", not IAC SE!) ");
|
||||
}
|
||||
}
|
||||
length -= 2;
|
||||
}
|
||||
if (length < 1)
|
||||
{
|
||||
printf("(Empty suboption?)");
|
||||
Curl_infof(data, "(Empty suboption?)");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -677,28 +677,28 @@ static void printsub(struct SessionHandle *data,
|
||||
case TELOPT_TTYPE:
|
||||
case TELOPT_XDISPLOC:
|
||||
case TELOPT_NEW_ENVIRON:
|
||||
printf("%s", TELOPT(pointer[0]));
|
||||
Curl_infof(data, "%s", TELOPT(pointer[0]));
|
||||
break;
|
||||
default:
|
||||
printf("%s (unsupported)", TELOPT(pointer[0]));
|
||||
Curl_infof(data, "%s (unsupported)", TELOPT(pointer[0]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("%d (unknown)", pointer[i]);
|
||||
Curl_infof(data, "%d (unknown)", pointer[i]);
|
||||
|
||||
switch(pointer[1]) {
|
||||
case TELQUAL_IS:
|
||||
printf(" IS");
|
||||
Curl_infof(data, " IS");
|
||||
break;
|
||||
case TELQUAL_SEND:
|
||||
printf(" SEND");
|
||||
Curl_infof(data, " SEND");
|
||||
break;
|
||||
case TELQUAL_INFO:
|
||||
printf(" INFO/REPLY");
|
||||
Curl_infof(data, " INFO/REPLY");
|
||||
break;
|
||||
case TELQUAL_NAME:
|
||||
printf(" NAME");
|
||||
Curl_infof(data, " NAME");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -706,21 +706,21 @@ static void printsub(struct SessionHandle *data,
|
||||
case TELOPT_TTYPE:
|
||||
case TELOPT_XDISPLOC:
|
||||
pointer[length] = 0;
|
||||
printf(" \"%s\"", &pointer[2]);
|
||||
Curl_infof(data, " \"%s\"", &pointer[2]);
|
||||
break;
|
||||
case TELOPT_NEW_ENVIRON:
|
||||
if(pointer[1] == TELQUAL_IS) {
|
||||
printf(" ");
|
||||
Curl_infof(data, " ");
|
||||
for(i = 3;i < length;i++) {
|
||||
switch(pointer[i]) {
|
||||
case NEW_ENV_VAR:
|
||||
printf(", ");
|
||||
Curl_infof(data, ", ");
|
||||
break;
|
||||
case NEW_ENV_VALUE:
|
||||
printf(" = ");
|
||||
Curl_infof(data, " = ");
|
||||
break;
|
||||
default:
|
||||
printf("%c", pointer[i]);
|
||||
Curl_infof(data, "%c", pointer[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -728,13 +728,13 @@ static void printsub(struct SessionHandle *data,
|
||||
break;
|
||||
default:
|
||||
for (i = 2; i < length; i++)
|
||||
printf(" %.2x", pointer[i]);
|
||||
Curl_infof(data, " %.2x", pointer[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (direction)
|
||||
{
|
||||
printf("\n");
|
||||
Curl_infof(data, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1564
lib/transfer.c
1564
lib/transfer.c
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* In order to be useful for every potential user, curl and libcurl are
|
||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||
@@ -24,6 +24,17 @@
|
||||
*****************************************************************************/
|
||||
CURLcode Curl_perform(struct SessionHandle *data);
|
||||
|
||||
CURLcode Curl_pretransfer(struct SessionHandle *data);
|
||||
CURLcode Curl_posttransfer(struct SessionHandle *data);
|
||||
|
||||
CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
|
||||
void Curl_single_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd);
|
||||
CURLcode Curl_readwrite_init(struct connectdata *conn);
|
||||
|
||||
/* This sets up a forthcoming transfer */
|
||||
CURLcode
|
||||
Curl_Transfer (struct connectdata *data,
|
||||
|
99
lib/url.c
99
lib/url.c
@@ -110,6 +110,10 @@
|
||||
|
||||
#include <curl/types.h>
|
||||
|
||||
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||
#include "inet_ntoa_r.h"
|
||||
#endif
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
@@ -247,13 +251,15 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
||||
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
|
||||
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
|
||||
|
||||
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
|
||||
|
||||
/* make libcurl quiet by default: */
|
||||
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
|
||||
/* Set the default size of the SSL session ID cache */
|
||||
data->set.ssl.numsessions = 5;
|
||||
|
||||
|
||||
/* create an array with connection data struct pointers */
|
||||
data->state.numconnects = 5; /* hard-coded right now */
|
||||
data->state.connects = (struct connectdata **)
|
||||
@@ -280,6 +286,19 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
va_start(param, option);
|
||||
|
||||
switch(option) {
|
||||
case CURLOPT_DNS_CACHE_TIMEOUT:
|
||||
data->set.dns_cache_timeout = va_arg(param, int);
|
||||
break;
|
||||
case CURLOPT_DNS_USE_GLOBAL_CACHE:
|
||||
{
|
||||
int use_cache = va_arg(param, int);
|
||||
if (use_cache) {
|
||||
Curl_global_host_cache_init();
|
||||
}
|
||||
|
||||
data->set.global_dns_cache = use_cache;
|
||||
}
|
||||
break;
|
||||
case CURLOPT_SSL_CIPHER_LIST:
|
||||
/* set a list of cipher we want to use in the SSL connection */
|
||||
data->set.ssl.cipher_list = va_arg(param, char *);
|
||||
@@ -940,9 +959,6 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
||||
if(conn->proto.generic)
|
||||
free(conn->proto.generic);
|
||||
|
||||
if(conn->hostent_buf) /* host name info */
|
||||
Curl_freeaddrinfo(conn->hostent_buf);
|
||||
|
||||
if(conn->newurl)
|
||||
free(conn->newurl);
|
||||
|
||||
@@ -1217,8 +1233,7 @@ static CURLcode ConnectPlease(struct connectdata *conn)
|
||||
}
|
||||
|
||||
static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
struct connectdata **in_connect,
|
||||
bool allow_port) /* allow set.use_port? */
|
||||
struct connectdata **in_connect)
|
||||
{
|
||||
char *tmp;
|
||||
char *buf;
|
||||
@@ -1228,6 +1243,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
struct connectdata *conn_temp;
|
||||
char endbracket;
|
||||
int urllen;
|
||||
#ifdef HAVE_INET_NTOA_R
|
||||
char ntoa_buf[64];
|
||||
#endif
|
||||
#ifdef HAVE_ALARM
|
||||
unsigned int prev_alarm;
|
||||
#endif
|
||||
@@ -1617,7 +1635,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
*************************************************************/
|
||||
|
||||
if (strequal(conn->protostr, "HTTP")) {
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTP;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port:PORT_HTTP;
|
||||
conn->remote_port = PORT_HTTP;
|
||||
conn->protocol |= PROT_HTTP;
|
||||
conn->curl_do = Curl_http;
|
||||
@@ -1627,7 +1646,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
else if (strequal(conn->protostr, "HTTPS")) {
|
||||
#ifdef USE_SSLEAY
|
||||
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTPS;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port:PORT_HTTPS;
|
||||
conn->remote_port = PORT_HTTPS;
|
||||
conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
|
||||
|
||||
@@ -1642,7 +1662,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
#endif /* !USE_SSLEAY */
|
||||
}
|
||||
else if (strequal(conn->protostr, "GOPHER")) {
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_GOPHER;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port:PORT_GOPHER;
|
||||
conn->remote_port = PORT_GOPHER;
|
||||
/* Skip /<item-type>/ in path if present */
|
||||
if (isdigit((int)conn->path[1])) {
|
||||
@@ -1668,7 +1689,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
#endif /* !USE_SSLEAY */
|
||||
}
|
||||
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_FTP;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port:PORT_FTP;
|
||||
conn->remote_port = PORT_FTP;
|
||||
conn->protocol |= PROT_FTP;
|
||||
|
||||
@@ -1723,21 +1745,24 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
/* telnet testing factory */
|
||||
conn->protocol |= PROT_TELNET;
|
||||
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port: PORT_TELNET;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port: PORT_TELNET;
|
||||
conn->remote_port = PORT_TELNET;
|
||||
conn->curl_do = Curl_telnet;
|
||||
conn->curl_done = Curl_telnet_done;
|
||||
}
|
||||
else if (strequal(conn->protostr, "DICT")) {
|
||||
conn->protocol |= PROT_DICT;
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_DICT;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port:PORT_DICT;
|
||||
conn->remote_port = PORT_DICT;
|
||||
conn->curl_do = Curl_dict;
|
||||
conn->curl_done = NULL; /* no DICT-specific done */
|
||||
}
|
||||
else if (strequal(conn->protostr, "LDAP")) {
|
||||
conn->protocol |= PROT_LDAP;
|
||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_LDAP;
|
||||
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||
data->set.use_port:PORT_LDAP;
|
||||
conn->remote_port = PORT_LDAP;
|
||||
conn->curl_do = Curl_ldap;
|
||||
conn->curl_done = NULL; /* no LDAP-specific done */
|
||||
@@ -2060,8 +2085,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
/* Resolve target host right on */
|
||||
if(!conn->hostaddr) {
|
||||
/* it might already be set if reusing a connection */
|
||||
conn->hostaddr = Curl_getaddrinfo(data, conn->name, conn->port,
|
||||
&conn->hostent_buf);
|
||||
conn->hostaddr = Curl_resolv(data, conn->name, conn->port,
|
||||
&conn->hostent_buf);
|
||||
}
|
||||
if(!conn->hostaddr) {
|
||||
failf(data, "Couldn't resolve host '%s'", conn->name);
|
||||
@@ -2075,8 +2100,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
|
||||
/* resolve proxy */
|
||||
/* it might already be set if reusing a connection */
|
||||
conn->hostaddr = Curl_getaddrinfo(data, conn->proxyhost, conn->port,
|
||||
&conn->hostent_buf);
|
||||
conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port,
|
||||
&conn->hostent_buf);
|
||||
|
||||
if(!conn->hostaddr) {
|
||||
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
|
||||
@@ -2211,7 +2236,12 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
struct in_addr in;
|
||||
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
||||
infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
|
||||
inet_ntoa(in));
|
||||
#if defined(HAVE_INET_NTOA_R)
|
||||
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf))
|
||||
#else
|
||||
inet_ntoa(in)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2231,14 +2261,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
CURLcode Curl_connect(struct SessionHandle *data,
|
||||
struct connectdata **in_connect,
|
||||
bool allow_port)
|
||||
struct connectdata **in_connect)
|
||||
{
|
||||
CURLcode code;
|
||||
struct connectdata *conn;
|
||||
|
||||
/* call the stuff that needs to be called */
|
||||
code = CreateConnection(data, in_connect, allow_port);
|
||||
code = CreateConnection(data, in_connect);
|
||||
|
||||
if(CURLE_OK != code) {
|
||||
/* We're not allowed to return failure with memory left allocated
|
||||
@@ -2294,14 +2323,38 @@ CURLcode Curl_done(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_do(struct connectdata *conn)
|
||||
CURLcode Curl_do(struct connectdata **connp)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
struct connectdata *conn = *connp;
|
||||
struct SessionHandle *data=conn->data;
|
||||
|
||||
if(conn->curl_do)
|
||||
if(conn->curl_do) {
|
||||
/* generic protocol-specific function pointer set in curl_connect() */
|
||||
result = conn->curl_do(conn);
|
||||
|
||||
/* This was formerly done in transfer.c, but we better do it here */
|
||||
|
||||
if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) {
|
||||
/* This was a re-use of a connection and we got a write error in the
|
||||
* DO-phase. Then we DISCONNECT this connection and have another attempt
|
||||
* to CONNECT and then DO again! The retry cannot possibly find another
|
||||
* connection to re-use, since we only keep one possible connection for
|
||||
* each. */
|
||||
|
||||
infof(data, "Re-used connection seems dead, get a new one\n");
|
||||
|
||||
conn->bits.close = TRUE; /* enforce close of this connetion */
|
||||
result = Curl_done(conn); /* we are so done with this */
|
||||
if(CURLE_OK == result) {
|
||||
/* Now, redo the connect and get a new connection */
|
||||
result = Curl_connect(data, connp);
|
||||
if(CURLE_OK == result)
|
||||
/* ... finally back to actually retry the DO phase */
|
||||
result = conn->curl_do(*connp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
10
lib/url.h
10
lib/url.h
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* In order to be useful for every potential user, curl and libcurl are
|
||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||
@@ -29,11 +29,9 @@
|
||||
|
||||
CURLcode Curl_open(struct SessionHandle **curl);
|
||||
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...);
|
||||
CURLcode Curl_close(struct SessionHandle *data); /* the opposite of curl_open() */
|
||||
CURLcode Curl_connect(struct SessionHandle *,
|
||||
struct connectdata **,
|
||||
bool allow_port);
|
||||
CURLcode Curl_do(struct connectdata *);
|
||||
CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
|
||||
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **);
|
||||
CURLcode Curl_do(struct connectdata **);
|
||||
CURLcode Curl_done(struct connectdata *);
|
||||
CURLcode Curl_disconnect(struct connectdata *);
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "setup.h"
|
||||
#include "hostip.h"
|
||||
#include "hash.h"
|
||||
|
||||
#define PORT_FTP 21
|
||||
#define PORT_TELNET 23
|
||||
@@ -211,6 +212,57 @@ struct ConnectBits {
|
||||
complete */
|
||||
};
|
||||
|
||||
/*
|
||||
* This struct is all the previously local variables from Curl_perform() moved
|
||||
* to struct to allow the function to return and get re-invoked better without
|
||||
* losing state.
|
||||
*/
|
||||
|
||||
struct Curl_transfer_keeper {
|
||||
int bytecount; /* total number of bytes read */
|
||||
int writebytecount; /* number of bytes written */
|
||||
long contentlength; /* size of incoming data */
|
||||
struct timeval start; /* transfer started at this time */
|
||||
struct timeval now; /* current time */
|
||||
bool header; /* incoming data has HTTP header */
|
||||
int headerline; /* counts header lines to better track the
|
||||
first one */
|
||||
char *hbufp; /* points at *end* of header line */
|
||||
int hbuflen;
|
||||
char *str; /* within buf */
|
||||
char *str_start; /* within buf */
|
||||
char *end_ptr; /* within buf */
|
||||
char *p; /* within headerbuff */
|
||||
bool content_range; /* set TRUE if Content-Range: was found */
|
||||
int offset; /* possible resume offset read from the
|
||||
Content-Range: header */
|
||||
int httpcode; /* error code from the 'HTTP/1.? XXX' line */
|
||||
int httpversion; /* the HTTP version*10 */
|
||||
bool write_after_100_header; /* should we enable the write after
|
||||
we received a 100-continue/timeout
|
||||
or directly */
|
||||
|
||||
/* for the low speed checks: */
|
||||
time_t timeofdoc;
|
||||
long bodywrites;
|
||||
int writetype;
|
||||
|
||||
/* the highest fd we use + 1 */
|
||||
struct SessionHandle *data;
|
||||
struct connectdata *conn;
|
||||
char *buf;
|
||||
int maxfd;
|
||||
|
||||
/* the file descriptors to play with */
|
||||
fd_set readfd;
|
||||
fd_set writefd;
|
||||
fd_set rkeepfd;
|
||||
fd_set wkeepfd;
|
||||
int keepon;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The connectdata struct contains all fields and variables that should be
|
||||
* unique for an entire connection.
|
||||
@@ -355,6 +407,8 @@ struct connectdata {
|
||||
void *generic;
|
||||
} proto;
|
||||
|
||||
/* This struct is inited when needed */
|
||||
struct Curl_transfer_keeper keep;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -460,6 +514,13 @@ struct UrlState {
|
||||
bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
|
||||
This must be set to FALSE every time _easy_perform() is
|
||||
called. */
|
||||
|
||||
#ifdef HAVE_SIGNAL
|
||||
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
|
||||
void (*prev_signal)(int sig);
|
||||
#endif
|
||||
bool allow_port; /* Is set.use_port allowed to take effect or not. This
|
||||
is always set TRUE when curl_easy_perform() is called. */
|
||||
};
|
||||
|
||||
|
||||
@@ -556,6 +617,8 @@ struct UserDefined {
|
||||
char *krb4_level; /* what security level */
|
||||
struct ssl_config_data ssl; /* user defined SSL stuff */
|
||||
|
||||
int dns_cache_timeout; /* DNS cache timeout */
|
||||
|
||||
/* Here follows boolean settings that define how to behave during
|
||||
this session. They are STATIC, set by libcurl users or at least initially
|
||||
and they don't change during operations. */
|
||||
@@ -569,7 +632,6 @@ struct UserDefined {
|
||||
bool hide_progress;
|
||||
bool http_fail_on_error;
|
||||
bool http_follow_location;
|
||||
|
||||
bool include_header;
|
||||
#define http_include_header include_header /* former name */
|
||||
|
||||
@@ -585,6 +647,8 @@ struct UserDefined {
|
||||
bool reuse_fresh; /* do not re-use an existing connection */
|
||||
bool expect100header; /* TRUE if we added Expect: 100-continue */
|
||||
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
|
||||
|
||||
bool global_dns_cache;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -599,6 +663,7 @@ struct UserDefined {
|
||||
* 'struct urlstate' instead. */
|
||||
|
||||
struct SessionHandle {
|
||||
curl_hash *hostcache;
|
||||
struct UserDefined set; /* values set by the libcurl user */
|
||||
struct DynamicStatic change; /* possibly modified userdefined data */
|
||||
|
||||
|
21
multi/Makefile.am
Normal file
21
multi/Makefile.am
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
bin_PROGRAMS = app single double
|
||||
|
||||
app_SOURCES = app.c
|
||||
app_LDADD = ../lib/libcurl.la
|
||||
app_DEPENDENCIES = ../lib/libcurl.la
|
||||
|
||||
single_SOURCES = single.c
|
||||
single_LDADD = ../lib/libcurl.la
|
||||
single_DEPENDENCIES = ../lib/libcurl.la
|
||||
|
||||
double_SOURCES = double.c
|
||||
double_LDADD = ../lib/libcurl.la
|
||||
double_DEPENDENCIES = ../lib/libcurl.la
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
92
multi/app.c
Normal file
92
multi/app.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This is an example application source code using the multi interface.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* somewhat unix-specific */
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* To start with, we include the header from the lib directory. This should
|
||||
later of course be moved to the proper include dir. */
|
||||
#include "../lib/multi.h"
|
||||
|
||||
/*
|
||||
* Download a HTTP file and upload an FTP file simultaneously.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CURL *http_handle;
|
||||
CURL *ftp_handle;
|
||||
CURLM *multi_handle;
|
||||
|
||||
int still_running; /* keep number of running handles */
|
||||
|
||||
http_handle = curl_easy_init();
|
||||
ftp_handle = curl_easy_init();
|
||||
|
||||
/* set the options (I left out a few, you'll get the point anyway) */
|
||||
curl_easy_setopt(http_handle, CURLOPT_URL, "http://website.com");
|
||||
|
||||
curl_easy_setopt(ftp_handle, CURLOPT_URL, "ftp://ftpsite.com");
|
||||
curl_easy_setopt(ftp_handle, CURLOPT_UPLOAD, TRUE);
|
||||
|
||||
/* init a multi stack */
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
/* add the individual transfers */
|
||||
curl_multi_add_handle(multi_handle, http_handle);
|
||||
curl_multi_add_handle(multi_handle, ftp_handle);
|
||||
|
||||
/* we start some action by calling perform right away */
|
||||
while(CURLM_CALL_MULTI_PERFORM ==
|
||||
curl_multi_perform(multi_handle, &still_running));
|
||||
|
||||
while(still_running) {
|
||||
struct timeval timeout;
|
||||
int rc; /* select() return code */
|
||||
|
||||
fd_set fdread;
|
||||
fd_set fdwrite;
|
||||
fd_set fdexcep;
|
||||
int maxfd;
|
||||
|
||||
FD_ZERO(&fdread);
|
||||
FD_ZERO(&fdwrite);
|
||||
FD_ZERO(&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(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||
|
||||
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||
|
||||
switch(rc) {
|
||||
case -1:
|
||||
/* select error */
|
||||
break;
|
||||
case 0:
|
||||
/* timeout, do something else */
|
||||
break;
|
||||
default:
|
||||
/* one or more of curl's file descriptors say there's data to read
|
||||
or write */
|
||||
curl_multi_perform(multi_handle, &still_running);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curl_multi_cleanup(multi_handle);
|
||||
|
||||
curl_easy_cleanup(http_handle);
|
||||
curl_easy_cleanup(ftp_handle);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
87
multi/double.c
Normal file
87
multi/double.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This is a simple example using the multi interface.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* somewhat unix-specific */
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* To start with, we include the header from the lib directory. This should
|
||||
later of course be moved to the proper include dir. */
|
||||
#include "../lib/multi.h"
|
||||
|
||||
/*
|
||||
* Simply download two HTTP files!
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CURL *http_handle;
|
||||
CURL *http_handle2;
|
||||
CURLM *multi_handle;
|
||||
|
||||
int still_running; /* keep number of running handles */
|
||||
|
||||
http_handle = curl_easy_init();
|
||||
http_handle2 = curl_easy_init();
|
||||
|
||||
/* set options */
|
||||
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
|
||||
|
||||
/* set options */
|
||||
curl_easy_setopt(http_handle2, CURLOPT_URL, "http://localhost/");
|
||||
|
||||
/* init a multi stack */
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
/* add the individual transfers */
|
||||
curl_multi_add_handle(multi_handle, http_handle);
|
||||
curl_multi_add_handle(multi_handle, http_handle2);
|
||||
|
||||
/* we start some action by calling perform right away */
|
||||
while(CURLM_CALL_MULTI_PERFORM ==
|
||||
curl_multi_perform(multi_handle, &still_running));
|
||||
|
||||
while(still_running) {
|
||||
struct timeval timeout;
|
||||
int rc; /* select() return code */
|
||||
|
||||
fd_set fdread;
|
||||
fd_set fdwrite;
|
||||
fd_set fdexcep;
|
||||
int maxfd;
|
||||
|
||||
FD_ZERO(&fdread);
|
||||
FD_ZERO(&fdwrite);
|
||||
FD_ZERO(&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(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||
|
||||
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||
|
||||
switch(rc) {
|
||||
case -1:
|
||||
/* select error */
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
/* timeout or readable/writable sockets */
|
||||
curl_multi_perform(multi_handle, &still_running);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curl_multi_cleanup(multi_handle);
|
||||
|
||||
curl_easy_cleanup(http_handle);
|
||||
curl_easy_cleanup(http_handle2);
|
||||
|
||||
return 0;
|
||||
}
|
80
multi/single.c
Normal file
80
multi/single.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This is a very simple example using the multi interface.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* somewhat unix-specific */
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* To start with, we include the header from the lib directory. This should
|
||||
later of course be moved to the proper include dir. */
|
||||
#include "../lib/multi.h"
|
||||
|
||||
/*
|
||||
* Simply download a HTTP file.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CURL *http_handle;
|
||||
CURLM *multi_handle;
|
||||
|
||||
int still_running; /* keep number of running handles */
|
||||
|
||||
http_handle = curl_easy_init();
|
||||
|
||||
/* set the options (I left out a few, you'll get the point anyway) */
|
||||
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
|
||||
|
||||
/* init a multi stack */
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
/* add the individual transfers */
|
||||
curl_multi_add_handle(multi_handle, http_handle);
|
||||
|
||||
/* we start some action by calling perform right away */
|
||||
while(CURLM_CALL_MULTI_PERFORM ==
|
||||
curl_multi_perform(multi_handle, &still_running));
|
||||
|
||||
while(still_running) {
|
||||
struct timeval timeout;
|
||||
int rc; /* select() return code */
|
||||
|
||||
fd_set fdread;
|
||||
fd_set fdwrite;
|
||||
fd_set fdexcep;
|
||||
int maxfd;
|
||||
|
||||
FD_ZERO(&fdread);
|
||||
FD_ZERO(&fdwrite);
|
||||
FD_ZERO(&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(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||
|
||||
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||
|
||||
switch(rc) {
|
||||
case -1:
|
||||
/* select error */
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
/* timeout or readable/writable sockets */
|
||||
curl_multi_perform(multi_handle, &still_running);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curl_multi_cleanup(multi_handle);
|
||||
|
||||
curl_easy_cleanup(http_handle);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,3 +1,3 @@
|
||||
#define CURL_NAME "curl"
|
||||
#define CURL_VERSION "7.9.2"
|
||||
#define CURL_VERSION "7.9.3-pre1"
|
||||
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
||||
|
@@ -68,6 +68,8 @@ my $debugprotocol;
|
||||
my $anyway;
|
||||
my $gdbthis; # run test case with gdb debugger
|
||||
my $keepoutfiles; # keep stdout and stderr files after tests
|
||||
my $listonly; # only list the tests
|
||||
|
||||
my $pwd; # current working directory
|
||||
|
||||
chomp($pwd = `pwd`);
|
||||
@@ -427,14 +429,6 @@ sub singletest {
|
||||
|
||||
my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
|
||||
|
||||
# remove previous server output logfile
|
||||
unlink($SERVERIN);
|
||||
|
||||
if(@ftpservercmd) {
|
||||
# write the instructions to file
|
||||
writearray($FTPDCMD, \@ftpservercmd);
|
||||
}
|
||||
|
||||
# name of the test
|
||||
my @testname= getpart("client", "name");
|
||||
|
||||
@@ -445,6 +439,18 @@ sub singletest {
|
||||
print "[$name]\n";
|
||||
}
|
||||
|
||||
if($listonly) {
|
||||
return 0; # look successful
|
||||
}
|
||||
|
||||
# remove previous server output logfile
|
||||
unlink($SERVERIN);
|
||||
|
||||
if(@ftpservercmd) {
|
||||
# write the instructions to file
|
||||
writearray($FTPDCMD, \@ftpservercmd);
|
||||
}
|
||||
|
||||
# get the command line options to use
|
||||
my ($cmd, @blaha)= getpart("client", "command");
|
||||
|
||||
@@ -775,6 +781,10 @@ do {
|
||||
# continue anyway, even if a test fail
|
||||
$anyway=1;
|
||||
}
|
||||
elsif($ARGV[0] eq "-l") {
|
||||
# lists the test case names only
|
||||
$listonly=1;
|
||||
}
|
||||
elsif($ARGV[0] eq "-k") {
|
||||
# keep stdout and stderr files after tests
|
||||
$keepoutfiles=1;
|
||||
@@ -788,6 +798,7 @@ Usage: runtests.pl [options]
|
||||
-g run the test case with gdb
|
||||
-h this help text
|
||||
-k keep stdout and stderr files present after tests
|
||||
-l list all test case names/descriptions
|
||||
-s short output
|
||||
-v verbose output
|
||||
[num] like "5 6 9" or " 5 to 22 " to run those tests only
|
||||
|
Reference in New Issue
Block a user