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