1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sal.hxx"
26
27 #include "osl/process.h"
28
29 #ifndef INCLUDED_LIMITS_H
30 #include <limits.h>
31 #define INCLUDED_LIMITS_H
32 #endif
33
34 #ifndef INCLUDED_PTHREAD_H
35 #include <pthread.h>
36 #define INCLUDED_PTHREAD_H
37 #endif
38
39 #ifndef INCLUDED_STDLIB_H
40 #include <stdlib.h>
41 #define INCLUDED_STDLIB_H
42 #endif
43
44 #ifndef INCLUDED_STRING_H
45 #include <string.h>
46 #define INCLUDED_STRING_H
47 #endif
48 #include "osl/diagnose.h"
49 #include "osl/file.h"
50 #include "osl/module.h"
51 #include "osl/thread.h"
52 #include "rtl/ustring.hxx"
53 #include "rtl/strbuf.h"
54
55 #ifndef _OSL_FILE_PATH_HELPER_H_
56 #include "file_path_helper.h"
57 #endif
58
59 #ifndef _OSL_UUNXAPI_H_
60 #include "uunxapi.h"
61 #endif
62
63 /***************************************
64 osl_bootstrap_getExecutableFile_Impl().
65
66 @internal
67 @see rtl_bootstrap
68 @see #i37371#
69
70 **************************************/
71
72 extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
73 rtl_uString ** ppFileURL
74 ) SAL_THROW_EXTERN_C();
75
76
77 #if defined(MACOSX)
78 #include <mach-o/dyld.h>
79
osl_bootstrap_getExecutableFile_Impl(rtl_uString ** ppFileURL)80 oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
81 rtl_uString ** ppFileURL
82 ) SAL_THROW_EXTERN_C()
83 {
84 oslProcessError result = osl_Process_E_NotFound;
85
86 char buffer[PATH_MAX];
87 size_t buflen = sizeof(buffer);
88
89 #if __GNUC__ >= 4 && defined(MACOSX)
90 if (_NSGetExecutablePath (buffer, (uint32_t*)&buflen) == 0)
91 #else
92 if (_NSGetExecutablePath (buffer, &buflen) == 0)
93 #endif
94 {
95 /* Determine absolute path. */
96 char abspath[PATH_MAX];
97 if (realpath (buffer, abspath) != 0)
98 {
99 /* Convert from utf8 to unicode. */
100 rtl_uString * pAbsPath = 0;
101 rtl_string2UString (
102 &(pAbsPath),
103 abspath, rtl_str_getLength (abspath),
104 RTL_TEXTENCODING_UTF8,
105 OSTRING_TO_OUSTRING_CVTFLAGS);
106
107 if (pAbsPath)
108 {
109 /* Convert from path to url. */
110 if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
111 {
112 /* Success. */
113 result = osl_Process_E_None;
114 }
115 rtl_uString_release (pAbsPath);
116 }
117 }
118 }
119
120 return (result);
121 }
122
123 #elif !defined(NO_DL_FUNCTIONS)
124 #include <dlfcn.h>
125
osl_bootstrap_getExecutableFile_Impl(rtl_uString ** ppFileURL)126 oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
127 rtl_uString ** ppFileURL
128 ) SAL_THROW_EXTERN_C()
129 {
130 oslProcessError result = osl_Process_E_NotFound;
131
132 /* Determine address of "main()" function. */
133 void * addr = dlsym (RTLD_DEFAULT, "main");
134 if (addr != 0)
135 {
136 /* Determine module URL. */
137 if (osl_getModuleURLFromAddress (addr, ppFileURL))
138 {
139 /* Success. */
140 result = osl_Process_E_None;
141 }
142 }
143
144 return (result);
145 }
146
147 #else /* NO_DL_FUNCTIONS */
148
osl_bootstrap_getExecutableFile_Impl(rtl_uString ** ppFileURL)149 oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
150 rtl_uString ** ppFileURL
151 ) SAL_THROW_EXTERN_C()
152 {
153 /* Fallback to ordinary osl_getExecutableFile(). */
154 return osl_getExecutableFile (ppFileURL);
155 }
156
157 #endif /* NO_DL_FUNCTIONS */
158
159 /***************************************
160 CommandArgs_Impl.
161 **************************************/
162 struct CommandArgs_Impl
163 {
164 pthread_mutex_t m_mutex;
165 sal_uInt32 m_nCount;
166 rtl_uString ** m_ppArgs;
167 };
168
169 static struct CommandArgs_Impl g_command_args =
170 {
171 PTHREAD_MUTEX_INITIALIZER,
172 0,
173 0
174 };
175
176 /***************************************
177 osl_getExecutableFile().
178 **************************************/
osl_getExecutableFile(rtl_uString ** ppustrFile)179 oslProcessError SAL_CALL osl_getExecutableFile (rtl_uString ** ppustrFile)
180 {
181 oslProcessError result = osl_Process_E_NotFound;
182
183 pthread_mutex_lock (&(g_command_args.m_mutex));
184 OSL_ASSERT(g_command_args.m_nCount > 0);
185 if (g_command_args.m_nCount > 0)
186 {
187 /* CommandArgs set. Obtain argv[0]. */
188 rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
189 result = osl_Process_E_None;
190 }
191 pthread_mutex_unlock (&(g_command_args.m_mutex));
192
193 return (result);
194 }
195
196 /***************************************
197 osl_getCommandArgCount().
198 **************************************/
osl_getCommandArgCount(void)199 sal_uInt32 SAL_CALL osl_getCommandArgCount (void)
200 {
201 sal_uInt32 result = 0;
202
203 pthread_mutex_lock (&(g_command_args.m_mutex));
204 OSL_ASSERT(g_command_args.m_nCount > 0);
205 if (g_command_args.m_nCount > 0)
206 result = g_command_args.m_nCount - 1;
207 pthread_mutex_unlock (&(g_command_args.m_mutex));
208
209 return (result);
210 }
211
212 /***************************************
213 osl_getCommandArg().
214 **************************************/
osl_getCommandArg(sal_uInt32 nArg,rtl_uString ** strCommandArg)215 oslProcessError SAL_CALL osl_getCommandArg (sal_uInt32 nArg, rtl_uString ** strCommandArg)
216 {
217 oslProcessError result = osl_Process_E_NotFound;
218
219 pthread_mutex_lock (&(g_command_args.m_mutex));
220 OSL_ASSERT(g_command_args.m_nCount > 0);
221 if (g_command_args.m_nCount > (nArg + 1))
222 {
223 rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
224 result = osl_Process_E_None;
225 }
226 pthread_mutex_unlock (&(g_command_args.m_mutex));
227
228 return (result);
229 }
230
231 /***************************************
232 osl_setCommandArgs().
233 **************************************/
osl_setCommandArgs(int argc,char ** argv)234 void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
235 {
236 OSL_ASSERT(argc > 0);
237 pthread_mutex_lock (&(g_command_args.m_mutex));
238 OSL_ENSURE (g_command_args.m_nCount == 0, "osl_setCommandArgs(): CommandArgs already set.");
239 if (g_command_args.m_nCount == 0)
240 {
241 rtl_uString** ppArgs = (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
242 if (ppArgs != 0)
243 {
244 rtl_TextEncoding encoding = osl_getThreadTextEncoding();
245 for (int i = 0; i < argc; i++)
246 {
247 rtl_string2UString (
248 &(ppArgs[i]),
249 argv[i], rtl_str_getLength (argv[i]), encoding,
250 OSTRING_TO_OUSTRING_CVTFLAGS);
251 }
252 if (ppArgs[0] != 0)
253 {
254 /* see @ osl_getExecutableFile(). */
255 if (rtl_ustr_indexOfChar (rtl_uString_getStr(ppArgs[0]), sal_Unicode('/')) == -1)
256 {
257 const rtl::OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));
258
259 rtl_uString * pSearchPath = 0;
260 osl_getEnvironment (PATH.pData, &pSearchPath);
261 if (pSearchPath)
262 {
263 rtl_uString * pSearchResult = 0;
264 osl_searchPath (ppArgs[0], pSearchPath, &pSearchResult);
265 if (pSearchResult)
266 {
267 rtl_uString_assign (&(ppArgs[0]), pSearchResult);
268 rtl_uString_release (pSearchResult);
269 }
270 rtl_uString_release (pSearchPath);
271 }
272 }
273
274 rtl_uString * pArg0 = 0;
275 if (realpath_u (ppArgs[0], &pArg0))
276 {
277 osl_getFileURLFromSystemPath (pArg0, &(ppArgs[0]));
278 rtl_uString_release (pArg0);
279 }
280 }
281 g_command_args.m_nCount = argc;
282 g_command_args.m_ppArgs = ppArgs;
283 }
284 }
285 pthread_mutex_unlock (&(g_command_args.m_mutex));
286 }
287
288 /***************************************
289 osl_getEnvironment().
290 **************************************/
osl_getEnvironment(rtl_uString * pustrEnvVar,rtl_uString ** ppustrValue)291 oslProcessError SAL_CALL osl_getEnvironment(rtl_uString* pustrEnvVar, rtl_uString** ppustrValue)
292 {
293 oslProcessError result = osl_Process_E_NotFound;
294 rtl_TextEncoding encoding = osl_getThreadTextEncoding();
295 rtl_String* pstr_env_var = 0;
296
297 OSL_PRECOND(pustrEnvVar, "osl_getEnvironment(): Invalid parameter");
298 OSL_PRECOND(ppustrValue, "osl_getEnvironment(): Invalid parameter");
299
300 rtl_uString2String(
301 &pstr_env_var,
302 rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
303 OUSTRING_TO_OSTRING_CVTFLAGS);
304 if (pstr_env_var != 0)
305 {
306 const char* p_env_var = getenv (rtl_string_getStr (pstr_env_var));
307 if (p_env_var != 0)
308 {
309 rtl_string2UString(
310 ppustrValue,
311 p_env_var, strlen(p_env_var), encoding,
312 OSTRING_TO_OUSTRING_CVTFLAGS);
313 OSL_ASSERT(*ppustrValue != NULL);
314
315 result = osl_Process_E_None;
316 }
317 rtl_string_release(pstr_env_var);
318 }
319
320 return (result);
321 }
322
323 /***************************************
324 osl_setEnvironment().
325 **************************************/
osl_setEnvironment(rtl_uString * pustrEnvVar,rtl_uString * pustrValue)326 oslProcessError SAL_CALL osl_setEnvironment(rtl_uString* pustrEnvVar, rtl_uString* pustrValue)
327 {
328 oslProcessError result = osl_Process_E_Unknown;
329 rtl_TextEncoding encoding = osl_getThreadTextEncoding();
330 rtl_String* pstr_env_var = 0;
331 rtl_String* pstr_val = 0;
332
333 OSL_PRECOND(pustrEnvVar, "osl_setEnvironment(): Invalid parameter");
334 OSL_PRECOND(pustrValue, "osl_setEnvironment(): Invalid parameter");
335
336 rtl_uString2String(
337 &pstr_env_var,
338 rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
339 OUSTRING_TO_OSTRING_CVTFLAGS);
340
341 rtl_uString2String(
342 &pstr_val,
343 rtl_uString_getStr(pustrValue), rtl_uString_getLength(pustrValue), encoding,
344 OUSTRING_TO_OSTRING_CVTFLAGS);
345
346 if (pstr_env_var != 0 && pstr_val != 0)
347 {
348 #if defined (SOLARIS)
349 rtl_String * pBuffer = NULL;
350
351 sal_Int32 nCapacity = rtl_stringbuffer_newFromStringBuffer( &pBuffer,
352 rtl_string_getLength(pstr_env_var) + rtl_string_getLength(pstr_val) + 1,
353 pstr_env_var );
354 rtl_stringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, "=", 1);
355 rtl_stringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length,
356 rtl_string_getStr(pstr_val), rtl_string_getLength(pstr_val) );
357
358 rtl_string_acquire(pBuffer); // argument to putenv must leak on success
359
360 if (putenv(rtl_string_getStr(pBuffer)) == 0)
361 result = osl_Process_E_None;
362 else
363 rtl_string_release(pBuffer);
364 #else
365 if (setenv(rtl_string_getStr(pstr_env_var), rtl_string_getStr(pstr_val), 1) == 0)
366 result = osl_Process_E_None;
367 #endif
368 }
369
370 if (pstr_val)
371 rtl_string_release(pstr_val);
372
373 if (pstr_env_var != 0)
374 rtl_string_release(pstr_env_var);
375
376 return (result);
377 }
378
379 /***************************************
380 osl_clearEnvironment().
381 **************************************/
osl_clearEnvironment(rtl_uString * pustrEnvVar)382 oslProcessError SAL_CALL osl_clearEnvironment(rtl_uString* pustrEnvVar)
383 {
384 oslProcessError result = osl_Process_E_Unknown;
385 rtl_TextEncoding encoding = osl_getThreadTextEncoding();
386 rtl_String* pstr_env_var = 0;
387
388 OSL_PRECOND(pustrEnvVar, "osl_clearEnvironment(): Invalid parameter");
389
390 rtl_uString2String(
391 &pstr_env_var,
392 rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
393 OUSTRING_TO_OSTRING_CVTFLAGS);
394
395 if (pstr_env_var)
396 {
397 #if defined (SOLARIS)
398 rtl_String * pBuffer = NULL;
399
400 sal_Int32 nCapacity = rtl_stringbuffer_newFromStringBuffer( &pBuffer,
401 rtl_string_getLength(pstr_env_var) + 1, pstr_env_var );
402 rtl_stringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, "=", 1);
403
404 rtl_string_acquire(pBuffer); // argument to putenv must leak on success
405
406 if (putenv(rtl_string_getStr(pBuffer)) == 0)
407 result = osl_Process_E_None;
408 else
409 rtl_string_release(pBuffer);
410 #elif (defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
411 //MacOSX baseline is 10.4, which has an old-school void return
412 //for unsetenv.
413 //See: http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/10.4/man3/unsetenv.3.html?useVersion=10.4
414 unsetenv(rtl_string_getStr(pstr_env_var));
415 result = osl_Process_E_None;
416 #else
417 if (unsetenv(rtl_string_getStr(pstr_env_var)) == 0)
418 result = osl_Process_E_None;
419 #endif
420 rtl_string_release(pstr_env_var);
421 }
422
423 return (result);
424 }
425
426
427 /***************************************
428 osl_getProcessWorkingDir().
429 **************************************/
osl_getProcessWorkingDir(rtl_uString ** ppustrWorkingDir)430 oslProcessError SAL_CALL osl_getProcessWorkingDir(rtl_uString **ppustrWorkingDir)
431 {
432 oslProcessError result = osl_Process_E_Unknown;
433 char buffer[PATH_MAX];
434
435 OSL_PRECOND(ppustrWorkingDir, "osl_getProcessWorkingDir(): Invalid parameter");
436
437 if (getcwd (buffer, sizeof(buffer)) != 0)
438 {
439 rtl_uString* ustrTmp = 0;
440
441 rtl_string2UString(
442 &ustrTmp,
443 buffer, strlen(buffer), osl_getThreadTextEncoding(),
444 OSTRING_TO_OUSTRING_CVTFLAGS);
445 if (ustrTmp != 0)
446 {
447 if (osl_getFileURLFromSystemPath (ustrTmp, ppustrWorkingDir) == osl_File_E_None)
448 result = osl_Process_E_None;
449 rtl_uString_release (ustrTmp);
450 }
451 }
452
453 return (result);
454 }
455
456 /******************************************************************************
457 *
458 * new functions to set/return the current process locale
459 *
460 *****************************************************************************/
461
462 struct ProcessLocale_Impl
463 {
464 pthread_mutex_t m_mutex;
465 rtl_Locale * m_pLocale;
466 };
467
468 static struct ProcessLocale_Impl g_process_locale =
469 {
470 PTHREAD_MUTEX_INITIALIZER,
471 0
472 };
473
474 extern "C" void _imp_getProcessLocale( rtl_Locale ** );
475 extern "C" int _imp_setProcessLocale( rtl_Locale * );
476
477 /**********************************************
478 osl_getProcessLocale().
479 *********************************************/
osl_getProcessLocale(rtl_Locale ** ppLocale)480 oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
481 {
482 oslProcessError result = osl_Process_E_Unknown;
483 OSL_PRECOND(ppLocale, "osl_getProcessLocale(): Invalid parameter.");
484 if (ppLocale)
485 {
486 pthread_mutex_lock(&(g_process_locale.m_mutex));
487
488 if (g_process_locale.m_pLocale == 0)
489 _imp_getProcessLocale (&(g_process_locale.m_pLocale));
490 *ppLocale = g_process_locale.m_pLocale;
491 result = osl_Process_E_None;
492
493 pthread_mutex_unlock (&(g_process_locale.m_mutex));
494 }
495 return (result);
496 }
497
498 /**********************************************
499 osl_setProcessLocale().
500 *********************************************/
osl_setProcessLocale(rtl_Locale * pLocale)501 oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
502 {
503 oslProcessError result = osl_Process_E_Unknown;
504
505 OSL_PRECOND(pLocale, "osl_setProcessLocale(): Invalid parameter.");
506
507 pthread_mutex_lock(&(g_process_locale.m_mutex));
508 if (_imp_setProcessLocale (pLocale) == 0)
509 {
510 g_process_locale.m_pLocale = pLocale;
511 result = osl_Process_E_None;
512 }
513 pthread_mutex_unlock (&(g_process_locale.m_mutex));
514
515 return (result);
516 }
517