www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Code to get all environment variables

reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Something like this should really be in Phobos, and unless it's already there,
Ares.

I figured I'd post what I coded to accomplish this task. It should work in
Windows and any Posix platform - I tested it only on Windows XP and Cygwin,
though, but it ought to be alright.

The Windows code uses the ASCII, not UTF-16, versions of the functions, since
I'm not comfortable messing around with different encodings - I'm not sure
whether it would be smarter to make the Posix version convert ASCII to wchars or
the Windows code to convert UTF-16 to chars.

I was never good with pointer twiddling, so I couldn't figure out a way to use
the same code for both versions. Feel free to do whatever you want with it, I
release it in the public domain.

--

version (Windows) {
	pragma (lib, "kernel32");

	extern (Windows) {
		void * GetEnvironmentStringsA();
		bool   FreeEnvironmentStringsA(char**);
	}

	char[][char[]] environment() {
		char ** env = cast(char**)GetEnvironmentStringsA();
		scope (exit) FreeEnvironmentStringsA(env);

		char[][char[]] arr;

		for (char * str = cast(char*)env; *str; ++str) {
			char[] key   = new char[20],
			       value = new char[40];

			size_t i;

			while (*str != '=') {
				key[i++] = *str++;

				if (i == key.length)
					key.length = 2 * key.length;
			}
			key.length = i;

			i = 0;
			++str;

			while (*str) {
				value[i++] = *str++;

				if (i == value.length)
					value.length = 2 * value.length;
			}
			value.length = i;

			arr[key] = value;
		}

		return arr;
	}
} else {
	pragma (msg, "If this is not a Posix-compliant platform, trying to access
environment\nvariables will probably cause an access violation and thereby a
crash.");

	extern (C) extern char ** environ;

	char[][char[]] environment() {
		char[][char[]] arr;

		for (char ** p = environ; *p; ++p) {
			char[] key   = new char[20],
			       value = new char[40];

			size_t i;
			char * str = *p;

			while (*str != '=') {
				key[i++] = *str++;

				if (i == key.length)
					key.length = 2 * key.length;
			}
			key.length = i;

			i = 0;
			++str;

			while (*str) {
				value[i++] = *str++;

				if (i == value.length)
					value.length = 2 * value.length;
			}
			value.length = i;

			arr[key] = value;
		}

		return arr;
	}
}
Jun 12 2006
parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Deewiant schrieb am 2006-06-12:

<snip>

 The Windows code uses the ASCII, not UTF-16, versions of the functions, since
 I'm not comfortable messing around with different encodings

I'm not a MSWindows native.. Are you sure that GetEnvironmentStringsA and FreeEnvironmentStringsA use ASCII? I'd expect them to use locale and/or installation dependent ANSI encoding.
 whether it would be smarter to make the Posix version convert ASCII to wchars
or
 the Windows code to convert UTF-16 to chars.

Unless there any strong reasons - like buggy implementations in some MSWindows versions - I'd opt for the UTF-16 to UTF-8 conversion. Thoms -----BEGIN PGP SIGNATURE----- iD8DBQFEjxeO3w+/yD4P9tIRAt/5AKCmlJvXPMsU/rc7NB+Q+VfAQKKjvwCggj/5 s0uuztlyz5hbDTFNeCqhzpQ= =qtgN -----END PGP SIGNATURE-----
Jun 13 2006
parent Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Thomas Kuehne wrote:
 Are you sure that GetEnvironmentStringsA and FreeEnvironmentStringsA use ASCII?
 I'd expect them to use locale and/or installation dependent ANSI encoding.
 
 Unless there any strong reasons - like buggy implementations in some MSWindows
 versions - I'd opt for the UTF-16 to UTF-8 conversion.
 
 Thoms
 

It seems you're right, they do. *sigh* Hence, replace the *A functions with *W, change "char" to "wchar" in everything but the declaration of "arr", and use toUTF8() in the last line of the loop, like so: arr[toUTF8(key)] = toUTF8(value); And thus, of course, import std.utf. The only problem now is that Windows 95/98/ME require the "Microsoft Layer for Unicode" - some sort of OS patch, I gather - for the UTF-16 versions of the functions to work. I'm not familiar enough with the Windows SDK to know whether there's an easy way to convert from "whatever encoding the ANSI versions of the functions return" to the UTF-16 form easily, so my suggestion to users of those OSs is to just go and update their systems.
Jun 14 2006