00001
00002
00003 #include "ace/OS_NS_stdlib.h"
00004
00005 ACE_RCSID (ace,
00006 OS_NS_stdlib,
00007 "$Id: OS_NS_stdlib.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00008
00009 #include "ace/Default_Constants.h"
00010
00011 #if !defined (ACE_HAS_INLINED_OSCALLS)
00012 # include "ace/OS_NS_stdlib.inl"
00013 #endif
00014
00015 #include "ace/OS_Memory.h"
00016
00017 #include "ace/OS_NS_unistd.h"
00018
00019 #if defined (ACE_LACKS_MKTEMP) \
00020 || defined (ACE_LACKS_MKSTEMP) \
00021 || defined (ACE_LACKS_REALPATH)
00022 # include "ace/OS_NS_stdio.h"
00023 # include "ace/OS_NS_sys_stat.h"
00024 #endif
00025
00026 #if defined (ACE_LACKS_MKSTEMP)
00027 # include "ace/OS_NS_fcntl.h"
00028 # include "ace/OS_NS_ctype.h"
00029 # include "ace/OS_NS_sys_time.h"
00030 # include "ace/OS_NS_Thread.h"
00031 # include "ace/Numeric_Limits.h"
00032 #endif
00033
00034 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00035
00036 ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0;
00037
00038 void *
00039 ACE_OS::calloc (size_t elements, size_t sizeof_elements)
00040 {
00041 #if !defined (ACE_HAS_WINCE)
00042 return ACE_CALLOC_FUNC (elements, sizeof_elements);
00043 #else
00044
00045
00046 return ACE_MALLOC_FUNC (elements * sizeof_elements);
00047 #endif
00048 }
00049
00050 void
00051 ACE_OS::exit (int status)
00052 {
00053 ACE_OS_TRACE ("ACE_OS::exit");
00054
00055 #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
00056
00057
00058
00059 if (exit_hook_)
00060 (*exit_hook_) ();
00061 #endif
00062
00063 #if !defined (ACE_HAS_WINCE)
00064 # if defined (ACE_WIN32)
00065 ::ExitProcess ((UINT) status);
00066 # else
00067 ::exit (status);
00068 # endif
00069 #else
00070
00071
00072 ::TerminateProcess (::GetCurrentProcess (), status);
00073 #endif
00074 }
00075
00076 void
00077 ACE_OS::free (void *ptr)
00078 {
00079 ACE_FREE_FUNC (ACE_MALLOC_T (ptr));
00080 }
00081
00082
00083
00084
00085
00086
00087 #if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR)
00088 #undef GetEnvironmentStrings
00089 #endif
00090
00091 ACE_TCHAR *
00092 ACE_OS::getenvstrings (void)
00093 {
00094 #if defined (ACE_LACKS_ENV)
00095 ACE_NOTSUP_RETURN (0);
00096 #elif defined (ACE_WIN32)
00097 # if defined (ACE_USES_WCHAR)
00098 return ::GetEnvironmentStringsW ();
00099 # else
00100 return ::GetEnvironmentStrings ();
00101 # endif
00102 #else
00103 ACE_NOTSUP_RETURN (0);
00104 #endif
00105 }
00106
00107
00108
00109
00110
00111
00112 ACE_TCHAR *
00113 ACE_OS::strenvdup (const ACE_TCHAR *str)
00114 {
00115 #if defined (ACE_HAS_WINCE)
00116
00117 return ACE_OS::strdup (str);
00118 #elif defined (ACE_LACKS_ENV)
00119 ACE_UNUSED_ARG (str);
00120 ACE_NOTSUP_RETURN (0);
00121 #else
00122 const ACE_TCHAR * start = 0;
00123 if ((start = ACE_OS::strchr (str, ACE_TEXT ('$'))) != 0)
00124 {
00125 ACE_TCHAR buf[ACE_DEFAULT_ARGV_BUFSIZ];
00126 size_t var_len = ACE_OS::strcspn (&start[1],
00127 ACE_TEXT ("$~!#%^&*()-+=\\|/?,.;:'\"`[]{} \t\n\r"));
00128 ACE_OS::strncpy (buf, &start[1], var_len);
00129 buf[var_len++] = ACE_TEXT ('\0');
00130 # if defined (ACE_WIN32)
00131
00132 ACE_TCHAR *temp = ACE_OS::getenv (buf);
00133 # else
00134
00135 char *temp = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (buf));
00136 # endif
00137 size_t buf_len = ACE_OS::strlen (str) + 1;
00138 if (temp != 0)
00139 buf_len += ACE_OS::strlen (temp) - var_len;
00140 ACE_TCHAR * buf_p = buf;
00141 if (buf_len > ACE_DEFAULT_ARGV_BUFSIZ)
00142 {
00143 buf_p =
00144 (ACE_TCHAR *) ACE_OS::malloc (buf_len * sizeof (ACE_TCHAR));
00145 if (buf_p == 0)
00146 {
00147 errno = ENOMEM;
00148 return 0;
00149 }
00150 }
00151 ACE_TCHAR * p = buf_p;
00152 size_t len = start - str;
00153 ACE_OS::strncpy (p, str, len);
00154 p += len;
00155 if (temp != 0)
00156 {
00157 # if defined (ACE_WIN32)
00158 p = ACE_OS::strecpy (p, temp) - 1;
00159 # else
00160 p = ACE_OS::strecpy (p, ACE_TEXT_CHAR_TO_TCHAR (temp)) - 1;
00161 # endif
00162 }
00163 else
00164 {
00165 ACE_OS::strncpy (p, start, var_len);
00166 p += var_len;
00167 *p = ACE_TEXT ('\0');
00168 }
00169 ACE_OS::strcpy (p, &start[var_len]);
00170 return (buf_p == buf) ? ACE_OS::strdup (buf) : buf_p;
00171 }
00172 else
00173 return ACE_OS::strdup (str);
00174 #endif
00175 }
00176
00177 #if !defined (ACE_HAS_ITOA)
00178 char *
00179 ACE_OS::itoa_emulation (int value, char *string, int radix)
00180 {
00181 char *e = string;
00182 char *b = string;
00183
00184
00185
00186 if (value == 0)
00187 {
00188 string[0] = '0';
00189 string[1] = 0;
00190 return string;
00191 }
00192
00193
00194
00195
00196 if (value < 0 && radix == 10)
00197 {
00198 string[0] = '-';
00199 ++b;
00200 ++e;
00201 value = -value;
00202 }
00203
00204
00205
00206 while (value != 0)
00207 {
00208 int mod = value % radix;
00209 value = value / radix;
00210
00211 *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
00212 }
00213
00214 *e-- = 0;
00215
00216
00217
00218 while (e > b)
00219 {
00220 char temp = *e;
00221 *e = *b;
00222 *b = temp;
00223 ++b;
00224 --e;
00225 }
00226
00227 return string;
00228 }
00229 #endif
00230
00231 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW)
00232 wchar_t *
00233 ACE_OS::itow_emulation (int value, wchar_t *string, int radix)
00234 {
00235 wchar_t *e = string;
00236 wchar_t *b = string;
00237
00238
00239
00240 if (value == 0)
00241 {
00242 string[0] = '0';
00243 string[1] = 0;
00244 return string;
00245 }
00246
00247
00248
00249
00250 if (value < 0 && radix == 10)
00251 {
00252 string[0] = '-';
00253 b++;
00254 }
00255
00256
00257
00258 while (value != 0)
00259 {
00260 int mod = value % radix;
00261 value = value / radix;
00262
00263 *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
00264 }
00265
00266 *e-- = 0;
00267
00268
00269
00270 while (e > b)
00271 {
00272 wchar_t temp = *e;
00273 *e = *b;
00274 *b = temp;
00275 ++b;
00276 --e;
00277 }
00278
00279 return string;
00280 }
00281 #endif
00282
00283 void *
00284 ACE_OS::malloc (size_t nbytes)
00285 {
00286 return ACE_MALLOC_FUNC (nbytes);
00287 }
00288
00289 #if defined (ACE_LACKS_MKTEMP)
00290 ACE_TCHAR *
00291 ACE_OS::mktemp (ACE_TCHAR *s)
00292 {
00293 ACE_OS_TRACE ("ACE_OS::mktemp");
00294 if (s == 0)
00295
00296 return 0;
00297 else
00298 {
00299 ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
00300
00301 if (xxxxxx == 0)
00302
00303 return s;
00304 else
00305 {
00306 ACE_TCHAR unique_letter = ACE_TEXT ('a');
00307 ACE_stat sb;
00308
00309
00310
00311
00312
00313
00314
00315 ACE_OS::sprintf (xxxxxx,
00316 ACE_TEXT ("%05d%c"),
00317 ACE_OS::getpid (),
00318 unique_letter);
00319 while (ACE_OS::stat (s, &sb) >= 0)
00320 {
00321 if (++unique_letter <= ACE_TEXT ('z'))
00322 ACE_OS::sprintf (xxxxxx,
00323 ACE_TEXT ("%05d%c"),
00324 ACE_OS::getpid (),
00325 unique_letter);
00326 else
00327 {
00328
00329 ACE_OS::sprintf (xxxxxx, ACE_TEXT ("%s"), ACE_TEXT (""));
00330 return s;
00331 }
00332 }
00333 }
00334 return s;
00335 }
00336 }
00337 #endif
00338
00339 void *
00340 ACE_OS::realloc (void *ptr, size_t nbytes)
00341 {
00342 return ACE_REALLOC_FUNC (ACE_MALLOC_T (ptr), nbytes);
00343 }
00344
00345 #if defined (ACE_LACKS_REALPATH) && !defined (ACE_HAS_WINCE)
00346 char *
00347 ACE_OS::realpath (const char *file_name,
00348 char *resolved_name)
00349 {
00350 ACE_OS_TRACE ("ACE_OS::realpath");
00351
00352 if (file_name == 0)
00353 {
00354
00355
00356 errno = EINVAL;
00357 return 0;
00358 }
00359
00360 if (*file_name == '\0')
00361 {
00362
00363
00364
00365 errno = ENOENT;
00366 return 0;
00367 }
00368
00369 char* rpath;
00370
00371 if (resolved_name == 0)
00372 {
00373
00374
00375
00376
00377
00378
00379 rpath = static_cast<char*>(ACE_OS::malloc (PATH_MAX));
00380 if (rpath == 0)
00381 {
00382 errno = ENOMEM;
00383 return 0;
00384 }
00385 }
00386 else
00387 {
00388 rpath = resolved_name;
00389 }
00390
00391 char* dest;
00392
00393 if (*file_name != '/')
00394 {
00395
00396 if (ACE_OS::getcwd (rpath, PATH_MAX) == 0)
00397 {
00398 if (resolved_name == 0)
00399 ACE_OS::free (rpath);
00400 return 0;
00401 }
00402 dest = ACE_OS::strchr (rpath, '\0');
00403 }
00404 else
00405 {
00406 dest = rpath;
00407 }
00408
00409 #if !defined (ACE_LACKS_SYMLINKS)
00410 char expand_buf[PATH_MAX];
00411 int nlinks = 0;
00412 #endif
00413
00414 while (*file_name)
00415 {
00416 *dest++ = '/';
00417
00418
00419 while (*file_name == '/')
00420 ++file_name;
00421
00422 char* start = dest;
00423
00424
00425 while (*file_name && *file_name != '/')
00426 {
00427 *dest++ = *file_name++;
00428 if (dest - rpath > PATH_MAX)
00429 {
00430 errno = ENAMETOOLONG;
00431 if (resolved_name == 0)
00432 ACE_OS::free (rpath);
00433 return 0;
00434 }
00435 }
00436
00437 if (start == dest)
00438 {
00439 if (dest - rpath > 1)
00440 --dest;
00441 break;
00442 }
00443 else if (dest - start == 1 && *start == '.')
00444 {
00445 dest -= 2;
00446 }
00447 else if (dest - start == 2 && *start == '.' && *(start +1) == '.')
00448 {
00449 dest -= 3;
00450 if (dest > rpath)
00451 while (*--dest != '/')
00452 ;
00453 }
00454 # if !defined (ACE_LACKS_SYMLINKS)
00455 else
00456 {
00457 ACE_stat st;
00458
00459 *dest = '\0';
00460 if (ACE_OS::lstat(rpath, &st) < 0)
00461 {
00462 if (resolved_name == 0)
00463 ACE_OS::free (rpath);
00464 return 0;
00465 }
00466
00467
00468 if (S_ISLNK (st.st_mode))
00469 {
00470 if (++nlinks > MAXSYMLINKS)
00471 {
00472 errno = ELOOP;
00473 if (resolved_name == 0)
00474 ACE_OS::free (rpath);
00475 return 0;
00476 }
00477
00478 char link_buf[PATH_MAX];
00479
00480 ssize_t link_len = ACE_OS::readlink (rpath, link_buf, PATH_MAX);
00481 int tail_len = ACE_OS::strlen (file_name) + 1;
00482
00483
00484 if (link_len + tail_len > PATH_MAX)
00485 {
00486 errno = ENAMETOOLONG;
00487 if (resolved_name == 0)
00488 ACE_OS::free (rpath);
00489 return 0;
00490 }
00491
00492
00493 ACE_OS::memmove (expand_buf + link_len, file_name, tail_len);
00494 ACE_OS::memcpy (expand_buf, link_buf, link_len);
00495
00496 if (*link_buf == '/')
00497 {
00498 dest = rpath;
00499 }
00500 else
00501 {
00502 --dest;
00503 while (*--dest != '/')
00504 ;
00505 }
00506 file_name = expand_buf;
00507 }
00508 }
00509 # endif
00510 }
00511
00512 *dest = '\0';
00513
00514 return rpath;
00515 }
00516 #endif
00517
00518 #if defined (ACE_LACKS_STRTOL)
00519 long
00520 ACE_OS::strtol_emulation (const char *nptr, char **endptr, int base)
00521 {
00522 register const char *s = nptr;
00523 register unsigned long acc;
00524 register int c;
00525 register unsigned long cutoff;
00526 register int neg = 0, any, cutlim;
00527
00528
00529
00530
00531
00532
00533 do {
00534 c = *s++;
00535 } while (isspace(c));
00536 if (c == '-') {
00537 neg = 1;
00538 c = *s++;
00539 } else if (c == '+')
00540 c = *s++;
00541 if ((base == 0 || base == 16) &&
00542 c == '0' && (*s == 'x' || *s == 'X')) {
00543 c = s[1];
00544 s += 2;
00545 base = 16;
00546 }
00547 if (base == 0)
00548 base = c == '0' ? 8 : 10;
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
00568 cutlim = cutoff % (unsigned long)base;
00569 cutoff /= (unsigned long)base;
00570 for (acc = 0, any = 0;; c = *s++) {
00571 if (isdigit(c))
00572 c -= '0';
00573 else if (isalpha(c))
00574 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00575 else
00576 break;
00577 if (c >= base)
00578 break;
00579 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
00580 any = -1;
00581 else {
00582 any = 1;
00583 acc *= base;
00584 acc += c;
00585 }
00586 }
00587 if (any < 0) {
00588 acc = neg ? LONG_MIN : LONG_MAX;
00589 errno = ERANGE;
00590 } else if (neg)
00591 acc = -acc;
00592 if (endptr != 0)
00593 *endptr = any ? (char *)s - 1 : (char *)nptr;
00594 return (acc);
00595 }
00596 #endif
00597
00598 #if defined (ACE_LACKS_STRTOUL)
00599 unsigned long
00600 ACE_OS::strtoul_emulation (const char *nptr,
00601 char **endptr,
00602 register int base)
00603 {
00604 register const char *s = nptr;
00605 register unsigned long acc;
00606 register int c;
00607 register unsigned long cutoff;
00608 register int neg = 0, any, cutlim;
00609
00610
00611
00612
00613 do
00614 c = *s++;
00615 while (isspace(c));
00616 if (c == '-')
00617 {
00618 neg = 1;
00619 c = *s++;
00620 }
00621 else if (c == '+')
00622 c = *s++;
00623 if ((base == 0 || base == 16) &&
00624 c == '0' && (*s == 'x' || *s == 'X'))
00625 {
00626 c = s[1];
00627 s += 2;
00628 base = 16;
00629 }
00630 if (base == 0)
00631 base = c == '0' ? 8 : 10;
00632 cutoff = (unsigned long) ULONG_MAX / (unsigned long) base;
00633 cutlim = (unsigned long) ULONG_MAX % (unsigned long) base;
00634
00635 for (acc = 0, any = 0;; c = *s++)
00636 {
00637 if (isdigit(c))
00638 c -= '0';
00639 else if (isalpha(c))
00640 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00641 else
00642 break;
00643 if (c >= base)
00644 break;
00645 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
00646 any = -1;
00647 else
00648 {
00649 any = 1;
00650 acc *= base;
00651 acc += c;
00652 }
00653 }
00654 if (any < 0)
00655 {
00656 acc = ULONG_MAX;
00657 errno = ERANGE;
00658 } else if (neg)
00659 acc = -acc;
00660 if (endptr != 0)
00661 *endptr = any ? (char *) s - 1 : (char *) nptr;
00662 return (acc);
00663 }
00664 #endif
00665
00666
00667 #if defined (ACE_LACKS_MKSTEMP)
00668 ACE_HANDLE
00669 ACE_OS::mkstemp_emulation (ACE_TCHAR * s)
00670 {
00671 if (s == 0)
00672 {
00673 errno = EINVAL;
00674 return ACE_INVALID_HANDLE;
00675 }
00676
00677
00678 ACE_TCHAR * const t = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
00679
00680 if (t == 0)
00681 {
00682 errno = EINVAL;
00683 return ACE_INVALID_HANDLE;
00684 }
00685
00686 static unsigned int const NUM_RETRIES = 50;
00687 static unsigned int const NUM_CHARS = 6;
00688
00689
00690
00691 ACE_UINT64 msec;
00692
00693
00694
00695 const ACE_Time_Value now = ACE_OS::gettimeofday();
00696 now.msec (msec);
00697
00698
00699 msec += ACE_OS::getpid();
00700 msec += (size_t) ACE_OS::thr_self();
00701
00702
00703
00704
00705 ACE_RANDR_TYPE seed = static_cast<ACE_RANDR_TYPE> (msec);
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 float const MAX_VAL =
00719 static_cast<float> (ACE_Numeric_Limits<char>::max ());
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 float const coefficient =
00731 static_cast<float> (MAX_VAL / (RAND_MAX + 1.0f));
00732
00733
00734
00735 for (unsigned int i = 0; i < NUM_RETRIES; ++i)
00736 {
00737 for (unsigned int n = 0; n < NUM_CHARS; ++n)
00738 {
00739 ACE_TCHAR r;
00740
00741
00742
00743 do
00744 {
00745 r = static_cast<ACE_TCHAR> (coefficient * ACE_OS::rand_r (seed));
00746 }
00747 while (!ACE_OS::ace_isalnum (r));
00748
00749 t[n] = r;
00750 }
00751
00752 static int const perms =
00753 #if defined (ACE_WIN32)
00754 0;
00755 #else
00756 0600;
00757 #endif
00758
00759
00760
00761
00762
00763
00764 ACE_HANDLE const handle = ACE_OS::open (s,
00765 O_RDWR | O_CREAT | O_EXCL,
00766 perms);
00767
00768 if (handle != ACE_INVALID_HANDLE)
00769 return handle;
00770 }
00771
00772 errno = EEXIST;
00773 return ACE_INVALID_HANDLE;
00774 }
00775 #endif
00776
00777 ACE_END_VERSIONED_NAMESPACE_DECL