2010-03-08 04:55:21 -06:00
|
|
|
/* Generic Communication Code HTTCP.c
|
|
|
|
** ==========================
|
|
|
|
**
|
|
|
|
** This code is in common between client and server sides.
|
|
|
|
**
|
|
|
|
** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.
|
|
|
|
** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* SOCKS mods by:
|
|
|
|
* Ying-Da Lee, <ylee@syl.dl.nec.com>
|
|
|
|
* NEC Systems Laboratory
|
|
|
|
* C&C Software Technology Center
|
|
|
|
*/
|
|
|
|
#include "../config.h"
|
|
|
|
#include "HTUtils.h"
|
|
|
|
#include "HTParse.h"
|
|
|
|
#include "HTAlert.h"
|
|
|
|
#include "HTAccess.h"
|
|
|
|
#include "tcp.h" /* Defines SHORT_NAMES if necessary */
|
|
|
|
#ifdef SHORT_NAMES
|
|
|
|
#define HTInetStatus HTInStat
|
|
|
|
#define HTInetString HTInStri
|
|
|
|
#define HTParseInet HTPaInet
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __STDC__
|
|
|
|
#include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(SVR4) && !defined(SCO) && !defined(linux) && !defined(DGUX)
|
|
|
|
#include <sys/filio.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(DGUX)
|
|
|
|
#include <sys/file.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Apparently needed for AIX 3.2. */
|
|
|
|
#ifndef FD_SETSIZE
|
|
|
|
#define FD_SETSIZE 256
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
extern int httpTrace;
|
|
|
|
extern int www2Trace;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Module-Wide variables
|
|
|
|
*/
|
|
|
|
|
|
|
|
PRIVATE char *hostname=0; /* The name of this host */
|
|
|
|
|
|
|
|
|
|
|
|
/* PUBLIC VARIABLES
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* PUBLIC SockA HTHostAddress; */ /* The internet address of the host */
|
|
|
|
/* Valid after call to HTHostName() */
|
|
|
|
|
|
|
|
/* Encode INET status (as in sys/errno.h) inet_status()
|
|
|
|
** ------------------
|
|
|
|
**
|
|
|
|
** On entry,
|
|
|
|
** where gives a description of what caused the error
|
|
|
|
** global errno gives the error number in the unix way.
|
|
|
|
**
|
|
|
|
** On return,
|
|
|
|
** returns a negative status in the unix way.
|
|
|
|
*/
|
|
|
|
#ifndef errno
|
|
|
|
extern int errno;
|
|
|
|
#endif /* errno */
|
|
|
|
|
|
|
|
/* Report Internet Error
|
|
|
|
** ---------------------
|
|
|
|
*/
|
|
|
|
#ifdef __STDC__
|
|
|
|
PUBLIC int HTInetStatus(char *where)
|
|
|
|
#else
|
|
|
|
PUBLIC int HTInetStatus(where)
|
|
|
|
char *where;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (www2Trace) {
|
|
|
|
fprintf(stderr, "TCP: Error %d in `errno' after call to %s() failed.\n\t%s\n",
|
|
|
|
errno, where, strerror(errno));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Parse a cardinal value parse_cardinal()
|
|
|
|
** ----------------------
|
|
|
|
**
|
|
|
|
** On entry,
|
|
|
|
** *pp points to first character to be interpreted, terminated by
|
|
|
|
** non 0:9 character.
|
|
|
|
** *pstatus points to status already valid
|
|
|
|
** maxvalue gives the largest allowable value.
|
|
|
|
**
|
|
|
|
** On exit,
|
|
|
|
** *pp points to first unread character
|
|
|
|
** *pstatus points to status updated iff bad
|
|
|
|
*/
|
|
|
|
|
|
|
|
PUBLIC unsigned int HTCardinal ARGS3
|
|
|
|
(int *, pstatus,
|
|
|
|
char **, pp,
|
|
|
|
unsigned int, max_value)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
if ( (**pp<'0') || (**pp>'9')) { /* Null string is error */
|
|
|
|
*pstatus = -3; /* No number where one expeceted */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
n=0;
|
|
|
|
while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
|
|
|
|
|
|
|
|
if (n>max_value) {
|
|
|
|
*pstatus = -4; /* Cardinal outside range */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Produce a string for an Internet address
|
|
|
|
** ----------------------------------------
|
|
|
|
**
|
|
|
|
** On exit,
|
|
|
|
** returns a pointer to a static string which must be copied if
|
|
|
|
** it is to be kept.
|
|
|
|
*/
|
|
|
|
|
|
|
|
PUBLIC WWW_CONST char * HTInetString ARGS1(SockA*,sin)
|
|
|
|
{
|
|
|
|
static char string[16];
|
|
|
|
sprintf(string, "%d.%d.%d.%d",
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+0),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+1),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+2),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+3));
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Parse a network node address and port
|
|
|
|
** -------------------------------------
|
|
|
|
**
|
|
|
|
** On entry,
|
|
|
|
** str points to a string with a node name or number,
|
|
|
|
** with optional trailing colon and port number.
|
|
|
|
** sin points to the binary internet or decnet address field.
|
|
|
|
**
|
|
|
|
** On exit,
|
|
|
|
** *sin is filled in. If no port is specified in str, that
|
|
|
|
** field is left unchanged in *sin.
|
|
|
|
*/
|
|
|
|
PUBLIC int HTParseInet ARGS2(SockA *,sin, WWW_CONST char *,str)
|
|
|
|
{
|
|
|
|
char *port;
|
|
|
|
char host[256];
|
|
|
|
struct hostent *phost; /* Pointer to host - See netdb.h */
|
|
|
|
int numeric_addr;
|
|
|
|
char *tmp;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
static char *cached_host = NULL;
|
|
|
|
static char *cached_phost_h_addr = NULL;
|
|
|
|
static int cached_phost_h_length = 0;
|
|
|
|
|
|
|
|
strcpy(host, str); /* Take a copy we can mutilate */
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
/* Parse port number if present */
|
|
|
|
if (port=strchr(host, ':'))
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
*port++ = 0; /* Chop off port */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (port[0]>='0' && port[0]<='9')
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
sin->sin_port = htons(atol(port));
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
/* Parse host number if present. */
|
2010-03-08 04:55:21 -06:00
|
|
|
numeric_addr = 1;
|
|
|
|
for (tmp = host; *tmp; tmp++)
|
|
|
|
{
|
|
|
|
/* If there's a non-numeric... */
|
|
|
|
if ((*tmp < '0' || *tmp > '9') && *tmp != '.')
|
|
|
|
{
|
|
|
|
numeric_addr = 0;
|
|
|
|
goto found_non_numeric_or_done;
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
found_non_numeric_or_done:
|
2013-03-09 18:59:42 -06:00
|
|
|
if (numeric_addr)
|
2010-03-08 04:55:21 -06:00
|
|
|
{ /* Numeric node address: */
|
|
|
|
sin->sin_addr.s_addr = inet_addr(host); /* See arpa/inet.h */
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
|
|
|
else
|
2010-03-08 04:55:21 -06:00
|
|
|
{ /* Alphanumeric node name: */
|
|
|
|
if (cached_host && (strcmp (cached_host, host) == 0))
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
fprintf (stderr, "=-= Matched '%s' and '%s', using cached_phost.\n",
|
|
|
|
cached_host, host);
|
|
|
|
#endif
|
|
|
|
memcpy(&sin->sin_addr, cached_phost_h_addr, cached_phost_h_length);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
extern int h_errno;
|
|
|
|
#if 0
|
|
|
|
fprintf (stderr, "=+= Fetching on '%s'\n", host);
|
|
|
|
#endif
|
|
|
|
phost = gethostbyname (host);
|
2013-03-09 18:59:42 -06:00
|
|
|
if (!phost)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
2013-03-09 18:59:42 -06:00
|
|
|
if (www2Trace)
|
2010-03-08 04:55:21 -06:00
|
|
|
fprintf
|
2013-03-09 18:59:42 -06:00
|
|
|
(stderr,
|
2010-03-08 04:55:21 -06:00
|
|
|
"HTTPAccess: Can't find internet node name `%s'.\n",host);
|
|
|
|
#endif
|
|
|
|
return -1; /* Fail? */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free previously cached strings. */
|
|
|
|
if (cached_host) {
|
|
|
|
free (cached_host);
|
|
|
|
cached_host=NULL;
|
|
|
|
}
|
|
|
|
if (cached_phost_h_addr) {
|
|
|
|
free (cached_phost_h_addr);
|
|
|
|
cached_phost_h_addr=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cache new stuff. */
|
|
|
|
cached_host = strdup (host);
|
|
|
|
cached_phost_h_addr = calloc (phost->h_length + 1, 1);
|
|
|
|
memcpy (cached_phost_h_addr, phost->h_addr, phost->h_length);
|
|
|
|
#if 0
|
|
|
|
cached_phost_h_addr = strdup (phost->h_addr);
|
|
|
|
#endif
|
|
|
|
cached_phost_h_length = phost->h_length;
|
|
|
|
|
|
|
|
memcpy(&sin->sin_addr, phost->h_addr, phost->h_length);
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
#ifndef DISABLE_TRACE
|
2013-03-09 18:59:42 -06:00
|
|
|
if (www2Trace)
|
|
|
|
fprintf(stderr,
|
2010-03-08 04:55:21 -06:00
|
|
|
"TCP: Parsed address as port %d, IP address %d.%d.%d.%d\n",
|
|
|
|
(int)ntohs(sin->sin_port),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+0),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+1),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+2),
|
|
|
|
(int)*((unsigned char *)(&sin->sin_addr)+3));
|
|
|
|
#endif
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
return 0; /* OK */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Derive the name of the host on which we are
|
|
|
|
** -------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
#ifdef __STDC__
|
|
|
|
PRIVATE void get_host_details(void)
|
|
|
|
#else
|
|
|
|
PRIVATE void get_host_details()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MAXHOSTNAMELEN
|
|
|
|
#define MAXHOSTNAMELEN 64 /* Arbitrary limit */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
{
|
|
|
|
char name[MAXHOSTNAMELEN+1]; /* The name of this host */
|
|
|
|
#ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
|
|
|
|
struct hostent * phost; /* Pointer to host -- See netdb.h */
|
|
|
|
#endif
|
|
|
|
int namelength = sizeof(name);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
if (hostname) return; /* Already done */
|
|
|
|
gethostname(name, namelength); /* Without domain */
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (www2Trace) {
|
|
|
|
fprintf(stderr, "TCP: Local host name is %s\n", name);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
StrAllocCopy(hostname, name);
|
|
|
|
|
|
|
|
#ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
|
|
|
|
phost=gethostbyname(name); /* See netdb.h */
|
|
|
|
if (!phost) {
|
|
|
|
#ifndef DISABLE_TRACE
|
2013-03-09 18:59:42 -06:00
|
|
|
if (www2Trace) fprintf(stderr,
|
2010-03-08 04:55:21 -06:00
|
|
|
"TCP: Can't find my own internet node address for `%s'!!\n",
|
|
|
|
name);
|
|
|
|
#endif
|
|
|
|
return; /* Fail! */
|
|
|
|
}
|
|
|
|
StrAllocCopy(hostname, phost->h_name);
|
|
|
|
memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (www2Trace) fprintf(stderr, " Name server says that I am `%s' = %s\n",
|
|
|
|
hostname, HTInetString(&HTHostAddress));
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __STDC__
|
|
|
|
PUBLIC char * HTHostName(void)
|
|
|
|
#else
|
|
|
|
PUBLIC char * HTHostName()
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
get_host_details();
|
|
|
|
return hostname;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SOCKS
|
|
|
|
struct in_addr SOCKS_ftpsrv;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
PUBLIC int HTDoConnect (char *url, char *protocol, int default_port, int *s)
|
|
|
|
{
|
|
|
|
struct sockaddr_in soc_address;
|
|
|
|
struct sockaddr_in *sin = &soc_address;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
/* Set up defaults: */
|
|
|
|
sin->sin_family = AF_INET;
|
|
|
|
sin->sin_port = htons(default_port);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* Get node name and optional port number: */
|
|
|
|
{
|
|
|
|
char line[256];
|
|
|
|
char *p1 = HTParse(url, "", PARSE_HOST);
|
|
|
|
int status;
|
|
|
|
|
|
|
|
sprintf (line, "Looking up %s.", p1);
|
|
|
|
HTProgress (line);
|
|
|
|
|
|
|
|
status = HTParseInet(sin, p1);
|
2013-03-09 18:59:42 -06:00
|
|
|
if (status)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
sprintf (line, "Unable to locate remote host %s.", p1);
|
|
|
|
HTProgress(line);
|
|
|
|
free (p1);
|
|
|
|
return HT_NO_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf (line, "Making %s connection to %s.", protocol, p1);
|
|
|
|
HTProgress (line);
|
|
|
|
free (p1);
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* Now, let's get a socket set up from the server for the data: */
|
2010-03-08 04:55:21 -06:00
|
|
|
*s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
|
|
|
|
|
|
#ifdef SOCKS
|
|
|
|
/* SOCKS can't yet deal with non-blocking connect request */
|
|
|
|
HTClearActiveIcon();
|
|
|
|
status = Rconnect(*s, (struct sockaddr*)&soc_address, sizeof(soc_address));
|
|
|
|
if ((status == 0) && (strcmp(protocol, "FTP") == 0))
|
|
|
|
SOCKS_ftpsrv.s_addr = soc_address.sin_addr.s_addr;
|
|
|
|
{
|
|
|
|
int intr;
|
|
|
|
intr = HTCheckActiveIcon(1);
|
|
|
|
if (intr)
|
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (www2Trace)
|
|
|
|
fprintf (stderr, "*** INTERRUPTED in middle of connect.\n");
|
|
|
|
#endif
|
|
|
|
status = HT_INTERRUPTED;
|
|
|
|
errno = EINTR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
#else /* SOCKS not defined */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make the socket non-blocking, so the connect can be canceled.
|
|
|
|
* This means that when we issue the connect we should NOT
|
|
|
|
* have to wait for the accept on the other end.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int val = 1;
|
|
|
|
char line[256];
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
ret = ioctl(*s, FIONBIO, &val);
|
|
|
|
if (ret == -1)
|
|
|
|
{
|
|
|
|
sprintf (line, "Could not make connection non-blocking.");
|
|
|
|
HTProgress(line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HTClearActiveIcon();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Issue the connect. Since the server can't do an instantaneous accept
|
|
|
|
* and we are non-blocking, this will almost certainly return a negative
|
|
|
|
* status.
|
|
|
|
*/
|
|
|
|
status = connect(*s, (struct sockaddr*)&soc_address, sizeof(soc_address));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* According to the Sun man page for connect:
|
|
|
|
* EINPROGRESS The socket is non-blocking and the con-
|
|
|
|
* nection cannot be completed immediately.
|
|
|
|
* It is possible to select(2) for comple-
|
|
|
|
* tion by selecting the socket for writ-
|
|
|
|
* ing.
|
|
|
|
* According to the Motorola SVR4 man page for connect:
|
|
|
|
* EAGAIN The socket is non-blocking and the con-
|
|
|
|
* nection cannot be completed immediately.
|
|
|
|
* It is possible to select for completion
|
|
|
|
* by selecting the socket for writing.
|
|
|
|
* However, this is only possible if the
|
|
|
|
* socket STREAMS module is the topmost
|
|
|
|
* module on the protocol stack with a
|
|
|
|
* write service procedure. This will be
|
|
|
|
* the normal case.
|
|
|
|
*/
|
|
|
|
#ifdef SVR4
|
|
|
|
if ((status < 0) && ((errno == EINPROGRESS)||(errno == EAGAIN)))
|
|
|
|
#else
|
|
|
|
if ((status < 0) && (errno == EINPROGRESS))
|
|
|
|
#endif /* SVR4 */
|
|
|
|
{
|
|
|
|
struct timeval timeout;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
while (ret <= 0)
|
|
|
|
{
|
|
|
|
fd_set writefds;
|
|
|
|
int intr;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
FD_ZERO(&writefds);
|
|
|
|
FD_SET(*s, &writefds);
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* linux (and some other os's, I think) clear timeout...
|
2010-03-08 04:55:21 -06:00
|
|
|
let's reset it every time. bjs */
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 100000;
|
|
|
|
|
|
|
|
#ifdef __hpux
|
|
|
|
ret = select(FD_SETSIZE, NULL, (int *)&writefds, NULL, &timeout);
|
|
|
|
#else
|
|
|
|
ret = select(FD_SETSIZE, NULL, &writefds, NULL, &timeout);
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* Again according to the Sun and Motorola man pagse for connect:
|
|
|
|
* EALREADY The socket is non-blocking and a previ-
|
|
|
|
* ous connection attempt has not yet been
|
|
|
|
* completed.
|
|
|
|
* Thus if the errno is NOT EALREADY we have a real error, and
|
|
|
|
* should break out here and return that error.
|
|
|
|
* Otherwise if it is EALREADY keep on trying to complete the
|
|
|
|
* connection.
|
|
|
|
*/
|
|
|
|
if ((ret < 0)&&(errno != EALREADY))
|
|
|
|
{
|
|
|
|
status = ret;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (ret > 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Extra check here for connection success, if we try to connect
|
|
|
|
* again, and get EISCONN, it means we have a successful
|
|
|
|
* connection.
|
|
|
|
*/
|
|
|
|
status = connect(*s, (struct sockaddr*)&soc_address,
|
|
|
|
sizeof(soc_address));
|
|
|
|
if ((status < 0)&&(errno == EISCONN))
|
|
|
|
{
|
|
|
|
status = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* The select says we aren't ready yet.
|
|
|
|
* Try to connect again to make sure. If we don't get EALREADY
|
|
|
|
* or EISCONN, something has gone wrong. Break out and report it.
|
|
|
|
* For some reason SVR4 returns EAGAIN here instead of EALREADY,
|
|
|
|
* even though the man page says it should be EALREADY.
|
|
|
|
*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = connect(*s, (struct sockaddr*)&soc_address,
|
|
|
|
sizeof(soc_address));
|
|
|
|
#ifdef SVR4
|
|
|
|
if ((status < 0)&&(errno != EALREADY)&&(errno != EAGAIN)&&
|
|
|
|
(errno != EISCONN))
|
|
|
|
#else
|
|
|
|
if ((status < 0)&&(errno != EALREADY)&&(errno != EISCONN))
|
|
|
|
#endif /* SVR4 */
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
intr = HTCheckActiveIcon(1);
|
|
|
|
if (intr)
|
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (www2Trace)
|
|
|
|
fprintf (stderr, "*** INTERRUPTED in middle of connect.\n");
|
|
|
|
#endif
|
|
|
|
status = HT_INTERRUPTED;
|
|
|
|
errno = EINTR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make the socket blocking again on good connect
|
|
|
|
*/
|
|
|
|
if (status >= 0)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int val = 0;
|
|
|
|
char line[256];
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
ret = ioctl(*s, FIONBIO, &val);
|
|
|
|
if (ret == -1)
|
|
|
|
{
|
|
|
|
sprintf (line, "Could not restore socket to blocking.");
|
|
|
|
HTProgress(line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Else the connect attempt failed or was interrupted.
|
|
|
|
* so close up the socket.
|
|
|
|
*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
close(*s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
#endif /* #ifdef SOCKS */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is so interruptible reads can be implemented cleanly. */
|
|
|
|
int HTDoRead (int fildes, void *buf, unsigned nbyte)
|
|
|
|
{
|
|
|
|
int ready, ret, intr;
|
|
|
|
fd_set readfds;
|
|
|
|
struct timeval timeout;
|
|
|
|
char *adtestbuf;
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
while (!ready)
|
|
|
|
{
|
|
|
|
FD_ZERO(&readfds);
|
|
|
|
FD_SET(fildes, &readfds);
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* linux (and some other os's, I think) clear timeout...
|
2010-03-08 04:55:21 -06:00
|
|
|
let's reset it every time. bjs */
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 100000;
|
|
|
|
|
|
|
|
#ifdef __hpux
|
|
|
|
ret = select(FD_SETSIZE, (int *)&readfds, NULL, NULL, &timeout);
|
|
|
|
#else
|
|
|
|
ret = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
|
|
|
|
#endif
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (ret > 0)
|
|
|
|
{
|
|
|
|
ready = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
intr = HTCheckActiveIcon(1);
|
|
|
|
if (intr)
|
|
|
|
{
|
|
|
|
return HT_INTERRUPTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = read (fildes, buf, nbyte);
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (httpTrace) {
|
|
|
|
adtestbuf = buf;
|
|
|
|
for (intr = 0; intr < ret; fprintf(stderr,"%c",adtestbuf[intr++]) ) ;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|