Blame src/internal/slibtool_lconf_impl.c

9c11fa
0801fe
/*******************************************************************/
0801fe
/*  slibtool: a skinny libtool implementation, written in C        */
0801fe
/*  Copyright (C) 2016--2018  Z. Gilboa                            */
0801fe
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
0801fe
/*******************************************************************/
0801fe
0801fe
#include <fcntl.h>
0801fe
#include <stdio.h>
0801fe
#include <stdint.h>
0801fe
#include <stdbool.h>
0801fe
#include <unistd.h>
0801fe
#include <sys/mman.h>
0801fe
#include <sys/stat.h>
0801fe
0801fe
#include "slibtool_lconf_impl.h"
0801fe
#include "slibtool_driver_impl.h"
0801fe
#include "slibtool_errinfo_impl.h"
0801fe
#include "slibtool_symlink_impl.h"
0801fe
#include "slibtool_readlink_impl.h"
0801fe
0801fe
enum slbt_lconf_opt {
0801fe
	SLBT_LCONF_OPT_UNKNOWN,
0801fe
	SLBT_LCONF_OPT_NO,
0801fe
	SLBT_LCONF_OPT_YES,
0801fe
};
0801fe
c58607
static const char aclr_reset[]   = "\x1b[0m";
c58607
static const char aclr_bold[]    = "\x1b[1m";
c58607
c58607
static const char aclr_red[]     = "\x1b[31m";
c58607
static const char aclr_green[]   = "\x1b[32m";
c58607
static const char aclr_yellow[]  = "\x1b[33m";
c58607
static const char aclr_blue[]    = "\x1b[34m";
c58607
static const char aclr_magenta[] = "\x1b[35m";
c58607
0801fe
static void slbt_lconf_close(int fdcwd, int fdlconfdir)
0801fe
{
0801fe
	if (fdlconfdir != fdcwd)
0801fe
		close(fdlconfdir);
0801fe
}
0801fe
c58607
static int slbt_lconf_trace_lconf_plain(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	const char *			lconf)
c58607
{
c58607
	int fderr = slbt_driver_fderr(dctx);
c58607
c58607
	if (slbt_dprintf(
c58607
			fderr,
c58607
			"%s: %s: {.name=%c%s%c}.\n",
c58607
			dctx->program,
c58607
			"lconf",
c58607
			'"',lconf,'"') < 0)
c58607
		return -1;
c58607
c58607
	return 0;
c58607
}
c58607
c58607
static int slbt_lconf_trace_lconf_annotated(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	const char *			lconf)
c58607
{
c58607
	int fderr = slbt_driver_fderr(dctx);
c58607
c58607
	if (slbt_dprintf(
c58607
			fderr,
c58607
			"%s%s%s%s: %s%s%s: {.name=%s%s%c%s%c%s}.\n",
c58607
c58607
			aclr_bold,aclr_magenta,
c58607
			dctx->program,
c58607
			aclr_reset,
c58607
c58607
			aclr_bold,
c58607
			"lconf",
c58607
			aclr_reset,
c58607
c58607
			aclr_bold,aclr_green,
c58607
			'"',lconf,'"',
c58607
			aclr_reset) < 0)
c58607
		return -1;
c58607
c58607
	return 0;
c58607
}
c58607
c58607
static int slbt_lconf_trace_openat_silent(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	int				fdat,
c58607
	const char *			path,
c58607
	int				oflag,
c58607
	int				mode)
c58607
{
c58607
	(void)dctx;
c58607
	return openat(fdat,path,oflag,mode);
c58607
}
c58607
c58607
static int slbt_lconf_trace_openat_plain(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	int				fdat,
c58607
	const char *			path,
c58607
	int				oflag,
c58607
	int				mode)
c58607
{
c58607
	char scwd[20];
c58607
	char serr[512];
c58607
c58607
	int  ret   = openat(fdat,path,oflag,mode);
c58607
	int  fderr = slbt_driver_fderr(dctx);
c58607
c58607
	if (fdat == AT_FDCWD) {
c58607
		strcpy(scwd,"AT_FDCWD");
c58607
	} else {
c58607
		sprintf(scwd,"%d",fdat);
c58607
	}
c58607
c58607
	if ((ret < 0) && (errno == ENOENT)) {
c58607
		strcpy(serr," [ENOENT]");
c58607
	} else if (ret < 0) {
c58607
		memset(serr,0,sizeof(serr));
c58607
		strerror_r(errno,&serr[2],sizeof(serr)-4);
c58607
		serr[0] = ' ';
c58607
		serr[1] = '(';
c58607
		serr[strlen(serr)] = ')';
c58607
	} else {
c58607
		serr[0] = 0;
c58607
	}
c58607
c58607
	slbt_dprintf(
c58607
		fderr,
c58607
		"%s: %s: openat(%s,%c%s%c,%s,%d) = %d%s.\n",
c58607
		dctx->program,
c58607
		"lconf",
c58607
		scwd,
c58607
		'"',path,'"',
c58607
		(oflag == O_DIRECTORY) ? "O_DIRECTORY" : "O_RDONLY",
c58607
		mode,ret,serr);
c58607
c58607
	return ret;
c58607
}
c58607
c58607
static int slbt_lconf_trace_openat_annotated(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	int				fdat,
c58607
	const char *			path,
c58607
	int				oflag,
c58607
	int				mode)
c58607
{
c58607
	char scwd[20];
c58607
	char serr[512];
c58607
c58607
	int  ret   = openat(fdat,path,oflag,mode);
c58607
	int  fderr = slbt_driver_fderr(dctx);
c58607
c58607
	if (fdat == AT_FDCWD) {
c58607
		strcpy(scwd,"AT_FDCWD");
c58607
	} else {
c58607
		sprintf(scwd,"%d",fdat);
c58607
	}
c58607
c58607
	if ((ret < 0) && (errno == ENOENT)) {
c58607
		strcpy(serr," [ENOENT]");
c58607
	} else if (ret < 0) {
c58607
		memset(serr,0,sizeof(serr));
c58607
		strerror_r(errno,&serr[2],sizeof(serr)-4);
c58607
		serr[0] = ' ';
c58607
		serr[1] = '(';
c58607
		serr[strlen(serr)] = ')';
c58607
	} else {
c58607
		serr[0] = 0;
c58607
	}
c58607
c58607
	slbt_dprintf(
c58607
		fderr,
c58607
		"%s%s%s%s: %s%s%s: openat(%s%s%s%s,%s%s%c%s%c%s,%s%s%s%s,%d) = %s%d%s%s%s%s%s.\n",
c58607
c58607
		aclr_bold,aclr_magenta,
c58607
		dctx->program,
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,
c58607
		"lconf",
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,aclr_blue,
c58607
		scwd,
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,aclr_green,
c58607
		'"',path,'"',
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,aclr_blue,
c58607
		(oflag == O_DIRECTORY) ? "O_DIRECTORY" : "O_RDONLY",
c58607
		aclr_reset,
c58607
c58607
		mode,
c58607
c58607
		aclr_bold,
c58607
		ret,
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,aclr_red,
c58607
		serr,
c58607
		aclr_reset);
c58607
c58607
	return ret;
c58607
}
c58607
c58607
static int slbt_lconf_trace_fstat_silent(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	int				fd,
c58607
	const char *			path,
c58607
	struct stat *			st)
c58607
{
c58607
	(void)dctx;
c58607
c58607
	return path ? fstatat(fd,path,st,0) : fstat(fd,st);
c58607
}
c58607
c58607
static int slbt_lconf_trace_fstat_plain(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	int				fd,
c58607
	const char *			path,
c58607
	struct stat *			st)
c58607
{
c58607
	char scwd[20];
c58607
	char serr[512];
c58607
	char quot[2] = {'"',0};
c58607
c58607
	int  ret   = path ? fstatat(fd,path,st,0) : fstat(fd,st);
c58607
	int  fderr = slbt_driver_fderr(dctx);
c58607
c58607
	if (fd == AT_FDCWD) {
c58607
		strcpy(scwd,"AT_FDCWD");
c58607
	} else {
c58607
		sprintf(scwd,"%d",fd);
c58607
	}
c58607
c58607
	if ((ret < 0) && (errno == ENOENT)) {
c58607
		strcpy(serr," [ENOENT]");
c58607
	} else if (ret < 0) {
c58607
		memset(serr,0,sizeof(serr));
c58607
		strerror_r(errno,&serr[2],sizeof(serr)-4);
c58607
		serr[0] = ' ';
c58607
		serr[1] = '(';
c58607
		serr[strlen(serr)] = ')';
c58607
	} else {
c58607
		serr[0] = 0;
c58607
	}
c58607
c58607
	slbt_dprintf(
c58607
		fderr,
c58607
		"%s: %s: %s(%s%s%s%s%s,...) = %d%s%s",
c58607
		dctx->program,
c58607
		"lconf",
c58607
		path ? "fstatat" : "fstat",
c58607
		scwd,
c58607
		path ? "," : "",
c58607
		path ? quot : "",
c58607
		path ? path : "",
c58607
		path ? quot : "",
c58607
		ret,
c58607
		serr,
c58607
		ret ? ".\n" : "");
c58607
c58607
	if (ret == 0)
c58607
		slbt_dprintf(
c58607
			fderr,
c58607
			" {.st_dev = %ld, .st_ino = %ld}.\n",
c58607
			st->st_dev,
c58607
			st->st_ino);
c58607
c58607
	return ret;
c58607
}
c58607
c58607
static int slbt_lconf_trace_fstat_annotated(
c58607
	struct slbt_driver_ctx *	dctx,
c58607
	int				fd,
c58607
	const char *			path,
c58607
	struct stat *			st)
c58607
{
c58607
	char scwd[20];
c58607
	char serr[512];
c58607
	char quot[2] = {'"',0};
c58607
c58607
	int  ret   = path ? fstatat(fd,path,st,0) : fstat(fd,st);
c58607
	int  fderr = slbt_driver_fderr(dctx);
c58607
c58607
	if (fd == AT_FDCWD) {
c58607
		strcpy(scwd,"AT_FDCWD");
c58607
	} else {
c58607
		sprintf(scwd,"%d",fd);
c58607
	}
c58607
c58607
	if ((ret < 0) && (errno == ENOENT)) {
c58607
		strcpy(serr," [ENOENT]");
c58607
	} else if (ret < 0) {
c58607
		memset(serr,0,sizeof(serr));
c58607
		strerror_r(errno,&serr[2],sizeof(serr)-4);
c58607
		serr[0] = ' ';
c58607
		serr[1] = '(';
c58607
		serr[strlen(serr)] = ')';
c58607
	} else {
c58607
		serr[0] = 0;
c58607
	}
c58607
c58607
	slbt_dprintf(
c58607
		fderr,
c58607
		"%s%s%s%s: %s%s%s: %s(%s%s%s%s%s%s%s%s%s%s%s,...) = %s%d%s%s%s%s%s%s",
c58607
c58607
		aclr_bold,aclr_magenta,
c58607
		dctx->program,
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,
c58607
		"lconf",
c58607
		aclr_reset,
c58607
c58607
		path ? "fstatat" : "fstat",
c58607
c58607
		aclr_bold,aclr_blue,
c58607
		scwd,
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,aclr_green,
c58607
		path ? "," : "",
c58607
		path ? quot : "",
c58607
		path ? path : "",
c58607
		path ? quot : "",
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,
c58607
		ret,
c58607
		aclr_reset,
c58607
c58607
		aclr_bold,aclr_red,
c58607
		serr,
c58607
		aclr_reset,
c58607
c58607
		ret ? ".\n" : "");
c58607
c58607
	if (ret == 0)
c58607
		slbt_dprintf(
c58607
			fderr,
c58607
			" {%s%s.st_dev%s = %s%ld%s, %s%s.st_ino%s = %s%ld%s}.\n",
c58607
c58607
			aclr_bold,aclr_yellow,aclr_reset,
c58607
c58607
			aclr_bold,
c58607
			st->st_dev,
c58607
			aclr_reset,
c58607
c58607
			aclr_bold,aclr_yellow,aclr_reset,
c58607
c58607
			aclr_bold,
c58607
			st->st_ino,
c58607
			aclr_reset);
c58607
c58607
	return ret;
c58607
}
c58607
9c11fa
static int slbt_lconf_trace_result_silent(
9c11fa
	struct slbt_driver_ctx *	dctx,
9c11fa
	int				fd,
9c11fa
	int				fdat,
9c11fa
	const char *			lconf,
9c11fa
	int				err)
9c11fa
{
9c11fa
	(void)dctx;
9c11fa
	(void)fd;
9c11fa
	(void)fdat;
9c11fa
	(void)lconf;
9c11fa
	return err ? (-1) : fd;
9c11fa
}
9c11fa
9c11fa
static int slbt_lconf_trace_result_plain(
9c11fa
	struct slbt_driver_ctx *	dctx,
9c11fa
	int				fd,
9c11fa
	int				fdat,
9c11fa
	const char *			lconf,
9c11fa
	int				err)
9c11fa
{
9c11fa
	int             fderr;
9c11fa
	const char *    cpath;
9c11fa
	char            path[PATH_MAX];
9c11fa
9c11fa
	fderr = slbt_driver_fderr(dctx);
9c11fa
9c11fa
	cpath = !(slbt_realpath(fdat,lconf,0,path,sizeof(path)))
9c11fa
		? path : lconf;
9c11fa
9c11fa
	switch (err) {
9c11fa
		case 0:
9c11fa
			slbt_dprintf(
9c11fa
				fderr,
9c11fa
				"%s: %s: found %c%s%c.\n",
9c11fa
				dctx->program,
9c11fa
				"lconf",
9c11fa
				'"',cpath,'"');
9c11fa
			return fd;
9c11fa
9c11fa
		case EXDEV:
9c11fa
			slbt_dprintf(
9c11fa
				fderr,
9c11fa
				"%s: %s: stopped in %c%s%c "
9c11fa
				"(config file not found on current device).\n",
9c11fa
				dctx->program,
9c11fa
				"lconf",
9c11fa
				'"',cpath,'"');
9c11fa
			return -1;
9c11fa
9c11fa
		default:
9c11fa
			slbt_dprintf(
9c11fa
				fderr,
9c11fa
				"%s: %s: stopped in %c%s%c "
9c11fa
				"(top-level directory reached).\n",
9c11fa
				dctx->program,
9c11fa
				"lconf",
9c11fa
				'"',cpath,'"');
9c11fa
			return -1;
9c11fa
	}
9c11fa
}
9c11fa
9c11fa
static int slbt_lconf_trace_result_annotated(
9c11fa
	struct slbt_driver_ctx *	dctx,
9c11fa
	int				fd,
9c11fa
	int				fdat,
9c11fa
	const char *			lconf,
9c11fa
	int				err)
9c11fa
{
9c11fa
	int             fderr;
9c11fa
	const char *    cpath;
9c11fa
	char            path[PATH_MAX];
9c11fa
9c11fa
	fderr = slbt_driver_fderr(dctx);
9c11fa
9c11fa
	cpath = !(slbt_realpath(fdat,lconf,0,path,sizeof(path)))
9c11fa
		? path : lconf;
9c11fa
9c11fa
	switch (err) {
9c11fa
		case 0:
9c11fa
			slbt_dprintf(
9c11fa
				fderr,
9c11fa
				"%s%s%s%s: %s%s%s: found %s%s%c%s%c%s.\n",
9c11fa
9c11fa
				aclr_bold,aclr_magenta,
9c11fa
				dctx->program,
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,
9c11fa
				"lconf",
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,aclr_green,
9c11fa
				'"',cpath,'"',
9c11fa
				aclr_reset);
9c11fa
			return fd;
9c11fa
9c11fa
		case EXDEV:
9c11fa
			slbt_dprintf(
9c11fa
				fderr,
9c11fa
				"%s%s%s%s: %s%s%s: stopped in %s%s%c%s%c%s "
9c11fa
				"%s%s(config file not found on current device)%s.\n",
9c11fa
9c11fa
				aclr_bold,aclr_magenta,
9c11fa
				dctx->program,
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,
9c11fa
				"lconf",
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,aclr_green,
9c11fa
				'"',cpath,'"',
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,aclr_red,
9c11fa
				aclr_reset);
9c11fa
			return -1;
9c11fa
9c11fa
		default:
9c11fa
			slbt_dprintf(
9c11fa
				fderr,
9c11fa
				"%s%s%s%s: %s%s%s: stopped in %s%s%c%s%c%s "
9c11fa
				"%s%s(top-level directory reached)%s.\n",
9c11fa
9c11fa
				aclr_bold,aclr_magenta,
9c11fa
				dctx->program,
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,
9c11fa
				"lconf",
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,aclr_green,
9c11fa
				'"',cpath,'"',
9c11fa
				aclr_reset,
9c11fa
9c11fa
				aclr_bold,aclr_red,
9c11fa
				aclr_reset);
9c11fa
			return -1;
9c11fa
	}
9c11fa
}
9c11fa
0801fe
static int slbt_lconf_open(
0801fe
	struct slbt_driver_ctx *	dctx,
0801fe
	const char *			lconf)
0801fe
{
c58607
	int		fderr;
0801fe
	int		fdcwd;
0801fe
	int		fdlconf;
0801fe
	int		fdlconfdir;
0801fe
	int		fdparent;
0801fe
	struct stat	stcwd;
0801fe
	struct stat	stparent;
0b404d
	ino_t		stinode;
0801fe
c58607
	int             (*trace_lconf)(struct slbt_driver_ctx *,
c58607
	                                const char *);
c58607
c58607
	int             (*trace_fstat)(struct slbt_driver_ctx *,
c58607
	                                int,const char *, struct stat *);
c58607
c58607
	int             (*trace_openat)(struct slbt_driver_ctx *,
c58607
	                                int,const char *,int,int);
c58607
9c11fa
	int             (*trace_result)(struct slbt_driver_ctx *,
9c11fa
	                                int,int,const char *,int);
9c11fa
c58607
	lconf      = lconf ? lconf : "libtool";
c58607
	fderr      = slbt_driver_fderr(dctx);
0801fe
	fdcwd      = slbt_driver_fdcwd(dctx);
0801fe
	fdlconfdir = fdcwd;
0801fe
c58607
	if (dctx->cctx->drvflags & SLBT_DRIVER_SILENT) {
c58607
		trace_lconf  = 0;
c58607
		trace_fstat  = slbt_lconf_trace_fstat_silent;
c58607
		trace_openat = slbt_lconf_trace_openat_silent;
9c11fa
		trace_result = slbt_lconf_trace_result_silent;
c58607
c58607
	} else if (dctx->cctx->drvflags & SLBT_DRIVER_ANNOTATE_NEVER) {
c58607
		trace_lconf  = slbt_lconf_trace_lconf_plain;
c58607
		trace_fstat  = slbt_lconf_trace_fstat_plain;
c58607
		trace_openat = slbt_lconf_trace_openat_plain;
9c11fa
		trace_result = slbt_lconf_trace_result_plain;
c58607
c58607
	} else if (dctx->cctx->drvflags & SLBT_DRIVER_ANNOTATE_ALWAYS) {
c58607
		trace_lconf  = slbt_lconf_trace_lconf_annotated;
c58607
		trace_fstat  = slbt_lconf_trace_fstat_annotated;
c58607
		trace_openat = slbt_lconf_trace_openat_annotated;
9c11fa
		trace_result = slbt_lconf_trace_result_annotated;
c58607
c58607
	} else if (isatty(fderr)) {
c58607
		trace_lconf  = slbt_lconf_trace_lconf_annotated;
c58607
		trace_fstat  = slbt_lconf_trace_fstat_annotated;
c58607
		trace_openat = slbt_lconf_trace_openat_annotated;
9c11fa
		trace_result = slbt_lconf_trace_result_annotated;
c58607
c58607
	} else {
c58607
		trace_lconf  = slbt_lconf_trace_lconf_plain;
c58607
		trace_fstat  = slbt_lconf_trace_fstat_plain;
c58607
		trace_openat = slbt_lconf_trace_openat_plain;
9c11fa
		trace_result = slbt_lconf_trace_result_plain;
c58607
	}
c58607
c58607
	if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) {
c58607
		trace_lconf(dctx,lconf);
c58607
		slbt_output_fdcwd(dctx);
c58607
	}
c58607
d70e37
	if (lconf && strchr(lconf,'/'))
c58607
		return ((fdlconf = trace_openat(dctx,fdcwd,lconf,O_RDONLY,0)) < 0)
0801fe
			? SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_LCONF_OPEN)
9c11fa
			: trace_result(dctx,fdlconf,fdcwd,lconf,0);
0801fe
c58607
	if (trace_fstat(dctx,fdlconfdir,".",&stcwd) < 0)
6beda1
		return SLBT_SYSTEM_ERROR(dctx,0);
0801fe
0b404d
	stinode = stcwd.st_ino;
c58607
	fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
0801fe
0801fe
	while (fdlconf < 0) {
c58607
		fdparent = trace_openat(dctx,fdlconfdir,"../",O_DIRECTORY,0);
0801fe
		slbt_lconf_close(fdcwd,fdlconfdir);
0801fe
0801fe
		if (fdparent < 0)
6beda1
			return SLBT_SYSTEM_ERROR(dctx,0);
0801fe
c58607
		if (trace_fstat(dctx,fdparent,0,&stparent) < 0) {
bab3d0
			close(fdparent);
6beda1
			return SLBT_SYSTEM_ERROR(dctx,0);
bab3d0
		}
0801fe
bab3d0
		if (stparent.st_dev != stcwd.st_dev) {
9c11fa
			trace_result(dctx,fdparent,fdparent,".",EXDEV);
bab3d0
			close(fdparent);
0801fe
			return SLBT_CUSTOM_ERROR(
0801fe
				dctx,SLBT_ERR_LCONF_OPEN);
bab3d0
		}
0801fe
0b404d
		if (stparent.st_ino == stinode) {
9c11fa
			trace_result(dctx,fdparent,fdparent,".",ELOOP);
0b404d
			close(fdparent);
0b404d
			return SLBT_CUSTOM_ERROR(
0b404d
				dctx,SLBT_ERR_LCONF_OPEN);
0b404d
		}
0b404d
0801fe
		fdlconfdir = fdparent;
c58607
		fdlconf    = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
0b404d
		stinode    = stparent.st_ino;
0801fe
	}
0801fe
9c11fa
	trace_result(dctx,fdlconf,fdlconfdir,lconf,0);
9c11fa
bab3d0
	slbt_lconf_close(fdcwd,fdlconfdir);
bab3d0
0801fe
	return fdlconf;
0801fe
}
0801fe
0801fe
int slbt_get_lconf_flags(
0801fe
	struct slbt_driver_ctx *	dctx,
0801fe
	const char *			lconf,
0801fe
	uint64_t *			flags)
0801fe
{
0801fe
	int				fdlconf;
0801fe
	struct stat			st;
0801fe
	void *				addr;
0801fe
	const char *			mark;
0801fe
	const char *			cap;
0801fe
	uint64_t			optshared;
0801fe
	uint64_t			optstatic;
0801fe
	int				optlenmax;
0801fe
	int				optsharedlen;
0801fe
	int				optstaticlen;
0801fe
	const char *			optsharedstr;
0801fe
	const char *			optstaticstr;
0801fe
0801fe
	/* open relative libtool script */
0801fe
	if ((fdlconf = slbt_lconf_open(dctx,lconf)) < 0)
0801fe
		return SLBT_NESTED_ERROR(dctx);
0801fe
0801fe
	/* map relative libtool script */
0801fe
	if (fstat(fdlconf,&st) < 0)
6beda1
		return SLBT_SYSTEM_ERROR(dctx,0);
0801fe
0801fe
	addr = mmap(
0801fe
		0,st.st_size,
0801fe
		PROT_READ,MAP_SHARED,
0801fe
		fdlconf,0);
0801fe
0801fe
	close(fdlconf);
0801fe
0801fe
	if (addr == MAP_FAILED)
0801fe
		return SLBT_CUSTOM_ERROR(
0801fe
			dctx,SLBT_ERR_LCONF_MAP);
0801fe
0801fe
	mark = addr;
0801fe
	cap  = &mark[st.st_size];
0801fe
0801fe
	/* hard-coded options in the generated libtool precede the code */
0801fe
	if (st.st_size >= (optlenmax = strlen("build_libtool_libs=yes\n")))
0801fe
		cap -= optlenmax;
0801fe
0801fe
	/* scan */
0801fe
	optshared = 0;
0801fe
	optstatic = 0;
0801fe
0801fe
	optsharedstr = "build_libtool_libs=";
0801fe
	optstaticstr = "build_old_libs=";
0801fe
0801fe
	optsharedlen = strlen(optsharedstr);
0801fe
	optstaticlen = strlen(optstaticstr);
0801fe
0801fe
	for (; mark && mark
0801fe
		if (!strncmp(mark,optsharedstr,optsharedlen)) {
0801fe
			mark += optsharedlen;
0801fe
0801fe
			if ((mark[0]=='n')
0801fe
					&& (mark[1]=='o')
0801fe
					&& (mark[2]=='\n'))
0801fe
				optshared = SLBT_DRIVER_DISABLE_SHARED;
0801fe
0801fe
			if ((mark[0]=='y')
0801fe
					&& (mark[1]=='e')
0801fe
					&& (mark[2]=='s')
0801fe
					&& (mark[3]=='\n'))
0801fe
				optshared = SLBT_DRIVER_SHARED;
0801fe
0801fe
		} if (!strncmp(mark,optstaticstr,optstaticlen)) {
0801fe
			mark += optstaticlen;
0801fe
0801fe
			if ((mark[0]=='n')
0801fe
					&& (mark[1]=='o')
0801fe
					&& (mark[2]=='\n'))
0801fe
				optstatic = SLBT_DRIVER_DISABLE_STATIC;
0801fe
0801fe
			if ((mark[0]=='y')
0801fe
					&& (mark[1]=='e')
0801fe
					&& (mark[2]=='s')
0801fe
					&& (mark[3]=='\n'))
0801fe
				optstatic = SLBT_DRIVER_STATIC;
0801fe
		}
0801fe
0801fe
		if (optshared && optstatic)
0801fe
			mark = 0;
0801fe
0801fe
		else {
0801fe
			for (; (mark
0801fe
				mark++;
0801fe
			mark++;
0801fe
		}
0801fe
	}
0801fe
0801fe
	munmap(addr,st.st_size);
0801fe
0801fe
	if (!optshared || !optstatic)
0801fe
		return SLBT_CUSTOM_ERROR(
0801fe
			dctx,SLBT_ERR_LCONF_PARSE);
0801fe
0801fe
	*flags = optshared | optstatic;
0801fe
0801fe
	return 0;
0801fe
}