Merge Samba3 and Samba4 together
[sfrench/samba-autobuild/.git] / source4 / lib / appweb / ejs-2.0 / mpr / WIN / mprPlatform.c
1 /**
2  *      @file   mprPlatform.c
3  *      @brief  Cross platform routines 
4  *      @overview This module provides low level cross platform routines.
5  *      @remarks Most routines in this file are not thread-safe. It is the callers 
6  *              responsibility to perform all thread synchronization.
7  */
8
9 /*
10  *      @copy   default
11  *      
12  *      Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
13  *      
14  *      This software is distributed under commercial and open source licenses.
15  *      You may use the GPL open source license described below or you may acquire 
16  *      a commercial license from Mbedthis Software. You agree to be fully bound 
17  *      by the terms of either license. Consult the LICENSE.TXT distributed with 
18  *      this software for full details.
19  *      
20  *      This software is open source; you can redistribute it and/or modify it 
21  *      under the terms of the GNU General Public License as published by the 
22  *      Free Software Foundation; either version 2 of the License, or (at your 
23  *      option) any later version. See the GNU General Public License for more 
24  *      details at: http://www.mbedthis.com/downloads/gplLicense.html
25  *      
26  *      This program is distributed WITHOUT ANY WARRANTY; without even the 
27  *      implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
28  *      
29  *      This GPL license does NOT permit incorporating this software into 
30  *      proprietary programs. If you are unable to comply with the GPL, you must
31  *      acquire a commercial license to use this software. Commercial licenses 
32  *      for this software and support services are available from Mbedthis 
33  *      Software at http://www.mbedthis.com 
34  *      
35  *      @end
36  */
37
38 /********************************** Includes **********************************/
39 /*
40  *      We need to use the underlying str(cpy) routines to implement our safe
41  *      alternatives
42  */
43 #if !DOXYGEN
44 #define         UNSAFE_FUNCTIONS_OK 1
45 #endif
46
47 #include        "mpr.h"
48
49 /**************************** Forward Declarations ****************************/
50
51 static const char *getHive(const char *keyPath, HKEY *hive);
52
53 /************************************ Code ************************************/
54
55 char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in)
56 {
57 #if HAVE_NTOA_R
58         inet_ntoa_r(in, buffer, bufsize);
59 #else
60         uchar   *cp;
61         cp = (uchar*) ∈
62         mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
63 #endif
64         return buffer;
65 }
66
67 /******************************************************************************/
68
69 void mprSetShell(MprCtx ctx, void *shell)
70 {
71 }
72
73 /******************************************************************************/
74
75 void *mprGetShell(MprCtx ctx)
76 {
77         return 0;
78 }
79
80 /******************************************************************************/
81 /*
82  *      Sleep. Period given in milliseconds.
83  */
84
85 void mprSleep(MprCtx ctx, int milliseconds)
86 {
87         Sleep(milliseconds);
88 }
89
90 /******************************************************************************/
91 /*
92  *      Make intervening directories
93  */
94
95 int mprMakeDirPath(MprCtx ctx, const char *path)
96 {
97         char    dir[MPR_MAX_PATH], buf[MPR_MAX_PATH];
98         char    *dirSep;
99         char    *next, *tok;
100
101         dir[0] = '\0';
102         dirSep = "/\\";
103
104         if (path == 0 || *path == '\0') {
105                 return MPR_ERR_BAD_ARGS;
106         }
107
108         mprStrcpy(buf, sizeof(buf), path);
109         next = mprStrTok(buf, dirSep, &tok);
110         if (*buf == '/') {
111                 dir[0] = '/';
112         }
113         while (next != NULL) {
114                 if (strcmp(next, ".") == 0 ) {
115                         next = mprStrTok(NULL, dirSep, &tok);
116                         continue;
117                 }
118                 strcat(dir, next);
119                 if (access(dir, R_OK) != 0) {
120                         if (_mkdir(dir) < 0) {
121                                 return MPR_ERR_CANT_CREATE;
122                         }
123                 }
124                 strcat(dir, "/");
125                 next = mprStrTok(NULL, dirSep, &tok);
126         }
127         return 0;
128 }
129
130 /******************************************************************************/
131 /*
132  *      Get a fully qualified file name for the given path. Return with forward
133  *      slashes always
134  */
135
136 char *mprGetFullPathName(char *buf, int buflen, const char *path)
137 {
138 #if (WIN || NW || OS2) && !BLD_FEATURE_ROMFS
139         char    *junk, *cp;
140         int     rc;
141
142         --buflen;
143         rc = GetFullPathName(path, buflen, buf, &junk);
144         for (cp = buf; *cp; cp++) {
145                 if (*cp == '\\') {
146                         *cp = '/';
147                 }
148         }
149         buf[buflen] = '\0';
150 #else
151         if (mprStrcpy(buf, buflen, path) < 0) {
152                 mprAssert(0);
153                 return 0;
154         }
155 #endif
156         return buf;
157 }
158
159 /******************************************************************************/
160 /*
161  *      Replacement for gethostbyname that is multi-thread safe
162  */
163
164 struct hostent *mprGetHostByName(MprCtx ctx, const char *name)
165 {
166         MprApp                  *app;
167         struct hostent  *hp;
168         struct hostent  *ip;
169         int                             count, i;
170
171         hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent));
172         memset(hp, 0, sizeof(struct hostent));
173
174         app = mprGetApp(ctx);
175
176         #undef gethostbyname
177
178         mprGlobalLock(app);
179         ip = gethostbyname(name);
180         mprGlobalUnlock(app);
181
182         if (ip == 0) {
183                 return 0;
184         }
185         hp->h_addrtype = ip->h_addrtype;
186         hp->h_length = ip->h_length;
187         hp->h_name = mprStrdup(hp, ip->h_name);
188         hp->h_addr_list = 0;
189         hp->h_aliases = 0;
190
191         for (count = 0; ip->h_addr_list[count] != 0; ) {
192                 count++;
193         }
194         if (count > 0) {
195                 count++;
196                 hp->h_addr_list = mprAlloc(hp, count * sizeof(char*));
197                 for (i = 0; ip->h_addr_list[i] != 0; i++) {
198                         memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length);
199                 }
200                 hp->h_addr_list[i] = 0;
201         }
202
203         for (count = 0; ip->h_aliases[count] != 0; ) {
204                 count++;
205         }
206         if (count > 0) {
207                 count++;
208                 hp->h_aliases = mprAlloc(hp, count * sizeof(char*));
209                 for (i = 0; ip->h_aliases[i] != 0; i++) {
210                         hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]);
211                 }
212                 hp->h_aliases[i] = 0;
213         }
214         return hp;
215 }
216
217 /******************************************************************************/
218 /*
219  *      Read a registry value. Returns allocated memory in buf.
220  */ 
221
222 int mprReadRegistry(MprCtx ctx, char **buf, int max, const char *key, 
223         const char *name)
224 {
225         HKEY            top, h;
226         char            *value;
227         ulong           type, size;
228
229         mprAssert(key && *key);
230         mprAssert(buf);
231
232         /*
233          *      Get the registry hive
234          */
235         if ((key = getHive(key, &top)) == 0) {
236                 return MPR_ERR_CANT_ACCESS;
237         }
238
239         if (RegOpenKeyEx(top, key, 0, KEY_READ, &h) != ERROR_SUCCESS) {
240                 return MPR_ERR_CANT_ACCESS;
241         }
242
243         /*
244          *      Get the type
245          */
246         if (RegQueryValueEx(h, name, 0, &type, 0, &size) != ERROR_SUCCESS) {
247                 RegCloseKey(h);
248                 return MPR_ERR_CANT_READ;
249         }
250         if (type != REG_SZ && type != REG_EXPAND_SZ) {
251                 RegCloseKey(h);
252                 return MPR_ERR_BAD_TYPE;
253         }
254
255         value = (char*) mprAlloc(ctx, size);
256         if ((int) size > max) {
257                 RegCloseKey(h);
258                 return MPR_ERR_WONT_FIT;
259         }
260         if (RegQueryValueEx(h, name, 0, &type, (uchar*) value, &size) != 
261                         ERROR_SUCCESS) {
262                 mprFree(value);
263                 RegCloseKey(h);
264                 return MPR_ERR_CANT_READ;
265         }
266
267     RegCloseKey(h);
268         *buf = value;
269         return 0;
270 }
271
272 /******************************************************************************/
273 /*
274  *      Write a string registry value. Returns allocated memory in buf.
275  */ 
276
277 int mprWriteRegistry(MprCtx ctx, const char *key, const char *name, 
278         const char *value)
279 {
280         HKEY    top, h, subHandle;
281         ulong   disposition;
282
283         mprAssert(key && *key);
284         mprAssert(name && *name);
285         mprAssert(value && *value);
286
287         /*
288          *      Get the registry hive
289          */
290         if ((key = getHive(key, &top)) == 0) {
291                 return MPR_ERR_CANT_ACCESS;
292         }
293
294         if (name) {
295                 /*
296                  *      Write a registry string value
297                  */
298                 if (RegOpenKeyEx(top, key, 0, KEY_ALL_ACCESS, &h) != ERROR_SUCCESS) {
299                         return MPR_ERR_CANT_ACCESS;
300                 }
301                 if (RegSetValueEx(h, name, 0, REG_SZ, value, strlen(value) + 1) 
302                                 != ERROR_SUCCESS) {
303                         RegCloseKey(h);
304                         return MPR_ERR_CANT_READ;
305                 }
306
307         } else {
308                 /*
309                  *      Create a new sub key
310                  */
311                 if (RegOpenKeyEx(top, key, 0, KEY_CREATE_SUB_KEY, &h) != ERROR_SUCCESS){
312                         return MPR_ERR_CANT_ACCESS;
313                 }
314                 if (RegCreateKeyEx(h, name, 0, NULL, REG_OPTION_NON_VOLATILE,
315                         KEY_ALL_ACCESS, NULL, &subHandle, &disposition) != ERROR_SUCCESS) {
316                         return MPR_ERR_CANT_ACCESS;
317                 }
318                 RegCloseKey(subHandle);
319         }
320     RegCloseKey(h);
321         return 0;
322 }
323
324 /******************************************************************************/
325 /*
326  *      Determine the registry hive by the first portion of the path. Return 
327  *      a pointer to the rest of key path after the hive portion.
328  */ 
329
330 static const char *getHive(const char *keyPath, HKEY *hive)
331 {
332         char    key[MPR_MAX_STRING], *cp;
333         int             len;
334
335         mprAssert(keyPath && *keyPath);
336
337         *hive = 0;
338
339         mprStrcpy(key, sizeof(key), keyPath);
340         key[sizeof(key) - 1] = '\0';
341
342         if (cp = strchr(key, '\\')) {
343                 *cp++ = '\0';
344         }
345         if (cp == 0 || *cp == '\0') {
346                 return 0;
347         }
348
349         if (!mprStrcmpAnyCase(key, "HKEY_LOCAL_MACHINE")) {
350                 *hive = HKEY_LOCAL_MACHINE;
351         } else if (!mprStrcmpAnyCase(key, "HKEY_CURRENT_USER")) {
352                 *hive = HKEY_CURRENT_USER;
353         } else if (!mprStrcmpAnyCase(key, "HKEY_USERS")) {
354                 *hive = HKEY_USERS;
355         } else if (!mprStrcmpAnyCase(key, "HKEY_CLASSES_ROOT")) {
356                 *hive = HKEY_CLASSES_ROOT;
357         } else {
358                 return 0;
359         }
360
361         if (*hive == 0) {
362                 return 0;
363         }
364         len = strlen(key) + 1;
365         return keyPath + len;
366 }
367
368 /******************************************************************************/
369
370 /*
371  * Local variables:
372  * tab-width: 4
373  * c-basic-offset: 4
374  * End:
375  * vim:tw=78
376  * vim600: sw=4 ts=4 fdm=marker
377  * vim<600: sw=4 ts=4
378  */