]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZInit.c
391992f1c3bad73c653f9280c2ecddca879b95cf
[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 #ifdef HAVE_KRB5_ERR_H
25 #include <krb5_err.h>
26 #endif
27
28 #ifndef INADDR_NONE
29 #define INADDR_NONE 0xffffffff
30 #endif
31
32 Code_t ZInitialize()
33 {
34     struct servent *hmserv;
35     struct hostent *hostent;
36     char addr[4], hostname[MAXHOSTNAMELEN];
37     struct in_addr servaddr;
38     struct sockaddr_in sin;
39     int s, sinsize = sizeof(sin);
40     Code_t code;
41     ZNotice_t notice;
42 #ifdef HAVE_KRB4
43     char *krealm = NULL;
44     int krbval;
45     char d1[ANAME_SZ], d2[INST_SZ];
46
47     initialize_krb_error_table();
48 #endif
49 #ifdef HAVE_KRB5
50     initialize_krb5_error_table();
51 #endif
52
53     initialize_zeph_error_table();
54     
55     (void) memset((char *)&__HM_addr, 0, sizeof(__HM_addr));
56
57     __HM_addr.sin_family = AF_INET;
58
59     /* Set up local loopback address for HostManager */
60     addr[0] = 127;
61     addr[1] = 0;
62     addr[2] = 0;
63     addr[3] = 1;
64
65     hmserv = (struct servent *)getservbyname(HM_SVCNAME, "udp");
66     __HM_addr.sin_port = (hmserv) ? hmserv->s_port : HM_SVC_FALLBACK;
67
68     (void) memcpy((char *)&__HM_addr.sin_addr, addr, 4);
69
70     __HM_set = 0;
71
72     /* Initialize the input queue */
73     __Q_Tail = NULL;
74     __Q_Head = NULL;
75     
76 #ifdef HAVE_KRB5
77     if ((code = krb5_init_context(&Z_krb5_ctx)))
78         return(code);
79 #endif
80
81     /* if the application is a server, there might not be a zhm.  The
82        code will fall back to something which might not be "right",
83        but this is is ok, since none of the servers call krb_rd_req. */
84
85     servaddr.s_addr = INADDR_NONE;
86     if (! __Zephyr_server) {
87        if ((code = ZOpenPort(NULL)) != ZERR_NONE)
88           return(code);
89
90        if ((code = ZhmStat(NULL, &notice)) != ZERR_NONE)
91           return(code);
92
93        ZClosePort();
94
95        /* the first field, which is NUL-terminated, is the server name.
96           If this code ever support a multiplexing zhm, this will have to
97           be made smarter, and probably per-message */
98
99 #ifdef HAVE_KRB4
100        krealm = krb_realmofhost(notice.z_message);
101 #endif
102        hostent = gethostbyname(notice.z_message);
103        if (hostent && hostent->h_addrtype == AF_INET)
104            memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
105
106        ZFreeNotice(&notice);
107     }
108
109 #ifdef HAVE_KRB4
110     if (krealm) {
111         strcpy(__Zephyr_realm, krealm);
112     } else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm)
113                 != KSUCCESS) &&
114                ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) {
115         return (krbval);
116     }
117 #else
118     strcpy(__Zephyr_realm, "local-realm");
119 #endif
120
121     __My_addr.s_addr = INADDR_NONE;
122     if (servaddr.s_addr != INADDR_NONE) {
123         /* Try to get the local interface address by connecting a UDP
124          * socket to the server address and getting the local address.
125          * Some broken operating systems (e.g. Solaris 2.0-2.5) yield
126          * INADDR_ANY (zero), so we have to check for that. */
127         s = socket(AF_INET, SOCK_DGRAM, 0);
128         if (s != -1) {
129             memset(&sin, 0, sizeof(sin));
130             sin.sin_family = AF_INET;
131             memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr));
132             sin.sin_port = HM_SRV_SVC_FALLBACK;
133             if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0
134                 && getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0
135                 && sin.sin_addr.s_addr != 0)
136                 memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr));
137             close(s);
138         }
139     }
140     if (__My_addr.s_addr == INADDR_NONE) {
141         /* We couldn't figure out the local interface address by the
142          * above method.  Try by resolving the local hostname.  (This
143          * is a pretty broken thing to do, and unfortunately what we
144          * always do on server machines.) */
145         if (gethostname(hostname, sizeof(hostname)) == 0) {
146             hostent = gethostbyname(hostname);
147             if (hostent && hostent->h_addrtype == AF_INET)
148                 memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr));
149         }
150     }
151     /* If the above methods failed, zero out __My_addr so things will
152      * sort of kind of work. */
153     if (__My_addr.s_addr == INADDR_NONE)
154         __My_addr.s_addr = 0;
155
156     /* Get the sender so we can cache it */
157     (void) ZGetSender();
158
159     return (ZERR_NONE);
160 }
161