add eEnv::resolve() to resolve install paths at runtime
authorAndreas Oberritter <obi@opendreambox.org>
Thu, 28 Oct 2010 18:23:36 +0000 (20:23 +0200)
committerAndreas Oberritter <obi@opendreambox.org>
Tue, 16 Nov 2010 16:15:37 +0000 (17:15 +0100)
lib/base/Makefile.am
lib/base/eenv.cpp.in [new file with mode: 0644]
lib/base/eenv.h [new file with mode: 0644]
lib/python/enigma_python.i

index 498244f..230a37a 100644 (file)
@@ -14,6 +14,8 @@ libenigma_base_la_SOURCES = \
        console.h \
        ebase.cpp \
        ebase.h \
+       eenv.cpp \
+       eenv.h \
        eerror.cpp \
        eerror.h \
        elock.cpp \
@@ -45,3 +47,6 @@ libenigma_base_la_SOURCES = \
        smartptr.h \
        thread.cpp \
        thread.h
+
+EXTRA_DIST = \
+       eenv.cpp.in
diff --git a/lib/base/eenv.cpp.in b/lib/base/eenv.cpp.in
new file mode 100644 (file)
index 0000000..52c4214
--- /dev/null
@@ -0,0 +1,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;
+}
diff --git a/lib/base/eenv.h b/lib/base/eenv.h
new file mode 100644 (file)
index 0000000..3d149f5
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __lib_base_paths_h
+#define __lib_base_paths_h
+
+#include <string>
+
+class eEnv {
+private:
+       static bool initialized;
+       static void initialize();
+       static int resolveVar(std::string &dest, const char *src);
+       static int resolveVar(std::string &dest, const std::string &src);
+public:
+       static std::string resolve(const std::string &path);
+};
+
+#endif
index 19fb925..43d94ac 100644 (file)
@@ -38,6 +38,7 @@ is usually caused by not marking PSignals as immutable.
 #define SWIG_COMPILE
 #include <lib/base/ebase.h>
 #include <lib/base/smartptr.h>
+#include <lib/base/eenv.h>
 #include <lib/base/eerror.h>
 #include <lib/base/etpm.h>
 #include <lib/base/nconfig.h>
@@ -133,6 +134,7 @@ typedef long time_t;
 %include "std_string.i"
 %include <lib/python/swig.h>
 %include <lib/base/object.h>
+%include <lib/base/eenv.h>
 %include <lib/base/eerror.h>
 
 %immutable eSocketNotifier::activated;