Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 128810 | Differences between
and this patch

Collapse All | Expand All

(-)wrapper-1.4.7.c (-2 / +187 lines)
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;

Return to bug 128810