firasuke / cross / slibtool

Forked from cross/slibtool 3 months ago
Clone

Blame src/driver/slbt_host_params.c

8f60d4
/*******************************************************************/
8f60d4
/*  slibtool: a skinny libtool implementation, written in C        */
8f60d4
/*  Copyright (C) 2016--2021  SysDeer Technologies, LLC            */
8f60d4
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
8f60d4
/*******************************************************************/
8f60d4
8f60d4
#include <stdint.h>
8f60d4
#include <string.h>
8f60d4
#include <unistd.h>
8f60d4
#include <stdlib.h>
8f60d4
#include <stdbool.h>
8f60d4
#include <fcntl.h>
8f60d4
#include <spawn.h>
8f60d4
#include <sys/wait.h>
8f60d4
8f60d4
#include <slibtool/slibtool.h>
8f60d4
#include "slibtool_driver_impl.h"
8f60d4
#include "slibtool_errinfo_impl.h"
8f60d4
#include "slibtool_ar_impl.h"
8f60d4
8f60d4
8f60d4
/* annotation strings */
8f60d4
static const char cfgexplicit[] = "command-line argument";
8f60d4
static const char cfghost[]     = "derived from <host>";
8f60d4
static const char cfgtarget[]   = "derived from <target>";
8f60d4
static const char cfgcompiler[] = "derived from <compiler>";
8f60d4
static const char cfgnmachine[] = "native (cached in ccenv/host.mk)";
8f60d4
static const char cfgxmachine[] = "foreign (derived from -dumpmachine)";
8f60d4
static const char cfgnative[]   = "native";
8f60d4
8f60d4
/* elf rpath */
8f60d4
static const char*ldrpath_elf[] = {
8f60d4
	"/lib",
8f60d4
	"/lib/64",
8f60d4
	"/usr/lib",
8f60d4
	"/usr/lib64",
8f60d4
	"/usr/local/lib",
8f60d4
	"/usr/local/lib64",
8f60d4
	0};
8f60d4
8f60d4
/* flavor settings */
8f60d4
#define SLBT_FLAVOR_SETTINGS(flavor,          \
8f60d4
		bfmt,pic,                     \
8f60d4
		arp,ars,dsop,dsos,osds,osdf,  \
8f60d4
		exep,exes,impp,imps,          \
8f60d4
		ldenv)                        \
8f60d4
	static const struct slbt_flavor_settings flavor = {  \
8f60d4
		bfmt,arp,ars,dsop,dsos,osds,osdf,           \
8f60d4
		exep,exes,impp,imps,                       \
8f60d4
		ldenv,pic}
8f60d4
8f60d4
SLBT_FLAVOR_SETTINGS(host_flavor_default,       \
8f60d4
	"elf","-fPIC",                          \
8f60d4
	"lib",".a","lib",".so",".so","",        \
8f60d4
	"","","","",                            \
8f60d4
	"LD_LIBRARY_PATH");
8f60d4
8f60d4
SLBT_FLAVOR_SETTINGS(host_flavor_midipix,       \
8f60d4
	"pe","-fPIC",                           \
8f60d4
	"lib",".a","lib",".so",".so","",        \
8f60d4
	"","","lib",".lib.a",                   \
8f60d4
	"LD_LIBRARY_PATH");
8f60d4
8f60d4
SLBT_FLAVOR_SETTINGS(host_flavor_mingw,         \
8f60d4
	"pe",0,                                 \
8f60d4
	"lib",".a","lib",".dll","",".dll",      \
8f60d4
	"",".exe","lib",".dll.a",               \
8f60d4
	"PATH");
8f60d4
8f60d4
SLBT_FLAVOR_SETTINGS(host_flavor_cygwin,        \
8f60d4
	"pe",0,                                 \
8f60d4
	"lib",".a","lib",".dll","",".dll",      \
8f60d4
	"",".exe","lib",".dll.a",               \
8f60d4
	"PATH");
8f60d4
8f60d4
SLBT_FLAVOR_SETTINGS(host_flavor_darwin,        \
8f60d4
	"macho","-fPIC",                        \
8f60d4
	"lib",".a","lib",".dylib","",".dylib",  \
8f60d4
	"","","","",                            \
8f60d4
	"DYLD_LIBRARY_PATH");
8f60d4
8f60d4
8f60d4
static void slbt_get_host_quad(
8f60d4
	char *	hostbuf,
8f60d4
	char ** hostquad)
8f60d4
{
8f60d4
	char *	mark;
8f60d4
	char *	ch;
8f60d4
	int	i;
8f60d4
8f60d4
	for (i=0, ch=hostbuf, mark=hostbuf; *ch && i<4; ch++) {
8f60d4
		if (*ch == '-') {
8f60d4
			*ch = 0;
8f60d4
			hostquad[i++] = mark;
8f60d4
			mark = &ch[1];
8f60d4
		}
8f60d4
	}
8f60d4
8f60d4
	if (i<4)
8f60d4
		hostquad[i] = mark;
8f60d4
8f60d4
	if (i==3) {
8f60d4
		hostquad[1] = hostquad[2];
8f60d4
		hostquad[2] = hostquad[3];
8f60d4
		hostquad[3] = 0;
8f60d4
	}
8f60d4
}
8f60d4
8f60d4
8f60d4
static void slbt_spawn_ar(char ** argv, int * ecode)
8f60d4
{
8f60d4
	int	estatus;
8f60d4
	pid_t	pid;
8f60d4
8f60d4
	*ecode = 127;
8f60d4
8f60d4
	if ((pid = fork()) < 0) {
8f60d4
		return;
8f60d4
8f60d4
	} else if (pid == 0) {
8f60d4
		execvp(argv[0],argv);
8f60d4
		_exit(errno);
8f60d4
8f60d4
	} else {
8f60d4
		waitpid(pid,&estatus,0);
8f60d4
8f60d4
		if (WIFEXITED(estatus))
8f60d4
			*ecode = WEXITSTATUS(estatus);
8f60d4
	}
8f60d4
}
8f60d4
8f60d4
8f60d4
int slbt_init_host_params(
8f60d4
	const struct slbt_driver_ctx *	dctx,
8f60d4
	const struct slbt_common_ctx *	cctx,
8f60d4
	struct slbt_host_strs *		drvhost,
8f60d4
	struct slbt_host_params *	host,
8f60d4
	struct slbt_host_params *	cfgmeta,
8f60d4
	const char *                    cfgmeta_ar,
8f60d4
	const char *                    cfgmeta_ranlib)
8f60d4
{
8f60d4
	int		fdcwd;
8f60d4
	int		arprobe;
8f60d4
	int		arfd;
8f60d4
	int		ecode;
8f60d4
	size_t		toollen;
8f60d4
	char *		dash;
8f60d4
	char *		base;
8f60d4
	char *		mark;
8f60d4
	const char *	machine;
8f60d4
	bool		ftarget       = false;
8f60d4
	bool		fhost         = false;
8f60d4
	bool		fcompiler     = false;
8f60d4
	bool		fnative       = false;
8f60d4
	bool		fdumpmachine  = false;
8f60d4
	char		buf        [256];
8f60d4
	char		hostbuf    [256];
8f60d4
	char		machinebuf [256];
8f60d4
	char *		hostquad   [4];
8f60d4
	char *		machinequad[4];
8f60d4
	char *		arprobeargv[4];
8f60d4
	char		archivename[] = "/tmp/slibtool.ar.probe.XXXXXXXXXXXXXXXX";
8f60d4
8f60d4
	/* base */
8f60d4
	if ((base = strrchr(cctx->cargv[0],'/')))
8f60d4
		base++;
8f60d4
	else
8f60d4
		base = cctx->cargv[0];
8f60d4
8f60d4
	fdumpmachine  = (cctx->mode == SLBT_MODE_COMPILE)
8f60d4
			|| (cctx->mode == SLBT_MODE_LINK)
8f60d4
			|| (cctx->mode == SLBT_MODE_INFO);
8f60d4
8f60d4
	fdumpmachine &= (!strcmp(base,"xgcc")
8f60d4
			|| !strcmp(base,"xg++"));
8f60d4
8f60d4
	/* support the portbld <--> unknown synonym */
8f60d4
	if (!(drvhost->machine = strdup(SLBT_MACHINE)))
8f60d4
		return -1;
8f60d4
8f60d4
	if ((mark = strstr(drvhost->machine,"-portbld-")))
8f60d4
		memcpy(mark,"-unknown",8);
8f60d4
8f60d4
	/* host */
8f60d4
	if (host->host) {
8f60d4
		cfgmeta->host = cfgexplicit;
8f60d4
		fhost         = true;
8f60d4
8f60d4
	} else if (cctx->target) {
8f60d4
		host->host    = cctx->target;
8f60d4
		cfgmeta->host = cfgtarget;
8f60d4
		ftarget       = true;
8f60d4
8f60d4
	} else if (strrchr(base,'-')) {
8f60d4
		if (!(drvhost->host = strdup(cctx->cargv[0])))
8f60d4
			return -1;
8f60d4
8f60d4
		dash          = strrchr(drvhost->host,'-');
8f60d4
		*dash         = 0;
8f60d4
		host->host    = drvhost->host;
8f60d4
		cfgmeta->host = cfgcompiler;
8f60d4
		fcompiler     = true;
8f60d4
8f60d4
	} else if (!fdumpmachine) {
8f60d4
		host->host    = drvhost->machine;
8f60d4
		cfgmeta->host = cfgnmachine;
8f60d4
8f60d4
	} else if (slbt_dump_machine(cctx->cargv[0],buf,sizeof(buf)) < 0) {
8f60d4
		if (dctx)
8f60d4
			slbt_dprintf(
8f60d4
				slbt_driver_fderr(dctx),
8f60d4
				"%s: could not determine host "
8f60d4
				"via -dumpmachine\n",
8f60d4
				dctx->program);
8f60d4
		return -1;
8f60d4
8f60d4
	} else {
8f60d4
		if (!(drvhost->host = strdup(buf)))
8f60d4
			return -1;
8f60d4
8f60d4
		host->host    = drvhost->host;
8f60d4
		fcompiler     = true;
8f60d4
		fnative       = !strcmp(host->host,drvhost->machine);
8f60d4
		cfgmeta->host = fnative ? cfgnmachine : cfgxmachine;
8f60d4
8f60d4
		if (!fnative) {
8f60d4
			strcpy(hostbuf,host->host);
8f60d4
			strcpy(machinebuf,drvhost->machine);
8f60d4
8f60d4
			slbt_get_host_quad(hostbuf,hostquad);
8f60d4
			slbt_get_host_quad(machinebuf,machinequad);
8f60d4
8f60d4
			if (hostquad[2] && machinequad[2])
8f60d4
				fnative = !strcmp(hostquad[0],machinequad[0])
8f60d4
					&& !strcmp(hostquad[1],machinequad[1])
8f60d4
					&& !strcmp(hostquad[2],machinequad[2]);
8f60d4
		}
8f60d4
	}
8f60d4
8f60d4
	/* flavor */
8f60d4
	if (host->flavor) {
8f60d4
		cfgmeta->flavor = cfgexplicit;
8f60d4
	} else {
8f60d4
		if (fhost) {
8f60d4
			machine         = host->host;
8f60d4
			cfgmeta->flavor = cfghost;
8f60d4
		} else if (ftarget) {
8f60d4
			machine         = cctx->target;
8f60d4
			cfgmeta->flavor = cfgtarget;
8f60d4
		} else if (fcompiler) {
8f60d4
			machine         = drvhost->host;
8f60d4
			cfgmeta->flavor = cfgcompiler;
8f60d4
		} else {
8f60d4
			machine         = drvhost->machine;
8f60d4
			cfgmeta->flavor = cfgnmachine;
8f60d4
		}
8f60d4
8f60d4
		dash = strrchr(machine,'-');
8f60d4
		cfgmeta->flavor = cfghost;
8f60d4
8f60d4
		if ((dash && !strcmp(dash,"-bsd")) || strstr(machine,"-bsd-"))
8f60d4
			host->flavor = "bsd";
8f60d4
		else if ((dash && !strcmp(dash,"-cygwin")) || strstr(machine,"-cygwin-"))
8f60d4
			host->flavor = "cygwin";
8f60d4
		else if ((dash && !strcmp(dash,"-darwin")) || strstr(machine,"-darwin"))
8f60d4
			host->flavor = "darwin";
8f60d4
		else if ((dash && !strcmp(dash,"-linux")) || strstr(machine,"-linux-"))
8f60d4
			host->flavor = "linux";
8f60d4
		else if ((dash && !strcmp(dash,"-midipix")) || strstr(machine,"-midipix-"))
8f60d4
			host->flavor = "midipix";
8f60d4
		else if ((dash && !strcmp(dash,"-mingw")) || strstr(machine,"-mingw-"))
8f60d4
			host->flavor = "mingw";
8f60d4
		else if ((dash && !strcmp(dash,"-mingw32")) || strstr(machine,"-mingw32-"))
8f60d4
			host->flavor = "mingw";
8f60d4
		else if ((dash && !strcmp(dash,"-mingw64")) || strstr(machine,"-mingw64-"))
8f60d4
			host->flavor = "mingw";
8f60d4
		else if ((dash && !strcmp(dash,"-windows")) || strstr(machine,"-windows-"))
8f60d4
			host->flavor = "mingw";
8f60d4
		else {
8f60d4
			host->flavor   = "default";
8f60d4
			cfgmeta->flavor = "fallback, unverified";
8f60d4
		}
8f60d4
8f60d4
		if (fcompiler && !fnative)
8f60d4
			if ((mark = strstr(drvhost->machine,host->flavor)))
8f60d4
				if (mark > drvhost->machine)
8f60d4
					fnative = (*--mark == '-');
8f60d4
	}
8f60d4
8f60d4
	/* toollen */
8f60d4
	toollen =  fnative ? 0 : strlen(host->host);
8f60d4
	toollen += strlen("-utility-name");
8f60d4
8f60d4
	/* ar */
8f60d4
	if (host->ar)
8f60d4
		cfgmeta->ar = cfgmeta_ar ? cfgmeta_ar : cfgexplicit;
8f60d4
	else {
8f60d4
		if (!(drvhost->ar = calloc(1,toollen)))
8f60d4
			return -1;
8f60d4
8f60d4
		if (fnative) {
8f60d4
			strcpy(drvhost->ar,"ar");
8f60d4
			cfgmeta->ar = cfgnative;
8f60d4
			arprobe = 0;
8f60d4
		} else if (cctx->mode == SLBT_MODE_LINK) {
8f60d4
			arprobe = true;
8f60d4
		} else if (cctx->mode == SLBT_MODE_INFO) {
8f60d4
			arprobe = true;
8f60d4
		} else {
8f60d4
			arprobe = false;
8f60d4
		}
8f60d4
8f60d4
		/* arprobe */
8f60d4
		if (arprobe) {
8f60d4
			sprintf(drvhost->ar,"%s-ar",host->host);
8f60d4
			cfgmeta->ar = cfghost;
8f60d4
			ecode       = 127;
8f60d4
8f60d4
			/* empty archive */
8f60d4
			if ((arfd = mkstemp(archivename)) >= 0) {
8f60d4
				slbt_dprintf(arfd,"!<arch>\n");
8f60d4
8f60d4
				arprobeargv[0] = drvhost->ar;
8f60d4
				arprobeargv[1] = "-t";
8f60d4
				arprobeargv[2] = archivename;
8f60d4
				arprobeargv[3] = 0;
8f60d4
8f60d4
				/* <target>-ar */
8f60d4
				slbt_spawn_ar(
8f60d4
					arprobeargv,
8f60d4
					&ecode);
8f60d4
			}
8f60d4
8f60d4
			/* <target>-<compiler>-ar */
8f60d4
			if (ecode && !strchr(base,'-')) {
8f60d4
				sprintf(drvhost->ar,"%s-%s-ar",host->host,base);
8f60d4
8f60d4
				slbt_spawn_ar(
8f60d4
					arprobeargv,
8f60d4
					&ecode);
8f60d4
			}
8f60d4
8f60d4
			/* <compiler>-ar */
8f60d4
			if (ecode && !strchr(base,'-')) {
8f60d4
				sprintf(drvhost->ar,"%s-ar",base);
8f60d4
8f60d4
				slbt_spawn_ar(
8f60d4
					arprobeargv,
8f60d4
					&ecode);
8f60d4
			}
8f60d4
8f60d4
			/* if target is the native target, fallback to native ar */
8f60d4
			if (ecode && !strcmp(host->host,SLBT_MACHINE)) {
8f60d4
				strcpy(drvhost->ar,"ar");
8f60d4
				cfgmeta->ar = cfgnative;
8f60d4
			}
8f60d4
8f60d4
			/* fdcwd */
8f60d4
			fdcwd = slbt_driver_fdcwd(dctx);
8f60d4
8f60d4
			/* clean up */
8f60d4
			if (arfd >= 0) {
8f60d4
				unlinkat(fdcwd,archivename,0);
8f60d4
				close(arfd);
8f60d4
			}
8f60d4
		}
8f60d4
8f60d4
		host->ar = drvhost->ar;
8f60d4
	}
8f60d4
8f60d4
	/* ranlib */
8f60d4
	if (host->ranlib)
8f60d4
		cfgmeta->ranlib = cfgmeta_ranlib ? cfgmeta_ranlib : cfgexplicit;
8f60d4
	else {
8f60d4
		if (!(drvhost->ranlib = calloc(1,toollen)))
8f60d4
			return -1;
8f60d4
8f60d4
		if (fnative) {
8f60d4
			strcpy(drvhost->ranlib,"ranlib");
8f60d4
			cfgmeta->ranlib = cfgnative;
8f60d4
		} else {
8f60d4
			sprintf(drvhost->ranlib,"%s-ranlib",host->host);
8f60d4
			cfgmeta->ranlib = cfghost;
8f60d4
		}
8f60d4
8f60d4
		host->ranlib = drvhost->ranlib;
8f60d4
	}
8f60d4
8f60d4
	/* windres */
8f60d4
	if (host->windres)
8f60d4
		cfgmeta->windres = cfgexplicit;
8f60d4
8f60d4
	else if (strcmp(host->flavor,"cygwin")
8f60d4
			&& strcmp(host->flavor,"midipix")
8f60d4
			&& strcmp(host->flavor,"mingw")) {
8f60d4
		host->windres    = "";
8f60d4
		cfgmeta->windres = "not applicable";
8f60d4
8f60d4
	} else {
8f60d4
		if (!(drvhost->windres = calloc(1,toollen)))
8f60d4
			return -1;
8f60d4
8f60d4
		if (fnative) {
8f60d4
			strcpy(drvhost->windres,"windres");
8f60d4
			cfgmeta->windres = cfgnative;
8f60d4
		} else {
8f60d4
			sprintf(drvhost->windres,"%s-windres",host->host);
8f60d4
			cfgmeta->windres = cfghost;
8f60d4
		}
8f60d4
8f60d4
		host->windres = drvhost->windres;
8f60d4
	}
8f60d4
8f60d4
	/* dlltool */
8f60d4
	if (host->dlltool)
8f60d4
		cfgmeta->dlltool = cfgexplicit;
8f60d4
8f60d4
	else if (strcmp(host->flavor,"cygwin")
8f60d4
			&& strcmp(host->flavor,"midipix")
8f60d4
			&& strcmp(host->flavor,"mingw")) {
8f60d4
		host->dlltool = "";
8f60d4
		cfgmeta->dlltool = "not applicable";
8f60d4
8f60d4
	} else {
8f60d4
		if (!(drvhost->dlltool = calloc(1,toollen)))
8f60d4
			return -1;
8f60d4
8f60d4
		if (fnative) {
8f60d4
			strcpy(drvhost->dlltool,"dlltool");
8f60d4
			cfgmeta->dlltool = cfgnative;
8f60d4
		} else {
8f60d4
			sprintf(drvhost->dlltool,"%s-dlltool",host->host);
8f60d4
			cfgmeta->dlltool = cfghost;
8f60d4
		}
8f60d4
8f60d4
		host->dlltool = drvhost->dlltool;
8f60d4
	}
8f60d4
8f60d4
	/* mdso */
8f60d4
	if (host->mdso)
8f60d4
		cfgmeta->mdso = cfgexplicit;
8f60d4
8f60d4
	else if (strcmp(host->flavor,"cygwin")
8f60d4
			&& strcmp(host->flavor,"midipix")
8f60d4
			&& strcmp(host->flavor,"mingw")) {
8f60d4
		host->mdso = "";
8f60d4
		cfgmeta->mdso = "not applicable";
8f60d4
8f60d4
	} else {
8f60d4
		if (!(drvhost->mdso = calloc(1,toollen)))
8f60d4
			return -1;
8f60d4
8f60d4
		if (fnative) {
8f60d4
			strcpy(drvhost->mdso,"mdso");
8f60d4
			cfgmeta->mdso = cfgnative;
8f60d4
		} else {
8f60d4
			sprintf(drvhost->mdso,"%s-mdso",host->host);
8f60d4
			cfgmeta->mdso = cfghost;
8f60d4
		}
8f60d4
8f60d4
		host->mdso = drvhost->mdso;
8f60d4
	}
8f60d4
8f60d4
	return 0;
8f60d4
}
8f60d4
8f60d4
8f60d4
void slbt_free_host_params(struct slbt_host_strs * host)
8f60d4
{
8f60d4
	if (host->machine)
8f60d4
		free(host->machine);
8f60d4
8f60d4
	if (host->host)
8f60d4
		free(host->host);
8f60d4
8f60d4
	if (host->flavor)
8f60d4
		free(host->flavor);
8f60d4
8f60d4
	if (host->ar)
8f60d4
		free(host->ar);
8f60d4
8f60d4
	if (host->ranlib)
8f60d4
		free(host->ranlib);
8f60d4
8f60d4
	if (host->windres)
8f60d4
		free(host->windres);
8f60d4
8f60d4
	if (host->dlltool)
8f60d4
		free(host->dlltool);
8f60d4
8f60d4
	if (host->mdso)
8f60d4
		free(host->mdso);
8f60d4
8f60d4
	memset(host,0,sizeof(*host));
8f60d4
}
8f60d4
8f60d4
8f60d4
void slbt_init_flavor_settings(
8f60d4
	struct slbt_common_ctx *	cctx,
8f60d4
	const struct slbt_host_params * ahost,
8f60d4
	struct slbt_flavor_settings *	psettings)
8f60d4
{
8f60d4
	const struct slbt_host_params *     host;
8f60d4
	const struct slbt_flavor_settings * settings;
8f60d4
8f60d4
	host = ahost ? ahost : &cctx->host;
8f60d4
8f60d4
	if (!strcmp(host->flavor,"midipix"))
8f60d4
		settings = &host_flavor_midipix;
8f60d4
	else if (!strcmp(host->flavor,"mingw"))
8f60d4
		settings = &host_flavor_mingw;
8f60d4
	else if (!strcmp(host->flavor,"cygwin"))
8f60d4
		settings = &host_flavor_cygwin;
8f60d4
	else if (!strcmp(host->flavor,"darwin"))
8f60d4
		settings = &host_flavor_darwin;
8f60d4
	else
8f60d4
		settings = &host_flavor_default;
8f60d4
8f60d4
	if (!ahost) {
8f60d4
		if (!strcmp(settings->imagefmt,"elf"))
8f60d4
			cctx->drvflags |= SLBT_DRIVER_IMAGE_ELF;
8f60d4
		else if (!strcmp(settings->imagefmt,"pe"))
8f60d4
			cctx->drvflags |= SLBT_DRIVER_IMAGE_PE;
8f60d4
		else if (!strcmp(settings->imagefmt,"macho"))
8f60d4
			cctx->drvflags |= SLBT_DRIVER_IMAGE_MACHO;
8f60d4
	}
8f60d4
8f60d4
	memcpy(psettings,settings,sizeof(*settings));
8f60d4
8f60d4
	if (cctx->shrext)
8f60d4
		psettings->dsosuffix = cctx->shrext;
8f60d4
}
8f60d4
8f60d4
8f60d4
int slbt_init_ldrpath(
8f60d4
	struct slbt_common_ctx *  cctx,
8f60d4
	struct slbt_host_params * host)
8f60d4
{
8f60d4
	char *         buf;
8f60d4
	const char **  ldrpath;
8f60d4
8f60d4
	if (!cctx->rpath || !(cctx->drvflags & SLBT_DRIVER_IMAGE_ELF)) {
8f60d4
		host->ldrpath = 0;
8f60d4
		return 0;
8f60d4
	}
8f60d4
8f60d4
	/* common? */
8f60d4
	for (ldrpath=ldrpath_elf; *ldrpath; ldrpath ++)
8f60d4
		if (!(strcmp(cctx->rpath,*ldrpath))) {
8f60d4
			host->ldrpath = 0;
8f60d4
			return 0;
8f60d4
		}
8f60d4
8f60d4
	/* buf */
8f60d4
	if (!(buf = malloc(12 + strlen(cctx->host.host))))
8f60d4
		return -1;
8f60d4
8f60d4
	/* /usr/{host}/lib */
8f60d4
	sprintf(buf,"/usr/%s/lib",cctx->host.host);
8f60d4
8f60d4
	if (!(strcmp(cctx->rpath,buf))) {
8f60d4
		host->ldrpath = 0;
8f60d4
		free(buf);
8f60d4
		return 0;
8f60d4
	}
8f60d4
8f60d4
	/* /usr/{host}/lib64 */
8f60d4
	sprintf(buf,"/usr/%s/lib64",cctx->host.host);
8f60d4
8f60d4
	if (!(strcmp(cctx->rpath,buf))) {
8f60d4
		host->ldrpath = 0;
8f60d4
		free(buf);
8f60d4
		return 0;
8f60d4
	}
8f60d4
8f60d4
	host->ldrpath = cctx->rpath;
8f60d4
8f60d4
	free(buf);
8f60d4
	return 0;
8f60d4
}
8f60d4
8f60d4
8f60d4
void slbt_reset_alternate_host(const struct slbt_driver_ctx * ctx)
8f60d4
{
8f60d4
	struct slbt_driver_ctx_alloc *	ictx;
8f60d4
	uintptr_t			addr;
8f60d4
8f60d4
	addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
8f60d4
	addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
8f60d4
	ictx = (struct slbt_driver_ctx_alloc *)addr;
8f60d4
8f60d4
	slbt_free_host_params(&ictx->ctx.ahost);
8f60d4
}
8f60d4
8f60d4
int  slbt_set_alternate_host(
8f60d4
	const struct slbt_driver_ctx *	ctx,
8f60d4
	const char *			host,
8f60d4
	const char *			flavor)
8f60d4
{
8f60d4
	struct slbt_driver_ctx_alloc *	ictx;
8f60d4
	uintptr_t			addr;
8f60d4
8f60d4
	addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
8f60d4
	addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
8f60d4
	ictx = (struct slbt_driver_ctx_alloc *)addr;
8f60d4
	slbt_free_host_params(&ictx->ctx.ahost);
8f60d4
8f60d4
	if (!(ictx->ctx.ahost.host = strdup(host)))
8f60d4
		return SLBT_SYSTEM_ERROR(ctx,0);
8f60d4
8f60d4
	if (!(ictx->ctx.ahost.flavor = strdup(flavor))) {
8f60d4
		slbt_free_host_params(&ictx->ctx.ahost);
8f60d4
		return SLBT_SYSTEM_ERROR(ctx,0);
8f60d4
	}
8f60d4
8f60d4
	ictx->ctx.cctx.ahost.host   = ictx->ctx.ahost.host;
8f60d4
	ictx->ctx.cctx.ahost.flavor = ictx->ctx.ahost.flavor;
8f60d4
8f60d4
	if (slbt_init_host_params(
8f60d4
			0,
8f60d4
			ctx->cctx,
8f60d4
			&ictx->ctx.ahost,
8f60d4
			&ictx->ctx.cctx.ahost,
8f60d4
			&ictx->ctx.cctx.acfgmeta,
8f60d4
			0,0)) {
8f60d4
		slbt_free_host_params(&ictx->ctx.ahost);
8f60d4
		return SLBT_CUSTOM_ERROR(ctx,SLBT_ERR_HOST_INIT);
8f60d4
	}
8f60d4
8f60d4
	slbt_init_flavor_settings(
8f60d4
		&ictx->ctx.cctx,
8f60d4
		&ictx->ctx.cctx.ahost,
8f60d4
		&ictx->ctx.cctx.asettings);
8f60d4
8f60d4
	if (slbt_init_ldrpath(
8f60d4
			&ictx->ctx.cctx,
8f60d4
			&ictx->ctx.cctx.ahost)) {
8f60d4
		slbt_free_host_params(&ictx->ctx.ahost);
8f60d4
		return SLBT_CUSTOM_ERROR(ctx,SLBT_ERR_LDRPATH_INIT);
8f60d4
	}
8f60d4
8f60d4
	return 0;
8f60d4
}
8f60d4
8f60d4
int slbt_get_flavor_settings(
8f60d4
	const char *                            flavor,
8f60d4
	const struct slbt_flavor_settings **    settings)
8f60d4
{
8f60d4
	if (!strcmp(flavor,"midipix"))
8f60d4
		*settings = &host_flavor_midipix;
8f60d4
	else if (!strcmp(flavor,"mingw"))
8f60d4
		*settings = &host_flavor_mingw;
8f60d4
	else if (!strcmp(flavor,"cygwin"))
8f60d4
		*settings = &host_flavor_cygwin;
8f60d4
	else if (!strcmp(flavor,"darwin"))
8f60d4
		*settings = &host_flavor_darwin;
8f60d4
	else if (!strcmp(flavor,"default"))
8f60d4
		*settings = &host_flavor_default;
8f60d4
	else
8f60d4
		*settings = 0;
8f60d4
8f60d4
	return *settings ? 0 : -1;
8f60d4
}