38
38
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39
39
* SOFTWARE.
40
40
*/
41
+ #include <assert.h>
41
42
#include <ctype.h>
42
43
#include <stdio.h>
43
44
#include <stdlib.h>
44
45
#include <unistd.h>
45
46
#include <libgen.h>
46
47
#include <string.h>
47
48
#include <limits.h>
49
+ #include <stdarg.h>
48
50
#include <mach-o/dyld.h>
49
51
50
- #define MAX_LINE 4096
51
- #define MAX_ARGS 100
52
-
53
52
#define GRAAL_PYTHON_EXE_ARG "--python.Executable="
54
53
#define GRAAL_PYTHON_BASE_EXE_ARG "--python.VenvlauncherCommand="
55
54
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
+
56
73
/**
57
74
* Reads the 'venvlauncher_command' from a pyvenv.cfg file.
58
75
* Returns a newly allocated string. Caller must free() it.
@@ -110,47 +127,53 @@ char *get_pyenvcfg_command(const char *pyenv_cfg_path) {
110
127
111
128
}
112
129
}
130
+
113
131
free (current_line );
132
+ if (ferror (fp )) {
133
+ perror ("getline failed" );
134
+ fclose (fp );
135
+ exit (1 );
136
+ }
137
+
138
+ fclose (fp );
114
139
fprintf (stderr , "venvlauncher_command not found in pyenv.cfg file" );
115
140
exit (1 );
116
141
}
117
142
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
+
118
156
char * * split_venv_command_into_args (const char * venv_command , int * argc_out ) {
119
157
120
158
char * copy = strdup (venv_command );
121
- size_t capacity = 5 ;
159
+ const int capacity = count_args ( copy ) ;
122
160
char * * args = malloc (capacity * sizeof (char * ));
123
161
if (!args ) {
124
162
fprintf (stderr , "allocation failed failed\n" );
125
163
free (copy );
126
164
exit (1 );
127
165
}
128
166
129
- size_t count = 0 ;
167
+ int count = 0 ;
130
168
char * current_token = strtok (copy , " " );
131
169
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
-
148
170
args [count ++ ] = strdup (current_token );
149
171
current_token = strtok (NULL , " " );
150
172
}
151
173
152
174
free (copy );
153
- * argc_out = (int ) count ;
175
+ assert (capacity == count );
176
+ * argc_out = count ;
154
177
return args ;
155
178
}
156
179
@@ -167,10 +190,12 @@ void find_pyvenv(char *pyvenv_cfg_path, size_t path_size) {
167
190
// First try search for the pyvenv on top level
168
191
char * dir_path = dirname (executable_path );
169
192
snprintf (pyvenv_cfg_path , path_size , "%s/pyvenv.cfg" , dir_path );
193
+ debug ("Searching for pyenv.cfg file in %s\n" , pyvenv_cfg_path );
170
194
if (access (pyvenv_cfg_path , F_OK ) != 0 ) {
171
195
// Try searching one level up
172
196
dir_path = dirname (dir_path );
173
197
snprintf (pyvenv_cfg_path , path_size , "%s/pyvenv.cfg" , dir_path );
198
+ debug ("Searching for pyenv.cfg file in %s\n" , pyvenv_cfg_path );
174
199
if (access (pyvenv_cfg_path , F_OK ) != 0 ) {
175
200
fprintf (stderr , "Error: pyvenv.cfg file not found at %s\n" , pyvenv_cfg_path );
176
201
exit (1 );
@@ -179,10 +204,16 @@ void find_pyvenv(char *pyvenv_cfg_path, size_t path_size) {
179
204
}
180
205
181
206
int 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
+ }
183
214
215
+ char pyvenv_cfg_path [PATH_MAX ];
184
216
find_pyvenv (pyvenv_cfg_path , sizeof (pyvenv_cfg_path ));
185
-
186
217
char * venv_command = get_pyenvcfg_command (pyvenv_cfg_path );
187
218
188
219
int venv_argc = 0 ;
@@ -224,6 +255,11 @@ int main(int argc, char *argv[]) {
224
255
225
256
args [k ] = NULL ;
226
257
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
+
227
263
execv (args [0 ], args );
228
264
perror ("execv failed" ); // only runs if execv fails
229
265
return 1 ;
0 commit comments