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 }