1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1997,2008 Oracle.  All rights reserved.
5 *
6 * $Id: os_getenv.c,v 1.9 2008/01/08 20:58:46 bostic Exp $
7 */
8
9#include "db_config.h"
10
11#include "db_int.h"
12
13/*
14 * __os_getenv --
15 *	Retrieve an environment variable.
16 */
17int
18__os_getenv(env, name, bpp, buflen)
19	ENV *env;
20	const char *name;
21	char **bpp;
22	size_t buflen;
23{
24#ifdef DB_WINCE
25	COMPQUIET(name, NULL);
26	/* WinCE does not have a getenv implementation. */
27	return (0);
28#else
29	_TCHAR *tname, tbuf[1024];
30	int ret;
31	char *p;
32
33	/*
34	 * If there's a value and the buffer is large enough:
35	 *	copy value into the pointer, return 0
36	 * If there's a value and the buffer is too short:
37	 *	set pointer to NULL, return EINVAL
38	 * If there's no value:
39	 *	set pointer to NULL, return 0
40	 */
41	if ((p = getenv(name)) != NULL) {
42		if (strlen(p) < buflen) {
43			(void)strcpy(*bpp, p);
44			return (0);
45		}
46		goto small_buf;
47	}
48
49	TO_TSTRING(env, name, tname, ret);
50	if (ret != 0)
51		return (ret);
52	/*
53	 * The declared size of the tbuf buffer limits the maximum environment
54	 * variable size in Berkeley DB on Windows.  If that's too small, or if
55	 * we need to get rid of large allocations on the BDB stack, we should
56	 * malloc the tbuf memory.
57	 */
58	ret = GetEnvironmentVariable(tname, tbuf, sizeof(tbuf));
59	FREE_STRING(env, tname);
60
61	/*
62	 * If GetEnvironmentVariable succeeds, the return value is the number
63	 * of characters stored in the buffer pointed to by lpBuffer, not
64	 * including the terminating null character.  If the buffer is not
65	 * large enough to hold the data, the return value is the buffer size,
66	 * in characters, required to hold the string and its terminating null
67	 * character.  If GetEnvironmentVariable fails, the return value is
68	 * zero.  If the specified environment variable was not found in the
69	 * environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND.
70	 */
71	if (ret == 0) {
72		if ((ret = __os_get_syserr()) == ERROR_ENVVAR_NOT_FOUND) {
73			*bpp = NULL;
74			return (0);
75		}
76		__db_syserr(env, ret, "GetEnvironmentVariable");
77		return (__os_posix_err(ret));
78	}
79	if (ret > (int)sizeof(tbuf))
80		goto small_buf;
81
82	FROM_TSTRING(env, tbuf, p, ret);
83	if (ret != 0)
84		return (ret);
85	if (strlen(p) < buflen)
86		(void)strcpy(*bpp, p);
87	else
88		*bpp = NULL;
89	FREE_STRING(env, p);
90	if (*bpp == NULL)
91		goto small_buf;
92
93	return (0);
94
95small_buf:
96	*bpp = NULL;
97	__db_errx(env,
98	    "%s: buffer too small to hold environment variable %s",
99	    name, p);
100	return (EINVAL);
101#endif
102}
103