Annotation of libwww/Library/src/HTInet.c, revision 2.1

2.1     ! frystyk     1: /*                                                                    HTInet.c
        !             2: **     GENERIC INTERNET UTILITIES
        !             3: **
        !             4: **     (c) COPYRIGHT MIT 1995.
        !             5: **     Please first read the full copyright statement in the file COPYRIGH.
        !             6: **     @(#) $Id: Date Author State $
        !             7: **
        !             8: **     This code is in common between client and server sides.
        !             9: **
        !            10: **     16 Mar 96  HFN  Spawned off from HTTCP.c
        !            11: */
        !            12: 
        !            13: /* Library include files */
        !            14: #include "sysdep.h"
        !            15: #include "WWWUtil.h"
        !            16: #include "HTParse.h"
        !            17: #include "HTAlert.h"
        !            18: #include "HTError.h"
        !            19: #include "HTReqMan.h"
        !            20: #include "HTNetMan.h"
        !            21: #include "HTDNS.h"
        !            22: #include "HTInet.h"                                     /* Implemented here */
        !            23: 
        !            24: /* VMS stuff */
        !            25: #ifdef VMS
        !            26: #ifndef MULTINET
        !            27: #define FD_SETSIZE 32
        !            28: #else /* Multinet */
        !            29: #define FD_SETSIZE 256
        !            30: #endif /* Multinet */
        !            31: #endif /* VMS */
        !            32: 
        !            33: PRIVATE char *hostname = NULL;                     /* The name of this host */
        !            34: PRIVATE char *mailaddress = NULL;                   /* Current mail address */
        !            35: 
        !            36: /* ------------------------------------------------------------------------- */
        !            37: 
        !            38: /*
        !            39: **     Returns the string equivalent to the errno passed in the argument.
        !            40: **     We can't use errno directly as we have both errno and socerrno. The
        !            41: **     result is a static buffer.
        !            42: */
        !            43: PUBLIC const char * HTErrnoString (int errornumber)
        !            44: {
        !            45: #ifdef HAVE_STRERROR
        !            46:     return strerror(errornumber);
        !            47: #else
        !            48: #ifdef HAVE_SYS_ERRLIST
        !            49: #ifdef HAVE_SYS_NERR
        !            50:     return (errno < sys_nerr ? sys_errlist[errno] : "Unknown error");
        !            51: #else
        !            52:     return sys_errlist[errno];
        !            53: #endif /* HAVE_SYS_NERR */
        !            54: #else
        !            55: #ifdef VMS
        !            56:     static char buf[60];
        !            57:     sprintf(buf, "Unix errno=%ld dec, VMS error=%lx hex", errornumber,
        !            58:            vaxc$errno);
        !            59:     return buf;
        !            60: #else
        !            61: #ifdef _WINSOCKAPI_
        !            62:     static char buf[60];
        !            63:     sprintf(buf, "Unix errno=%ld dec, WinSock error=%ld", errornumber,
        !            64:            WSAGetLastError());
        !            65:     return buf;
        !            66: #else
        !            67:     return "(Error number not translated)";
        !            68: #endif /* _WINSOCKAPI_ */
        !            69: #endif /* VMS */
        !            70: #endif /* HAVE_SYS_ERRLIST */
        !            71: #endif /* HAVE_STRERROR */
        !            72: }
        !            73: 
        !            74: 
        !            75: /*     Debug error message
        !            76: */
        !            77: PUBLIC int HTInetStatus (int errnum, char * where)
        !            78: {
        !            79: #ifdef VMS
        !            80:     if (PROT_TRACE) HTTrace("System Error Unix = %ld dec\n", errno);
        !            81:     if (PROT_TRACE) HTTrace("System Error VMS  = %lx hex\n", vaxc$errno);
        !            82:     return (-vaxc$errno);
        !            83: #else
        !            84: #ifdef _WINSOCKAPI_
        !            85:     if (PROT_TRACE) HTTrace("System Error Unix = %ld dec\n", errno);
        !            86:     if (PROT_TRACE) HTTrace("System Error WinSock error=%lx hex\n",
        !            87:                            WSAGetLastError());
        !            88:     return (-errnum);
        !            89: #else
        !            90:     if (PROT_TRACE)
        !            91:        HTTrace("System Error %d after call to %s() failed\n............ %s\n",
        !            92:                errno, where, HTErrnoString(errnum));
        !            93:     return (-errnum);
        !            94: #endif /* _WINSOCKAPI_ */
        !            95: #endif /* VMS */
        !            96: }
        !            97: 
        !            98: 
        !            99: /*     Parse a cardinal value                                 parse_cardinal()
        !           100: **     ----------------------
        !           101: **
        !           102: ** On entry,
        !           103: **     *pp         points to first character to be interpreted, terminated by
        !           104: **                 non 0:9 character.
        !           105: **     *pstatus    points to status already valid
        !           106: **     maxvalue    gives the largest allowable value.
        !           107: **
        !           108: ** On exit,
        !           109: **     *pp         points to first unread character
        !           110: **     *pstatus    points to status updated iff bad
        !           111: */
        !           112: 
        !           113: PUBLIC unsigned int HTCardinal (int *          pstatus,
        !           114:                                char **         pp,
        !           115:                                unsigned int    max_value)
        !           116: {
        !           117:     unsigned int n=0;
        !           118:     if ( (**pp<'0') || (**pp>'9')) {       /* Null string is error */
        !           119:        *pstatus = -3;  /* No number where one expeceted */
        !           120:        return 0;
        !           121:     }
        !           122:     while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
        !           123: 
        !           124:     if (n>max_value) {
        !           125:        *pstatus = -4;  /* Cardinal outside range */
        !           126:        return 0;
        !           127:     }
        !           128: 
        !           129:     return n;
        !           130: }
        !           131: 
        !           132: /* ------------------------------------------------------------------------- */
        !           133: /*                             SIGNAL HANDLING                              */
        !           134: /* ------------------------------------------------------------------------- */
        !           135: 
        !           136: #ifdef WWWLIB_SIG
        !           137: /*                                                                 HTSetSignal
        !           138: **  This function sets up signal handlers. This might not be necessary to
        !           139: **  call if the application has its own handlers.
        !           140: */
        !           141: #include <signal.h>
        !           142: PUBLIC void HTSetSignal (void)
        !           143: {
        !           144:     /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal
        !           145:     ** when attemting to connect to a remote host where you normally should
        !           146:     ** get `connection refused' back
        !           147:     */
        !           148:     if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
        !           149:        if (PROT_TRACE) HTTrace("HTSignal.... Can't catch SIGPIPE\n");
        !           150:     } else {
        !           151:        if (PROT_TRACE) HTTrace("HTSignal.... Ignoring SIGPIPE\n");
        !           152:     }
        !           153: }
        !           154: #else
        !           155: #ifdef WWW_WIN_DLL
        !           156: PUBLIC void HTSetSignal (void) {}
        !           157: #endif /* WWW_WIN_DLL */
        !           158: #endif /* WWWLIB_SIG */
        !           159: 
        !           160: /* ------------------------------------------------------------------------- */
        !           161: /*                          HOST NAME FUNCTIONS                             */
        !           162: /* ------------------------------------------------------------------------- */
        !           163: 
        !           164: /*     Produce a string for an Internet address
        !           165: **     ----------------------------------------
        !           166: **
        !           167: ** On exit,
        !           168: **     returns a pointer to a static string which must be copied if
        !           169: **             it is to be kept.
        !           170: */
        !           171: PUBLIC const char * HTInetString (SockA * sin)
        !           172: {
        !           173: #ifndef DECNET  /* Function only used below for a trace message */
        !           174: #if 0
        !           175:     /* This dumps core on some Sun systems :-(. The problem is now, that 
        !           176:        the current implememtation only works for IP-addresses and not in
        !           177:        other address spaces. */
        !           178:     return inet_ntoa(sin->sin_addr);
        !           179: #endif
        !           180:     static char string[16];
        !           181:     sprintf(string, "%d.%d.%d.%d",
        !           182:            (int)*((unsigned char *)(&sin->sin_addr)+0),
        !           183:            (int)*((unsigned char *)(&sin->sin_addr)+1),
        !           184:            (int)*((unsigned char *)(&sin->sin_addr)+2),
        !           185:            (int)*((unsigned char *)(&sin->sin_addr)+3));
        !           186:     return string;
        !           187: #else
        !           188:     return "";
        !           189: #endif /* Decnet */
        !           190: }
        !           191: 
        !           192: /*     Parse a network node address and port
        !           193: **     -------------------------------------
        !           194: **     It is assumed that any portnumber and numeric host address
        !           195: **     is given in decimal notation. Separation character is '.'
        !           196: **     Any port number given in host name overrides all other values.
        !           197: **     'host' might be modified.
        !           198: **      Returns:
        !           199: **             >0      Number of homes
        !           200: **              0      Wait for persistent socket
        !           201: **             -1      Error
        !           202: */
        !           203: PUBLIC int HTParseInet (HTNet * net, char * host)
        !           204: {
        !           205:     int status = 1;
        !           206:     SockA *sin = &net->sock_addr;
        !           207: 
        !           208: #ifdef DECNET
        !           209:     /* read Decnet node name. @@ Should know about DECnet addresses, but it's
        !           210:        probably worth waiting until the Phase transition from IV to V. */
        !           211: 
        !           212:     sin->sdn_nam.n_len = min(DN_MAXNAML, strlen(host));  /* <=6 in phase 4 */
        !           213:     strncpy (sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
        !           214: 
        !           215:     if (PROT_TRACE)
        !           216:        HTTrace("DECnet: Parsed address as object number %d on host %.6s...\n",
        !           217:                sin->sdn_objnum, host);
        !           218: #else /* Internet */
        !           219:     {
        !           220:        char *strptr = host;
        !           221:        while (*strptr) {
        !           222:            if (*strptr == ':') {
        !           223:                *strptr = '\0';    /* Don't want port number in numeric host */
        !           224:                break;
        !           225:            }
        !           226:            if (!isdigit(*strptr) && *strptr != '.')
        !           227:                break;
        !           228:            strptr++;
        !           229:        }
        !           230:        if (!*strptr) {
        !           231: #ifdef GUSI
        !           232:            sin->sin_addr = inet_addr(host);             /* See netinet/in.h */
        !           233: #else
        !           234:            sin->sin_addr.s_addr = inet_addr(host);       /* See arpa/inet.h */
        !           235: #endif
        !           236:        } else
        !           237:            status = HTGetHostByName(net, host);
        !           238: 
        !           239:        if (PROT_TRACE) {
        !           240:            if (status > 0)
        !           241:                HTTrace("ParseInet... as port %d on %s with %d homes\n",
        !           242:                        (int) ntohs(sin->sin_port), HTInetString(sin), status);
        !           243:        }
        !           244:     }
        !           245: #endif /* Internet vs. Decnet */
        !           246:     return status;
        !           247: }
        !           248: 
        !           249: 
        !           250: /*                                                             HTGetDomainName
        !           251: **     Returns the current domain name without the local host name.
        !           252: **     The response is pointing to a static area that might be changed
        !           253: **     using HTSetHostName().
        !           254: **
        !           255: **     Returns NULL on error, "" if domain name is not found
        !           256: */
        !           257: PUBLIC const char *HTGetDomainName (void)
        !           258: {
        !           259:     const char *host = HTGetHostName();
        !           260:     char *domain;
        !           261:     if (host && *host) {
        !           262:        if ((domain = strchr(host, '.')) != NULL)
        !           263:            return ++domain;
        !           264:        else
        !           265:            return "";
        !           266:     } else
        !           267:        return NULL;
        !           268: }
        !           269: 
        !           270: 
        !           271: /*                                                             HTSetHostName
        !           272: **     Sets the current hostname inclusive domain name.
        !           273: **     If this is not set then the default approach is used using
        !           274: **     HTGetHostname().
        !           275: */
        !           276: PUBLIC void HTSetHostName (char * host)
        !           277: {
        !           278:     if (host && *host) {
        !           279:        char *strptr;
        !           280:        StrAllocCopy(hostname, host);
        !           281:        strptr = hostname;
        !           282:        while (*strptr) {
        !           283:            *strptr = TOLOWER(*strptr);
        !           284:            strptr++;
        !           285:        }
        !           286:        if (*(hostname+strlen(hostname)-1) == '.')    /* Remove trailing dot */
        !           287:            *(hostname+strlen(hostname)-1) = '\0';
        !           288:     } else {
        !           289:        if (PROT_TRACE) HTTrace("SetHostName. Bad argument ignored\n");
        !           290:     }
        !           291: }
        !           292: 
        !           293: 
        !           294: /*                                                             HTGetHostName
        !           295: **     Returns the name of this host. It uses the following algoritm:
        !           296: **
        !           297: **     1) gethostname()
        !           298: **     2) if the hostname doesn't contain any '.' try to read
        !           299: **        /etc/resolv.conf. If there is no domain line in this file then
        !           300: **     3) Try getdomainname and do as the man pages say for resolv.conf (sun)
        !           301: **        If there is no domain line in this file, then it is derived
        !           302: **        from the domain name set by the domainname(1) command, usually
        !           303: **        by removing the first component. For example, if the domain-
        !           304: **        name is set to ``foo.podunk.edu'' then the default domain name
        !           305: **        used will be ``pudunk.edu''.
        !           306: **
        !           307: **     This is the same procedure as used by res_init() and sendmail.
        !           308: **
        !           309: **     Return: hostname on success else NULL
        !           310: */
        !           311: PUBLIC const char * HTGetHostName (void)
        !           312: {
        !           313:     int fqdn = 0;                                   /* 0=no, 1=host, 2=fqdn */
        !           314:     FILE *fp;
        !           315:     char name[MAXHOSTNAMELEN+1];
        !           316:     if (hostname) {                                      /* If already done */
        !           317:        if (*hostname)
        !           318:            return hostname;
        !           319:        else
        !           320:            return NULL;                    /* We couldn't get the last time */
        !           321:     }
        !           322:     *(name+MAXHOSTNAMELEN) = '\0';
        !           323: 
        !           324: #ifdef HAVE_SYSINFO
        !           325:     if (!fqdn && sysinfo(SI_HOSTNAME, name, MAXHOSTNAMELEN) > 0) {
        !           326:        char * dot = strchr(name, '.');
        !           327:        if (PROT_TRACE) HTTrace("HostName.... sysinfo says `%s\'\n", name);
        !           328:        StrAllocCopy(hostname, name);
        !           329:        fqdn = dot ? 2 : 1;
        !           330:     }
        !           331: #endif /* HAVE_SYSINFO */
        !           332: 
        !           333: #ifdef HAVE_GETHOSTNAME
        !           334:     if (!fqdn && gethostname(name, MAXHOSTNAMELEN) == 0) {
        !           335:        char * dot = strchr(name, '.');
        !           336:        if (PROT_TRACE) HTTrace("HostName.... gethostname says `%s\'\n", name);
        !           337:        StrAllocCopy(hostname, name);
        !           338:        fqdn = dot ? 2 : 1;
        !           339:     }
        !           340: #endif /* HAVE_GETHOSTNAME */
        !           341: 
        !           342: #ifdef RESOLV_CONF
        !           343:     /* Now try the resolver config file */
        !           344:     if (fqdn==1 && (fp = fopen(RESOLV_CONF, "r")) != NULL) {
        !           345:        char buffer[80];
        !           346:        *(buffer+79) = '\0';
        !           347:        while (fgets(buffer, 79, fp)) {
        !           348:            if (!strncasecomp(buffer, "domain", 6) ||
        !           349:                !strncasecomp(buffer, "search", 6)) {
        !           350:                char *domainstr = buffer+6;
        !           351:                char *end;
        !           352:                while (*domainstr == ' ' || *domainstr == '\t')
        !           353:                    domainstr++;
        !           354:                end = domainstr;
        !           355:                while (*end && !isspace(*end))
        !           356:                    end++;
        !           357:                *end = '\0';
        !           358:                if (*domainstr) {
        !           359:                    StrAllocCat(hostname, ".");
        !           360:                    StrAllocCat(hostname, domainstr);
        !           361:                    fqdn = YES;
        !           362:                    break;
        !           363:                }
        !           364:            }
        !           365:        }
        !           366:        fclose(fp);
        !           367:     }
        !           368: #endif /* RESOLV_CONF */
        !           369: 
        !           370: #ifdef HAVE_GETDOMAINNAME
        !           371:     /* If everything else has failed then try getdomainname */
        !           372:     if (fqdn==1) {
        !           373:        if (getdomainname(name, MAXHOSTNAMELEN)) {
        !           374:            if (PROT_TRACE)
        !           375:                HTTrace("HostName.... Can't get domain name\n");
        !           376:            StrAllocCopy(hostname, "");
        !           377:            return NULL;
        !           378:        }
        !           379: 
        !           380:        /* If the host name and the first part of the domain name are different
        !           381:           then use the former as it is more exact (I guess) */
        !           382:        if (strncmp(name, hostname, (int) strlen(hostname))) {
        !           383:            char *domain = strchr(name, '.');
        !           384:            if (!domain)
        !           385:                domain = name;
        !           386:            StrAllocCat(hostname, domain);
        !           387:        }
        !           388:     }
        !           389: #endif /* HAVE_GETDOMAINNAME */
        !           390: 
        !           391:     if (hostname) {
        !           392:        char *strptr = hostname;
        !           393:        while (*strptr) {           
        !           394:            *strptr = TOLOWER(*strptr);
        !           395:            strptr++;
        !           396:        }
        !           397:        if (*(hostname+strlen(hostname)-1) == '.')    /* Remove trailing dot */
        !           398:            *(hostname+strlen(hostname)-1) = '\0';
        !           399:        if (PROT_TRACE) HTTrace("HostName.... FQDN is `%s\'\n", hostname);
        !           400:     }
        !           401:     return hostname;
        !           402: }
        !           403: 
        !           404: 
        !           405: /*
        !           406: **     Free the host name. Called from HTLibTerminate
        !           407: */
        !           408: PUBLIC void HTFreeHostName (void)
        !           409: {
        !           410:     HT_FREE(hostname);
        !           411: }
        !           412: 
        !           413: 
        !           414: /*                                                            HTSetMailAddress
        !           415: **     Sets the current mail address plus host name and domain name.
        !           416: **     If this is not set then the default approach is used using
        !           417: **     HTGetMailAddress(). If the argument is NULL or "" then HTGetMailAddress
        !           418: **     returns NULL on a succeding request.
        !           419: */
        !           420: PUBLIC void HTSetMailAddress (char * address)
        !           421: {
        !           422:     if (!address || !*address)
        !           423:        StrAllocCopy(mailaddress, "");
        !           424:     else
        !           425:        StrAllocCopy(mailaddress, address);
        !           426:     if (WWWTRACE)
        !           427:        HTTrace("SetMailAdr.. Set mail address to `%s\'\n",
        !           428:                mailaddress);
        !           429: }
        !           430: 
        !           431: 
        !           432: /*                                                            HTGetMailAddress
        !           433: **
        !           434: **     Get the mail address of the current user on the current host. The
        !           435: **     domain name used is the one initialized in HTSetHostName or
        !           436: **     HTGetHostName. The login name is determined using (ordered):
        !           437: **
        !           438: **             getlogin
        !           439: **             getpwuid(getuid())
        !           440: **
        !           441: **     The weakness about the last attempt is if the user has multiple
        !           442: **     login names each with the same user ID. If this fails as well then:
        !           443: **
        !           444: **             LOGNAME environment variable
        !           445: **             USER environment variable
        !           446: **
        !           447: **     Returns NULL if error else pointer to static string
        !           448: */
        !           449: PUBLIC const char * HTGetMailAddress (void)
        !           450: {
        !           451: #ifdef HT_REENTRANT
        !           452:   char name[LOGNAME_MAX+1];    /* For getlogin_r or getUserName */
        !           453: #endif
        !           454: #ifdef WWW_MSWINDOWS/* what was the plan for this under windows? - EGP */
        !           455:   char name[256];    /* For getlogin_r or getUserName */
        !           456:   unsigned int bufSize = sizeof(name);
        !           457: #endif
        !           458: #ifdef HAVE_PWD_H
        !           459:     struct passwd * pw_info = NULL;
        !           460: #endif
        !           461:     char * login = NULL;
        !           462:     const char * domain;
        !           463:     if (mailaddress) {
        !           464:        if (*mailaddress)
        !           465:            return mailaddress;
        !           466:        else
        !           467:            return NULL;       /* No luck the last time so we wont try again */
        !           468:     }
        !           469: 
        !           470: #ifdef WWW_MSWINDOWS
        !           471:     if (!login && GetUserName(name, &bufSize) != TRUE)
        !           472:         if (PROT_TRACE) HTTrace("MailAddress. GetUsername returns NO\n");
        !           473: #endif /* WWW_MSWINDOWS */
        !           474: 
        !           475: #ifdef HAVE_CUSERID
        !           476:     if (!login && (login = (char *) cuserid(NULL)) == NULL)
        !           477:         if (PROT_TRACE) HTTrace("MailAddress. cuserid returns NULL\n");
        !           478: #endif /* HAVE_CUSERID */
        !           479: 
        !           480: #ifdef HAVE_GETLOGIN
        !           481: #ifdef HT_REENTRANT
        !           482:     if (!login && (login = (char *) getlogin_r(name, LOGNAME_MAX)) == NULL)
        !           483: #else
        !           484:     if (!login && (login = (char *) getlogin()) == NULL)
        !           485: #endif /* HT_REENTRANT */
        !           486:        if (PROT_TRACE) HTTrace("MailAddress. getlogin returns NULL\n");
        !           487: #endif /* HAVE_GETLOGIN */
        !           488: 
        !           489: #ifdef HAVE_PWD_H
        !           490:     if (!login && (pw_info = getpwuid(getuid())) != NULL)
        !           491:        login = pw_info->pw_name;
        !           492: #endif /* HAVE_PWD_H */
        !           493: 
        !           494:     if (!login && (login = getenv("LOGNAME")) == NULL)
        !           495:        if (PROT_TRACE) HTTrace("MailAddress. LOGNAME not found\n");
        !           496: 
        !           497:     if (!login && (login = getenv("USER")) == NULL)
        !           498:        if (PROT_TRACE) HTTrace("MailAddress. USER not found\n");
        !           499: 
        !           500:     if (!login) login = HT_DEFAULT_LOGIN;
        !           501: 
        !           502:     if (login) {
        !           503:        StrAllocCopy(mailaddress, login);
        !           504:        StrAllocCat(mailaddress, "@");
        !           505:        if ((domain = HTGetHostName()) != NULL)
        !           506:            StrAllocCat(mailaddress, domain);
        !           507:        else {
        !           508:            *mailaddress = '\0';
        !           509:            return NULL;                        /* Domain name not available */
        !           510:        }
        !           511:        return mailaddress;
        !           512:     }
        !           513:     return NULL;
        !           514: }
        !           515: 
        !           516: 
        !           517: /*
        !           518: **     Free the mail address. Called from HTLibTerminate
        !           519: */
        !           520: PUBLIC void HTFreeMailAddress (void)
        !           521: {
        !           522:     HT_FREE(mailaddress);
        !           523: }

Webmaster