22#include < string>
33#include < unordered_map>
44#include < cstring>
5+ #include < vector>
56#include " rules_cc/cc/runfiles/runfiles.h"
67
78#ifdef _WIN32
8- #include < process .h>
9+ #include < Windows .h>
910#else
1011#include < unistd.h>
1112#endif
@@ -14,8 +15,7 @@ using rules_cc::cc::runfiles::Runfiles;
1415
1516const char * env_vars[] = ENV;
1617
17-
18- static const char ** build_merged_envp (char *envp[], const std::string& layer_dir)
18+ static std::vector<std::string> build_merged_envp (char *envp[], const std::string& layer_dir)
1919{
2020 std::unordered_map<std::string, std::string> merged_env;
2121 for (char ** env = envp; env && *env; ++env)
@@ -28,6 +28,9 @@ static const char** build_merged_envp(char *envp[], const std::string& layer_dir
2828 }
2929
3030 std::string key = current.substr (0 , separator);
31+ #ifdef _WIN32
32+ for (auto & c : key) c = toupper ((unsigned char )c);
33+ #endif
3134 merged_env[key] = current.substr (separator + 1 );
3235 }
3336
@@ -41,6 +44,9 @@ static const char** build_merged_envp(char *envp[], const std::string& layer_dir
4144 }
4245
4346 std::string key = current.substr (0 , separator);
47+ #ifdef _WIN32
48+ for (auto & c : key) c = toupper ((unsigned char )c);
49+ #endif
4450 std::string value = current.substr (separator + 1 );
4551
4652 // Replace ${installPath} with the actual layer directory path.
@@ -64,16 +70,12 @@ static const char** build_merged_envp(char *envp[], const std::string& layer_dir
6470 }
6571
6672 // Convert the merged environment map back to an array of C strings.
67- const char ** merged_envp = new const char *[merged_env. size () + 1 ] ;
68- size_t i = 0 ;
73+ std::vector<std::string> merged_envp;
74+ merged_envp. reserve (merged_env. size ()) ;
6975 for (auto & [key, value] : merged_env)
7076 {
71- std::string entry = key + " =" + value;
72- char * buffer = new char [entry.size () + 1 ];
73- memcpy (buffer, entry.c_str (), entry.size () + 1 );
74- merged_envp[i++] = buffer;
77+ merged_envp.push_back (key + " =" + value);
7578 }
76- merged_envp[i] = nullptr ;
7779 return merged_envp;
7880}
7981
@@ -82,7 +84,6 @@ int main(int argc, char *argv[], char *envp[])
8284 (void )argc;
8385
8486 std::string error;
85-
8687 // Resolve the path to the executable in the runfiles structure
8788 auto runfiles = std::unique_ptr<Runfiles>(
8889 Runfiles::Create (argv[0 ], BAZEL_CURRENT_REPOSITORY, &error));
@@ -93,7 +94,6 @@ int main(int argc, char *argv[], char *envp[])
9394 }
9495 std::string bin_path = BIN_PATH;
9596 std::string path = runfiles->Rlocation (bin_path);
96-
9797 // Resolve the image layer root directory in the runfiles structure
9898 auto layer_dir_pos = bin_path.find (" /layer/" );
9999 if (layer_dir_pos == std::string::npos) {
@@ -102,19 +102,78 @@ int main(int argc, char *argv[], char *envp[])
102102 }
103103 auto bin_path_in_layer_length = bin_path.length () - layer_dir_pos - 7 ;
104104 std::string layer_dir = path.substr (0 , path.length () - bin_path_in_layer_length);
105-
106- const char ** merged_envp = build_merged_envp (envp, layer_dir);
105+ std::vector<std::string> merged_envp = build_merged_envp (envp, layer_dir);
107106
108107#ifdef _WIN32
109- int res = _execve (path.c_str (), argv, (char *const *) merged_envp);
110- #else
111- int res = execve (path.c_str (), argv, (char *const *) merged_envp);
112- #endif
108+ // Build command line
109+ std::string cmdline = " \" " + path + " \" " ;
110+ for (int i = 1 ; argv[i] != nullptr ; ++i) {
111+ cmdline += " \" " ;
112+ cmdline += argv[i];
113+ cmdline += " \" " ;
114+ }
113115
116+ // Build environment block (double-null-terminated)
117+ size_t env_block_len = 0 ;
118+ for (const auto & env : merged_envp) {
119+ env_block_len += env.size () + 1 ;
120+ }
121+ env_block_len += 1 ; // final null
122+ char * env_block = new char [env_block_len];
123+ char * p = env_block;
124+ for (const auto & env : merged_envp) {
125+ size_t len = env.size ();
126+ memcpy (p, env.c_str (), len);
127+ p += len;
128+ *p++ = ' \0 ' ;
129+ }
130+ *p = ' \0 ' ;
131+
132+ STARTUPINFOA si;
133+ PROCESS_INFORMATION pi;
134+ ZeroMemory (&si, sizeof (si));
135+ si.cb = sizeof (si);
136+ ZeroMemory (&pi, sizeof (pi));
137+
138+ BOOL success = CreateProcessA (
139+ path.c_str (),
140+ (LPSTR)cmdline.c_str (),
141+ NULL ,
142+ NULL ,
143+ FALSE ,
144+ 0 ,
145+ env_block,
146+ NULL ,
147+ &si,
148+ &pi
149+ );
150+ if (!success) {
151+ fprintf (stderr, " ERROR: failed to execute '%s' (CreateProcess failed)\n " , path.c_str ());
152+ delete[] env_block;
153+ return 1 ;
154+ }
155+ // Wait for process to finish
156+ WaitForSingleObject (pi.hProcess , INFINITE);
157+ DWORD exit_code = 0 ;
158+ GetExitCodeProcess (pi.hProcess , &exit_code);
159+ CloseHandle (pi.hProcess );
160+ CloseHandle (pi.hThread );
161+ delete[] env_block;
162+ return (int )exit_code;
163+ #else
164+ // Build char* array for execve
165+ std::vector<char *> envp_cstrs;
166+ envp_cstrs.reserve (merged_envp.size () + 1 );
167+ for (const auto & env : merged_envp) {
168+ envp_cstrs.push_back (const_cast <char *>(env.c_str ()));
169+ }
170+ envp_cstrs.push_back (nullptr );
171+ int res = execve (path.c_str (), argv, envp_cstrs.data ());
114172 if (res == -1 )
115173 {
116174 fprintf (stderr, " ERROR: failed to execute '%s'\n " , path.c_str ());
117175 return 1 ;
118176 }
119177 return 0 ;
178+ #endif
120179}
0 commit comments