changeset 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 a2cc1cf4198f
children 938a432173b4
files src/protocols/zephyr/.cvsignore src/protocols/zephyr/Makefile.am src/protocols/zephyr/ZInit.c src/protocols/zephyr/ZLocations.c src/protocols/zephyr/ZSendPkt.c src/protocols/zephyr/ZSubs.c src/protocols/zephyr/ZhmStat.c src/protocols/zephyr/Zinternal.c src/protocols/zephyr/internal.h src/protocols/zephyr/zephyr.h
diffstat 10 files changed, 211 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/zephyr/.cvsignore	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/.cvsignore	Wed Oct 03 19:38:28 2001 +0000
@@ -49,6 +49,7 @@
 ZSubs.lo
 ZVariables.lo
 ZWait4Not.lo
+ZhmStat.lo
 Zinternal.lo
 error_message.lo
 et_name.lo
--- a/src/protocols/zephyr/Makefile.am	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/Makefile.am	Wed Oct 03 19:38:28 2001 +0000
@@ -129,6 +129,7 @@
 			ZSubs.c \
 			ZVariables.c \
 			ZWait4Not.c \
+			ZhmStat.c \
 			Zinternal.c \
 			com_err.h \
 			error_message.c \
--- 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);
 }
+
--- a/src/protocols/zephyr/ZLocations.c	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/ZLocations.c	Wed Oct 03 19:38:28 2001 +0000
@@ -55,7 +55,7 @@
     int retval;
     time_t ourtime;
     ZNotice_t notice, retnotice;
-    char *bptr[3];
+    char *bptr[3], *p;
 #ifndef X_DISPLAY_MISSING
     char *display;
 #endif
@@ -89,36 +89,29 @@
 	      (void) strncpy(host, hent->h_name, sizeof(host));
 	      host[sizeof(host) - 1] = '\0';
 	    }
-	    bptr[0] = host;
 #ifndef X_DISPLAY_MISSING
 	    if ((display = getenv("DISPLAY")) && *display) {
 		    (void) strcpy(mytty, display);
-		    bptr[2] = mytty;
 	    } else {
 #endif
 		    ttyp = ttyname(0);
-		    if (ttyp) {
-			bptr[2] = strrchr(ttyp, '/');
-			if (bptr[2])
-			    bptr[2]++;
-			else
-			    bptr[2] = ttyp;
+		    if (ttyp && *ttyp) {
+			p = strchr(ttyp + 1, '/');
+			strcpy(mytty, (p) ? p + 1 : ttyp);
+		    } else {
+			strcpy(mytty, "unknown");
 		    }
-		    else
-			bptr[2] = "unknown";
-		    (void) strcpy(mytty, bptr[2]);
 #ifndef X_DISPLAY_MISSING
 	    }
 #endif
 	    reenter = 1;
-    } else {
-	    bptr[0] = host;
-	    bptr[2] = mytty;
     }
 
     ourtime = time((time_t *)0);
+    bptr[0] = host;
     bptr[1] = ctime(&ourtime);
     bptr[1][strlen(bptr[1])-1] = '\0';
+    bptr[2] = mytty;
 
 	
     if ((retval = ZSendList(&notice, bptr, 3, auth)) != ZERR_NONE)
--- a/src/protocols/zephyr/ZSendPkt.c	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/ZSendPkt.c	Wed Oct 03 19:38:28 2001 +0000
@@ -20,7 +20,7 @@
 #include <internal.h>
 #include <sys/socket.h>
 
-static int wait_for_ack();
+static int wait_for_hmack();
 
 Code_t ZSendPacket(packet, len, waitforack)
     char *packet;
@@ -53,7 +53,7 @@
     if ((retval = ZParseNotice(packet, len, &notice)) != ZERR_NONE)
 	return (retval);
     
-    retval = Z_WaitForNotice (&acknotice, wait_for_ack, &notice.z_uid,
+    retval = Z_WaitForNotice (&acknotice, wait_for_hmack, &notice.z_uid,
 			      HM_TIMEOUT);
     if (retval == ETIMEDOUT)
       return ZERR_HMDEAD;
@@ -62,12 +62,9 @@
     return retval;
 }
 
-static int wait_for_ack(notice, uid)
+static int wait_for_hmack(notice, uid)
     ZNotice_t *notice;
     ZUnique_Id_t *uid;
 {
-  return (ZCompareUID(&notice->z_uid, uid) &&
-	  (notice->z_kind == HMACK     ||
-	   notice->z_kind == SERVACK   ||
-	   notice->z_kind == CLIENTACK ));
+    return (notice->z_kind == HMACK && ZCompareUID(&notice->z_uid, uid));
 }
--- a/src/protocols/zephyr/ZSubs.c	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/ZSubs.c	Wed Oct 03 19:38:28 2001 +0000
@@ -16,7 +16,7 @@
 #include <internal.h>
 
 #ifndef lint
-static const char rcsid_ZSubscriptions_c[] = "$Id: ZSubs.c 2096 2001-07-31 01:00:39Z warmenhoven $";
+static const char rcsid_ZSubscriptions_c[] = "$Id: ZSubs.c 2432 2001-10-03 19:38:28Z warmenhoven $";
 #endif
 
 static Code_t Z_Subscriptions __P((register ZSubscription_t *sublist,
@@ -103,7 +103,7 @@
     retval = Z_FormatHeader(&notice, header, sizeof(header), &hdrlen, ZAUTH);
     if (retval != ZERR_NONE && !authit)
 	retval = Z_FormatHeader(&notice, header, sizeof(header),
-				&hdrlen, ZAUTH);
+				&hdrlen, ZNOAUTH);
     if (retval != ZERR_NONE) {
 	free((char *)list);
 	return(retval);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/zephyr/ZhmStat.c	Wed Oct 03 19:38:28 2001 +0000
@@ -0,0 +1,72 @@
+/* This file is part of the Project Athena Zephyr Notification System.
+ * It contains the ZhmStat() function.
+ *
+ *      Created by:     Marc Horowitz
+ *
+ *      $Id: ZhmStat.c 2432 2001-10-03 19:38:28Z warmenhoven $
+ *
+ *      Copyright (c) 1996 by the Massachusetts Institute of Technology.
+ *      For copying and distribution information, see the file
+ *      "mit-copyright.h". 
+ */
+
+#include <internal.h>
+#include <sys/socket.h>
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+Code_t ZhmStat(hostaddr, notice)
+    struct in_addr *hostaddr;
+    ZNotice_t *notice;
+{
+    struct servent *sp;
+    struct sockaddr_in sin;
+    ZNotice_t req;
+    Code_t code;
+    struct timeval tv;
+    fd_set readers;
+
+    (void) memset((char *)&sin, 0, sizeof(struct sockaddr_in));
+
+    sp = getservbyname(HM_SVCNAME, "udp");
+
+    sin.sin_port = (sp) ? sp->s_port : HM_SVC_FALLBACK;
+    sin.sin_family = AF_INET;
+
+    if (hostaddr)
+	sin.sin_addr = *hostaddr;
+    else
+	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    (void) memset((char *)&req, 0, sizeof(req));
+    req.z_kind = STAT;
+    req.z_port = 0;
+    req.z_class = HM_STAT_CLASS;
+    req.z_class_inst = HM_STAT_CLIENT;
+    req.z_opcode = HM_GIMMESTATS;
+    req.z_sender = "";
+    req.z_recipient = "";
+    req.z_default_format = "";
+    req.z_message_len = 0;
+	
+    if ((code = ZSetDestAddr(&sin)) != ZERR_NONE)
+	return(code);
+
+    if ((code = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE)
+	return(code);
+
+    /* Wait up to ten seconds for a response. */
+    FD_ZERO(&readers);
+    FD_SET(ZGetFD(), &readers);
+    tv.tv_sec = 10;
+    tv.tv_usec = 0;
+    code = select(ZGetFD() + 1, &readers, NULL, NULL, &tv);
+    if (code < 0 && errno != EINTR)
+	return(errno);
+    if (code == 0 || (code < 0 && errno == EINTR) || ZPending() == 0)
+	return(ZERR_HMDEAD);
+
+    return(ZReceiveNotice(notice, (struct sockaddr_in *) 0));
+}
--- a/src/protocols/zephyr/Zinternal.c	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/Zinternal.c	Wed Oct 03 19:38:28 2001 +0000
@@ -20,7 +20,7 @@
 
 #ifndef lint
 static const char rcsid_Zinternal_c[] =
-  "$Id: Zinternal.c 2096 2001-07-31 01:00:39Z warmenhoven $";
+  "$Id: Zinternal.c 2432 2001-10-03 19:38:28Z warmenhoven $";
 static const char copyright[] =
   "Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.";
 #endif
@@ -30,8 +30,7 @@
 int __Zephyr_fd = -1;
 int __Zephyr_open;
 int __Zephyr_port = -1;
-int __My_length;
-char *__My_addr;
+struct in_addr __My_addr;
 int __Q_CompleteLength;
 int __Q_Size;
 struct _Z_InputQ *__Q_Head, *__Q_Tail;
@@ -45,11 +44,12 @@
 ZSubscription_t *__subscriptions_list;
 int __subscriptions_num;
 int __subscriptions_next;
+int Z_discarded_packets = 0;
 
 #ifdef ZEPHYR_USES_KERBEROS
 C_Block __Zephyr_session;
+#endif
 char __Zephyr_realm[REALM_SZ];
-#endif
 
 #ifdef Z_DEBUG
 void (*__Z_debug_print) __P((const char *fmt, va_list args, void *closure));
@@ -133,35 +133,6 @@
     return 0;
 }
 
-/* Get the address of the local host and cache it */
-
-Code_t Z_GetMyAddr()
-{
-    register struct hostent *myhost;
-    char hostname[MAXHOSTNAMELEN];
-	
-    if (__My_length > 0)
-	return (ZERR_NONE);
-
-    if (gethostname(hostname, MAXHOSTNAMELEN) < 0)
-	return (errno);
-
-    if (!(myhost = gethostbyname(hostname)))
-	return (errno);
-
-    /* If h_length is 0, that is a serious problem and it doesn't
-       make it worse for malloc(0) to return NULL, so don't worry
-       about that case. */
-    if (!(__My_addr = (char *)malloc((unsigned)myhost->h_length)))
-	return (ENOMEM);
-
-    __My_length = myhost->h_length;
-
-    (void) memcpy(__My_addr, myhost->h_addr, myhost->h_length);
-
-    return (ZERR_NONE);
-} 
-
 
 /* Return 1 if there is a packet waiting, 0 otherwise */
 
@@ -254,14 +225,25 @@
     ZNotice_t notice;
     ZPacket_t packet;
     struct sockaddr_in olddest, from;
-    int from_len, packet_len, part, partof;
+    int from_len, packet_len, zvlen, part, partof;
     char *slash;
     Code_t retval;
-    register int i;
+    fd_set fds;
+    struct timeval tv;
 
     if (ZGetFD() < 0)
 	return (ZERR_NOPORT);
 	
+    FD_ZERO(&fds);
+    FD_SET(ZGetFD(), &fds);
+    tv.tv_sec = 60;
+    tv.tv_usec = 0;
+
+    if (select(ZGetFD() + 1, &fds, NULL, NULL, &tv) < 0)
+      return (errno);
+    if (!FD_ISSET(ZGetFD(), &fds))
+      return ETIMEDOUT;
+
     from_len = sizeof(struct sockaddr_in);
 
     packet_len = recvfrom(ZGetFD(), packet, sizeof(packet), 0, 
@@ -273,15 +255,12 @@
     if (!packet_len)
 	return (ZERR_EOF);
 
-    /* XXX Check for null data (debugging) */
-    for (i = packet_len - 1; i >= 0; i--)
-      if (packet[i])
-	goto not_all_null;
-#ifdef Z_DEBUG
-    Z_debug ("got null packet from %s", inet_ntoa (from.sin_addr));
-#endif
-    return ZERR_NONE;
-  not_all_null:
+    /* Ignore obviously non-Zephyr packets. */
+    zvlen = sizeof(ZVERSIONHDR) - 1;
+    if (packet_len < zvlen || memcmp(packet, ZVERSIONHDR, zvlen) != 0) {
+	Z_discarded_packets++;
+	return (ZERR_NONE);
+    }	
 
     /* Parse the notice */
     if ((retval = ZParseNotice(packet, packet_len, &notice)) != ZERR_NONE)
@@ -631,10 +610,7 @@
     notice->z_uid.tv.tv_sec = htonl((u_long) notice->z_uid.tv.tv_sec);
     notice->z_uid.tv.tv_usec = htonl((u_long) notice->z_uid.tv.tv_usec);
     
-    if ((retval = Z_GetMyAddr()) != ZERR_NONE)
-	return (retval);
-
-    (void) memcpy((char *)&notice->z_uid.zuid_addr, __My_addr, __My_length);
+    (void) memcpy(&notice->z_uid.zuid_addr, &__My_addr, sizeof(__My_addr));
 
     notice->z_multiuid = notice->z_uid;
 
@@ -742,8 +718,8 @@
     }
     else {
 	if (strlen(notice->z_recipient) + strlen(__Zephyr_realm) + 2 >
-		sizeof(newrecip))
-	    return (ZERR_HEADERLEN);            
+	    sizeof(newrecip))
+	    return (ZERR_HEADERLEN);
 	(void) sprintf(newrecip, "%s@%s", notice->z_recipient, __Zephyr_realm);
 	if (Z_AddField(&ptr, newrecip, end))
 	    return (ZERR_HEADERLEN);
@@ -905,10 +881,8 @@
 		htonl((u_long) partnotice.z_uid.tv.tv_sec);
 	    partnotice.z_uid.tv.tv_usec =
 		htonl((u_long) partnotice.z_uid.tv.tv_usec);
-	    if ((retval = Z_GetMyAddr()) != ZERR_NONE)
-		return (retval);
-	    (void) memcpy((char *)&partnotice.z_uid.zuid_addr, __My_addr, 
-			   __My_length);
+	    (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr, 
+			  sizeof(__My_addr));
 	}
 	message_len = min(notice->z_message_len-offset, fragsize);
 	partnotice.z_message = notice->z_message+offset;
--- a/src/protocols/zephyr/internal.h	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/internal.h	Wed Oct 03 19:38:28 2001 +0000
@@ -69,6 +69,7 @@
 extern int __subscriptions_next;
 
 extern int __Zephyr_port;		/* Port number */
+extern struct in_addr __My_addr;
 
 typedef Code_t (*Z_SendProc) __P((ZNotice_t *, char *, int, int));
 
--- a/src/protocols/zephyr/zephyr.h	Wed Oct 03 18:13:50 2001 +0000
+++ b/src/protocols/zephyr/zephyr.h	Wed Oct 03 19:38:28 2001 +0000
@@ -5,7 +5,7 @@
  *
  *	$Source$
  *	$Author: warmenhoven $
- *	$Id: zephyr.h 2096 2001-07-31 01:00:39Z warmenhoven $
+ *	$Id: zephyr.h 2432 2001-10-03 19:38:28Z warmenhoven $
  *
  *	Copyright (c) 1987,1988,1991 by the Massachusetts Institute of
  *	Technology. For copying and distribution information, see the
@@ -21,9 +21,6 @@
 #include <sys/time.h>
 
 #include <zephyr/zephyr_err.h>
-#ifdef ZEPHYR_USES_KERBEROS
-#include <krb.h>
-#endif
 
 #ifndef IPPROTO_MAX	/* Make sure not already included */
 #include <netinet/in.h>
@@ -166,6 +163,7 @@
 Code_t ZLocateUser ZP((char *, int *, Z_AuthProc));
 Code_t ZRequestLocations ZP((char *, ZAsyncLocateData_t *,
 			     ZNotice_Kind_t, Z_AuthProc));
+Code_t ZhmStat ZP((struct in_addr *, ZNotice_t *));
 Code_t ZInitialize ZP((void));
 Code_t ZSetServerState ZP((int));
 Code_t ZSetFD ZP((int));
@@ -178,10 +176,9 @@
 Code_t ZMakeAscii16 ZP((char *, int, unsigned int));
 Code_t ZReceivePacket ZP((ZPacket_t, int*, struct sockaddr_in*));
 Code_t ZCheckAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
+Code_t ZSetLocation ZP((char *exposure));
+Code_t ZUnsetLocation ZP((void));
 Code_t ZFlushMyLocations ZP((void));
-#ifdef ZEPHYR_USES_KERBEROS
-Code_t ZFormatAuthenticNotice ZP((ZNotice_t*, char*, int, int*, C_Block));
-#endif
 Code_t ZFormatRawNotice ZP((ZNotice_t *, char**, int *));
 Code_t ZRetrieveSubscriptions ZP((unsigned short, int*));
 Code_t ZOpenPort ZP((unsigned short *port));
@@ -230,15 +227,6 @@
 #define ZGetDestAddr()	__HM_addr
 #define ZGetRealm()	__Zephyr_realm
 
-#ifdef ZEPHYR_USES_KERBEROS
-/* Session key for last parsed packet - server only */
-extern C_Block __Zephyr_session;
-#define ZGetSession() (__Zephyr_session)
-#else
-#define __Zephyr_realm ("local-realm")
-#endif
-
-
 #ifdef Z_DEBUG
 void ZSetDebug ZP((void (*)(ZCONST char *, va_list, void *), void *));
 #define ZSetDebug(proc,closure)    (__Z_debug_print=(proc), \
@@ -338,5 +326,6 @@
 #define USER_REREAD		"REREAD"	/* Opcode: Reread desc file */
 #define USER_SHUTDOWN		"SHUTDOWN"	/* Opcode: Go catatonic */
 #define USER_STARTUP		"STARTUP"	/* Opcode: Come out of it */
+#define USER_EXIT		"EXIT"		/* Opcode: Exit the client */
 
 #endif /* __ZEPHYR_H__ */