00001
00002
00003 #include "ace/OS_NS_unistd.h"
00004
00005 ACE_RCSID(ace, OS_NS_unistd, "OS_NS_unistd.cpp,v 1.18 2006/06/19 11:35:26 jwillemsen Exp")
00006
00007 #if !defined (ACE_HAS_INLINED_OSCALLS)
00008 # include "ace/OS_NS_unistd.inl"
00009 #endif
00010
00011 #include "ace/Base_Thread_Adapter.h"
00012 #include "ace/OS_NS_stdlib.h"
00013 #include "ace/OS_NS_ctype.h"
00014 #include "ace/Default_Constants.h"
00015 #include "ace/OS_Memory.h"
00016 #include "ace/OS_NS_Thread.h"
00017 #include "ace/Object_Manager_Base.h"
00018 #include "ace/os_include/sys/os_pstat.h"
00019 #include "ace/os_include/sys/os_sysctl.h"
00020
00021 #if defined (ACE_NEEDS_FTRUNCATE)
00022 extern "C" int
00023 ftruncate (ACE_HANDLE handle, long len)
00024 {
00025 struct flock fl;
00026 fl.l_whence = 0;
00027 fl.l_len = 0;
00028 fl.l_start = len;
00029 fl.l_type = F_WRLCK;
00030
00031 return ACE_OS::fcntl (handle, F_FREESP, reinterpret_cast <long> (&fl));
00032 }
00033 #endif
00034
00035
00036
00037 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00038
00039 int
00040 ACE_OS::argv_to_string (ACE_TCHAR **argv,
00041 ACE_TCHAR *&buf,
00042 bool substitute_env_args)
00043 {
00044 if (argv == 0 || argv[0] == 0)
00045 return 0;
00046
00047 size_t buf_len = 0;
00048
00049
00050
00051 for (int i = 0; argv[i] != 0; i++)
00052 {
00053 #if !defined (ACE_LACKS_ENV)
00054
00055 if (substitute_env_args && argv[i][0] == ACE_LIB_TEXT ('$'))
00056 {
00057 # if defined (ACE_WIN32) || !defined (ACE_HAS_WCHAR)
00058 ACE_TCHAR *temp = 0;
00059
00060 if ((temp = ACE_OS::getenv (&argv[i][1])) != 0)
00061 buf_len += ACE_OS::strlen (temp);
00062 else
00063 buf_len += ACE_OS::strlen (argv[i]);
00064 # else
00065
00066
00067
00068
00069
00070 char *ctemp = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (&argv[i][1]));
00071 if (ctemp == 0)
00072 buf_len += ACE_OS::strlen (argv[i]);
00073 else
00074 buf_len += ACE_OS::strlen (ctemp);
00075 # endif
00076 }
00077 else
00078 #endif
00079 buf_len += ACE_OS::strlen (argv[i]);
00080
00081
00082 buf_len++;
00083 }
00084
00085
00086
00087
00088 ACE_NEW_RETURN (buf,
00089 ACE_TCHAR[buf_len + 1],
00090 0);
00091
00092
00093 buf[0] = '\0';
00094 ACE_TCHAR *end = buf;
00095 int j;
00096
00097 for (j = 0; argv[j] != 0; j++)
00098 {
00099
00100 #if !defined (ACE_LACKS_ENV)
00101
00102 if (substitute_env_args && argv[j][0] == ACE_LIB_TEXT ('$'))
00103 {
00104 # if defined (ACE_WIN32) || !defined (ACE_HAS_WCHAR)
00105
00106 ACE_TCHAR *temp = ACE_OS::getenv (&argv[j][1]);
00107 if (temp != 0)
00108 end = ACE_OS::strecpy (end, temp);
00109 else
00110 end = ACE_OS::strecpy (end, argv[j]);
00111 # else
00112
00113
00114
00115 char *ctemp = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (&argv[j][1]));
00116 if (ctemp == 0)
00117 end = ACE_OS::strecpy (end, argv[j]);
00118 else
00119 end = ACE_OS::strecpy (end, ACE_TEXT_CHAR_TO_TCHAR (ctemp));
00120 # endif
00121 }
00122 else
00123 #endif
00124 end = ACE_OS::strecpy (end, argv[j]);
00125
00126
00127
00128 end[-1] = ' ';
00129 }
00130
00131
00132 *end = '\0';
00133
00134 return j;
00135 }
00136
00137 int
00138 ACE_OS::execl (const char * , const char * , ...)
00139 {
00140 ACE_OS_TRACE ("ACE_OS::execl");
00141 ACE_NOTSUP_RETURN (-1);
00142
00143
00144 }
00145
00146 int
00147 ACE_OS::execle (const char * , const char * , ...)
00148 {
00149 ACE_OS_TRACE ("ACE_OS::execle");
00150 ACE_NOTSUP_RETURN (-1);
00151
00152
00153 }
00154
00155 int
00156 ACE_OS::execlp (const char * , const char * , ...)
00157 {
00158 ACE_OS_TRACE ("ACE_OS::execlp");
00159 ACE_NOTSUP_RETURN (-1);
00160
00161
00162 }
00163
00164 pid_t
00165 ACE_OS::fork (const ACE_TCHAR *program_name)
00166 {
00167 ACE_OS_TRACE ("ACE_OS::fork");
00168 # if defined (ACE_LACKS_FORK)
00169 ACE_UNUSED_ARG (program_name);
00170 ACE_NOTSUP_RETURN (pid_t (-1));
00171 # else
00172 pid_t pid =
00173 # if defined (ACE_HAS_STHREADS)
00174 ::fork1 ();
00175 #else
00176 ::fork ();
00177 #endif
00178
00179 #if !defined (ACE_HAS_MINIMAL_ACE_OS)
00180 if (pid == 0)
00181 ACE_Base_Thread_Adapter::sync_log_msg (program_name);
00182 #endif
00183
00184 return pid;
00185 # endif
00186 }
00187
00188
00189
00190
00191 pid_t
00192 ACE_OS::fork_exec (ACE_TCHAR *argv[])
00193 {
00194 # if defined (ACE_WIN32)
00195 ACE_TCHAR *buf;
00196
00197 if (ACE_OS::argv_to_string (argv, buf) != -1)
00198 {
00199 PROCESS_INFORMATION process_info;
00200 # if !defined (ACE_HAS_WINCE)
00201 ACE_TEXT_STARTUPINFO startup_info;
00202 ACE_OS::memset ((void *) &startup_info,
00203 0,
00204 sizeof startup_info);
00205 startup_info.cb = sizeof startup_info;
00206
00207 if (ACE_TEXT_CreateProcess (0,
00208 buf,
00209 0,
00210 0,
00211 TRUE,
00212 0,
00213 0,
00214 0,
00215 &startup_info,
00216 &process_info))
00217 # else
00218 if (ACE_TEXT_CreateProcess (0,
00219 buf,
00220 0,
00221 0,
00222 FALSE,
00223 0,
00224 0,
00225 0,
00226 0,
00227 &process_info))
00228 # endif
00229 {
00230
00231 ACE_OS::close (process_info.hThread);
00232 ACE_OS::close (process_info.hProcess);
00233
00234 delete [] buf;
00235 return process_info.dwProcessId;
00236 }
00237 }
00238
00239
00240 return -1;
00241 # else
00242 pid_t result = ACE_OS::fork ();
00243
00244 # if defined (ACE_USES_WCHAR)
00245
00246
00247 char **cargv;
00248 int arg_count;
00249 # endif
00250
00251 switch (result)
00252 {
00253 case -1:
00254
00255 return -1;
00256 case 0:
00257
00258 # if defined (ACE_USES_WCHAR)
00259 for (arg_count = 0; argv[arg_count] != 0; ++arg_count)
00260 ;
00261 ++arg_count;
00262 ACE_NEW_NORETURN (cargv, char*[arg_count]);
00263 if (cargv == 0)
00264 ACE_OS::exit (errno);
00265 --arg_count;
00266 cargv[arg_count] = 0;
00267 while (--arg_count >= 0)
00268 cargv[arg_count] = ACE_Wide_To_Ascii::convert (argv[arg_count]);
00269
00270
00271 if (ACE_OS::execv (cargv[0], cargv) == -1)
00272 ACE_OS::exit (errno);
00273 # else
00274 if (ACE_OS::execv (argv[0], argv) == -1)
00275 {
00276
00277
00278
00279
00280
00281 ACE_OS::exit (errno);
00282 }
00283 # endif
00284
00285 default:
00286
00287 return result;
00288 }
00289 # endif
00290 }
00291
00292 long
00293 ACE_OS::num_processors (void)
00294 {
00295 ACE_OS_TRACE ("ACE_OS::num_processors");
00296
00297 #if defined (ACE_HAS_PHARLAP)
00298 return 1;
00299 #elif defined (ACE_WIN32)
00300 SYSTEM_INFO sys_info;
00301 ::GetSystemInfo (&sys_info);
00302 return sys_info.dwNumberOfProcessors;
00303 #elif defined (_SC_NPROCESSORS_CONF)
00304 return ::sysconf (_SC_NPROCESSORS_CONF);
00305 #elif defined (ACE_HAS_SYSCTL)
00306 int num_processors;
00307 int mib[2] = { CTL_HW, HW_NCPU };
00308 size_t len = sizeof (num_processors);
00309
00310 sysctl(mib, 2, &num_processors, &len, NULL, 0);
00311 return num_processors;
00312 #else
00313 ACE_NOTSUP_RETURN (-1);
00314 #endif
00315 }
00316
00317 long
00318 ACE_OS::num_processors_online (void)
00319 {
00320 ACE_OS_TRACE ("ACE_OS::num_processors_online");
00321
00322 #if defined (ACE_HAS_PHARLAP)
00323 return 1;
00324 #elif defined (ACE_WIN32)
00325 SYSTEM_INFO sys_info;
00326 ::GetSystemInfo (&sys_info);
00327 return sys_info.dwNumberOfProcessors;
00328 #elif defined (_SC_NPROCESSORS_ONLN)
00329 return ::sysconf (_SC_NPROCESSORS_ONLN);
00330 #elif defined (ACE_HAS_SYSCTL)
00331 int num_processors;
00332 int mib[2] = { CTL_HW, HW_NCPU };
00333 size_t len = sizeof (num_processors);
00334
00335 sysctl(mib, 2, &num_processors, &len, NULL, 0);
00336 return num_processors;
00337 #elif defined (__hpux)
00338 struct pst_dynamic psd;
00339 if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
00340 return psd.psd_proc_cnt;
00341 else
00342 return -1;
00343 #else
00344 ACE_NOTSUP_RETURN (-1);
00345 #endif
00346 }
00347
00348 ssize_t
00349 ACE_OS::read_n (ACE_HANDLE handle,
00350 void *buf,
00351 size_t len,
00352 size_t *bt)
00353 {
00354 size_t temp;
00355 size_t &bytes_transferred = bt == 0 ? temp : *bt;
00356 ssize_t n;
00357
00358 for (bytes_transferred = 0;
00359 bytes_transferred < len;
00360 bytes_transferred += n)
00361 {
00362 n = ACE_OS::read (handle,
00363 (char *) buf + bytes_transferred,
00364 len - bytes_transferred);
00365
00366 if (n == -1 || n == 0)
00367 return n;
00368 }
00369
00370 return bytes_transferred;
00371 }
00372
00373 ssize_t
00374 ACE_OS::pread (ACE_HANDLE handle,
00375 void *buf,
00376 size_t nbytes,
00377 off_t offset)
00378 {
00379 # if defined (ACE_HAS_P_READ_WRITE)
00380 # if defined (ACE_WIN32)
00381
00382 ACE_OS_GUARD
00383
00384
00385 DWORD original_position = ::SetFilePointer (handle,
00386 0,
00387 0,
00388 FILE_CURRENT);
00389
00390 if (original_position == 0xFFFFFFFF)
00391 return -1;
00392
00393
00394 DWORD altered_position = ::SetFilePointer (handle,
00395 offset,
00396 0,
00397 FILE_BEGIN);
00398 if (altered_position == 0xFFFFFFFF)
00399 return -1;
00400
00401 DWORD bytes_read;
00402
00403 # if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
00404
00405 OVERLAPPED overlapped;
00406 overlapped.Internal = 0;
00407 overlapped.InternalHigh = 0;
00408 overlapped.Offset = offset;
00409 overlapped.OffsetHigh = 0;
00410 overlapped.hEvent = 0;
00411
00412 BOOL result = ::ReadFile (handle,
00413 buf,
00414 static_cast <DWORD> (nbytes),
00415 &bytes_read,
00416 &overlapped);
00417
00418 if (result == FALSE)
00419 {
00420 if (::GetLastError () != ERROR_IO_PENDING)
00421 return -1;
00422
00423 else
00424 {
00425 result = ::GetOverlappedResult (handle,
00426 &overlapped,
00427 &bytes_read,
00428 TRUE);
00429 if (result == FALSE)
00430 return -1;
00431 }
00432 }
00433
00434 # else
00435
00436 BOOL result = ::ReadFile (handle,
00437 buf,
00438 nbytes,
00439 &bytes_read,
00440 0);
00441 if (result == FALSE)
00442 return -1;
00443
00444 # endif
00445
00446
00447 if (::SetFilePointer (handle,
00448 original_position,
00449 0,
00450 FILE_BEGIN) == 0xFFFFFFFF)
00451 return -1;
00452
00453 return (ssize_t) bytes_read;
00454
00455 # else
00456
00457 return ::pread (handle, buf, nbytes, offset);
00458
00459 # endif
00460
00461 # else
00462
00463 ACE_OS_GUARD
00464
00465
00466 off_t original_position = ACE_OS::lseek (handle,
00467 0,
00468 SEEK_CUR);
00469
00470 if (original_position == -1)
00471 return -1;
00472
00473
00474 off_t altered_position = ACE_OS::lseek (handle,
00475 offset,
00476 SEEK_SET);
00477
00478 if (altered_position == -1)
00479 return -1;
00480
00481 ssize_t bytes_read = ACE_OS::read (handle,
00482 buf,
00483 nbytes);
00484
00485 if (bytes_read == -1)
00486 return -1;
00487
00488 if (ACE_OS::lseek (handle,
00489 original_position,
00490 SEEK_SET) == -1)
00491 return -1;
00492
00493 return bytes_read;
00494
00495 # endif
00496 }
00497
00498 ssize_t
00499 ACE_OS::pwrite (ACE_HANDLE handle,
00500 const void *buf,
00501 size_t nbytes,
00502 ACE_LOFF_T offset)
00503 {
00504 # if defined (ACE_HAS_P_READ_WRITE)
00505 # if defined (ACE_WIN32)
00506
00507 ACE_OS_GUARD
00508
00509
00510 DWORD original_position = ::SetFilePointer (handle,
00511 0,
00512 0,
00513 FILE_CURRENT);
00514
00515 if (original_position == 0xFFFFFFFF)
00516 return -1;
00517
00518
00519 LARGE_INTEGER loffset;
00520 loffset.QuadPart = offset;
00521 DWORD altered_position = ::SetFilePointerEx (handle,
00522 loffset,
00523 0,
00524 FILE_BEGIN);
00525 if (altered_position == 0xFFFFFFFF)
00526 return -1;
00527
00528 DWORD bytes_written;
00529
00530 # if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
00531
00532 OVERLAPPED overlapped;
00533 overlapped.Internal = 0;
00534 overlapped.InternalHigh = 0;
00535 overlapped.Offset = offset;
00536 overlapped.OffsetHigh = 0;
00537 overlapped.hEvent = 0;
00538
00539 BOOL result = ::WriteFile (handle,
00540 buf,
00541 static_cast <DWORD> (nbytes),
00542 &bytes_written,
00543 &overlapped);
00544
00545 if (result == FALSE)
00546 {
00547 if (::GetLastError () != ERROR_IO_PENDING)
00548 return -1;
00549
00550 else
00551 {
00552 result = ::GetOverlappedResult (handle,
00553 &overlapped,
00554 &bytes_written,
00555 TRUE);
00556 if (result == FALSE)
00557 return -1;
00558 }
00559 }
00560
00561 # else
00562
00563 BOOL result = ::WriteFile (handle,
00564 buf,
00565 nbytes,
00566 &bytes_written,
00567 0);
00568 if (result == FALSE)
00569 return -1;
00570
00571 # endif
00572
00573
00574 if (::SetFilePointer (handle,
00575 original_position,
00576 0,
00577 FILE_BEGIN) == 0xFFFFFFFF)
00578 return -1;
00579
00580 return (ssize_t) bytes_written;
00581
00582 # else
00583
00584 return ::pwrite (handle, buf, nbytes, offset);
00585 # endif
00586 # else
00587
00588 ACE_OS_GUARD
00589
00590
00591 off_t original_position = ACE_OS::lseek (handle,
00592 0,
00593 SEEK_CUR);
00594 if (original_position == -1)
00595 return -1;
00596
00597
00598 off_t altered_position = ACE_OS::lseek (handle,
00599 offset,
00600 SEEK_SET);
00601 if (altered_position == -1)
00602 return -1;
00603
00604 ssize_t bytes_written = ACE_OS::write (handle,
00605 buf,
00606 nbytes);
00607 if (bytes_written == -1)
00608 return -1;
00609
00610 if (ACE_OS::lseek (handle,
00611 original_position,
00612 SEEK_SET) == -1)
00613 return -1;
00614
00615 return bytes_written;
00616 # endif
00617 }
00618
00619 int
00620 ACE_OS::string_to_argv (ACE_TCHAR *buf,
00621 int &argc,
00622 ACE_TCHAR **&argv,
00623 bool substitute_env_args)
00624 {
00625
00626 argc = 0;
00627
00628 if (buf == 0)
00629 return -1;
00630
00631 ACE_TCHAR *cp = buf;
00632
00633
00634
00635
00636 while (*cp != ACE_LIB_TEXT ('\0') && *cp != ACE_LIB_TEXT ('#'))
00637 {
00638
00639 while (ACE_OS::ace_isspace (*cp))
00640 cp++;
00641
00642
00643 if (*cp != ACE_LIB_TEXT ('\0'))
00644 argc++;
00645
00646 while (*cp != ACE_LIB_TEXT ('\0') && !ACE_OS::ace_isspace (*cp))
00647 {
00648
00649 if (*cp == ACE_LIB_TEXT ('\'') || *cp == ACE_LIB_TEXT ('"'))
00650 {
00651 ACE_TCHAR quote = *cp;
00652
00653
00654 for (cp++; *cp != ACE_LIB_TEXT ('\0') && *cp != quote; cp++)
00655 continue;
00656
00657
00658 if (*cp == ACE_LIB_TEXT ('\0'))
00659 {
00660 argc--;
00661 break;
00662 }
00663 else
00664 cp++;
00665 }
00666 else
00667 cp++;
00668 }
00669 }
00670
00671
00672 ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
00673 ACE_TCHAR *argp = arg;
00674
00675
00676
00677 if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
00678 ACE_NEW_RETURN (argp,
00679 ACE_TCHAR[cp - buf + 1],
00680 -1);
00681
00682
00683 ACE_NEW_RETURN (argv,
00684 ACE_TCHAR *[argc + 1],
00685 -1);
00686
00687 ACE_TCHAR *ptr = buf;
00688
00689 for (int i = 0; i < argc; i++)
00690 {
00691
00692 while (ACE_OS::ace_isspace (*ptr))
00693 ptr++;
00694
00695
00696 cp = argp;
00697 while (*ptr != ACE_LIB_TEXT ('\0') && !ACE_OS::ace_isspace (*ptr))
00698 if (*ptr == ACE_LIB_TEXT ('\'') || *ptr == ACE_LIB_TEXT ('"'))
00699 {
00700 ACE_TCHAR quote = *ptr++;
00701
00702 while (*ptr != ACE_LIB_TEXT ('\0') && *ptr != quote)
00703 *cp++ = *ptr++;
00704
00705 if (*ptr == quote)
00706 ptr++;
00707 }
00708 else
00709 *cp++ = *ptr++;
00710
00711 *cp = ACE_LIB_TEXT ('\0');
00712
00713 #if !defined (ACE_LACKS_ENV)
00714
00715 if (substitute_env_args) {
00716 argv[i] = ACE_OS::strenvdup(argp);
00717
00718 if (argv[i] == 0)
00719 {
00720 if (argp != arg)
00721 delete [] argp;
00722 errno = ENOMEM;
00723 return -1;
00724 }
00725 }
00726 else
00727 #endif
00728 {
00729 argv[i] = ACE_OS::strdup(argp);
00730
00731 if (argv[i] == 0)
00732 {
00733 if (argp != arg)
00734 delete [] argp;
00735 errno = ENOMEM;
00736 return -1;
00737 }
00738 }
00739 }
00740
00741 if (argp != arg)
00742 delete [] argp;
00743
00744 argv[argc] = 0;
00745 return 0;
00746 }
00747
00748
00749
00750
00751 ssize_t
00752 ACE_OS::write_n (ACE_HANDLE handle,
00753 const void *buf,
00754 size_t len,
00755 size_t *bt)
00756 {
00757 size_t temp;
00758 size_t &bytes_transferred = bt == 0 ? temp : *bt;
00759 ssize_t n;
00760
00761 for (bytes_transferred = 0;
00762 bytes_transferred < len;
00763 bytes_transferred += n)
00764 {
00765 n = ACE_OS::write (handle,
00766 (char *) buf + bytes_transferred,
00767 len - bytes_transferred);
00768
00769 if (n == -1 || n == 0)
00770 return n;
00771 }
00772
00773 return bytes_transferred;
00774 }
00775
00776 ACE_END_VERSIONED_NAMESPACE_DECL