Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / host.c
1 /*
2  *  WINGs WMHost function library
3  *
4  *  Copyright (c) 1999-2003 Dan Pascu
5  *
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.
10  *
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.
15  *
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.
19  */
20
21 #include "wconfig.h"
22
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>
29
30 #include "WUtil.h"
31
32 /* For Solaris */
33 #ifndef INADDR_NONE
34 # define INADDR_NONE  (-1)
35 #endif
36
37 /* Max hostname length (RFC  1123) */
38 #define W_MAXHOSTNAMELEN        255
39
40 typedef struct W_Host {
41         char *name;
42
43         WMArray *names;
44         WMArray *addresses;
45
46         int refCount;
47 } W_Host;
48
49 static WMHashTable *hostCache = NULL;
50
51 static Bool hostCacheEnabled = True;
52
53 static WMHost *getHostFromCache(char *name)
54 {
55         if (!hostCache)
56                 return NULL;
57
58         return WMHashGet(hostCache, name);
59 }
60
61 static WMHost *getHostWithHostEntry(struct hostent *host, char *name)
62 {
63         WMHost *hPtr;
64         struct in_addr in;
65         int i;
66
67         hPtr = (WMHost *) wmalloc(sizeof(WMHost));
68         memset(hPtr, 0, sizeof(WMHost));
69
70         hPtr->names = WMCreateArrayWithDestructor(1, wfree);
71         hPtr->addresses = WMCreateArrayWithDestructor(1, wfree);
72
73         WMAddToArray(hPtr->names, wstrdup(host->h_name));
74
75         for (i = 0; host->h_aliases[i] != NULL; i++) {
76                 WMAddToArray(hPtr->names, wstrdup(host->h_aliases[i]));
77         }
78
79         for (i = 0; host->h_addr_list[i] != NULL; i++) {
80                 memcpy((void *)&in.s_addr, (const void *)host->h_addr_list[i], host->h_length);
81                 WMAddToArray(hPtr->addresses, wstrdup(inet_ntoa(in)));
82         }
83
84         hPtr->refCount = 1;
85
86         if (hostCacheEnabled) {
87                 if (!hostCache)
88                         hostCache = WMCreateHashTable(WMStringPointerHashCallbacks);
89                 hPtr->name = wstrdup(name);
90                 wassertr(WMHashInsert(hostCache, hPtr->name, hPtr) == NULL);
91                 hPtr->refCount++;
92         }
93
94         return hPtr;
95 }
96
97 WMHost *WMGetCurrentHost()
98 {
99         char name[W_MAXHOSTNAMELEN + 1];
100
101         if (gethostname(name, W_MAXHOSTNAMELEN) < 0) {
102                 wsyserror(_("Cannot get current host name"));
103                 return NULL;
104         }
105
106         name[W_MAXHOSTNAMELEN] = 0;
107
108         return WMGetHostWithName(name);
109 }
110
111 WMHost *WMGetHostWithName(char *name)
112 {
113         struct hostent *host;
114         WMHost *hPtr;
115
116         wassertrv(name != NULL, NULL);
117
118         if (hostCacheEnabled) {
119                 if ((hPtr = getHostFromCache(name)) != NULL) {
120                         WMRetainHost(hPtr);
121                         return hPtr;
122                 }
123         }
124
125         host = gethostbyname(name);
126         if (host == NULL) {
127                 return NULL;
128         }
129
130         hPtr = getHostWithHostEntry(host, name);
131
132         return hPtr;
133 }
134
135 WMHost *WMGetHostWithAddress(char *address)
136 {
137         struct hostent *host;
138         struct in_addr in;
139         WMHost *hPtr;
140
141         wassertrv(address != NULL, NULL);
142
143         if (hostCacheEnabled) {
144                 if ((hPtr = getHostFromCache(address)) != NULL) {
145                         WMRetainHost(hPtr);
146                         return hPtr;
147                 }
148         }
149 #ifndef HAVE_INET_ATON
150         if ((in.s_addr = inet_addr(address)) == INADDR_NONE)
151                 return NULL;
152 #else
153         if (inet_aton(address, &in) == 0)
154                 return NULL;
155 #endif
156
157         host = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
158         if (host == NULL) {
159                 return NULL;
160         }
161
162         hPtr = getHostWithHostEntry(host, address);
163
164         return hPtr;
165 }
166
167 WMHost *WMRetainHost(WMHost * hPtr)
168 {
169         hPtr->refCount++;
170         return hPtr;
171 }
172
173 void WMReleaseHost(WMHost * hPtr)
174 {
175         hPtr->refCount--;
176
177         if (hPtr->refCount > 0)
178                 return;
179
180         WMFreeArray(hPtr->names);
181         WMFreeArray(hPtr->addresses);
182
183         if (hPtr->name) {
184                 WMHashRemove(hostCache, hPtr->name);
185                 wfree(hPtr->name);
186         }
187
188         wfree(hPtr);
189 }
190
191 void WMSetHostCacheEnabled(Bool flag)
192 {
193         hostCacheEnabled = ((flag == 0) ? 0 : 1);
194 }
195
196 Bool WMIsHostCacheEnabled()
197 {
198         return hostCacheEnabled;
199 }
200
201 void WMFlushHostCache()
202 {
203         if (hostCache && WMCountHashTable(hostCache) > 0) {
204                 WMArray *hostArray = WMCreateArray(WMCountHashTable(hostCache));
205                 WMHashEnumerator enumer = WMEnumerateHashTable(hostCache);
206                 WMHost *hPtr;
207                 int i;
208
209                 while ((hPtr = WMNextHashEnumeratorItem(&enumer))) {
210                         /* we can't release the host here, because we can't change the
211                          * hash while using the enumerator functions. */
212                         WMAddToArray(hostArray, hPtr);
213                 }
214                 for (i = 0; i < WMGetArrayItemCount(hostArray); i++)
215                         WMReleaseHost(WMGetFromArray(hostArray, i));
216                 WMFreeArray(hostArray);
217                 WMResetHashTable(hostCache);
218         }
219 }
220
221 static int matchAddress(void *item, void *cdata)
222 {
223         return (strcmp((char *)item, (char *)cdata) == 0);
224 }
225
226 Bool WMIsHostEqualToHost(WMHost * hPtr, WMHost * aPtr)
227 {
228         char *adr;
229         int i;
230
231         wassertrv(hPtr != NULL && aPtr != NULL, False);
232
233         if (hPtr == aPtr)
234                 return True;
235
236         for (i = 0; i < WMGetArrayItemCount(aPtr->addresses); i++) {
237                 adr = WMGetFromArray(aPtr->addresses, i);
238                 if (WMFindInArray(hPtr->addresses, matchAddress, adr) != WANotFound) {
239                         return True;
240                 }
241         }
242
243         return False;
244 }
245
246 char *WMGetHostName(WMHost * hPtr)
247 {
248         return (WMGetArrayItemCount(hPtr->names) > 0 ? WMGetFromArray(hPtr->names, 0) : NULL);
249         /*return WMGetFromArray(hPtr->names, 0); */
250 }
251
252 WMArray *WMGetHostNames(WMHost * hPtr)
253 {
254         return hPtr->names;
255 }
256
257 char *WMGetHostAddress(WMHost * hPtr)
258 {
259         return (WMGetArrayItemCount(hPtr->addresses) > 0 ? WMGetFromArray(hPtr->addresses, 0) : NULL);
260 }
261
262 WMArray *WMGetHostAddresses(WMHost * hPtr)
263 {
264         return hPtr->addresses;
265 }