The right fix for the comparison of hosts. Previous was not good.
[wmaker-crm.git] / WINGs / host.c
blob3a318b4f3b548a93590eb7688de4a0faebdde78c
1 /*
2 * WINGs WMHost function library
4 * Copyright (c) 1999 Dan Pascu
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <unistd.h>
24 #include <string.h>
25 #include <netdb.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
30 #include "WUtil.h"
33 typedef struct W_Host {
34 char *name;
36 WMBag *names;
37 WMBag *addresses;
39 int refCount;
40 } W_Host;
43 static WMHashTable *hostCache = NULL;
44 static Bool hostCacheEnabled = True;
47 /* Max hostname length (RFC 1123) */
48 #define W_MAXHOSTNAMELEN 255
51 static WMHost*
52 getHostFromCache(char *name)
54 if (!hostCache)
55 return NULL;
57 return WMHashGet(hostCache, name);
61 static WMHost*
62 getHostWithHostEntry(struct hostent *host, char *name)
64 WMHost *hPtr;
65 struct in_addr in;
66 int i;
68 hPtr = (WMHost*)wmalloc(sizeof(WMHost));
69 memset(hPtr, 0, sizeof(WMHost));
71 hPtr->names = WMCreateBag(1);
72 hPtr->addresses = WMCreateBag(1);
74 WMPutInBag(hPtr->names, wstrdup(host->h_name));
76 for (i=0; host->h_aliases[i]!=NULL; i++) {
77 WMPutInBag(hPtr->names, wstrdup(host->h_aliases[i]));
80 for (i=0; host->h_addr_list[i]!=NULL; i++) {
81 memcpy((void*)&in.s_addr, (const void*)host->h_addr_list[i],
82 host->h_length);
83 WMPutInBag(hPtr->addresses, wstrdup(inet_ntoa(in)));
86 hPtr->refCount = 1;
88 if (hostCacheEnabled) {
89 if (!hostCache)
90 hostCache = WMCreateHashTable(WMStringPointerHashCallbacks);
91 hPtr->name = wstrdup(name);
92 wassertr(WMHashInsert(hostCache, hPtr->name, hPtr)==NULL);
93 hPtr->refCount++;
96 return hPtr;
100 WMHost*
101 WMGetCurrentHost()
103 char name[W_MAXHOSTNAMELEN+1];
105 if (gethostname(name, W_MAXHOSTNAMELEN) < 0) {
106 wsyserror("Cannot get current host name");
107 return NULL;
110 name[W_MAXHOSTNAMELEN] = '\0';
112 return WMGetHostWithName(name);
116 WMHost*
117 WMGetHostWithName(char* name)
119 struct hostent *host;
120 WMHost *hPtr;
122 if (name == NULL) {
123 wwarning("NULL host name in 'WMGetHostWithName()'");
124 return NULL;
127 if (hostCacheEnabled) {
128 if ((hPtr = getHostFromCache(name)) != NULL) {
129 WMRetainHost(hPtr);
130 return hPtr;
134 host = gethostbyname(name);
135 if (host == NULL) {
136 return NULL;
139 hPtr = getHostWithHostEntry(host, name);
141 return hPtr;
145 WMHost*
146 WMGetHostWithAddress(char* address)
148 struct hostent *host;
149 struct in_addr in;
150 WMHost *hPtr;
152 if (address == NULL) {
153 wwarning("NULL address in 'WMGetHostWithAddress()'");
154 return NULL;
157 if (hostCacheEnabled) {
158 if ((hPtr = getHostFromCache(address)) != NULL) {
159 WMRetainHost(hPtr);
160 return hPtr;
164 #ifndef HAVE_INET_ATON
165 if ((in.s_addr = inet_addr(address)) == INADDR_NONE)
166 return NULL;
167 #else
168 if (inet_aton(address, &in.s_addr) == 0)
169 return NULL;
170 #endif
172 host = gethostbyaddr((char*)&in, sizeof(in), AF_INET);
173 if (host == NULL) {
174 return NULL;
177 hPtr = getHostWithHostEntry(host, address);
179 return hPtr;
183 WMHost*
184 WMRetainHost(WMHost *hPtr)
186 hPtr->refCount++;
187 return hPtr;
191 void
192 WMReleaseHost(WMHost *hPtr)
194 int i;
196 hPtr->refCount--;
198 if (hPtr->refCount > 0)
199 return;
201 for (i=0; i<WMGetBagItemCount(hPtr->names); i++)
202 wfree(WMGetFromBag(hPtr->names, i));
203 for (i=0; i<WMGetBagItemCount(hPtr->addresses); i++)
204 wfree(WMGetFromBag(hPtr->addresses, i));
206 WMFreeBag(hPtr->names);
207 WMFreeBag(hPtr->addresses);
209 if (hPtr->name) {
210 WMHashRemove(hostCache, hPtr->name);
211 wfree(hPtr->name);
214 wfree(hPtr);
218 void
219 WMSetHostCacheEnabled(Bool flag)
221 hostCacheEnabled = flag;
225 Bool
226 WMIsHostCacheEnabled()
228 return hostCacheEnabled;
232 void
233 WMFlushHostCache()
235 if (hostCache && WMCountHashTable(hostCache)>0) {
236 WMBag *hostBag = WMCreateBag(WMCountHashTable(hostCache));
237 WMHashEnumerator enumer = WMEnumerateHashTable(hostCache);
238 WMHost *hPtr;
239 int i;
241 while ((hPtr = WMNextHashEnumeratorItem(&enumer))) {
242 /* we can't release the host here, because we can't change the
243 * hash while using the enumerator functions. */
244 WMPutInBag(hostBag, hPtr);
246 for (i=0; i<WMGetBagItemCount(hostBag); i++)
247 WMReleaseHost(WMGetFromBag(hostBag, i));
248 WMFreeBag(hostBag);
249 WMResetHashTable(hostCache);
254 Bool
255 WMIsHostEqualToHost(WMHost* hPtr, WMHost* aPtr)
257 int i, j;
258 char *adr1, *adr2;
260 wassertrv(hPtr!=NULL && aPtr!=NULL, False);
262 if (hPtr == aPtr)
263 return True;
265 for (i=0; i<WMGetBagItemCount(aPtr->addresses); i++) {
266 adr1 = WMGetFromBag(aPtr->addresses, i);
267 for (j=0; j<WMGetBagItemCount(hPtr->addresses); j++) {
268 adr2 = WMGetFromBag(hPtr->addresses, j);
269 if (strcmp(adr1, adr2)==0)
270 return True;
274 return False;
278 char*
279 WMGetHostName(WMHost *hPtr)
281 return (WMGetBagItemCount(hPtr->names) > 0 ?
282 WMGetFromBag(hPtr->names, 0) : NULL);
283 /*return WMGetFromBag(hPtr->names, 0);*/
287 WMBag*
288 WMGetHostNames(WMHost *hPtr)
290 return hPtr->names;
294 char*
295 WMGetHostAddress(WMHost *hPtr)
297 return (WMGetBagItemCount(hPtr->addresses) > 0 ?
298 WMGetFromBag(hPtr->addresses, 0) : NULL);
302 WMBag*
303 WMGetHostAddresses(WMHost *hPtr)
305 return hPtr->addresses;