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