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