3

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.

Marcin
  • 48,559
  • 18
  • 128
  • 201

2 Answers2

4

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).

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Thanks, that's devious. I can't work out if this is the right or wrong thing, but it's definitely an answer to my question. I'll hold off on accepting/bounty until the end of the period, though. – Marcin Dec 19 '13 at 15:22
  • Are then any obvious downsides to this approach? – Marcin Dec 19 '13 at 18:38
  • 2
    It's a little fragile - if anything else calls connect in the same way (including child processes) then it might be somewhat unexpected. Since it's not a supported interface it's liable to break at any upgrade. – Flexo Dec 19 '13 at 19:33
  • Thanks, that makes sense. I think I'll hold this one in reserve, in case I absolutely need to get the socket out `/tmp`. – Marcin Dec 19 '13 at 19:36
  • You can avoid most of the side-effects simply by making the interposer function not test if the pipe is in /tmp, but instead test if the end of the pipe matches the known value ("marci_OOffice"). This should prevent misfires. – Tuna-Fish Dec 20 '13 at 14:05
-1

You should interpose between bind() (same signature as connect) as this is where the socket is created, then for the clients interpose between connect().

Rodrigo Taboada
  • 2,727
  • 4
  • 24
  • 27
eric
  • 1