Skip to content

Instantly share code, notes, and snippets.

@skeeto
Created September 30, 2024 23:22
Show Gist options
  • Save skeeto/8493f6304eb3f6e2edd3351e0ad40332 to your computer and use it in GitHub Desktop.
Save skeeto/8493f6304eb3f6e2edd3351e0ad40332 to your computer and use it in GitHub Desktop.
Quick test of environment variable passing
// Quick test of environment variable passing
// $ cc -nostartfiles -o testenv testenv.cpp
// $ cl testenv.cpp /link /subsystem:console kernel32.lib
//
// Spawns a copy of itself with a custom-built environment block, and
// the spawned child examines/probes that block.
//
// This is free and unencumbered software released into the public domain.
typedef int I;
typedef char16_t C;
enum H : decltype(sizeof(0));
struct SI {
I cb = sizeof(SI);
H _0[3];
I _1[9];
H _2[4];
};
struct PI {
H ph, th;
I pi, ti;
};
enum { CREATE_UNICODE_ENVIRONMENT = 0x400 };
#define W32(r) extern "C" __declspec(dllimport) r __stdcall
W32(I) CreateProcessW(C*, C*, H, H, I, I, C*, C*, SI*, PI*);
W32(void) ExitProcess(I);
W32(C *) GetCommandLineW();
W32(C *) GetEnvironmentStringsW();
W32(I) GetEnvironmentVariableW(C const *, C *, I);
W32(I) GetModuleFileNameW(H, C *, I);
W32(H) GetStdHandle(I);
W32(I) WaitForSingleObject(H, I);
W32(I) WriteConsoleW(H, C const *, I, I *, H);
template<typename T, I N>
constexpr I countof(T const (&)[N]) { return N; };
static I print(C const *s)
{
H stdout = GetStdHandle(-11);
I len = 0;
for (; s[len]; len++) {}
I dummy;
WriteConsoleW(stdout, s, len, &dummy, {});
return len;
}
static void printenv()
{
C *env = GetEnvironmentStringsW();
for (C *e = env; *e;) {
e += print(e) + 1;
print(u"\n");
}
C value[1<<10];
GetEnvironmentVariableW(u"=x", value, countof(value));
print(u"\"");
print(value);
print(u"\"\n");
}
static I spawn()
{
C path[1<<10];
GetModuleFileNameW({}, path, countof(path));
SI si = {};
PI pi = {};
C cmd[] = u"?";
C env[] = u"=x=hello world\0";
I flags = CREATE_UNICODE_ENVIRONMENT;
I ok = CreateProcessW(path, cmd, {}, {}, 0, flags, env, 0, &si, &pi);
if (!ok) {
return 1;
}
WaitForSingleObject(pi.ph, -1);
return 0;
}
extern "C" void __stdcall mainCRTStartup()
{
I r = 0;
if (*GetCommandLineW() == '?') {
printenv();
} else {
r = spawn();
}
ExitProcess(r);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment