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
mprInetToStr(char * buffer,int bufsize,const struct in_addr in)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
mprSetShell(MprCtx ctx,void * shell)69 void mprSetShell(MprCtx ctx, void *shell)
70 {
71 }
72
73 /******************************************************************************/
74
mprGetShell(MprCtx ctx)75 void *mprGetShell(MprCtx ctx)
76 {
77 return 0;
78 }
79
80 /******************************************************************************/
81 /*
82 * Sleep. Period given in milliseconds.
83 */
84
mprSleep(MprCtx ctx,int milliseconds)85 void mprSleep(MprCtx ctx, int milliseconds)
86 {
87 Sleep(milliseconds);
88 }
89
90 /******************************************************************************/
91 /*
92 * Make intervening directories
93 */
94
mprMakeDirPath(MprCtx ctx,const char * path)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
mprGetFullPathName(char * buf,int buflen,const char * path)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
mprGetHostByName(MprCtx ctx,const char * name)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
mprReadRegistry(MprCtx ctx,char ** buf,int max,const char * key,const char * name)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
mprWriteRegistry(MprCtx ctx,const char * key,const char * name,const char * value)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
getHive(const char * keyPath,HKEY * hive)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 */
379