2013-12-13 8 views
3

Можно получить Openoffice принять UNO соединения через сокет домена Unix с:Труба Openoffice (сокет домена unix) где-то, кроме/tmp?

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

NetStat показывает, что доменный сокет создается в /tmp/OSL_PIPE_1001_marcin_OOffice. Это нормально, но поскольку я буду запускать это на общем хосте, я хотел бы иметь сокет где-то еще, например. в моем домашнем приводе. Тем не менее, передача полного пути к файлу (как относительного, так и абсолютного), поскольку параметр name приводит к тому, что сокет не создается.

Есть ли способ, которым я могу влиять на создание сокета, например. с переменной окружения?

РЕДАКТИРОВАНИЕ: переменные окружения TMP и TMPDIR не влияют на это поведение. Я запускаю это на linux.

ответ

3

Поскольку, похоже, не существует «официального» способа управления созданием сокета, вы можете спуститься по дороге «кувалда, чтобы раскалывать ореховую скорлупу», написав свой собственный общий объект, который вставляет на connect() и перезаписывает любые AF_FILE адреса в/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); 
} 

компилировать с:

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

а потом бегут, как:

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

, который, похоже, работает с чтением выхода strace (но я не знаю, как на самом деле реализовать сокет, чтобы доказать, что он действительно работает).

+0

Спасибо, это коварно. Я не могу разобраться, если это правильно или неправильно, но это определенно ответ на мой вопрос. Тем не менее, я буду удерживать прием/награду до конца периода. – Marcin

+0

Существуют ли какие-либо очевидные недостатки этого подхода? – Marcin

+2

Это немного хрупко - если что-то еще вызывает соединение таким же образом (включая дочерние процессы), то это может быть несколько неожиданно. Поскольку это не поддерживаемый интерфейс, он может сломаться при любом обновлении. – Flexo

-1

Вы должны вставить между bind() (та же подпись, что и для подключения), так как здесь создается сокет, а для клиентов - между connect().

+0

Любые предложения о том, как я могу это сделать? – Marcin