Bug fix in the networking code
[wmaker-crm.git] / WINGs / host.c
blob84c532e26d10cadd29eee16a242e4b8ddd95f995
1 /*
2 * WINGs WMHost function library
4 * Copyright (c) 1999-2000 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.
22 #include "../src/config.h"
24 #include <unistd.h>
25 #include <string.h>
26 #include <netdb.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
31 #include "WUtil.h"
34 /* For some Solaris systems */
35 #if !defined(HAVE_INET_ATON) && !defined(INADDR_NONE)
36 # define INADDR_NONE (-1)
37 #endif
40 typedef struct W_Host {
41 char *name;
43 WMBag *names;
44 WMBag *addresses;
46 int refCount;
47 } W_Host;
50 static WMHashTable *hostCache = NULL;
51 static Bool hostCacheEnabled = True;
54 /* Max hostname length (RFC 1123) */
55 #define W_MAXHOSTNAMELEN 255
58 static WMHost*
59 getHostFromCache(char *name)
61 if (!hostCache)
62 return NULL;
64 return WMHashGet(hostCache, name);
68 static WMHost*
69 getHostWithHostEntry(struct hostent *host, char *name)
71 WMHost *hPtr;
72 struct in_addr in;
73 int i;
75 hPtr = (WMHost*)wmalloc(sizeof(WMHost));
76 memset(hPtr, 0, sizeof(WMHost));
78 hPtr->names = WMCreateBag(1);
79 hPtr->addresses = WMCreateBag(1);
81 WMPutInBag(hPtr->names, wstrdup(host->h_name));
83 for (i=0; host->h_aliases[i]!=NULL; i++) {
84 WMPutInBag(hPtr->names, wstrdup(host->h_aliases[i]));
87 for (i=0; host->h_addr_list[i]!=NULL; i++) {
88 memcpy((void*)&in.s_addr, (const void*)host->h_addr_list[i],
89 host->h_length);
90 WMPutInBag(hPtr->addresses, wstrdup(inet_ntoa(in)));
93 hPtr->refCount = 1;
95 if (hostCacheEnabled) {
96 if (!hostCache)
97 hostCache = WMCreateHashTable(WMStringPointerHashCallbacks);
98 hPtr->name = wstrdup(name);
99 wassertr(WMHashInsert(hostCache, hPtr->name, hPtr)==NULL);
100 hPtr->refCount++;
103 return hPtr;
107 WMHost*
108 WMGetCurrentHost()
110 char name[W_MAXHOSTNAMELEN+1];
112 if (gethostname(name, W_MAXHOSTNAMELEN) < 0) {
113 wsyserror("Cannot get current host name");
114 return NULL;
117 name[W_MAXHOSTNAMELEN] = '\0';
119 return WMGetHostWithName(name);
123 WMHost*
124 WMGetHostWithName(char* name)
126 struct hostent *host;
127 WMHost *hPtr;
129 if (name == NULL) {
130 wwarning("NULL host name in 'WMGetHostWithName()'");
131 return NULL;
134 if (hostCacheEnabled) {
135 if ((hPtr = getHostFromCache(name)) != NULL) {
136 WMRetainHost(hPtr);
137 return hPtr;
141 host = gethostbyname(name);
142 if (host == NULL) {
143 return NULL;
146 hPtr = getHostWithHostEntry(host, name);
148 return hPtr;
152 WMHost*
153 WMGetHostWithAddress(char* address)
155 struct hostent *host;
156 struct in_addr in;
157 WMHost *hPtr;
159 if (address == NULL) {
160 wwarning("NULL address in 'WMGetHostWithAddress()'");
161 return NULL;
164 if (hostCacheEnabled) {
165 if ((hPtr = getHostFromCache(address)) != NULL) {
166 WMRetainHost(hPtr);
167 return hPtr;
171 #ifndef HAVE_INET_ATON
172 if ((in.s_addr = inet_addr(address)) == INADDR_NONE)
173 return NULL;
174 #else
175 if (inet_aton(address, &in) == 0)
176 return NULL;
177 #endif
179 host = gethostbyaddr((char*)&in, sizeof(in), AF_INET);
180 if (host == NULL) {
181 return NULL;
184 hPtr = getHostWithHostEntry(host, address);
186 return hPtr;
190 WMHost*
191 WMRetainHost(WMHost *hPtr)
193 hPtr->refCount++;
194 return hPtr;
198 void
199 WMReleaseHost(WMHost *hPtr)
201 int i;
203 hPtr->refCount--;
205 if (hPtr->refCount > 0)
206 return;
208 for (i=0; i<WMGetBagItemCount(hPtr->names); i++)
209 wfree(WMGetFromBag(hPtr->names, i));
210 for (i=0; i<WMGetBagItemCount(hPtr->addresses); i++)
211 wfree(WMGetFromBag(hPtr->addresses, i));
213 WMFreeBag(hPtr->names);
214 WMFreeBag(hPtr->addresses);
216 if (hPtr->name) {
217 WMHashRemove(hostCache, hPtr->name);
218 wfree(hPtr->name);
221 wfree(hPtr);
225 void
226 WMSetHostCacheEnabled(Bool flag)
228 hostCacheEnabled = flag;
232 Bool
233 WMIsHostCacheEnabled()
235 return hostCacheEnabled;
239 void
240 WMFlushHostCache()
242 if (hostCache && WMCountHashTable(hostCache)>0) {
243 WMBag *hostBag = WMCreateBag(WMCountHashTable(hostCache));
244 WMHashEnumerator enumer = WMEnumerateHashTable(hostCache);
245 WMHost *hPtr;
246 int i;
248 while ((hPtr = WMNextHashEnumeratorItem(&enumer))) {
249 /* we can't release the host here, because we can't change the
250 * hash while using the enumerator functions. */
251 WMPutInBag(hostBag, hPtr);
253 for (i=0; i<WMGetBagItemCount(hostBag); i++)
254 WMReleaseHost(WMGetFromBag(hostBag, i));
255 WMFreeBag(hostBag);
256 WMResetHashTable(hostCache);
261 Bool
262 WMIsHostEqualToHost(WMHost* hPtr, WMHost* aPtr)
264 int i, j;
265 char *adr1, *adr2;
267 wassertrv(hPtr!=NULL && aPtr!=NULL, False);
269 if (hPtr == aPtr)
270 return True;
272 for (i=0; i<WMGetBagItemCount(aPtr->addresses); i++) {
273 adr1 = WMGetFromBag(aPtr->addresses, i);
274 for (j=0; j<WMGetBagItemCount(hPtr->addresses); j++) {
275 adr2 = WMGetFromBag(hPtr->addresses, j);
276 if (strcmp(adr1, adr2)==0)
277 return True;
281 return False;
285 char*
286 WMGetHostName(WMHost *hPtr)
288 return (WMGetBagItemCount(hPtr->names) > 0 ?
289 WMGetFromBag(hPtr->names, 0) : NULL);
290 /*return WMGetFromBag(hPtr->names, 0);*/
294 WMBag*
295 WMGetHostNames(WMHost *hPtr)
297 return hPtr->names;
301 char*
302 WMGetHostAddress(WMHost *hPtr)
304 return (WMGetBagItemCount(hPtr->addresses) > 0 ?
305 WMGetFromBag(hPtr->addresses, 0) : NULL);
309 WMBag*
310 WMGetHostAddresses(WMHost *hPtr)
312 return hPtr->addresses;