Line data Source code
1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
11 : #define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
12 :
13 : #include "LibreOfficeKit.h"
14 :
15 : #ifdef __cplusplus
16 : extern "C"
17 : {
18 : #endif
19 :
20 : #if defined(__linux__) || defined (__FreeBSD_kernel__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
21 :
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <sys/stat.h>
26 :
27 : #ifndef _WIN32
28 :
29 : #include "dlfcn.h"
30 :
31 : #ifdef _AIX
32 : # include <sys/ldr.h>
33 : #endif
34 : #ifdef __APPLE__
35 : #define TARGET_LIB "lib" "sofficeapp" ".dylib"
36 : #define TARGET_MERGED_LIB "lib" "mergedlo" ".dylib"
37 : #else
38 : #define TARGET_LIB "lib" "sofficeapp" ".so"
39 : #define TARGET_MERGED_LIB "lib" "mergedlo" ".so"
40 : #endif
41 : #define SEPARATOR '/'
42 :
43 1 : void *_dlopen(const char *pFN)
44 : {
45 : return dlopen(pFN, RTLD_LAZY
46 : #if defined __clang__ && defined __linux__ \
47 : && defined ENABLE_RUNTIME_OPTIMIZATIONS
48 : #if !ENABLE_RUNTIME_OPTIMIZATIONS
49 : | RTLD_GLOBAL
50 : #endif
51 : #endif
52 1 : );
53 : }
54 :
55 0 : char *_dlerror(void)
56 : {
57 0 : return dlerror();
58 : }
59 :
60 1 : void *_dlsym(void *Hnd, const char *pName)
61 : {
62 1 : return dlsym(Hnd, pName);
63 : }
64 :
65 0 : int _dlclose(void *Hnd)
66 : {
67 0 : return dlclose(Hnd);
68 : }
69 :
70 1 : void extendUnoPath(const char *pPath)
71 : {
72 : (void)pPath;
73 1 : }
74 :
75 : #else
76 :
77 : #include <windows.h>
78 : #define TARGET_LIB "sofficeapp" ".dll"
79 : #define TARGET_MERGED_LIB "mergedlo" ".dll"
80 : #define SEPARATOR '\\'
81 : #define UNOPATH "\\..\\URE\\bin"
82 :
83 : void *_dlopen(const char *pFN)
84 : {
85 : return (void *) LoadLibrary(pFN);
86 : }
87 :
88 : char *_dlerror(void)
89 : {
90 : LPSTR buf = NULL;
91 : FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, reinterpret_cast<LPSTR>(&buf), 0, NULL);
92 : return buf;
93 : }
94 :
95 : void *_dlsym(void *Hnd, const char *pName)
96 : {
97 : return GetProcAddress((HINSTANCE) Hnd, pName);
98 : }
99 :
100 : int _dlclose(void *Hnd)
101 : {
102 : return FreeLibrary((HINSTANCE) Hnd);
103 : }
104 :
105 : void extendUnoPath(const char *pPath)
106 : {
107 : if (!pPath)
108 : return;
109 :
110 : char* sEnvPath = NULL;
111 : DWORD cChars = GetEnvironmentVariable("PATH", sEnvPath, 0);
112 : if (cChars > 0)
113 : {
114 : sEnvPath = new char[cChars];
115 : cChars = GetEnvironmentVariable("PATH", sEnvPath, cChars);
116 : //If PATH is not set then it is no error
117 : if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
118 : {
119 : delete[] sEnvPath;
120 : return;
121 : }
122 : }
123 : //prepare the new PATH. Add the Ure/bin directory at the front.
124 : //note also adding ';'
125 : char * sNewPath = new char[strlen(sEnvPath) + strlen(pPath) + strlen(UNOPATH) + 2];
126 : sNewPath[0] = L'\0';
127 : strcat(sNewPath, pPath);
128 : strcat(sNewPath, UNOPATH);
129 : if (strlen(sEnvPath))
130 : {
131 : strcat(sNewPath, ";");
132 : strcat(sNewPath, sEnvPath);
133 : }
134 :
135 : SetEnvironmentVariable("PATH", sNewPath);
136 :
137 : delete[] sEnvPath;
138 : delete[] sNewPath;
139 : }
140 : #endif
141 :
142 : typedef LibreOfficeKit *(HookFunction)( const char *install_path);
143 :
144 : typedef LibreOfficeKit *(HookFunction2)( const char *install_path, const char *user_profile_path );
145 :
146 1 : static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_profile_path )
147 : {
148 : char *imp_lib;
149 : void *dlhandle;
150 : HookFunction *pSym;
151 : HookFunction2 *pSym2;
152 :
153 : #if !(defined(__APPLE__) && defined(__arm__))
154 : size_t partial_length;
155 :
156 1 : if (!install_path)
157 0 : return NULL;
158 :
159 : // allocate large enough buffer
160 1 : partial_length = strlen(install_path);
161 1 : imp_lib = (char *) malloc(partial_length + sizeof(TARGET_LIB) + sizeof(TARGET_MERGED_LIB) + 2);
162 1 : if (!imp_lib)
163 : {
164 0 : fprintf( stderr, "failed to open library : not enough memory\n");
165 0 : return NULL;
166 : }
167 :
168 1 : strcpy(imp_lib, install_path);
169 :
170 1 : extendUnoPath(install_path);
171 :
172 1 : imp_lib[partial_length++] = SEPARATOR;
173 1 : strcpy(imp_lib + partial_length, TARGET_LIB);
174 :
175 1 : dlhandle = _dlopen(imp_lib);
176 1 : if (!dlhandle)
177 : {
178 : // If TARGET_LIB exists, and likely is a real library (not a
179 : // small one-line text stub as in the --enable-mergedlib
180 : // case), but dlopen failed for some reason, don't try
181 : // TARGET_MERGED_LIB.
182 : struct stat st;
183 0 : if (stat(imp_lib, &st) == 0 && st.st_size > 100)
184 : {
185 : fprintf(stderr, "failed to open library '%s': %s\n",
186 0 : imp_lib, _dlerror());
187 0 : free(imp_lib);
188 0 : return NULL;
189 : }
190 :
191 0 : strcpy(imp_lib + partial_length, TARGET_MERGED_LIB);
192 :
193 0 : dlhandle = _dlopen(imp_lib);
194 0 : if (!dlhandle)
195 : {
196 : fprintf(stderr, "failed to open library '%s': %s\n",
197 0 : imp_lib, _dlerror());
198 0 : free(imp_lib);
199 0 : return NULL;
200 : }
201 : }
202 : #else
203 : imp_lib = strdup("the app executable");
204 : dlhandle = RTLD_MAIN_ONLY;
205 : #endif
206 :
207 1 : pSym2 = (HookFunction2 *) _dlsym( dlhandle, "libreofficekit_hook_2" );
208 1 : if (!pSym2)
209 : {
210 0 : if (user_profile_path != NULL)
211 : {
212 : fprintf( stderr, "the LibreOffice version in '%s' does not support passing a user profile to the hook function\n",
213 0 : imp_lib );
214 0 : _dlclose( dlhandle );
215 0 : free( imp_lib );
216 0 : return NULL;
217 : }
218 0 : pSym = (HookFunction *) _dlsym( dlhandle, "libreofficekit_hook" );
219 0 : if (!pSym)
220 : {
221 0 : fprintf( stderr, "failed to find hook in library '%s'\n", imp_lib );
222 0 : _dlclose( dlhandle );
223 0 : free( imp_lib );
224 0 : return NULL;
225 : }
226 0 : free( imp_lib );
227 : // dlhandle is "leaked"
228 : // coverity[leaked_storage]
229 0 : return pSym( install_path );
230 : }
231 :
232 1 : free( imp_lib );
233 : // dlhandle is "leaked"
234 : // coverity[leaked_storage]
235 1 : return pSym2( install_path, user_profile_path );
236 : }
237 :
238 : static
239 : #ifdef __GNUC__
240 : __attribute__((used))
241 : #endif
242 0 : LibreOfficeKit *lok_init( const char *install_path )
243 : {
244 0 : return lok_init_2( install_path, NULL );
245 : }
246 :
247 : #undef SEPARATOR // It is used at least in enum class MenuItemType
248 :
249 : #endif // defined(__linux__) || defined (__FreeBSD_kernel__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
250 :
251 : #ifdef __cplusplus
252 : }
253 : #endif
254 :
255 : #endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
256 :
257 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|