about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/applications/networking/instant-messengers/hipchat/default.nix13
-rw-r--r--pkgs/build-support/libredirect/default.nix14
-rw-r--r--pkgs/build-support/libredirect/libredirect.c104
-rw-r--r--pkgs/top-level/all-packages.nix2
4 files changed, 128 insertions, 5 deletions
diff --git a/pkgs/applications/networking/instant-messengers/hipchat/default.nix b/pkgs/applications/networking/instant-messengers/hipchat/default.nix
index 857f162d7e47..6da12905f560 100644
--- a/pkgs/applications/networking/instant-messengers/hipchat/default.nix
+++ b/pkgs/applications/networking/instant-messengers/hipchat/default.nix
@@ -1,6 +1,7 @@
 { stdenv, fetchurl, libtool, xlibs, freetype, fontconfig, openssl, glib
 , mesa, gstreamer, gst_plugins_base, dbus, alsaLib, zlib, libuuid
-, libxml2, libxslt, sqlite, libogg, libvorbis, xz, libcanberra, makeWrapper }:
+, libxml2, libxslt, sqlite, libogg, libvorbis, xz, libcanberra
+, makeWrapper, libredirect, xkeyboard_config }:
 
 let
 
@@ -67,8 +68,8 @@ stdenv.mkDerivation {
   buildCommand = ''
     tar xf ${src}
 
-    d=$out/libexec/hipchat
-    mkdir -p $out/libexec
+    mkdir -p $out/libexec/hipchat/bin
+    d=$out/libexec/hipchat/lib
     rm -rfv opt/HipChat/lib/{libstdc++*,libz*,libuuid*,libxml2*,libxslt*,libsqlite*,libogg*,libvorbis*,liblzma*,libcanberra.*,libcanberra-*}
     mv opt/HipChat/lib/ $d
     mv usr/share $out
@@ -85,9 +86,11 @@ stdenv.mkDerivation {
 
     makeWrapper $d/hipchat.bin $out/bin/hipchat \
       --set HIPCHAT_LD_LIBRARY_PATH '"$LD_LIBRARY_PATH"' \
-      --set HIPCHAT_QT_PLUGIN_PATH '"$QT_PLUGIN_PATH"'
+      --set HIPCHAT_QT_PLUGIN_PATH '"$QT_PLUGIN_PATH"' \
+      --set LD_PRELOAD "${libredirect}/lib/libredirect.so" \
+      --set NIX_REDIRECTS /usr/share/X11/xkb=${xkeyboard_config}/share/X11/xkb
 
-    mv opt/HipChat/bin/linuxbrowserlaunch $out/bin
+    mv opt/HipChat/bin/linuxbrowserlaunch $out/libexec/hipchat/bin/
   '';
 
   meta = {
diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix
new file mode 100644
index 000000000000..a8a497d46d73
--- /dev/null
+++ b/pkgs/build-support/libredirect/default.nix
@@ -0,0 +1,14 @@
+{ stdenv }:
+
+stdenv.mkDerivation {
+  name = "libredirect-0";
+
+  unpackPhase = "cp ${./libredirect.c} libredirect.c";
+
+  buildPhase =
+    ''
+      gcc -Wall -std=c99 -O3 -shared libredirect.c -o libredirect.so -fPIC -ldl
+    '';
+
+  installPhase = "mkdir -p $out/lib; cp libredirect.so $out/lib";
+}
diff --git a/pkgs/build-support/libredirect/libredirect.c b/pkgs/build-support/libredirect/libredirect.c
new file mode 100644
index 000000000000..4afed3add75b
--- /dev/null
+++ b/pkgs/build-support/libredirect/libredirect.c
@@ -0,0 +1,104 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <string.h>
+
+#define MAX_REDIRECTS 128
+
+static int nrRedirects = 0;
+static char * from[MAX_REDIRECTS];
+static char * to[MAX_REDIRECTS];
+
+// FIXME: might run too late.
+static void init() __attribute__((constructor));
+
+static void init()
+{
+    char * spec = getenv("NIX_REDIRECTS");
+    if (!spec) return;
+
+    unsetenv("NIX_REDIRECTS");
+
+    char * spec2 = malloc(strlen(spec) + 1);
+    strcpy(spec2, spec);
+
+    char * pos = spec2, * eq;
+    while ((eq = strchr(pos, '='))) {
+        *eq = 0;
+        from[nrRedirects] = pos;
+        pos = eq + 1;
+        to[nrRedirects] = pos;
+        nrRedirects++;
+        if (nrRedirects == MAX_REDIRECTS) break;
+        char * end = strchr(pos, ':');
+        if (!end) break;
+        *end = 0;
+        pos = end + 1;
+    }
+
+}
+
+static const char * rewrite(const char * path, char * buf)
+{
+    for (int n = 0; n < nrRedirects; ++n) {
+        int len = strlen(from[n]);
+        if (strncmp(path, from[n], len) != 0) continue;
+        if (snprintf(buf, PATH_MAX, "%s%s", to[n], path + len) >= PATH_MAX)
+            abort();
+        return buf;
+    }
+
+    return path;
+}
+
+/* The following set of Glibc library functions is very incomplete -
+   it contains only what we needed for programs in Nixpkgs. Just add
+   more functions as needed. */
+
+int open(const char * path, int flags, ...)
+{
+    int (*open_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open");
+    mode_t mode = 0;
+    if (flags & O_CREAT) {
+        va_list ap;
+        va_start(ap, flags);
+        mode = va_arg(ap, mode_t);
+        va_end(ap);
+    }
+    char buf[PATH_MAX];
+    return open_real(rewrite(path, buf), flags, mode);
+}
+
+int open64(const char * path, int flags, ...)
+{
+    int (*open64_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open64");
+    mode_t mode = 0;
+    if (flags & O_CREAT) {
+        va_list ap;
+        va_start(ap, flags);
+        mode = va_arg(ap, mode_t);
+        va_end(ap);
+    }
+    char buf[PATH_MAX];
+    return open64_real(rewrite(path, buf), flags, mode);
+}
+
+FILE * fopen(const char * path, const char * mode)
+{
+    FILE * (*fopen_real) (const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
+    char buf[PATH_MAX];
+    return fopen_real(rewrite(path, buf), mode);
+}
+
+int __xstat(int ver, const char * path, struct stat * st)
+{
+    int (*__xstat_real) (int ver, const char *, struct stat *) = dlsym(RTLD_NEXT, "__xstat");
+    char buf[PATH_MAX];
+    return __xstat_real(ver, rewrite(path, buf), st);
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index fd4161190b65..f27efd104df1 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -373,6 +373,8 @@ let
     inherit url;
   };
 
+  libredirect = callPackage ../build-support/libredirect { };
+
   makeDesktopItem = import ../build-support/make-desktopitem {
     inherit stdenv;
   };