diff src/protocols/zephyr/ZInit.c @ 2419:7ba69b8e0de5

[gaim-migrate @ 2432] Salvatore Valente says this is better. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Wed, 03 Oct 2001 19:38:28 +0000
parents 424a40f12a6c
children 43d6c08d7e96
line wrap: on
line diff
--- a/src/protocols/zephyr/ZInit.c	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/ZInit.c	Wed Oct 03 19:38:28 2001 +0000
@@ -24,12 +24,24 @@
 #include <krb_err.h>
 #endif
 
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
 Code_t ZInitialize()
 {
     struct servent *hmserv;
-    char addr[4];
+    struct hostent *hostent;
+    char addr[4], hostname[MAXHOSTNAMELEN];
+    struct in_addr servaddr;
+    struct sockaddr_in sin;
+    int s, sinsize = sizeof(sin);
+    Code_t code;
+    ZNotice_t notice;
 #ifdef ZEPHYR_USES_KERBEROS
+    char *krealm = NULL;
     int krbval;
+    char d1[ANAME_SZ], d2[INST_SZ];
 
     initialize_krb_error_table();
 #endif
@@ -53,17 +65,88 @@
 
     __HM_set = 0;
 
+    /* Initialize the input queue */
+    __Q_Tail = NULL;
+    __Q_Head = NULL;
+    
+    /* if the application is a server, there might not be a zhm.  The
+       code will fall back to something which might not be "right",
+       but this is is ok, since none of the servers call krb_rd_req. */
+
+    servaddr.s_addr = INADDR_NONE;
+    if (! __Zephyr_server) {
+       if ((code = ZOpenPort(NULL)) != ZERR_NONE)
+	  return(code);
+
+       if ((code = ZhmStat(NULL, &notice)) != ZERR_NONE)
+	  return(code);
+
+       ZClosePort();
+
+       /* the first field, which is NUL-terminated, is the server name.
+	  If this code ever support a multiplexing zhm, this will have to
+	  be made smarter, and probably per-message */
+
 #ifdef ZEPHYR_USES_KERBEROS
-    if ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)
+       krealm = krb_realmofhost(notice.z_message);
+#endif
+       hostent = gethostbyname(notice.z_message);
+       if (hostent && hostent->h_addrtype == AF_INET)
+	   memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
+
+       ZFreeNotice(&notice);
+    }
+
+#ifdef ZEPHYR_USES_KERBEROS
+    if (krealm) {
+	strcpy(__Zephyr_realm, krealm);
+    } else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm)
+		!= KSUCCESS) &&
+	       ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) {
 	return (krbval);
+    }
+#else
+    strcpy(__Zephyr_realm, "local-realm");
 #endif
 
+    __My_addr.s_addr = INADDR_NONE;
+    if (servaddr.s_addr != INADDR_NONE) {
+	/* Try to get the local interface address by connecting a UDP
+	 * socket to the server address and getting the local address.
+	 * Some broken operating systems (e.g. Solaris 2.0-2.5) yield
+	 * INADDR_ANY (zero), so we have to check for that. */
+	s = socket(AF_INET, SOCK_DGRAM, 0);
+	if (s != -1) {
+	    memset(&sin, 0, sizeof(sin));
+	    sin.sin_family = AF_INET;
+	    memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr));
+	    sin.sin_port = HM_SRV_SVC_FALLBACK;
+	    if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0
+		&& getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0
+		&& sin.sin_addr.s_addr != 0)
+		memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr));
+	    close(s);
+	}
+    }
+    if (__My_addr.s_addr == INADDR_NONE) {
+	/* We couldn't figure out the local interface address by the
+	 * above method.  Try by resolving the local hostname.  (This
+	 * is a pretty broken thing to do, and unfortunately what we
+	 * always do on server machines.) */
+	if (gethostname(hostname, sizeof(hostname)) == 0) {
+	    hostent = gethostbyname(hostname);
+	    if (hostent && hostent->h_addrtype == AF_INET)
+		memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr));
+	}
+    }
+    /* If the above methods failed, zero out __My_addr so things will
+     * sort of kind of work. */
+    if (__My_addr.s_addr == INADDR_NONE)
+	__My_addr.s_addr = 0;
+
     /* Get the sender so we can cache it */
     (void) ZGetSender();
 
-    /* Initialize the input queue */
-    __Q_Tail = NULL;
-    __Q_Head = NULL;
-    
     return (ZERR_NONE);
 }
+