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 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 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 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 **************************************/ 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 **************************************/ 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 **************************************/ 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 **************************************/ 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 **************************************/ 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 **************************************/ 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 **************************************/ 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_setEnvironment(): 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 **************************************/ 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 *********************************************/ 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 *********************************************/ 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