]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZInit.c
5479de974b87b70d582fb36599fb6051d564632a
[1ts-debian.git] / zephyr / lib / ZInit.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains source for the ZInitialize function.
3  *
4  *      Created by:     Robert French
5  *
6  *      $Id: ZInit.c,v 1.27 1999/01/22 23:19:14 ghudson Exp $
7  *
8  *      Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #ifndef lint
14 static char rcsid_ZInitialize_c[] =
15     "$Zephyr: /afs/athena.mit.edu/astaff/project/zephyr/src/lib/RCS/ZInitialize.c,v 1.17 89/05/30 18:11:25 jtkohl Exp $";
16 #endif
17
18 #include <internal.h>
19
20 #include <sys/socket.h>
21 #ifdef HAVE_KRB4
22 #include <krb_err.h>
23 #endif
24
25 #ifndef INADDR_NONE
26 #define INADDR_NONE 0xffffffff
27 #endif
28
29 Code_t ZInitialize()
30 {
31     struct servent *hmserv;
32     struct hostent *hostent;
33     char addr[4], hostname[MAXHOSTNAMELEN];
34     struct in_addr servaddr;
35     struct sockaddr_in sin;
36     int s, sinsize = sizeof(sin);
37     Code_t code;
38     ZNotice_t notice;
39 #ifdef HAVE_KRB4
40     char *krealm = NULL;
41     int krbval;
42     char d1[ANAME_SZ], d2[INST_SZ];
43
44     initialize_krb_error_table();
45 #endif
46
47     initialize_zeph_error_table();
48     
49     (void) memset((char *)&__HM_addr, 0, sizeof(__HM_addr));
50
51     __HM_addr.sin_family = AF_INET;
52
53     /* Set up local loopback address for HostManager */
54     addr[0] = 127;
55     addr[1] = 0;
56     addr[2] = 0;
57     addr[3] = 1;
58
59     hmserv = (struct servent *)getservbyname(HM_SVCNAME, "udp");
60     __HM_addr.sin_port = (hmserv) ? hmserv->s_port : HM_SVC_FALLBACK;
61
62     (void) memcpy((char *)&__HM_addr.sin_addr, addr, 4);
63
64     __HM_set = 0;
65
66     /* Initialize the input queue */
67     __Q_Tail = NULL;
68     __Q_Head = NULL;
69     
70     /* if the application is a server, there might not be a zhm.  The
71        code will fall back to something which might not be "right",
72        but this is is ok, since none of the servers call krb_rd_req. */
73
74     servaddr.s_addr = INADDR_NONE;
75     if (! __Zephyr_server) {
76        if ((code = ZOpenPort(NULL)) != ZERR_NONE)
77           return(code);
78
79        if ((code = ZhmStat(NULL, &notice)) != ZERR_NONE)
80           return(code);
81
82        ZClosePort();
83
84        /* the first field, which is NUL-terminated, is the server name.
85           If this code ever support a multiplexing zhm, this will have to
86           be made smarter, and probably per-message */
87
88 #ifdef HAVE_KRB4
89        krealm = krb_realmofhost(notice.z_message);
90 #endif
91        hostent = gethostbyname(notice.z_message);
92        if (hostent && hostent->h_addrtype == AF_INET)
93            memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
94
95        ZFreeNotice(&notice);
96     }
97
98 #ifdef HAVE_KRB4
99     if (krealm) {
100         strcpy(__Zephyr_realm, krealm);
101     } else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm)
102                 != KSUCCESS) &&
103                ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) {
104         return (krbval);
105     }
106 #else
107     strcpy(__Zephyr_realm, "local-realm");
108 #endif
109
110     __My_addr.s_addr = INADDR_NONE;
111     if (servaddr.s_addr != INADDR_NONE) {
112         /* Try to get the local interface address by connecting a UDP
113          * socket to the server address and getting the local address.
114          * Some broken operating systems (e.g. Solaris 2.0-2.5) yield
115          * INADDR_ANY (zero), so we have to check for that. */
116         s = socket(AF_INET, SOCK_DGRAM, 0);
117         if (s != -1) {
118             memset(&sin, 0, sizeof(sin));
119             sin.sin_family = AF_INET;
120             memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr));
121             sin.sin_port = HM_SRV_SVC_FALLBACK;
122             if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0
123                 && getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0
124                 && sin.sin_addr.s_addr != 0)
125                 memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr));
126             close(s);
127         }
128     }
129     if (__My_addr.s_addr == INADDR_NONE) {
130         /* We couldn't figure out the local interface address by the
131          * above method.  Try by resolving the local hostname.  (This
132          * is a pretty broken thing to do, and unfortunately what we
133          * always do on server machines.) */
134         if (gethostname(hostname, sizeof(hostname)) == 0) {
135             hostent = gethostbyname(hostname);
136             if (hostent && hostent->h_addrtype == AF_INET)
137                 memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr));
138         }
139     }
140     /* If the above methods failed, zero out __My_addr so things will
141      * sort of kind of work. */
142     if (__My_addr.s_addr == INADDR_NONE)
143         __My_addr.s_addr = 0;
144
145     /* Get the sender so we can cache it */
146     (void) ZGetSender();
147
148     return (ZERR_NONE);
149 }
150