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