Lines 24-29
Link Here
|
24 |
#define GCC_CONFIG "/usr/bin/gcc-config" |
24 |
#define GCC_CONFIG "/usr/bin/gcc-config" |
25 |
#define ENVD_BASE "/etc/env.d/05gcc" |
25 |
#define ENVD_BASE "/etc/env.d/05gcc" |
26 |
|
26 |
|
|
|
27 |
#ifndef FALSE |
28 |
#define FALSE 0 |
29 |
#endif |
30 |
#ifndef TRUE |
31 |
#define TRUE 1 |
32 |
#endif |
33 |
|
27 |
struct wrapper_data { |
34 |
struct wrapper_data { |
28 |
char name[MAXPATHLEN + 1]; |
35 |
char name[MAXPATHLEN + 1]; |
29 |
char fullname[MAXPATHLEN + 1]; |
36 |
char fullname[MAXPATHLEN + 1]; |
Lines 300-311
Link Here
|
300 |
return retargv; |
307 |
return retargv; |
301 |
} |
308 |
} |
302 |
|
309 |
|
|
|
310 |
|
311 |
/** Prepend SPECS to the argv list */ |
312 |
static char **buildNewArgvSpecs(char **argv, const char *newSpecsStr) { |
313 |
#define MAX_NEWSPECS 32 |
314 |
char *newSpecs[MAX_NEWSPECS]; |
315 |
char **retargv; |
316 |
unsigned int argc; |
317 |
size_t nspecs; |
318 |
char *state, *flagsTokenized; |
319 |
char *spec; |
320 |
|
321 |
for (argc = 0; argv[argc]; ++argc); |
322 |
|
323 |
/* Tokenize the flag list and put it into newflags array */ |
324 |
flagsTokenized = strdup(newSpecsStr); |
325 |
if (flagsTokenized == NULL) |
326 |
return argv; |
327 |
nspecs = 0; |
328 |
for (spec = strtok_r(flagsTokenized, ":", &state); |
329 |
spec != NULL & nspecs < MAX_NEWSPECS; |
330 |
spec = strtok_r(NULL, ":", &state)) { |
331 |
newSpecs[nspecs] = (char *)malloc((strlen(spec)+8) * sizeof(char)); |
332 |
if (newSpecs[nspecs] == NULL) { |
333 |
free(flagsTokenized); |
334 |
return argv; |
335 |
} |
336 |
snprintf(newSpecs[nspecs], strlen(spec)+8, "-specs=%s", spec); |
337 |
nspecs++; |
338 |
} |
339 |
|
340 |
/* allocate memory for our spiffy new argv */ |
341 |
retargv = (char**)calloc(argc + nspecs + 1, sizeof(char*)); |
342 |
if (retargv == NULL) { |
343 |
free(flagsTokenized); |
344 |
return argv; |
345 |
} |
346 |
/* start building retargv */ |
347 |
retargv[0] = argv[0]; |
348 |
/* insert the ABI flags first so cmdline always overrides ABI flags */ |
349 |
memcpy(retargv+1, newSpecs, nspecs * sizeof(char*)); |
350 |
/* copy over the old argv */ |
351 |
if (argc > 1) |
352 |
memcpy(retargv+1+nspecs, argv+1, (argc-1) * sizeof(char*)); |
353 |
|
354 |
free(flagsTokenized); |
355 |
|
356 |
return retargv; |
357 |
} |
358 |
|
359 |
/** Add path to the environment variable envVar */ |
360 |
static int addPathToEnv(char *envVar, char *path) { |
361 |
char *envVal; |
362 |
char *newEnvVal; |
363 |
|
364 |
envVal = getenv(envVar); |
365 |
if (envVal == NULL) { |
366 |
newEnvVal=strdup(path); |
367 |
if (newEnvVal == NULL) |
368 |
return FALSE; |
369 |
} else { |
370 |
newEnvVal = (char *)malloc((strlen(envVal)+1+strlen(path)+1)*sizeof(char)); |
371 |
if (newEnvVal == NULL) |
372 |
return FALSE; |
373 |
snprintf(newEnvVal, strlen(envVal)+1+strlen(path)+1, "%s:%s", envVal,path); |
374 |
} |
375 |
setenv(envVar,newEnvVal,TRUE); |
376 |
return TRUE; |
377 |
} |
378 |
|
379 |
static char **prependArgv(char **argv, char *bin) { |
380 |
int argc; |
381 |
char **newArgv; |
382 |
for (argc=0; argv[argc]; argc++); |
383 |
newArgv = (char**)calloc(argc + 2, sizeof(char*)); |
384 |
if (newArgv == NULL) |
385 |
return argv; |
386 |
newArgv[0]=bin; |
387 |
memcpy(newArgv+1,argv,argc * sizeof(char *)); |
388 |
return newArgv; |
389 |
} |
390 |
|
391 |
/** Return TRUE iff word is in COMPILER_FEATURES and -word is not (last wins) */ |
392 |
static int inFeatures(char *word) { |
393 |
char *features, *feature; |
394 |
char *state, *featuresTokenised; |
395 |
int on; |
396 |
|
397 |
features = getenv("COMPILER_FEATURES"); |
398 |
if (features==NULL) |
399 |
return FALSE; |
400 |
featuresTokenised = strdup(features); |
401 |
if (featuresTokenised == NULL) |
402 |
return FALSE; |
403 |
on = FALSE; |
404 |
for (feature = strtok_r(featuresTokenised, " \t\n", &state); |
405 |
feature != NULL; |
406 |
feature = strtok_r(NULL, " \t\n", &state)) { |
407 |
if (strcmp(feature,word)==0) { |
408 |
on = TRUE; |
409 |
} else if (word[0]=='-' && strcmp(feature,word+1)==0) { |
410 |
on = FALSE; |
411 |
} |
412 |
} |
413 |
return on; |
414 |
} |
415 |
|
416 |
/** Return TRUE iff distcc is wanted */ |
417 |
static int distccRequired(void) { |
418 |
return inFeatures("distcc"); |
419 |
} |
420 |
|
421 |
/** Return TRUE iff distcc is wanted */ |
422 |
static int ccacheRequired(void) { |
423 |
return inFeatures("ccache"); |
424 |
} |
425 |
|
426 |
/** Set environment variable envVar to environment variable envDir |
427 |
* suffixed with , provided envVar is empty or not defined. |
428 |
* Returns TRUE if the envVar is already set, or if it is |
429 |
* successfully set. */ |
430 |
static int appendEnv(char *envVar, char *envDir, char *suffix) { |
431 |
char *envVarVal; |
432 |
char *envDirVal; |
433 |
envVarVal = getenv (envVar); |
434 |
if (envVarVal == NULL || strlen(envVarVal)==0) { |
435 |
if (envDir == NULL) { |
436 |
setenv(envVar,suffix,TRUE); |
437 |
} else { |
438 |
envDirVal = getenv(envDir); |
439 |
if (envDirVal == NULL) |
440 |
return FALSE; |
441 |
envVarVal = (char *)malloc((strlen(envDirVal)+strlen(suffix)+1)*sizeof(char)); |
442 |
if (envVarVal == NULL) |
443 |
return FALSE; |
444 |
if (snprintf(envVarVal, strlen(envDirVal)+strlen(suffix)+1,"%s%s",envDirVal,suffix) < 0) |
445 |
return FALSE; |
446 |
setenv(envVar,envVarVal,TRUE); |
447 |
} |
448 |
} |
449 |
return TRUE; |
450 |
} |
451 |
|
303 |
int main(int argc, char *argv[]) |
452 |
int main(int argc, char *argv[]) |
304 |
{ |
453 |
{ |
305 |
struct wrapper_data *data; |
454 |
struct wrapper_data *data; |
306 |
size_t size; |
455 |
size_t size; |
307 |
int i; |
456 |
int i; |
308 |
char **newargv = argv; |
457 |
char **newargv = argv; |
|
|
458 |
char *gcc_specs; |
309 |
|
459 |
|
310 |
data = alloca(sizeof(*data)); |
460 |
data = alloca(sizeof(*data)); |
311 |
if (data == NULL) |
461 |
if (data == NULL) |
Lines 369-376
Link Here
|
369 |
} |
519 |
} |
370 |
} |
520 |
} |
371 |
|
521 |
|
372 |
/* Ok, lets do it one more time ... */ |
522 |
/* Convert env specs or config specs into arguments |
373 |
if (execv(data->bin, newargv) < 0) |
523 |
* Env GCC_SPECS is honoured for native compiler only |
|
|
524 |
*/ |
525 |
gcc_specs = getenv("GCC_SPECS"); |
526 |
if (gcc_specs) { |
527 |
/* TODO: && not cross-compiler |
528 |
* && strcmp(data->ctarget, data->selectionConf->defaultCtarget) == 0) { |
529 |
*/ |
530 |
newargv = buildNewArgvSpecs(newargv, gcc_specs); |
531 |
} |
532 |
unsetenv("GCC_SPECS"); |
533 |
|
534 |
/* Prepend distcc, if enabled. |
535 |
* Set DISTCC_DIR to PORTAGE_TMPDIR/.distcc if not already set |
536 |
* Append DISTCC_DIR to SANDBOX_WRITE |
537 |
* Shuffle argv and set argv[0] to /usr/bin/distcc |
538 |
*/ |
539 |
if (distccRequired() && |
540 |
appendEnv("DISTCC_DIR", "PORTAGE_TMPDIR", "/.distcc") && |
541 |
addPathToEnv("SANDBOX_WRITE",getenv("DISTCC_DIR"))) { |
542 |
newargv = prependArgv(newargv, "/usr/bin/distcc"); |
543 |
} |
544 |
|
545 |
/* Prepend ccache, if enabled. |
546 |
* Set CCACHE_DIR to /var/tmp/ccache if not already set |
547 |
* Append CCACHE_DIR to SANDBOX_WRITE, SANDBOX_READ |
548 |
* Shuffle argv and set argv[0] to /usr/bin/ccache |
549 |
*/ |
550 |
if (ccacheRequired() && |
551 |
appendEnv("CCACHE_DIR", NULL, "/var/tmp/ccache") && |
552 |
addPathToEnv("SANDBOX_READ",getenv("CCACHE_DIR")) && |
553 |
addPathToEnv("SANDBOX_WRITE",getenv("CCACHE_DIR"))) { |
554 |
newargv = prependArgv(newargv, "/usr/bin/ccache"); |
555 |
} |
556 |
|
557 |
/* Ok, lets exec it. */ |
558 |
if (execv(newargv[0], newargv) < 0) |
374 |
wrapper_exit("Could not run/locate \"%s\"\n", data->name); |
559 |
wrapper_exit("Could not run/locate \"%s\"\n", data->name); |
375 |
|
560 |
|
376 |
return 0; |
561 |
return 0; |