Annotation of libwww/Library/src/HTTCP.c, revision 2.24

1.1       timbl       1: /*                     Generic Communication Code              HTTCP.c
                      2: **                     ==========================
                      3: **
                      4: **     This code is in common between client and server sides.
                      5: **
                      6: **     16 Jan 92  TBL  Fix strtol() undefined on CMU Mach.
                      7: **     25 Jun 92  JFG  Added DECNET option through TCP socket emulation.
2.7       duns        8: **     13 Sep 93  MD   Added correct return of vmserrorno for HTInetStatus.
                      9: **                     Added decoding of vms error message for MULTINET.
2.13      frystyk    10: **     31 May 94  HF   Added cache on host id's; now use inet_ntoa() to
                     11: **                     HTInetString and some other fixes. Added HTDoConnect
                     12: **                     and HTDoAccept
1.1       timbl      13: */
                     14: 
2.23      duns       15: #ifndef VMS
2.19      frystyk    16: #include <pwd.h>
2.23      duns       17: #endif /* not VMS */
                     18: 
2.13      frystyk    19: #include "tcp.h"               /* Defines SHORT_NAMES if necessary */
2.19      frystyk    20: 
2.13      frystyk    21: #include "HTUtils.h"
                     22: #include "HTAtom.h"
                     23: #include "HTList.h"
                     24: #include "HTParse.h"
                     25: #include "HTAccess.h"
                     26: #include "HTError.h"
2.24    ! frystyk    27: #include "HTTCP.h"                                      /* Implemented here */
1.1       timbl      28: 
2.23      duns       29: #ifdef VMS 
                     30: #include "HTVMSUtils.h"
                     31: #endif /* VMS */
                     32: 
1.1       timbl      33: #ifdef SHORT_NAMES
                     34: #define HTInetStatus           HTInStat
2.12      luotonen   35: #define HTErrnoString          HTErrnoS
1.1       timbl      36: #define HTInetString           HTInStri
                     37: #define HTParseInet            HTPaInet
                     38: #endif
                     39: 
2.8       luotonen   40: 
2.11      duns       41: /* VMS stuff */
                     42: #ifdef VMS
                     43: #ifndef MULTINET
                     44: #define FD_SETSIZE 32
                     45: #else /* Multinet */
                     46: #define FD_SETSIZE 256
                     47: #endif /* Multinet */
                     48: #endif /* VMS */
                     49: 
2.13      frystyk    50: /* Macros and other defines */
2.24    ! frystyk    51: /* x seconds penalty on a multi-homed host if IP-address is down */
        !            52: #define TCP_PENALTY            1200
        !            53: 
        !            54: /* x seconds penalty on a multi-homed host if IP-address is timed out */
        !            55: #define TCP_DELAY              600
        !            56: 
        !            57: /* Max number of non-blocking accepts */
2.13      frystyk    58: #define MAX_ACCEPT_POLL                30
                     59: #define FCNTL(r, s, t)         fcntl(r, s, t)
                     60: 
2.18      frystyk    61: #ifndef RESOLV_CONF
                     62: #define RESOLV_CONF "/etc/resolv.conf"
                     63: #endif
                     64: 
2.13      frystyk    65: /* Globals */
                     66: PUBLIC unsigned int    HTConCacheSize = 512;    /* Number of cached servers */
                     67: 
                     68: /* Type definitions and global variables etc. local to this module */
                     69: 
                     70: /* This structure is a cache of hosts to whom we have connected over time.
                     71:    The structure contains the necessary parts from hostent. For Internet host
                     72:    hostent->h_addr_list is not an array of char pointers but an array of 
                     73:    pointers of type in_addr. */
                     74: typedef struct _host_info {
                     75:     HTAtom *           hostname;                   /* Official name of host */
                     76:     int                        hits;           /* Total number of hits on this host */
                     77:     int                        addrlength;            /* Length of address in bytes */
2.24    ! frystyk    78:     int                        homes;         /* Number of IP addresses on the host */
2.13      frystyk    79:     int                        offset;         /* Offset value of active IP address */
                     80:     char **            addrlist;      /* List of addresses from name server */
                     81:     float *            weight;                    /* Weight on each address */
                     82: } host_info;
                     83: 
                     84: PRIVATE char *hostname = NULL;                     /* The name of this host */
2.19      frystyk    85: PRIVATE char *mailaddress = NULL;                   /* Current mail address */
2.13      frystyk    86: PRIVATE HTList *hostcache = NULL;  /* List of servers that we have talked to */
                     87: PRIVATE unsigned int HTCacheSize = 0;              /* Current size of cache */
2.11      duns       88: 
2.13      frystyk    89: /* ------------------------------------------------------------------------- */
1.1       timbl      90: 
                     91: /*     Encode INET status (as in sys/errno.h)                    inet_status()
                     92: **     ------------------
                     93: **
                     94: ** On entry,
                     95: **     where           gives a description of what caused the error
                     96: **     global errno    gives the error number in the unix way.
                     97: **
                     98: ** On return,
                     99: **     returns         a negative status in the unix way.
                    100: */
                    101: #ifndef PCNFS
2.7       duns      102: #ifdef VMS
2.10      duns      103: #ifndef __DECC
1.1       timbl     104: extern int uerrno;     /* Deposit of error info (as per errno.h) */
2.7       duns      105: extern volatile noshare int socket_errno; /* socket VMS error info 
                    106:                                              (used for translation of vmserrno) */
1.1       timbl     107: extern volatile noshare int vmserrno;  /* Deposit of VMS error info */
                    108: extern volatile noshare int errno;  /* noshare to avoid PSECT conflict */
2.10      duns      109: #endif /* not DECC */
2.11      duns      110: #endif /* VMS */
                    111: 
1.1       timbl     112: #ifndef errno
                    113: extern int errno;
                    114: #endif /* errno */
                    115: 
                    116: #ifndef VM
2.7       duns      117: #ifndef VMS
1.1       timbl     118: #ifndef NeXT
                    119: #ifndef THINK_C
                    120: extern char *sys_errlist[];            /* see man perror on cernvax */
                    121: extern int sys_nerr;
                    122: #endif  /* think c */
                    123: #endif /* NeXT */
2.7       duns      124: #endif  /* VMS */
1.1       timbl     125: #endif /* VM */
                    126: 
                    127: #endif /* PCNFS */
                    128: 
2.12      luotonen  129: 
                    130: /*
                    131:  *     Returns the string equivalent of the current errno.
                    132:  */
                    133: PUBLIC CONST char * HTErrnoString NOARGS
1.1       timbl     134: {
2.11      duns      135: #ifndef VMS
2.7       duns      136: 
1.1       timbl     137: #ifdef VM
2.12      luotonen  138:     return "(Error number not translated)";    /* What Is the VM equiv? */
1.1       timbl     139: #define ER_NO_TRANS_DONE
                    140: #endif
2.12      luotonen  141: 
                    142: #if defined(NeXT) || defined(THINK_C)
                    143:     return strerror(errno);
1.1       timbl     144: #define ER_NO_TRANS_DONE
                    145: #endif
2.12      luotonen  146: 
                    147: #ifndef ER_NO_TRANS_DONE
                    148:     return (errno < sys_nerr ? sys_errlist[errno] : "Unknown error");
1.1       timbl     149: #endif
                    150: 
2.12      luotonen  151: #else /* VMS */
                    152: 
                    153:     static char buf[60];
                    154:     sprintf(buf,"Unix errno = %ld dec, VMS error = %lx hex",errno,vaxc$errno);
                    155:     return buf;
                    156: 
1.1       timbl     157: #endif
2.12      luotonen  158: }
                    159: 
                    160: 
                    161: /*     Report Internet Error
                    162: **     ---------------------
                    163: */
                    164: PUBLIC int HTInetStatus ARGS1(char *, where)
                    165: {
                    166: #ifndef VMS
                    167: 
                    168:     CTRACE(tfp,
                    169:           "TCP errno... %d after call to %s() failed.\n............ %s\n",
                    170:           errno, where, HTErrnoString());
1.1       timbl     171: 
2.11      duns      172: #else /* VMS */
2.12      luotonen  173: 
2.11      duns      174:     CTRACE(tfp, "         Unix error number          = %ld dec\n", errno);
                    175:     CTRACE(tfp, "         VMS error                  = %lx hex\n", vaxc$errno);
2.12      luotonen  176: 
2.11      duns      177: #ifdef MULTINET
                    178:     CTRACE(tfp, "         Multinet error             = %lx hex\n", socket_errno); 
2.23      duns      179:     CTRACE(tfp, "         Error String               = %s\n", vms_errno_string());
2.11      duns      180: #endif /* MULTINET */
2.12      luotonen  181: 
2.11      duns      182: #endif /* VMS */
2.7       duns      183: 
                    184: #ifdef VMS
2.11      duns      185:     /* errno happen to be zero if vaxc$errno <> 0 */
                    186:     return -vaxc$errno;
2.7       duns      187: #else
1.1       timbl     188:     return -errno;
2.7       duns      189: #endif
1.1       timbl     190: }
                    191: 
                    192: 
                    193: /*     Parse a cardinal value                                 parse_cardinal()
                    194: **     ----------------------
                    195: **
                    196: ** On entry,
                    197: **     *pp         points to first character to be interpreted, terminated by
                    198: **                 non 0:9 character.
                    199: **     *pstatus    points to status already valid
                    200: **     maxvalue    gives the largest allowable value.
                    201: **
                    202: ** On exit,
                    203: **     *pp         points to first unread character
                    204: **     *pstatus    points to status updated iff bad
                    205: */
                    206: 
                    207: PUBLIC unsigned int HTCardinal ARGS3
                    208:        (int *,         pstatus,
                    209:        char **,        pp,
                    210:        unsigned int,   max_value)
                    211: {
                    212:     int   n;
                    213:     if ( (**pp<'0') || (**pp>'9')) {       /* Null string is error */
                    214:        *pstatus = -3;  /* No number where one expeceted */
                    215:        return 0;
                    216:     }
                    217: 
                    218:     n=0;
                    219:     while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
                    220: 
                    221:     if (n>max_value) {
                    222:        *pstatus = -4;  /* Cardinal outside range */
                    223:        return 0;
                    224:     }
                    225: 
                    226:     return n;
                    227: }
                    228: 
2.19      frystyk   229: /* ------------------------------------------------------------------------- */
                    230: /*                          HOST CACHE MANAGEMENT                           */
                    231: /* ------------------------------------------------------------------------- */
1.1       timbl     232: 
2.13      frystyk   233: /*                                                     HTTCPCacheRemoveElement
                    234: **
                    235: **     Remove the element specified from the cache
                    236: */
                    237: PRIVATE void HTTCPCacheRemoveElement ARGS1(host_info *, element)
                    238: {
                    239:     if (!hostcache) {
                    240:         if (TRACE)
                    241:             fprintf(stderr, "HostCache... Remove not done, no cache\n");
                    242:         return;
                    243:     }
                    244:     if (TRACE) fprintf(stderr, "HostCache... Remove `%s' from cache\n",
                    245:                       HTAtom_name(element->hostname));
                    246:     HTList_removeObject(hostcache, element);
2.22      frystyk   247:     if (*element->addrlist)
                    248:        free(*element->addrlist);
2.13      frystyk   249:     if (element->addrlist)
                    250:        free(element->addrlist);
                    251:     if (element->weight)
                    252:        free(element->weight);
                    253:     free(element);
                    254: }
                    255: 
                    256: 
                    257: /*                                                     HTTCPCacheRemoveHost
                    258: **
                    259: **     Removes the corresponding entrance in the cache
                    260: */
                    261: PRIVATE void HTTCPCacheRemoveHost ARGS1(char *, host)
                    262: {
                    263:     HTAtom *hostatom = HTAtom_for(host);
                    264:     HTList *cur = hostcache;
                    265:     host_info *pres = NULL;
                    266:     if (!hostcache) {
                    267:        fprintf(stderr, "HostCache... Remove host not done, no cache\n");
                    268:        return;
                    269:     }
                    270:     while ((pres = (host_info *) HTList_nextObject(cur)) != NULL) {
                    271:        if (pres->hostname == hostatom) {
                    272:            break;
                    273:        }
                    274:     }
                    275:     if (pres)
                    276:        HTTCPCacheRemoveElement(pres);
                    277: }
                    278: 
                    279: 
                    280: /*                                                     HTTCPCacheGarbage
                    281: **
                    282: **     Remove the element with the lowest hit rate
                    283: */
                    284: PRIVATE void HTTCPCacheGarbage NOARGS
                    285: {
                    286:     HTList *cur = hostcache;
                    287:     host_info *pres, *worst_match = NULL;
                    288:     unsigned int worst_hits = 30000;             /* Should use UINT_MAX :-( */
                    289:     if (!hostcache) {
                    290:        if (TRACE)
                    291:            fprintf(stderr, "HostCache... Garbage collection not done, no cache\n");
                    292:        return;
                    293:     }
                    294: 
                    295:     /* Seek for worst element */
                    296:     while ((pres = (host_info *) HTList_nextObject(cur))) {
                    297:        if (!worst_match || pres->hits <= worst_hits) {
                    298:            worst_match = pres;
                    299:            worst_hits = pres->hits;
                    300:        }
                    301:     }
                    302:     if (worst_match)
                    303:        HTTCPCacheRemoveElement(worst_match);
                    304: }
                    305: 
                    306: 
                    307: /*                                                     HTTCPCacheAddElement
                    308: **
                    309: **     Add an element to the cache of visited hosts. Note that this function
                    310: **     requires the system implemented structure hostent and not our own
2.24    ! frystyk   311: **     host_info. The homes variable indicates the number of
        !           312: **     IP addresses found.
2.13      frystyk   313: **
                    314: **      Returns new element if OK NULL if error
                    315: */
                    316: PRIVATE host_info *HTTCPCacheAddElement ARGS2(HTAtom *, host,
                    317:                                              struct hostent *, element)
                    318: {
                    319:     host_info *new;
2.22      frystyk   320:     char *addr;
                    321:     char **index = element->h_addr_list;
                    322:     int cnt = 1;
2.13      frystyk   323:     if (!host || !element) {
                    324:        if (TRACE)
                    325:            fprintf(stderr, "HostCache... Bad argument to add to cache\n");
                    326:        return NULL;
                    327:     }
2.22      frystyk   328:     while(*index++)
                    329:        cnt++;
2.13      frystyk   330:     if ((new = (host_info *) calloc(1, sizeof(host_info))) == NULL ||
2.22      frystyk   331:        (new->addrlist = (char **) calloc(1, cnt*sizeof(char*))) == NULL ||
                    332:        (addr = (char *) calloc(1, cnt*element->h_length)) == NULL)
2.18      frystyk   333:        outofmem(__FILE__, "HTTCPCacheAddElement");
2.13      frystyk   334:     new->hostname = host;
2.22      frystyk   335:     index = element->h_addr_list;
                    336:     cnt = 0;
                    337:     while (*index) {
                    338:        *(new->addrlist+cnt) = addr+cnt*element->h_length;
                    339:        memcpy((void *) *(new->addrlist+cnt++), *index++, element->h_length);
                    340:     }
2.24    ! frystyk   341:     new->homes = cnt;
        !           342:     if ((new->weight = (float *) calloc(new->homes, sizeof(float))) == NULL)
        !           343:        outofmem(__FILE__, "HTTCPCacheAddElement");
        !           344: 
2.13      frystyk   345:     new->addrlength = element->h_length;
                    346:     if (!hostcache)
                    347:        hostcache = HTList_new();
                    348: 
                    349:     if (TRACE) {
2.24    ! frystyk   350:        if (new->homes == 1)
        !           351:            fprintf(stderr, "HostCache... Adding single-homed host `%s'\n",
        !           352:                    HTAtom_name(host));
2.13      frystyk   353:        else
2.24    ! frystyk   354:            fprintf(stderr, "HostCache... Adding host `%s' with %d homes\n",
        !           355:                    HTAtom_name(host), new->homes);
2.13      frystyk   356:     }
                    357:     HTList_addObject(hostcache, (void *) new);
                    358:     HTCacheSize++;                             /* Update number of elements */
                    359:     return new;
                    360: }
                    361: 
                    362: 
                    363: /*                                                                   HTTCPAddrWeights
                    364: **
                    365: **     This function calculates the weights of the different IP addresses
                    366: **     on a multi homed host. Each weight is calculated as
                    367: **
                    368: **             w(n+1) = w(n)*a + (1-a) * deltatime
                    369: **             a = exp(-1/Neff)
                    370: **             Neff is the effective number of samples used
                    371: **             deltatime is time spend on making a connection
                    372: **
                    373: **     A short window (low Neff) gives a high sensibility, but this is
                    374: **     required as we can't expect a lot of data to test on.
                    375: **
                    376: */
                    377: PUBLIC void HTTCPAddrWeights ARGS2(char *, host, time_t, deltatime)
                    378: {
                    379:     HTAtom *hostatom = HTAtom_for(host);
                    380:     HTList *cur = hostcache;
                    381:     host_info *pres = NULL;
                    382:     if (!hostcache) {
                    383:        fprintf(stderr, "HostCache... Weights not calculated, no cache\n");
                    384:        return;
                    385:     }
2.24    ! frystyk   386:     /* Skip any port number from host name */
        !           387:     if (strchr(host, ':')) {
        !           388:        char *newhost = NULL;
        !           389:        char *strptr;
        !           390:        StrAllocCopy(newhost, host);
        !           391:        strptr = strchr(newhost, ':');
        !           392:        *strptr = '\0';
        !           393:        hostatom = HTAtom_for(newhost);
        !           394:        free(newhost);
        !           395:     } else
        !           396:        hostatom = HTAtom_for(host);
        !           397:     
2.13      frystyk   398:     while ((pres = (host_info *) HTList_nextObject(cur)) != NULL) {
                    399:        if (pres->hostname == hostatom) {
                    400:            break;
                    401:        }
                    402:     }
2.24    ! frystyk   403:     if (pres) {
2.13      frystyk   404:        int cnt;
2.14      frystyk   405:        CONST float passive = 0.9;        /* Factor for all passive IP_addrs */
2.13      frystyk   406: #if 0
2.14      frystyk   407:        CONST int Neff = 3;
                    408:        CONST float alpha = exp(-1.0/Neff);
2.13      frystyk   409: #else
2.24    ! frystyk   410:        CONST float alpha = 0.716531310574;     /* Doesn't need the math lib */
2.13      frystyk   411: #endif
2.24    ! frystyk   412:        for (cnt=0; cnt<pres->homes; cnt++) {
2.13      frystyk   413:            if (cnt == pres->offset) {
                    414:                *(pres->weight+pres->offset) = *(pres->weight+pres->offset)*alpha + (1.0-alpha)*deltatime;
                    415:            } else {
                    416:                *(pres->weight+cnt) = *(pres->weight+cnt) * passive;
                    417:            }
2.24    ! frystyk   418:            if (PROT_TRACE)
        !           419:                fprintf(stderr, "AddrWeights. Home %d has weight %4.2f\n", cnt,
        !           420:                        *(pres->weight+cnt));
2.13      frystyk   421:        }
                    422:     } else if (TRACE) {
2.24    ! frystyk   423:        fprintf(stderr, "HostCache... Weights not calculated, host not found in cache: `%s\'\n", host);
2.13      frystyk   424:     }
                    425: }
                    426: 
2.19      frystyk   427: /* ------------------------------------------------------------------------- */
                    428: /*                          HOST NAME FUNCTIONS                             */
                    429: /* ------------------------------------------------------------------------- */
                    430: 
                    431: #ifndef DECNET  /* Function only used below for a trace message */
                    432: 
                    433: /*     Produce a string for an Internet address
                    434: **     ----------------------------------------
                    435: **
                    436: ** On exit,
                    437: **     returns a pointer to a static string which must be copied if
                    438: **             it is to be kept.
                    439: */
                    440: 
                    441: PUBLIC CONST char * HTInetString ARGS1(SockA *, sin)
                    442: {
                    443: #if 0
2.24    ! frystyk   444:     /* This dumps core on some Sun systems :-(. The problem is now, that 
2.19      frystyk   445:        the current implememtation only works for IP-addresses and not in
                    446:        other address spaces. */
                    447:     return inet_ntoa(sin->sin_addr);
                    448: #endif
                    449:     static char string[16];
                    450:     sprintf(string, "%d.%d.%d.%d",
                    451:            (int)*((unsigned char *)(&sin->sin_addr)+0),
                    452:            (int)*((unsigned char *)(&sin->sin_addr)+1),
                    453:            (int)*((unsigned char *)(&sin->sin_addr)+2),
                    454:            (int)*((unsigned char *)(&sin->sin_addr)+3));
                    455:     return string;
                    456: }
                    457: #endif /* Decnet */
                    458: 
2.13      frystyk   459: 
                    460: /*                                                          HTGetHostByName
                    461: **
                    462: **     Searched first the local cache then asks the DNS for an address of
                    463: **     the host specified.
                    464: **
2.24    ! frystyk   465: **      Returns:       >0 if OK the number of homes are returned
        !           466: **                     -1 if error
2.13      frystyk   467: */
2.24    ! frystyk   468: PUBLIC int HTGetHostByName ARGS3(char *, host, SockA *, sin,
        !           469:                                 BOOL, use_cur)
2.13      frystyk   470: {
                    471:     HTAtom *hostatom = HTAtom_for(host);
                    472:     host_info *pres = NULL;
                    473:     if (!hostcache)
                    474:        hostcache = HTList_new();                      /* First time through */
                    475:     else {
                    476:        HTList *cur = hostcache;                             /* Search cache */
                    477:        while ((pres = (host_info *) HTList_nextObject(cur)) != NULL) {
                    478:            if (pres->hostname == hostatom) {
                    479:                if (TRACE)
2.18      frystyk   480:                    fprintf(stderr, "HostByName.. Host `%s\' found in cache.\n", host);
2.13      frystyk   481:                break;
                    482:            }
                    483:        }
                    484:     }
                    485:     
                    486:     /* If the host was not found in the cache, then do gethostbyname.
2.24    ! frystyk   487:        If we are talking to a multi homed host then take the IP address with
        !           488:        the lowest weight. If `use_cur'=YES then use current IP-address */
2.13      frystyk   489:     if (pres) {
2.24    ! frystyk   490:        if (pres->homes > 1 && !use_cur) {
2.13      frystyk   491:            int cnt;
                    492:            float best_weight = 1e30;               /* Should be FLT_MAX :-( */
2.24    ! frystyk   493:            for (cnt=0; cnt<pres->homes; cnt++) {
2.13      frystyk   494:                if (*(pres->weight+cnt) < best_weight) {
                    495:                    best_weight = *(pres->weight+cnt);
                    496:                    pres->offset = cnt;
                    497:                }
                    498:            }
2.24    ! frystyk   499:        }
        !           500:        pres->hits++;            /* Update total number of hits on this host */
2.13      frystyk   501:     } else {                                           /* Go and ask for it */
                    502:        struct hostent *hostelement;                          /* see netdb.h */
                    503: #ifdef MVS     /* Outstanding problem with crash in MVS gethostbyname */
                    504:        if (TRACE)
2.24    ! frystyk   505:            fprintf(stderr, "HTTCP on MVS gethostbyname(%s)\n", host);
2.13      frystyk   506: #endif
                    507:        if ((hostelement = gethostbyname(host)) == NULL) {
2.18      frystyk   508:            if (TRACE) fprintf(stderr, "HostByName.. Can't find internet node name `%s'.\n", host);
2.13      frystyk   509:            return -1;
                    510:        }
                    511:        
                    512:        /* Add element to the cache and maybe do garbage collection */
                    513:        if (HTCacheSize >= HTConCacheSize)
                    514:            HTTCPCacheGarbage();
                    515:        if ((pres = HTTCPCacheAddElement(hostatom, hostelement)) == NULL) {
                    516:            return -1;
                    517:        }
                    518:     }
                    519:     
                    520:     /* Update socket structure using the element with the lowest weight. On
                    521:        single homed hosts it means the first value */
                    522:     memcpy(&sin->sin_addr, *(pres->addrlist+pres->offset), pres->addrlength);
2.24    ! frystyk   523:     return pres->homes;
2.13      frystyk   524: }
                    525: 
                    526: 
2.19      frystyk   527: /*
                    528: **     Get host name of the machine on the other end of a socket.
                    529: **
                    530: */
                    531: PUBLIC char * HTGetHostBySock ARGS1(int, soc)
                    532: {
                    533:     struct sockaddr addr;
                    534:     int len = sizeof(struct sockaddr);
                    535:     struct in_addr *iaddr;
                    536:     struct hostent * phost;            /* Pointer to host -- See netdb.h */
                    537:     char *name = NULL;
                    538: 
                    539: #ifdef DECNET  /* Decnet ain't got no damn name server 8#OO */
                    540:     return NULL;
                    541: #else
                    542:     if (getpeername(soc, &addr, &len) < 0)
                    543:        return NULL;
                    544: 
                    545:     iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
                    546:     phost=gethostbyaddr((char*)iaddr,
                    547:                        sizeof(struct in_addr),
                    548:                        AF_INET);
                    549:     if (!phost) {
                    550:        if (TRACE) fprintf(stderr,
                    551:                           "TCP......... Can't find internet node name for peer!!\n");
                    552:        return NULL;
                    553:     }
                    554:     StrAllocCopy(name, phost->h_name);
                    555:     if (TRACE) fprintf(stderr, "TCP......... Peer name is `%s'\n", name);
                    556: 
                    557:     return name;
                    558: 
                    559: #endif /* not DECNET */
                    560: }
                    561: 
                    562: 
1.1       timbl     563: /*     Parse a network node address and port
                    564: **     -------------------------------------
                    565: **
                    566: ** On entry,
                    567: **     str     points to a string with a node name or number,
                    568: **             with optional trailing colon and port number.
                    569: **     sin     points to the binary internet or decnet address field.
                    570: **
2.24    ! frystyk   571: ** On exit,    -1      If error
        !           572: **             >0      If OK the number of homes on the host
1.1       timbl     573: **     *sin    is filled in. If no port is specified in str, that
                    574: **             field is left unchanged in *sin.
2.13      frystyk   575: **
                    576: ** NOTE:       It is assumed that any portnumber and numeric host address
                    577: **             is given in decimal notation. Separation character is '.'
1.1       timbl     578: */
2.24    ! frystyk   579: PUBLIC int HTParseInet ARGS3(SockA *, sin, CONST char *, str,
        !           580:                             BOOL, use_cur)
1.1       timbl     581: {
2.13      frystyk   582:     char *host = NULL;
2.24    ! frystyk   583:     int status = 0;
2.13      frystyk   584:     StrAllocCopy(host, str);                 /* Take a copy we can mutilate */
1.1       timbl     585: 
2.13      frystyk   586:     /* Parse port number if present. */    
                    587:     {
                    588:        char *port;
                    589:        if ((port=strchr(host, ':'))) {
                    590:            *port++ = 0;                                    /* Chop off port */
                    591:            if (isdigit(*port)) {
1.1       timbl     592: #ifdef DECNET
2.13      frystyk   593:                sin->sdn_objnum = (unsigned char)(strtol(port, (char**)0, 10));
                    594: #else /* Internet */
                    595:                sin->sin_port = htons(atol(port));
1.1       timbl     596: #endif
2.13      frystyk   597:            } else {
2.24    ! frystyk   598:                if (PROT_TRACE)
        !           599:                    fprintf(stderr, "ParseInet... No port indicated\n");
        !           600:                free(host);
        !           601:                return -1;
2.13      frystyk   602:            }
1.1       timbl     603:        }
2.13      frystyk   604:     }
1.1       timbl     605: 
2.13      frystyk   606:     /* Parse Internet host */
1.1       timbl     607: #ifdef DECNET
                    608:     /* read Decnet node name. @@ Should know about DECnet addresses, but it's
                    609:        probably worth waiting until the Phase transition from IV to V. */
                    610: 
                    611:     sin->sdn_nam.n_len = min(DN_MAXNAML, strlen(host));  /* <=6 in phase 4 */
                    612:     strncpy (sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
                    613: 
                    614:     if (TRACE) fprintf(stderr,  
                    615:        "DECnet: Parsed address as object number %d on host %.6s...\n",
                    616:                      sin->sdn_objnum, host);
                    617: 
2.13      frystyk   618: #else /* Internet */
1.1       timbl     619: 
2.13      frystyk   620:     /* Parse host number if present */
                    621:     {
                    622:        BOOL numeric = YES;
                    623:        char *strptr = host;
                    624:        while (*strptr) {
                    625:            if (!isdigit(*strptr) && *strptr != '.') {
                    626:                numeric = NO;
                    627:                break;
                    628:            }
                    629:            ++strptr;
                    630:        }
                    631:        if (numeric) {
                    632:            sin->sin_addr.s_addr = inet_addr(host);       /* See arpa/inet.h */
                    633:        } else {
2.24    ! frystyk   634:            if ((status = HTGetHostByName(host, sin, use_cur)) < 0) {
2.13      frystyk   635:                free(host);
                    636:                return -1;
                    637:            }
                    638:        }
                    639:        if (TRACE) {
                    640:            fprintf(stderr, "ParseInet... Parsed address as port %d on %s\n",
                    641:                    (int) ntohs(sin->sin_port),
                    642:                    HTInetString(sin));
1.1       timbl     643:        }
                    644:     }
                    645: #endif  /* Internet vs. Decnet */
2.13      frystyk   646:     free(host);
2.24    ! frystyk   647:     return status;
1.1       timbl     648: }
                    649: 
                    650: 
2.16      frystyk   651: #ifdef OLD_CODE
1.1       timbl     652: /*     Derive the name of the host on which we are
                    653: **     -------------------------------------------
                    654: **
                    655: */
2.8       luotonen  656: PRIVATE void get_host_details NOARGS
1.1       timbl     657: 
                    658: #ifndef MAXHOSTNAMELEN
                    659: #define MAXHOSTNAMELEN 64              /* Arbitrary limit */
                    660: #endif
                    661: 
                    662: {
                    663:     char name[MAXHOSTNAMELEN+1];       /* The name of this host */
                    664:     struct hostent * phost;            /* Pointer to host -- See netdb.h */
                    665:     int namelength = sizeof(name);
                    666:     
                    667:     if (hostname) return;              /* Already done */
                    668:     gethostname(name, namelength);     /* Without domain */
2.18      frystyk   669:     if (TRACE) fprintf(stderr, "TCP......... Local host name is %s\n", name);
1.1       timbl     670:     StrAllocCopy(hostname, name);
                    671: 
                    672: #ifndef DECNET  /* Decnet ain't got no damn name server 8#OO */
                    673:     phost=gethostbyname(name);         /* See netdb.h */
                    674:     if (!phost) {
                    675:        if (TRACE) fprintf(stderr, 
2.9       luotonen  676:                "TCP......... Can't find my own internet node address for `%s'!!\n",
1.1       timbl     677:                name);
                    678:        return;  /* Fail! */
                    679:     }
                    680:     StrAllocCopy(hostname, phost->h_name);
2.18      frystyk   681:     if (TRACE)
                    682:        fprintf(stderr, "TCP......... Full local host name is %s\n", hostname);
2.8       luotonen  683: 
                    684: #ifdef NEED_HOST_ADDRESS               /* no -- needs name server! */
1.1       timbl     685:     memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
                    686:     if (TRACE) fprintf(stderr, "     Name server says that I am `%s' = %s\n",
                    687:            hostname, HTInetString(&HTHostAddress));
2.8       luotonen  688: #endif /* NEED_HOST_ADDRESS */
1.1       timbl     689: 
                    690: #endif /* not Decnet */
                    691: }
2.16      frystyk   692: #endif /* OLD_CODE */
1.1       timbl     693: 
2.19      frystyk   694: 
2.24    ! frystyk   695: /*                                                             HTGetDomainName
        !           696: **     Returns the current domain name without the local host name.
        !           697: **     The response is pointing to a static area that might be changed
        !           698: **     using HTSetHostName(). Returns NULL on error
        !           699: */
        !           700: PUBLIC CONST char *HTGetDomainName NOARGS
        !           701: {
        !           702:     CONST char *host = HTGetHostName();
        !           703:     char *domain;
        !           704:     if (host && *host) {
        !           705:        if ((domain = strchr(host, '.')) != NULL)
        !           706:            return ++domain;
        !           707:        else
        !           708:            return host;
        !           709:     } else
        !           710:        return NULL;
        !           711: }
        !           712: 
        !           713: 
        !           714: 
2.19      frystyk   715: /*                                                             HTSetHostName
                    716: **     Sets the current hostname inclusive domain name.
                    717: **     If this is not set then the default approach is used using
                    718: **     HTGetHostname().
                    719: */
                    720: PUBLIC void HTSetHostName ARGS1(char *, host)
                    721: {
2.24    ! frystyk   722:     if (host && *host) {
        !           723:        char *strptr;
2.19      frystyk   724:        StrAllocCopy(hostname, host);
2.24    ! frystyk   725:        strptr = hostname;
        !           726:        while (*strptr) {
        !           727:            *strptr = TOLOWER(*strptr);
        !           728:            strptr++;
        !           729:        }
        !           730:        if (*(hostname+strlen(hostname)-1) == '.')    /* Remove trailing dot */
        !           731:            *(hostname+strlen(hostname)-1) = '\0';
        !           732:     } else {
2.19      frystyk   733:        if (TRACE) fprintf(stderr, "SetHostName. Bad argument ignored\n");
                    734:     }
                    735: }
                    736: 
                    737: 
                    738: /*                                                             HTGetHostName
2.18      frystyk   739: **     Returns the name of this host. It uses the following algoritm:
                    740: **
                    741: **     1) gethostname()
                    742: **     2) if the hostname doesn't contain any '.' try to read
                    743: **        /etc/resolv.conf. If there is no domain line in this file then
                    744: **     3) Try getdomainname and do as the man pages say for resolv.conf (sun)
                    745: **             If there is no domain line in this file, then it is derived
                    746: **             from the domain name set by the domainname(1) command, usually
                    747: **             by removing the first component. For example, if the domain-
                    748: **             name is set to ``foo.podunk.edu'' then the default domain name
                    749: **             used will be ``pudunk.edu''.
                    750: **
                    751: **     This is the same procedure as used by res_init() and sendmail.
2.16      frystyk   752: **
                    753: **     Return: hostname on success else NULL
                    754: */
2.19      frystyk   755: PUBLIC CONST char * HTGetHostName NOARGS
1.1       timbl     756: {
2.18      frystyk   757:     BOOL got_it = NO;
                    758:     FILE *fp;
2.16      frystyk   759:     char name[MAXHOSTNAMELEN+1];
2.18      frystyk   760:     if (hostname) {                                      /* If already done */
                    761:        if (*hostname)
                    762:            return hostname;
                    763:        else
                    764:            return NULL;                    /* We couldn't get the last time */
                    765:     }
2.16      frystyk   766:     *(name+MAXHOSTNAMELEN) = '\0';
                    767:     if (gethostname(name, MAXHOSTNAMELEN)) {        /* Maybe without domain */
                    768:        if (TRACE)
                    769:            fprintf(stderr, "HostName.... Can't get host name\n");
                    770:        return NULL;
                    771:     }
2.18      frystyk   772:     if (TRACE)
2.24    ! frystyk   773:        fprintf(stderr, "HostName.... Local host name is  `%s\'\n", name);
2.16      frystyk   774:     StrAllocCopy(hostname, name);
2.24    ! frystyk   775:     {
        !           776:        char *strptr = strchr(hostname, '.');
        !           777:        if (strptr != NULL)                                /* We have it all */
        !           778:            got_it = YES;
        !           779:     }
2.16      frystyk   780: 
2.23      duns      781: #ifndef VMS
2.18      frystyk   782:     /* Now try the resolver config file */
2.24    ! frystyk   783:     if (!got_it && (fp = fopen(RESOLV_CONF, "r")) != NULL) {
2.18      frystyk   784:        char buffer[80];
                    785:        *(buffer+79) = '\0';
                    786:        while (fgets(buffer, 79, fp)) {
                    787:            if (!strncasecomp(buffer, "domain", 6)) {   
                    788:                char *domainstr = buffer+6;
                    789:                char *end;
                    790:                while (*domainstr == ' ' || *domainstr == '\t')
                    791:                    domainstr++;
                    792:                end = domainstr;
                    793:                while (*end && !isspace(*end))
                    794:                    end++;
                    795:                *end = '\0';
                    796:                if (*domainstr) {
                    797:                    StrAllocCat(hostname, ".");
                    798:                    StrAllocCat(hostname, domainstr);
                    799:                    got_it = YES;
                    800:                    break;
                    801:                }
                    802:            }
                    803:        }
                    804:        fclose(fp);
2.16      frystyk   805:     }
                    806: 
2.18      frystyk   807:     /* If everything else has failed then try getdomainname */
                    808:     if (!got_it) {
                    809:        if (getdomainname(name, MAXHOSTNAMELEN)) {
                    810:            if (TRACE)
                    811:                fprintf(stderr, "HostName.... Can't get domain name\n");
2.24    ! frystyk   812:            StrAllocCopy(hostname, "");
2.18      frystyk   813:            return NULL;
                    814:        }
                    815: 
                    816:        /* If the host name and the first part of the domain name are different
                    817:           then use the former as it is more exact (I guess) */
                    818:        if (strncmp(name, hostname, (int) strlen(hostname))) {
                    819:            char *domain = strchr(name, '.');
                    820:            if (!domain)
                    821:                domain = name;
                    822:            StrAllocCat(hostname, domain);
                    823:        }
2.16      frystyk   824:     }
2.23      duns      825: #endif /* not VMS */
                    826: 
2.24    ! frystyk   827:     {
        !           828:        char *strptr = hostname;
        !           829:        while (*strptr) {           
        !           830:            *strptr = TOLOWER(*strptr);
        !           831:            strptr++;
        !           832:        }
        !           833:        if (*(hostname+strlen(hostname)-1) == '.')    /* Remove trailing dot */
        !           834:            *(hostname+strlen(hostname)-1) = '\0';
        !           835:     }
2.18      frystyk   836:     if (TRACE)
2.24    ! frystyk   837:        fprintf(stderr, "HostName.... Full host name is `%s\'\n", hostname);
2.18      frystyk   838:     return hostname;
                    839: 
                    840: #ifndef DECNET  /* Decnet ain't got no damn name server 8#OO */
                    841: #ifdef OLD_CODE
                    842:                              /* Now we try to get information on the domain */
2.16      frystyk   843:     {
                    844:        struct hostent *hostelement;
                    845:        if ((hostelement = gethostbyname(hostname)) == NULL) {
                    846:            if (TRACE)
                    847:                fprintf(stderr, "HostName.... Can't find host name on DNS\n");
                    848:            FREE(hostname);
                    849:            return NULL;
                    850:        }
2.17      frystyk   851:        StrAllocCopy(hostname, (char *) hostelement->h_name);
2.16      frystyk   852:     }
2.18      frystyk   853: #endif /* OLD_CODE */
2.16      frystyk   854: #endif /* not Decnet */
2.13      frystyk   855: }
                    856: 
2.19      frystyk   857: 
                    858: /*                                                            HTSetMailAddress
                    859: **     Sets the current mail address plus host name and domain name.
                    860: **     If this is not set then the default approach is used using
                    861: **     HTGetMailAddress().
                    862: */
                    863: PUBLIC void HTSetMailAddress ARGS1(char *, address)
                    864: {
                    865:     if (address && *address)
                    866:        StrAllocCopy(mailaddress, address);
                    867:     else {
                    868:        if (TRACE) fprintf(stderr, "SetMailAddress. Bad argument ignored\n");
                    869:     }
                    870: }
                    871: 
                    872: 
                    873: /*                                                            HTGetMailAddress
                    874: **
                    875: **     Get the mail address of the current user on the current host. The
                    876: **     domain name used is the one initialized in HTSetHostName or
                    877: **     HTGetHostName. The login name is determined using (ordered):
                    878: **
                    879: **             getlogin
                    880: **             getpwuid(getuid())
                    881: **
                    882: **     The weakness about the last attempt is if the user has multiple
                    883: **     login names each with the same user ID. If this fails as well then:
                    884: **
                    885: **             LOGNAME environment variable
                    886: **             USER environment variable
                    887: **
                    888: **     Returns NULL if error else pointer to static string
                    889: */
                    890: PUBLIC CONST char * HTGetMailAddress NOARGS
                    891: {
                    892:     char *login;
                    893:     CONST char *domain;
                    894:     struct passwd *pw_info;
2.21      frystyk   895:     if (mailaddress) {
                    896:        if (*mailaddress)
                    897:            return mailaddress;
                    898:        else
                    899:            return NULL;       /* No luck the last time so we wont try again */
                    900:     }
2.23      duns      901: 
                    902: #ifdef VMS
                    903:     if ((login = (char *) cuserid(NULL)) == NULL) {
                    904:         if (TRACE) fprintf(stderr, "MailAddress. cuserid returns NULL\n");
                    905:     }
                    906: 
                    907: #else /* not VMS */
2.19      frystyk   908:     if ((login = (char *) getlogin()) == NULL) {
                    909:        if (TRACE) fprintf(stderr, "MailAddress. getlogin returns NULL\n");
                    910:        if ((pw_info = getpwuid(getuid())) == NULL) {
                    911:            if (TRACE) fprintf(stderr, "MailAddress. getpwid returns NULL\n");
                    912:            if ((login = getenv("LOGNAME")) == NULL) {
                    913:                if (TRACE) fprintf(stderr, "MailAddress. LOGNAME not found\n");
                    914:                if ((login = getenv("USER")) == NULL) {
                    915:                    if (TRACE) fprintf(stderr,"MailAddress. USER not found\n");
                    916:                    return NULL;                /* I GIVE UP */
                    917:                }
                    918:            }
                    919:        } else
                    920:            login = pw_info->pw_name;
                    921:     }
2.23      duns      922: #endif /* not VMS */
                    923: 
2.19      frystyk   924:     if (login) {
                    925:        StrAllocCopy(mailaddress, login);
                    926:        StrAllocCat(mailaddress, "@");
                    927:        if ((domain = HTGetHostName()) != NULL)
                    928:            StrAllocCat(mailaddress, domain);
2.21      frystyk   929:        else {
                    930:            *mailaddress = '\0';
                    931:            return NULL;                        /* Domain name not available */
                    932:        }
2.19      frystyk   933:        return mailaddress;
                    934:     }
                    935:     return NULL;
                    936: }
                    937: 
                    938: /* ------------------------------------------------------------------------- */
                    939: /*                   CONNECTION ESTABLISHMENT MANAGEMENT                    */
                    940: /* ------------------------------------------------------------------------- */
2.13      frystyk   941: 
                    942: /*                                                             HTDoConnect()
                    943: **
                    944: **     Note: Any port indication in URL, e.g., as `host:port' overwrites
                    945: **     the default_port value.
                    946: **
                    947: **     Returns 0 if OK, -1 on error
                    948: */
2.24    ! frystyk   949: PUBLIC int HTDoConnect ARGS5(HTNetInfo *, net, char *, url,
        !           950:                             u_short, default_port, u_long *, addr,
        !           951:                             BOOL, use_cur)
2.13      frystyk   952: {
                    953:     time_t deltatime;
2.24    ! frystyk   954:     int hosts;
2.13      frystyk   955:     int status;
                    956:     SockA sock_addr;                           /* SockA is defined in tcp.h */
                    957:     char *p1 = HTParse(url, "", PARSE_HOST);
                    958:     char *at_sign;
                    959:     char *host;
                    960: 
                    961:     /* if theres an @ then use the stuff after it as a hostname */
                    962:     if((at_sign = strchr(p1,'@')) != NULL)
                    963:        host = at_sign+1;
                    964:     else
                    965:        host = p1;
2.24    ! frystyk   966:     if (!*host) {
        !           967:        HTErrorAdd(net->request, ERR_FATAL, NO, HTERR_NO_HOST,
        !           968:                   NULL, 0, "HTDoConnect");
        !           969:        free(p1);
        !           970:        return -1;
        !           971:     } else
        !           972:        if (TRACE) fprintf(stderr, "HTDoConnect. Looking up `%s\'\n", host);
2.13      frystyk   973: 
                    974:    /* Set up defaults */
                    975:     memset((void *) &sock_addr, '\0', sizeof(sock_addr));
                    976: #ifdef DECNET
                    977:     sock_addr.sdn_family = AF_DECnet;        /* Family = DECnet, host order */
                    978:     sock_addr.sdn_objnum = DNP_OBJ;          /* Default: http object number */
                    979: #else  /* Internet */
                    980:     sock_addr.sin_family = AF_INET;
                    981:     sock_addr.sin_port = htons(default_port);
                    982: #endif
                    983: 
2.24    ! frystyk   984:     /* If we are trying to connect to a multi-homed host then loop here until
        !           985:        success or we have tried all IP-addresses */
        !           986:     do {
        !           987:        if ((hosts = HTParseInet(&sock_addr, host, use_cur)) < 0) {
        !           988:            if (TRACE) fprintf(stderr, "HTDoConnect. Can't locate remote host `%s\'\n", host);
        !           989:            HTErrorAdd(net->request, ERR_FATAL, NO, HTERR_NO_REMOTE_HOST,
        !           990:                       (void *) host, strlen(host), "HTDoConnect");
        !           991:            goto errorend;
        !           992:        }
2.13      frystyk   993: 
                    994: #ifdef DECNET
2.24    ! frystyk   995:        if ((net->sockfd = socket(AF_DECnet, SOCK_STREAM, 0)) < 0)
2.13      frystyk   996: #else
2.24    ! frystyk   997:        if ((net->sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
2.13      frystyk   998: #endif
2.24    ! frystyk   999:        {
        !          1000:            HTErrorSysAdd(net->request, ERR_FATAL, NO, "socket");
        !          1001:            goto errorend;
        !          1002:        }
        !          1003:        if (addr)
        !          1004:            *addr = ntohl(sock_addr.sin_addr.s_addr);
        !          1005:        if (PROT_TRACE)
        !          1006:            fprintf(stderr, "HTDoConnect. Created socket number %d\n",
        !          1007:                    net->sockfd);
        !          1008:        
        !          1009:        /* If multi-homed host then start timer on connection */
        !          1010:        if (hosts > 1)
        !          1011:            deltatime = time(NULL);
        !          1012: 
        !          1013:        status = connect(net->sockfd, (struct sockaddr *) &sock_addr,
        !          1014:                         sizeof(sock_addr));
        !          1015:        if (hosts > 1) {
        !          1016:            deltatime = time(NULL) - deltatime;
        !          1017:            if (status < 0) {
        !          1018:                HTErrorSysAdd(net->request, ERR_NON_FATAL, NO, "connect");
        !          1019:                if (errno==ECONNREFUSED || errno==ETIMEDOUT ||
        !          1020:                    errno==ENETUNREACH || errno==EHOSTUNREACH ||
        !          1021:                    errno==EHOSTDOWN)
        !          1022:                    deltatime += TCP_DELAY;
        !          1023:                else
        !          1024:                    deltatime += TCP_PENALTY;
        !          1025:                if (NETCLOSE(net->sockfd) < 0)
        !          1026:                    HTErrorSysAdd(net->request, ERR_FATAL, NO, "close");
        !          1027:                HTTCPAddrWeights(host, deltatime);
        !          1028:            } else {
        !          1029:                HTTCPAddrWeights(host, deltatime);
        !          1030:                break;
        !          1031:            }
        !          1032:        } else if (status < 0) {
        !          1033:            HTErrorSysAdd(net->request, ERR_FATAL, NO, "connect");
        !          1034:            HTTCPCacheRemoveHost(host);
        !          1035:            if (NETCLOSE(net->sockfd) < 0)
        !          1036:                HTErrorSysAdd(net->request, ERR_FATAL, NO, "close");
        !          1037:            goto errorend;
        !          1038:        }
        !          1039:     } while (net->addressCount++ < hosts-1);
2.13      frystyk  1040: 
2.24    ! frystyk  1041:     if (hosts > 1 && net->addressCount >= hosts) {
        !          1042:        if (PROT_TRACE) fprintf(stderr, "HTDoConnect. None of the %d addresses on multi-homed host is accessible\n", hosts);
        !          1043:        goto errorend;
2.13      frystyk  1044:     }
                   1045: 
                   1046:     free(p1);
2.24    ! frystyk  1047:     net->addressCount = 0;
2.13      frystyk  1048:     return status;
2.24    ! frystyk  1049: 
        !          1050:   errorend:
        !          1051:     free (p1);
        !          1052:     net->addressCount = 0;
        !          1053:     net->sockfd = -1;
        !          1054:     return -1;
2.13      frystyk  1055: }
                   1056: 
                   1057: 
                   1058: /*                                                             HTDoAccept()
                   1059: **
                   1060: **     This function makes a non-blocking accept on a port and polls every
                   1061: **     second until MAX_ACCEPT_POLL or interrupted by user.
                   1062: **
                   1063: **     BUGS Interrupted is not yet implemented!!!
                   1064: **
                   1065: **     Returns 0 if OK, -1 on error
                   1066: */
2.15      frystyk  1067: PUBLIC int HTDoAccept ARGS1(HTNetInfo *, net)
2.13      frystyk  1068: {
                   1069:     SockA soc_address;                         /* SockA is defined in tcp.h */
                   1070:     int status;
                   1071:     int cnt;
                   1072:     int soc_addrlen = sizeof(soc_address);
2.15      frystyk  1073:     if (net->sockfd < 0) {
2.13      frystyk  1074:        if (TRACE) fprintf(stderr, "HTDoAccept.. Bad socket number\n");
                   1075:        return -1;
                   1076:     }
                   1077:        
                   1078:     /* First make the socket non-blocking */
2.23      duns     1079: #ifdef VMS
                   1080: #ifdef MULTINET
                   1081:     {
                   1082:        int enable = 1;
                   1083:        status = socket_ioctl(net->sockfd, FIONBIO, &enable);
                   1084:     }
                   1085: #endif /* MULTINET */
                   1086: #else /* not VMS */
2.15      frystyk  1087:     if((status = FCNTL(net->sockfd, F_GETFL, 0)) != -1) {
2.23      duns     1088:        status |= FNDELAY;                                      /* O_NDELAY; */
2.15      frystyk  1089:        status = FCNTL(net->sockfd, F_SETFL, status);
2.13      frystyk  1090:     }
2.23      duns     1091: #endif /* not VMS */
2.13      frystyk  1092:     if (status == -1) {
2.15      frystyk  1093:        HTErrorSysAdd(net->request, ERR_FATAL, NO, "fcntl");
2.13      frystyk  1094:        return -1;
                   1095:     }
                   1096: 
                   1097:     /* Now poll every sekund */
                   1098:     for(cnt=0; cnt<MAX_ACCEPT_POLL; cnt++) {
2.15      frystyk  1099:        if ((status = accept(net->sockfd, (struct sockaddr*) &soc_address,
2.13      frystyk  1100:                             &soc_addrlen)) >= 0) {
                   1101:            if (TRACE) fprintf(stderr,
                   1102:                               "HTDoAccept.. Accepted new socket %d\n", 
                   1103:                               status);
                   1104:            return status;
                   1105:        } else
2.15      frystyk  1106:            HTErrorSysAdd(net->request, ERR_WARNING, YES, "accept");
2.13      frystyk  1107:        sleep(1);
                   1108:     }  
                   1109:     
                   1110:     /* If nothing has happened */    
                   1111:     if (TRACE)
                   1112:        fprintf(stderr, "HTDoAccept.. Timed out, no connection!\n");
2.15      frystyk  1113:     HTErrorAdd(net->request, ERR_FATAL, NO, HTERR_TIME_OUT, NULL, 0,
                   1114:               "HTDoAccept");
2.13      frystyk  1115:     return -1;
1.1       timbl    1116: }
                   1117: 

Webmaster