add eEnv::resolve() to resolve install paths at runtime
[openblackhole/openblackhole-enigma2.git] / lib / base / eenv.cpp.in
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <wordexp.h>
5 #include <lib/base/eenv.h>
6 #include <lib/base/eerror.h>
7
8 bool eEnv::initialized = false;
9
10 void eEnv::initialize()
11 {
12         static const struct {
13                 std::string name;
14                 std::string value;
15         } cfgenv[] = {
16                 { "prefix", "@prefix@" },
17                 { "exec_prefix", "@exec_prefix@" },
18                 { "bindir", "@bindir@" },
19                 { "sbindir", "@sbindir@" },
20                 { "libexecdir", "@libexecdir@" },
21                 { "datarootdir", "@datarootdir@" },
22                 { "datadir", "@datadir@" },
23                 { "sysconfdir", "@sysconfdir@" },
24                 { "sharedstatedir", "@sharedstatedir@" },
25                 { "localstatedir", "@localstatedir@" },
26                 { "libdir", "@libdir@" },
27                 { "localedir", "@localedir@" },
28         };
29         size_t i;
30
31         // 1st pass, as generated by configure.
32         // Variables set by the user will not be overwritten.
33         for (i = 0; i < (sizeof(cfgenv) / sizeof(*cfgenv)); i++) {
34                 eDebug("setenv('%s', '%s', 0)", cfgenv[i].name.c_str(), cfgenv[i].value.c_str());
35                 setenv(cfgenv[i].name.c_str(), cfgenv[i].value.c_str(), 0);
36         }
37
38         // 2nd pass: Resolve directories.
39         for (i = 0; i < (sizeof(cfgenv) / sizeof(*cfgenv)); i++) {
40                 std::string dest;
41                 eEnv::resolveVar(dest, "${" + cfgenv[i].name + "}");
42                 eDebug("setenv('%s', '%s', 1)", cfgenv[i].name.c_str(), dest.c_str());
43                 setenv(cfgenv[i].name.c_str(), dest.c_str(), 1);
44         }
45 }
46
47 int eEnv::resolveVar(std::string &dest, const char *src)
48 {
49         size_t i = 0;
50         int ret;
51         wordexp_t p;
52
53         ret = wordexp(src, &p, WRDE_NOCMD | WRDE_UNDEF);
54         if (ret != 0) {
55                 switch (ret) {
56                 case WRDE_BADCHAR:
57                         eDebug("%s: bad character", __func__);
58                         break;
59                 case WRDE_BADVAL:
60                         eDebug("%s: bad value", __func__);
61                         break;
62                 case WRDE_CMDSUB:
63                         eDebug("%s: invalid command substitution", __func__);
64                         break;
65                 case WRDE_NOSPACE:
66                         eDebug("%s: out of memory", __func__);
67                         break;
68                 case WRDE_SYNTAX:
69                         eDebug("%s: syntax error", __func__);
70                         break;
71                 default:
72                         eDebug("%s: unknown error", __func__);
73                         break;
74                 }
75
76                 return -1;
77         }
78
79         while (i < p.we_wordc) {
80                 if (strchr(p.we_wordv[i], '$')) {
81                         ret = eEnv::resolveVar(dest, p.we_wordv[i]);
82                         if (ret < 0)
83                                 break;
84                 } else {
85                         dest.append(p.we_wordv[i]);
86                 }
87
88                 if (++i < p.we_wordc)
89                         dest.append(" ");
90         }
91
92         wordfree(&p);
93         return ret;
94 }
95
96 int eEnv::resolveVar(std::string &dest, const std::string &src)
97 {
98         return eEnv::resolveVar(dest, src.c_str());
99 }
100
101 std::string eEnv::resolve(const std::string &src)
102 {
103         std::string dest;
104
105         if (!initialized) {
106                 eEnv::initialize();
107                 initialized = true;
108         }
109
110         eDebug("%s: resolve %s", __func__, src.c_str());
111
112         eEnv::resolveVar(dest, src);
113
114         eDebug("%s: -> %s", __func__, dest.c_str());
115
116         return dest;
117 }