1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "system.h" 29 30 #ifdef NO_PTHREAD_RTL 31 32 static pthread_mutex_t getrtl_mutex = PTHREAD_MUTEX_INITIALIZER; 33 34 /* struct passwd differs on some platforms */ 35 #if defined NETBSD 36 struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size ) 37 { 38 struct passwd* res; 39 40 pthread_mutex_lock(&getrtl_mutex); 41 42 if ( (res = getpwnam(name)) ) 43 { 44 int nname, npasswd, nclass, ngecos, ndir; 45 46 nname= strlen(res->pw_name)+1; 47 npasswd= strlen(res->pw_passwd)+1; 48 nclass= strlen(res->pw_class)+1; 49 ngecos= strlen(res->pw_gecos)+1; 50 ndir= strlen(res->pw_dir)+1; 51 52 if (nname+npasswd+nclass+ngecos 53 +ndir+strlen(res->pw_shell) < size) 54 { 55 memcpy(s, res, sizeof(struct passwd)); 56 57 strcpy(buffer, res->pw_name); 58 s->pw_name = buffer; 59 buffer += nname; 60 61 strcpy(buffer, res->pw_passwd); 62 s->pw_passwd = buffer; 63 buffer += npasswd; 64 65 strcpy(buffer, res->pw_class); 66 s->pw_class = buffer; 67 buffer += nclass; 68 69 strcpy(buffer, res->pw_gecos); 70 s->pw_gecos = buffer; 71 buffer += ngecos; 72 73 strcpy(buffer, res->pw_dir); 74 s->pw_dir = buffer; 75 buffer += ndir; 76 77 strcpy(buffer, res->pw_shell); 78 s->pw_shell = buffer; 79 80 res = s; 81 } 82 else 83 res = 0; 84 } 85 86 pthread_mutex_unlock(&getrtl_mutex); 87 88 return(res); 89 } 90 91 int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, 92 size_t buflen, struct passwd **result) 93 { 94 struct passwd* res; 95 int retval = 0; 96 97 pthread_mutex_lock(&getrtl_mutex); 98 99 if ( (res = getpwuid(uid)) ) 100 { 101 size_t pw_name, pw_passwd, pw_class, pw_gecos, pw_dir, pw_shell; 102 103 pw_name = strlen(res->pw_name)+1; 104 pw_passwd = strlen(res->pw_passwd)+1; 105 pw_class = strlen(res->pw_class)+1; 106 pw_gecos = strlen(res->pw_gecos)+1; 107 pw_dir = strlen(res->pw_dir)+1; 108 pw_shell = strlen(res->pw_shell)+1; 109 110 if (pw_name+pw_passwd+pw_class+pw_gecos 111 +pw_dir+pw_shell < buflen) 112 { 113 memcpy(pwd, res, sizeof(struct passwd)); 114 115 strncpy(buffer, res->pw_name, pw_name); 116 pwd->pw_name = buffer; 117 buffer += pw_name; 118 119 strncpy(buffer, res->pw_passwd, pw_passwd); 120 pwd->pw_passwd = buffer; 121 buffer += pw_passwd; 122 123 strncpy(buffer, res->pw_class, pw_class); 124 pwd->pw_class = buffer; 125 buffer += pw_class; 126 127 strncpy(buffer, res->pw_gecos, pw_gecos); 128 pwd->pw_gecos = buffer; 129 buffer += pw_gecos; 130 131 strncpy(buffer, res->pw_dir, pw_dir); 132 pwd->pw_dir = buffer; 133 buffer += pw_dir; 134 135 strncpy(buffer, res->pw_shell, pw_shell); 136 pwd->pw_shell = buffer; 137 buffer += pw_shell; 138 139 *result = pwd ; 140 retval = 0 ; 141 142 } 143 else 144 retval = ENOMEM; 145 } 146 else 147 retval = errno ; 148 149 pthread_mutex_unlock(&getrtl_mutex); 150 151 return retval; 152 } 153 154 struct tm *localtime_r(const time_t *timep, struct tm *buffer) 155 { 156 struct tm* res; 157 158 pthread_mutex_lock(&getrtl_mutex); 159 160 if ( (res = localtime(timep))) 161 { 162 memcpy(buffer, res, sizeof(struct tm)); 163 res = buffer; 164 } 165 166 pthread_mutex_unlock(&getrtl_mutex); 167 168 return res; 169 } 170 171 struct tm *gmtime_r(const time_t *timep, struct tm *buffer) 172 { 173 struct tm* res; 174 175 pthread_mutex_lock(&getrtl_mutex); 176 177 if ( (res = gmtime(timep)) ) 178 { 179 memcpy(buffer, res, sizeof(struct tm)); 180 res = buffer; 181 } 182 183 pthread_mutex_unlock(&getrtl_mutex); 184 185 return res; 186 } 187 #endif /* defined NETBSD */ 188 189 #ifdef SCO 190 #include <pwd.h> 191 #include <shadow.h> 192 #include <sys/types.h> 193 194 struct spwd *getspnam_r(const char *name, struct spwd* s, char* buffer, int size ) 195 { 196 struct spwd* res; 197 198 pthread_mutex_lock(&getrtl_mutex); 199 200 if ( res = getspnam(name) ) 201 { 202 int nnamp; 203 204 nnamp = strlen(res->sp_namp)+1; 205 206 if (nnamp+strlen(res->sp_pwdp) < size) { 207 memcpy(s, res, sizeof(struct spwd)); 208 209 strcpy(buffer, res->sp_namp); 210 s->sp_namp = buffer; 211 buffer += nnamp; 212 213 strcpy(buffer, res->sp_pwdp); 214 s->sp_pwdp = buffer; 215 216 res = s; 217 } 218 else 219 res = 0; 220 } 221 222 pthread_mutex_unlock(&getrtl_mutex); 223 224 return res; 225 } 226 227 struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size ) 228 { 229 struct passwd* res; 230 231 pthread_mutex_lock(&getrtl_mutex); 232 233 if ( res = getpwnam(name) ) 234 { 235 int nname, npasswd, nage; 236 int ncomment, ngecos, ndir; 237 238 nname= strlen(res->pw_name)+1; 239 npasswd= strlen(res->pw_passwd)+1; 240 nage= strlen(res->pw_age)+1; 241 ncomment= strlen(res->pw_comment)+1; 242 ngecos= strlen(res->pw_gecos)+1; 243 ndir= strlen(res->pw_dir)+1; 244 245 if (nname+npasswd+nage+ncomment+ngecos+ndir 246 +strlen(res->pw_shell) < size) 247 { 248 memcpy(s, res, sizeof(struct passwd)); 249 250 strcpy(buffer, res->pw_name); 251 s->pw_name = buffer; 252 buffer += nname; 253 254 strcpy(buffer, res->pw_passwd); 255 s->pw_passwd = buffer; 256 buffer += npasswd; 257 258 strcpy(buffer, res->pw_age); 259 s->pw_age = buffer; 260 buffer += nage; 261 262 strcpy(buffer, res->pw_comment); 263 s->pw_comment = buffer; 264 buffer += ncomment; 265 266 strcpy(buffer, res->pw_gecos); 267 s->pw_gecos = buffer; 268 buffer += ngecos; 269 270 strcpy(buffer, res->pw_dir); 271 s->pw_dir = buffer; 272 buffer += ndir; 273 274 strcpy(buffer, res->pw_shell); 275 s->pw_shell = buffer; 276 277 res = s; 278 } 279 else 280 res = 0; 281 } 282 283 pthread_mutex_unlock(&getrtl_mutex); 284 285 return res; 286 } 287 #endif /* defined SCO */ 288 289 #if !defined(FREEBSD) || (__FreeBSD_version < 601103) 290 291 extern int h_errno; 292 293 struct hostent *gethostbyname_r(const char *name, struct hostent *result, 294 char *buffer, int buflen, int *h_errnop) 295 { 296 /* buffer layout: name\0 297 * array_of_pointer_to_aliases 298 * NULL 299 * alias1\0...aliasn\0 300 * array_of_pointer_to_addresses 301 * NULL 302 * addr1addr2addr3...addrn 303 */ 304 struct hostent* res; 305 306 pthread_mutex_lock(&getrtl_mutex); 307 308 if ( (res = gethostbyname(name)) ) 309 { 310 int nname, naliases, naddr_list, naliasesdata, n; 311 char **p, **parray, *data; 312 313 /* Check buffer size before copying, we want to leave the 314 * buffers unmodified in case something goes wrong. 315 * 316 * Is this required? 317 */ 318 319 nname= strlen(res->h_name)+1; 320 321 naliases = naddr_list = naliasesdata = 0; 322 323 for ( p = res->h_aliases; *p != NULL; p++) { 324 naliases++; 325 naliasesdata += strlen(*p)+1; 326 } 327 328 for ( p = res->h_addr_list; *p != NULL; p++) 329 naddr_list++; 330 331 if ( nname 332 + (naliases+1)*sizeof(char*) + naliasesdata 333 + (naddr_list+1)*sizeof(char*) + naddr_list*res->h_length 334 <= buflen ) 335 { 336 memcpy(result, res, sizeof(struct hostent)); 337 338 strcpy(buffer, res->h_name); 339 result->h_name = buffer; 340 buffer += nname; 341 342 parray = (char**)buffer; 343 result->h_aliases = parray; 344 data = buffer + (naliases+1)*sizeof(char*); 345 for ( p = res->h_aliases; *p != NULL; p++) { 346 n = strlen(*p)+1; 347 *parray++ = data; 348 memcpy(data, *p, n); 349 data += n; 350 } 351 *parray = NULL; 352 buffer = data; 353 parray = (char**)buffer; 354 result->h_addr_list = parray; 355 data = buffer + (naddr_list+1)*sizeof(char*); 356 for ( p = res->h_addr_list; *p != NULL; p++) { 357 *parray++ = data; 358 memcpy(data, *p, res->h_length); 359 data += res->h_length; 360 } 361 *parray = NULL; 362 363 res = result; 364 } 365 else 366 { 367 errno = ERANGE; 368 res = NULL; 369 } 370 } 371 else 372 { 373 *h_errnop = h_errno; 374 } 375 376 pthread_mutex_unlock(&getrtl_mutex); 377 378 return res; 379 } 380 #endif /* !defined(FREEBSD) || (__FreeBSD_version < 601103) */ 381 382 #if defined(MACOSX) 383 /* 384 * Add support for resolving Mac native alias files (not the same as unix alias files) 385 * returns 0 on success. 386 */ 387 int macxp_resolveAlias(char *path, int buflen) 388 { 389 FSRef aFSRef; 390 OSStatus nErr; 391 Boolean bFolder; 392 Boolean bAliased; 393 char *unprocessedPath = path; 394 395 if ( *unprocessedPath == '/' ) 396 unprocessedPath++; 397 398 int nRet = 0; 399 while ( !nRet && unprocessedPath && *unprocessedPath ) 400 { 401 unprocessedPath = strchr( unprocessedPath, '/' ); 402 if ( unprocessedPath ) 403 *unprocessedPath = '\0'; 404 405 nErr = noErr; 406 bFolder = FALSE; 407 bAliased = FALSE; 408 if ( FSPathMakeRef( (const UInt8 *)path, &aFSRef, 0 ) == noErr ) 409 { 410 nErr = FSResolveAliasFileWithMountFlags( &aFSRef, TRUE, &bFolder, &bAliased, kResolveAliasFileNoUI ); 411 if ( nErr == nsvErr ) 412 { 413 errno = ENOENT; 414 nRet = -1; 415 } 416 else if ( nErr == noErr && bAliased ) 417 { 418 char tmpPath[ PATH_MAX ]; 419 if ( FSRefMakePath( &aFSRef, (UInt8 *)tmpPath, PATH_MAX ) == noErr ) 420 { 421 int nLen = strlen( tmpPath ) + ( unprocessedPath ? strlen( unprocessedPath + 1 ) + 1 : 0 ); 422 if ( nLen < buflen && nLen < PATH_MAX ) 423 { 424 if ( unprocessedPath ) 425 { 426 int nTmpPathLen = strlen( tmpPath ); 427 strcat( tmpPath, "/" ); 428 strcat( tmpPath, unprocessedPath + 1 ); 429 strcpy( path, tmpPath); 430 unprocessedPath = path + nTmpPathLen; 431 } 432 else if ( !unprocessedPath ) 433 { 434 strcpy( path, tmpPath); 435 } 436 } 437 else 438 { 439 errno = ENAMETOOLONG; 440 nRet = -1; 441 } 442 } 443 } 444 } 445 446 if ( unprocessedPath ) 447 *unprocessedPath++ = '/'; 448 } 449 450 return nRet; 451 } 452 453 #endif /* defined MACOSX */ 454 455 #endif /* NO_PTHREAD_RTL */ 456 457 #if (defined (LINUX) && (GLIBC >= 2)) 458 /* The linux kernel thread implemention, always return the pid of the 459 thread subprocess and not of the main process. So we save the main 460 pid at startup 461 */ 462 463 // Directly from libc.so.6, obviously missing from some unistd.h: 464 extern __pid_t __getpid(void); 465 466 static pid_t pid = -1; 467 468 static void savePid(void) __attribute__((constructor)); 469 470 static void savePid(void) 471 { 472 if (pid == -1) 473 pid = __getpid(); 474 } 475 476 pid_t getpid(void) 477 { 478 if (pid == -1) 479 savePid(); 480 481 return (pid); 482 } 483 #endif /* (defined (LINUX) && (GLIBC >= 2)) */ 484 485 #ifdef NO_PTHREAD_SEMAPHORES 486 int sem_init(sem_t* sem, int pshared, unsigned int value) 487 { 488 pthread_mutex_init(&sem->mutex, PTHREAD_MUTEXATTR_DEFAULT); 489 pthread_cond_init(&sem->increased, PTHREAD_CONDATTR_DEFAULT); 490 491 sem->value = (int)value; 492 return 0; 493 } 494 495 int sem_destroy(sem_t* sem) 496 { 497 pthread_mutex_destroy(&sem->mutex); 498 pthread_cond_destroy(&sem->increased); 499 sem->value = 0; 500 return 0; 501 } 502 503 int sem_wait(sem_t* sem) 504 { 505 pthread_mutex_lock(&sem->mutex); 506 507 while (sem->value <= 0) 508 { 509 pthread_cond_wait(&sem->increased, &sem->mutex); 510 } 511 512 sem->value--; 513 pthread_mutex_unlock(&sem->mutex); 514 515 return 0; 516 } 517 518 int sem_trywait(sem_t* sem) 519 { 520 int result = 0; 521 522 pthread_mutex_lock(&sem->mutex); 523 524 if (sem->value > 0) 525 { 526 sem->value--; 527 } 528 else 529 { 530 errno = EAGAIN; 531 result = -1; 532 } 533 534 pthread_mutex_unlock(&sem->mutex); 535 536 return result; 537 } 538 539 int sem_post(sem_t* sem) 540 { 541 pthread_mutex_lock(&sem->mutex); 542 543 sem->value++; 544 545 pthread_mutex_unlock(&sem->mutex); 546 547 pthread_cond_signal(&sem->increased); 548 549 return 0; 550 } 551 #endif 552 553 #if defined(FREEBSD) 554 char *fcvt(double value, int ndigit, int *decpt, int *sign) 555 { 556 static char ret[256]; 557 char buf[256],zahl[256],format[256]="%"; 558 char *v1,*v2; 559 560 if (value==0.0) value=1e-30; 561 562 if (value<0.0) *sign=1; else *sign=0; 563 564 if (value<1.0) 565 { 566 *decpt=(int)log10(value); 567 value*=pow(10.0,1-*decpt); 568 ndigit+=*decpt-1; 569 if (ndigit<0) ndigit=0; 570 } 571 else 572 { 573 *decpt=(int)log10(value)+1; 574 } 575 576 sprintf(zahl,"%d",ndigit); 577 strcat(format,zahl); 578 strcat(format,"."); 579 strcat(format,zahl); 580 strcat(format,"f"); 581 582 sprintf(buf,format,value); 583 584 if (ndigit!=0) 585 { 586 v1=strtok(buf,"."); 587 v2=strtok(NULL,"."); 588 strcpy(ret,v1); 589 strcat(ret,v2); 590 } 591 else 592 { 593 strcpy(ret,buf); 594 } 595 596 return(ret); 597 } 598 599 #endif 600