Search code examples
posixopenoffice.orgunounix-socketpyuno

Openoffice pipe (unix domain socket) somewhere other than /tmp?


It's possible to get Openoffice to accept UNO connections over a unix domain socket with:

$soffice -headless -invisible -nocrashreport -nodefault -nologo -nofirststartwizard -norestore -conversionmode -accept='pipe,name=marcin_OOffice;urp;StarOffice.ComponentContext'

netstat shows that the domain socket is created at /tmp/OSL_PIPE_1001_marcin_OOffice. That's fine, but as I will be running this on a shared host, I'd like to have the socket somewhere else, e.g. in my home drive. However, passing a full file path (either relative or absolute) as the name parameter results in no socket being created.

Is there a way I can influence where the socket is created, e.g. with an environment variable?

EDIT: Setting TMP and TMPDIR environment variables does not affect this behaviour. I'm running this on linux.


Solution

  • Since there doesn't seem to be an "official" way of controlling where the socket gets created you can go down the "sledgehammer to crack a nutshell" road by writing your own shared object that interposes on connect() and rewrites any AF_FILE addresses in /tmp:

    #define _GNU_SOURCE
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <assert.h>
    #include <linux/un.h>
    #include <dlfcn.h>
    #include <stdlib.h>
    #include <string.h>
    
    int connect(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen) 
    {
      static int (*real_connect)(int, const struct sockaddr *, socklen_t) = NULL;
      if (!real_connect)
        real_connect = dlsym(RTLD_NEXT, "connect");
    
      if (addr->sa_family == AF_FILE) {
        // mutate sockaddr
        assert(addrlen >= sizeof(struct sockaddr_un));
        const struct sockaddr_un u = { AF_UNIX, "/foo/bar/path" };
        // but only if it is in /tmp
        if (!strncmp(((const struct sockaddr_un*)addr)->sun_path, "/tmp", 4)) {
          return real_connect(sockfd, (const struct sockaddr*)&u, sizeof u);
        }
      }
      return real_connect(sockfd, addr, addrlen);
    }
    

    Compile with:

    gcc -Wall -Wextra test.c -ldl -shared -o interpose.so -fPIC
    

    And then run as:

    LD_PRELOAD=./interpose.so soffice -headless -invisible -nocrashreport -nodefault -nologo -nofirststartwizard -norestore -conversionmode -accept='pipe,name=marcin_OOffice;urp;StarOffice.ComponentContext'
    

    which seems to work from reading the strace output (but I have no idea how to actually exercise the socket to prove that it really works).