aboutsummaryrefslogtreecommitdiff
path: root/lib/base/eenv.cpp.in
blob: 52c421472ce346b21bd3a75fe4fa4ef94c60912e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <wordexp.h>
#include <lib/base/eenv.h>
#include <lib/base/eerror.h>

bool eEnv::initialized = false;

void eEnv::initialize()
{
	static const struct {
		std::string name;
		std::string value;
	} cfgenv[] = {
		{ "prefix", "@prefix@" },
		{ "exec_prefix", "@exec_prefix@" },
		{ "bindir", "@bindir@" },
		{ "sbindir", "@sbindir@" },
		{ "libexecdir", "@libexecdir@" },
		{ "datarootdir", "@datarootdir@" },
		{ "datadir", "@datadir@" },
		{ "sysconfdir", "@sysconfdir@" },
		{ "sharedstatedir", "@sharedstatedir@" },
		{ "localstatedir", "@localstatedir@" },
		{ "libdir", "@libdir@" },
		{ "localedir", "@localedir@" },
	};
	size_t i;

	// 1st pass, as generated by configure.
	// Variables set by the user will not be overwritten.
	for (i = 0; i < (sizeof(cfgenv) / sizeof(*cfgenv)); i++) {
		eDebug("setenv('%s', '%s', 0)", cfgenv[i].name.c_str(), cfgenv[i].value.c_str());
		setenv(cfgenv[i].name.c_str(), cfgenv[i].value.c_str(), 0);
	}

	// 2nd pass: Resolve directories.
	for (i = 0; i < (sizeof(cfgenv) / sizeof(*cfgenv)); i++) {
		std::string dest;
		eEnv::resolveVar(dest, "${" + cfgenv[i].name + "}");
		eDebug("setenv('%s', '%s', 1)", cfgenv[i].name.c_str(), dest.c_str());
		setenv(cfgenv[i].name.c_str(), dest.c_str(), 1);
	}
}

int eEnv::resolveVar(std::string &dest, const char *src)
{
	size_t i = 0;
	int ret;
	wordexp_t p;

	ret = wordexp(src, &p, WRDE_NOCMD | WRDE_UNDEF);
	if (ret != 0) {
		switch (ret) {
		case WRDE_BADCHAR:
			eDebug("%s: bad character", __func__);
			break;
		case WRDE_BADVAL:
			eDebug("%s: bad value", __func__);
			break;
		case WRDE_CMDSUB:
			eDebug("%s: invalid command substitution", __func__);
			break;
		case WRDE_NOSPACE:
			eDebug("%s: out of memory", __func__);
			break;
		case WRDE_SYNTAX:
			eDebug("%s: syntax error", __func__);
			break;
		default:
			eDebug("%s: unknown error", __func__);
			break;
		}

		return -1;
	}

	while (i < p.we_wordc) {
		if (strchr(p.we_wordv[i], '$')) {
			ret = eEnv::resolveVar(dest, p.we_wordv[i]);
			if (ret < 0)
				break;
		} else {
			dest.append(p.we_wordv[i]);
		}

		if (++i < p.we_wordc)
			dest.append(" ");
	}

	wordfree(&p);
	return ret;
}

int eEnv::resolveVar(std::string &dest, const std::string &src)
{
	return eEnv::resolveVar(dest, src.c_str());
}

std::string eEnv::resolve(const std::string &src)
{
	std::string dest;

	if (!initialized) {
		eEnv::initialize();
		initialized = true;
	}

	eDebug("%s: resolve %s", __func__, src.c_str());

	eEnv::resolveVar(dest, src);

	eDebug("%s: -> %s", __func__, dest.c_str());

	return dest;
}