3838 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3939 * SOFTWARE.
4040 */
41+ #include <assert.h>
4142#include <ctype.h>
4243#include <stdio.h>
4344#include <stdlib.h>
4445#include <unistd.h>
4546#include <libgen.h>
4647#include <string.h>
4748#include <limits.h>
49+ #include <stdarg.h>
4850#include <mach-o/dyld.h>
4951
50- #define MAX_LINE 4096
51- #define MAX_ARGS 100
52-
5352#define GRAAL_PYTHON_EXE_ARG "--python.Executable="
5453#define GRAAL_PYTHON_BASE_EXE_ARG "--python.VenvlauncherCommand="
5554
55+ static bool debug_enabled = false;
56+
57+ void debug (const char * format , ...) {
58+ if (!debug_enabled ) return ;
59+
60+ va_list va ;
61+ char buffer [1024 ];
62+ va_start (va , format );
63+ int result = vsnprintf (buffer , sizeof (buffer ), format , va );
64+ va_end (va );
65+
66+ if (result <= 0 ) return ;
67+
68+ fprintf (stderr , "%s" , buffer );
69+ fflush (stderr );
70+ }
71+
72+
5673/**
5774 * Reads the 'venvlauncher_command' from a pyvenv.cfg file.
5875 * Returns a newly allocated string. Caller must free() it.
@@ -110,47 +127,53 @@ char *get_pyenvcfg_command(const char *pyenv_cfg_path) {
110127
111128 }
112129 }
130+
113131 free (current_line );
132+ if (ferror (fp )) {
133+ perror ("getline failed" );
134+ fclose (fp );
135+ exit (1 );
136+ }
137+
138+ fclose (fp );
114139 fprintf (stderr , "venvlauncher_command not found in pyenv.cfg file" );
115140 exit (1 );
116141}
117142
143+ int count_args (const char * cmd ) {
144+ char * copy = strdup (cmd );
145+ int count = 0 ;
146+ char * token = strtok (copy , " " );
147+ while (token ) {
148+ count ++ ;
149+ token = strtok (NULL , " " );
150+ }
151+
152+ free (copy );
153+ return count ;
154+ }
155+
118156char * * split_venv_command_into_args (const char * venv_command , int * argc_out ) {
119157
120158 char * copy = strdup (venv_command );
121- size_t capacity = 5 ;
159+ const int capacity = count_args ( copy ) ;
122160 char * * args = malloc (capacity * sizeof (char * ));
123161 if (!args ) {
124162 fprintf (stderr , "allocation failed failed\n" );
125163 free (copy );
126164 exit (1 );
127165 }
128166
129- size_t count = 0 ;
167+ int count = 0 ;
130168 char * current_token = strtok (copy , " " );
131169 while (current_token ) {
132- if (count >= capacity ) {
133- capacity *= 2 ;
134- char * * tmp = realloc (args , capacity * sizeof (char * ));
135- if (!tmp ) {
136- // allocation failed
137- fprintf (stderr , "reallocation failed\n" );
138- for (size_t i = 0 ; i < count ; i ++ ) {
139- free (args [i ]);
140- }
141- free (args );
142- free (copy );
143- exit (1 );
144- }
145- args = tmp ;
146- }
147-
148170 args [count ++ ] = strdup (current_token );
149171 current_token = strtok (NULL , " " );
150172 }
151173
152174 free (copy );
153- * argc_out = (int ) count ;
175+ assert (capacity == count );
176+ * argc_out = count ;
154177 return args ;
155178}
156179
@@ -167,10 +190,12 @@ void find_pyvenv(char *pyvenv_cfg_path, size_t path_size) {
167190 // First try search for the pyvenv on top level
168191 char * dir_path = dirname (executable_path );
169192 snprintf (pyvenv_cfg_path , path_size , "%s/pyvenv.cfg" , dir_path );
193+ debug ("Searching for pyenv.cfg file in %s\n" , pyvenv_cfg_path );
170194 if (access (pyvenv_cfg_path , F_OK ) != 0 ) {
171195 // Try searching one level up
172196 dir_path = dirname (dir_path );
173197 snprintf (pyvenv_cfg_path , path_size , "%s/pyvenv.cfg" , dir_path );
198+ debug ("Searching for pyenv.cfg file in %s\n" , pyvenv_cfg_path );
174199 if (access (pyvenv_cfg_path , F_OK ) != 0 ) {
175200 fprintf (stderr , "Error: pyvenv.cfg file not found at %s\n" , pyvenv_cfg_path );
176201 exit (1 );
@@ -179,10 +204,16 @@ void find_pyvenv(char *pyvenv_cfg_path, size_t path_size) {
179204}
180205
181206int main (int argc , char * argv []) {
182- char pyvenv_cfg_path [PATH_MAX ];
207+ if (getenv ("PYLAUNCHER_DEBUG" ) != NULL ) {
208+ debug_enabled = true;
209+ }
210+ debug ("Original argv are:\n" );
211+ for (int i = 1 ; i < argc ; i ++ ) {
212+ debug ("argv[%d] = %s\n" , i , argv [i ]);
213+ }
183214
215+ char pyvenv_cfg_path [PATH_MAX ];
184216 find_pyvenv (pyvenv_cfg_path , sizeof (pyvenv_cfg_path ));
185-
186217 char * venv_command = get_pyenvcfg_command (pyvenv_cfg_path );
187218
188219 int venv_argc = 0 ;
@@ -224,6 +255,11 @@ int main(int argc, char *argv[]) {
224255
225256 args [k ] = NULL ;
226257
258+ debug ("Final arguments to execv: \n" );
259+ for (int i = 0 ; i < k ; i ++ ) {
260+ debug ("arg[%d] = %s\n" , i , args [i ]);
261+ }
262+
227263 execv (args [0 ], args );
228264 perror ("execv failed" ); // only runs if execv fails
229265 return 1 ;
0 commit comments