OS_NS_unistd.cpp

Go to the documentation of this file.
00001 // $Id: OS_NS_unistd.cpp 79134 2007-07-31 18:23:50Z johnnyw $
00002 
00003 #include "ace/OS_NS_unistd.h"
00004 
00005 ACE_RCSID (ace, OS_NS_unistd, "$Id: OS_NS_unistd.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00006 
00007 #if !defined (ACE_HAS_INLINED_OSCALLS)
00008 # include "ace/OS_NS_unistd.inl"
00009 #endif /* ACE_HAS_INLINED_OSCALLS */
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/Auto_Ptr.h"
00019 #include "ace/os_include/sys/os_pstat.h"
00020 #include "ace/os_include/sys/os_sysctl.h"
00021 
00022 #if defined (ACE_NEEDS_FTRUNCATE)
00023 extern "C" int
00024 ftruncate (ACE_HANDLE handle, long len)
00025 {
00026   struct flock fl;
00027   fl.l_whence = 0;
00028   fl.l_len = 0;
00029   fl.l_start = len;
00030   fl.l_type = F_WRLCK;
00031 
00032   return ACE_OS::fcntl (handle, F_FREESP, reinterpret_cast <long> (&fl));
00033 }
00034 #endif /* ACE_NEEDS_FTRUNCATE */
00035 
00036 /*****************************************************************************/
00037 
00038 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00039 
00040 int
00041 ACE_OS::argv_to_string (ACE_TCHAR **argv,
00042                         ACE_TCHAR *&buf,
00043                         bool substitute_env_args,
00044                         bool quote_args)
00045 {
00046   if (argv == 0 || argv[0] == 0)
00047     return 0;
00048 
00049   size_t buf_len = 0;
00050 
00051   // Determine the length of the buffer.
00052 
00053   int argc;
00054   for (argc = 0; argv[argc] != 0; ++argc)
00055     continue;
00056   ACE_TCHAR **argv_p = argv;
00057 
00058   for (int i = 0; i < argc; ++i)
00059     {
00060 #if !defined (ACE_LACKS_ENV)
00061       // Account for environment variables.
00062       if (substitute_env_args
00063           && ACE_OS::strchr (argv[i], ACE_TEXT ('$')) != 0)
00064         {
00065           if (argv_p == argv)
00066             {
00067               argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
00068               if (argv_p == 0)
00069                 {
00070                   errno = ENOMEM;
00071                   return 0;
00072                 }
00073               ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
00074             }
00075           argv_p[i] = ACE_OS::strenvdup (argv[i]);
00076           if (argv_p[i] == 0)
00077             {
00078               ACE_OS::free (argv_p);
00079               errno = ENOMEM;
00080               return 0;
00081             }
00082         }
00083 #endif /* ACE_LACKS_ENV */
00084       if (quote_args
00085           && ACE_OS::strchr (argv_p[i], ACE_TEXT (' ')) != 0)
00086         {
00087           if (argv_p == argv)
00088             {
00089               argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
00090               if (argv_p == 0)
00091                 {
00092                   errno = ENOMEM;
00093                   return 0;
00094                 }
00095               ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
00096             }
00097           int quotes = 0;
00098           ACE_TCHAR *temp = argv_p[i];
00099           if (ACE_OS::strchr (temp, ACE_TEXT ('"')) != 0)
00100             {
00101               for (int j = 0; temp[j] != 0; ++j)
00102                 if (temp[j] == ACE_TEXT ('"'))
00103                   ++quotes;
00104             }
00105           argv_p[i] =
00106             (ACE_TCHAR *) ACE_OS::malloc (ACE_OS::strlen (temp) * sizeof (ACE_TCHAR) + quotes + 3);
00107           if (argv_p[i] == 0)
00108             {
00109               ACE_OS::free (argv_p);
00110               errno = ENOMEM;
00111               return 0;
00112             }
00113           ACE_TCHAR *end = argv_p[i];
00114 
00115           *end++ = ACE_TEXT ('"');
00116 
00117           if (quotes > 0)
00118             {
00119               for (ACE_TCHAR *p = temp;
00120                    *p != 0;
00121                    *end++ = *p++)
00122                 if (*p == ACE_TEXT ('"'))
00123                   *end++ = ACE_TEXT ('\\');
00124 
00125               *end++ = ACE_TEXT ('\0');
00126             }
00127           else
00128             end = ACE_OS::strecpy (end, temp);
00129 
00130           end[-1] = ACE_TEXT ('"');
00131 
00132           *end = ACE_TEXT ('\0');
00133           if (temp != argv[i])
00134             ACE_OS::free (temp);
00135         }
00136       buf_len += ACE_OS::strlen (argv_p[i]);
00137 
00138       // Add one for the extra space between each string.
00139       buf_len++;
00140     }
00141 
00142   // Step through all argv params and copy each one into buf; separate
00143   // each param with white space.
00144 
00145   ACE_NEW_RETURN (buf,
00146                   ACE_TCHAR[buf_len + 1],
00147                   0);
00148 
00149   // Initial null charater to make it a null string.
00150   buf[0] = ACE_TEXT ('\0');
00151   ACE_TCHAR *end = buf;
00152 
00153   for (int i = 0; i < argc; ++i)
00154     {
00155       end = ACE_OS::strecpy (end, argv_p[i]);
00156       if (argv_p[i] != argv[i])
00157         ACE_OS::free (argv_p[i]);
00158 
00159       // Replace the null char that strecpy put there with white
00160       // space.
00161       end[-1] = ACE_TEXT (' ');
00162     }
00163   // Null terminate the string.
00164   *end = ACE_TEXT ('\0');
00165 
00166   if (argv_p != argv)
00167     ACE_OS::free (argv_p);
00168 
00169   // The number of arguments.
00170   return argc;
00171 }
00172 
00173 int
00174 ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...)
00175 {
00176   ACE_OS_TRACE ("ACE_OS::execl");
00177   ACE_NOTSUP_RETURN (-1);
00178   // Need to write this code.
00179   // ACE_OSCALL_RETURN (::execv (path, argv), int, -1);
00180 }
00181 
00182 int
00183 ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...)
00184 {
00185   ACE_OS_TRACE ("ACE_OS::execle");
00186   ACE_NOTSUP_RETURN (-1);
00187   // Need to write this code.
00188   //  ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1);
00189 }
00190 
00191 int
00192 ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...)
00193 {
00194   ACE_OS_TRACE ("ACE_OS::execlp");
00195   ACE_NOTSUP_RETURN (-1);
00196   // Need to write this code.
00197   //  ACE_OSCALL_RETURN (::execvp (file, argv), int, -1);
00198 }
00199 
00200 pid_t
00201 ACE_OS::fork (const ACE_TCHAR *program_name)
00202 {
00203   ACE_OS_TRACE ("ACE_OS::fork");
00204 # if defined (ACE_LACKS_FORK)
00205   ACE_UNUSED_ARG (program_name);
00206   ACE_NOTSUP_RETURN (pid_t (-1));
00207 # else
00208   pid_t const pid =
00209 # if defined (ACE_HAS_STHREADS)
00210     ::fork1 ();
00211 #else
00212     ::fork ();
00213 #endif /* ACE_HAS_STHREADS */
00214 
00215 #if !defined (ACE_HAS_MINIMAL_ACE_OS)
00216   if (pid == 0)
00217     ACE_Base_Thread_Adapter::sync_log_msg (program_name);
00218 #endif /* ! ACE_HAS_MINIMAL_ACE_OS */
00219 
00220   return pid;
00221 # endif /* ACE_WIN32 */
00222 }
00223 
00224 // Create a contiguous command-line argument buffer with each arg
00225 // separated by spaces.
00226 
00227 pid_t
00228 ACE_OS::fork_exec (ACE_TCHAR *argv[])
00229 {
00230 # if defined (ACE_WIN32)
00231 
00232   ACE_TCHAR *buf = 0;
00233   ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_ptr (buf);
00234   if (ACE_OS::argv_to_string (argv, buf) != -1)
00235     {
00236       PROCESS_INFORMATION process_info;
00237 #   if !defined (ACE_HAS_WINCE)
00238       ACE_TEXT_STARTUPINFO startup_info;
00239       ACE_OS::memset ((void *) &startup_info,
00240                       0,
00241                       sizeof startup_info);
00242       startup_info.cb = sizeof startup_info;
00243 
00244       if (ACE_TEXT_CreateProcess (0,
00245                                   buf,
00246                                   0, // No process attributes.
00247                                   0,  // No thread attributes.
00248                                   TRUE, // Allow handle inheritance.
00249                                   0, // Don't create a new console window.
00250                                   0, // No environment.
00251                                   0, // No current directory.
00252                                   &startup_info,
00253                                   &process_info))
00254 #   else
00255       if (ACE_TEXT_CreateProcess (0,
00256                                   buf,
00257                                   0, // No process attributes.
00258                                   0,  // No thread attributes.
00259                                   FALSE, // Can's inherit handles on CE
00260                                   0, // Don't create a new console window.
00261                                   0, // No environment.
00262                                   0, // No current directory.
00263                                   0, // Can't use startup info on CE
00264                                   &process_info))
00265 #   endif /* ! ACE_HAS_WINCE */
00266         {
00267           // Free resources allocated in kernel.
00268           ACE_OS::close (process_info.hThread);
00269           ACE_OS::close (process_info.hProcess);
00270           // Return new process id.
00271           return process_info.dwProcessId;
00272         }
00273     }
00274 
00275   // CreateProcess failed.
00276   return -1;
00277 # else
00278       pid_t const result = ACE_OS::fork ();
00279 
00280 #   if defined (ACE_USES_WCHAR)
00281       // Wide-char builds need to convert the command-line args to
00282       // narrow char strings for execv ().
00283       char **cargv = 0;
00284       int arg_count;
00285 #   endif /* ACE_HAS_WCHAR */
00286 
00287       switch (result)
00288         {
00289         case -1:
00290           // Error.
00291           return -1;
00292         case 0:
00293           // Child process.
00294 #   if defined (ACE_USES_WCHAR)
00295           for (arg_count = 0; argv[arg_count] != 0; ++arg_count)
00296             ;
00297           ++arg_count;    // Need a 0-pointer end-of-array marker
00298           ACE_NEW_NORETURN (cargv, char*[arg_count]);
00299           if (cargv == 0)
00300             ACE_OS::exit (errno);
00301           --arg_count;    // Back to 0-indexed
00302           cargv[arg_count] = 0;
00303           while (--arg_count >= 0)
00304             cargv[arg_count] = ACE_Wide_To_Ascii::convert (argv[arg_count]);
00305           // Don't worry about freeing the cargv or the strings it points to.
00306           // Either the process will be replaced, or we'll exit.
00307           if (ACE_OS::execv (cargv[0], cargv) == -1)
00308             ACE_OS::exit (errno);
00309 #   else
00310           if (ACE_OS::execv (argv[0], argv) == -1)
00311             {
00312               // The OS layer should not print stuff out
00313               // ACE_ERROR ((LM_ERROR,
00314               //             "%p Exec failed\n"));
00315 
00316               // If the execv fails, this child needs to exit.
00317               ACE_OS::exit (errno);
00318             }
00319 #   endif /* ACE_HAS_WCHAR */
00320 
00321         default:
00322           // Server process.  The fork succeeded.
00323           return result;
00324         }
00325 # endif /* ACE_WIN32 */
00326 }
00327 
00328 long
00329 ACE_OS::num_processors (void)
00330 {
00331   ACE_OS_TRACE ("ACE_OS::num_processors");
00332 
00333 #if defined (ACE_HAS_PHARLAP)
00334   return 1;
00335 #elif defined (ACE_WIN32)
00336   SYSTEM_INFO sys_info;
00337   ::GetSystemInfo (&sys_info);
00338   return sys_info.dwNumberOfProcessors;
00339 #elif defined (_SC_NPROCESSORS_CONF)
00340   return ::sysconf (_SC_NPROCESSORS_CONF);
00341 #elif defined (ACE_HAS_SYSCTL)
00342   int num_processors;
00343   int mib[2] = { CTL_HW, HW_NCPU };
00344   size_t len = sizeof (num_processors);
00345   if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
00346     return num_processors;
00347   else
00348     return -1;
00349 #elif defined (__hpux)
00350   struct pst_dynamic psd;
00351   if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
00352     return psd.psd_max_proc_cnt;
00353   else
00354     return -1;
00355 #else
00356   ACE_NOTSUP_RETURN (-1);
00357 #endif
00358 }
00359 
00360 long
00361 ACE_OS::num_processors_online (void)
00362 {
00363   ACE_OS_TRACE ("ACE_OS::num_processors_online");
00364 
00365 #if defined (ACE_HAS_PHARLAP)
00366   return 1;
00367 #elif defined (ACE_WIN32)
00368   SYSTEM_INFO sys_info;
00369   ::GetSystemInfo (&sys_info);
00370   return sys_info.dwNumberOfProcessors;
00371 #elif defined (_SC_NPROCESSORS_ONLN)
00372   return ::sysconf (_SC_NPROCESSORS_ONLN);
00373 #elif defined (ACE_HAS_SYSCTL)
00374   int num_processors;
00375   int mib[2] = { CTL_HW, HW_NCPU };
00376   size_t len = sizeof (num_processors);
00377   if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
00378     return num_processors;
00379   else
00380     return -1;
00381 #elif defined (__hpux)
00382   struct pst_dynamic psd;
00383   if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
00384     return psd.psd_proc_cnt;
00385   else
00386     return -1;
00387 #else
00388   ACE_NOTSUP_RETURN (-1);
00389 #endif
00390 }
00391 
00392 ssize_t
00393 ACE_OS::read_n (ACE_HANDLE handle,
00394                 void *buf,
00395                 size_t len,
00396                 size_t *bt)
00397 {
00398   size_t temp;
00399   size_t &bytes_transferred = bt == 0 ? temp : *bt;
00400   ssize_t n = 0;
00401 
00402   for (bytes_transferred = 0;
00403        bytes_transferred < len;
00404        bytes_transferred += n)
00405     {
00406       n = ACE_OS::read (handle,
00407                         (char *) buf + bytes_transferred,
00408                         len - bytes_transferred);
00409 
00410       if (n == -1 || n == 0)
00411         return n;
00412     }
00413 
00414   return bytes_transferred;
00415 }
00416 
00417 ssize_t
00418 ACE_OS::pread (ACE_HANDLE handle,
00419                void *buf,
00420                size_t nbytes,
00421                ACE_OFF_T offset)
00422 {
00423 # if defined (ACE_HAS_P_READ_WRITE)
00424 #   if defined (ACE_WIN32)
00425 
00426   ACE_OS_GUARD
00427 
00428   // Remember the original file pointer position
00429   LONG original_high_position = 0;
00430   DWORD original_low_position = ::SetFilePointer (handle,
00431                                                   0,
00432                                                   &original_high_position,
00433                                                   FILE_CURRENT);
00434 
00435   if (original_low_position == INVALID_SET_FILE_POINTER
00436       && GetLastError () != NO_ERROR)
00437     return -1;
00438 
00439   // Go to the correct position
00440   LONG low_offset = ACE_LOW_PART (offset);
00441   LONG high_offset = ACE_HIGH_PART (offset);
00442   DWORD altered_position = ::SetFilePointer (handle,
00443                                              low_offset,
00444                                              &high_offset,
00445                                              FILE_BEGIN);
00446   if (altered_position == INVALID_SET_FILE_POINTER
00447       && GetLastError () != NO_ERROR)
00448     return -1;
00449 
00450   DWORD bytes_read;
00451 
00452 #     if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
00453 
00454   OVERLAPPED overlapped;
00455   overlapped.Internal = 0;
00456   overlapped.InternalHigh = 0;
00457   overlapped.Offset = low_offset;
00458   overlapped.OffsetHigh = high_offset;
00459   overlapped.hEvent = 0;
00460 
00461   BOOL result = ::ReadFile (handle,
00462                             buf,
00463                             static_cast <DWORD> (nbytes),
00464                             &bytes_read,
00465                             &overlapped);
00466 
00467   if (result == FALSE)
00468     {
00469       if (::GetLastError () != ERROR_IO_PENDING)
00470         return -1;
00471 
00472       else
00473         {
00474           result = ::GetOverlappedResult (handle,
00475                                           &overlapped,
00476                                           &bytes_read,
00477                                           TRUE);
00478           if (result == FALSE)
00479             return -1;
00480         }
00481     }
00482 
00483 #     else /* ACE_HAS_WIN32_OVERLAPPED_IO */
00484 
00485   BOOL result = ::ReadFile (handle,
00486                             buf,
00487                             nbytes,
00488                             &bytes_read,
00489                             0);
00490   if (result == FALSE)
00491     return -1;
00492 
00493 #     endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
00494 
00495   // Reset the original file pointer position
00496   if (::SetFilePointer (handle,
00497                         original_low_position,
00498                         &original_high_position,
00499                         FILE_BEGIN) == INVALID_SET_FILE_POINTER
00500       && GetLastError () != NO_ERROR)
00501     return -1;
00502 
00503   return (ssize_t) bytes_read;
00504 
00505 #   else /* ACE_WIN32 */
00506 
00507   return ::pread (handle, buf, nbytes, offset);
00508 
00509 #   endif /* ACE_WIN32 */
00510 
00511 # else /* ACE_HAS_P_READ_WRITE */
00512 
00513   ACE_OS_GUARD
00514 
00515   // Remember the original file pointer position
00516   ACE_OFF_T original_position = ACE_OS::lseek (handle,
00517                                                0,
00518                                                SEEK_CUR);
00519 
00520   if (original_position == -1)
00521     return -1;
00522 
00523   // Go to the correct position
00524   ACE_OFF_T altered_position = ACE_OS::lseek (handle, offset, SEEK_SET);
00525 
00526   if (altered_position == -1)
00527     return -1;
00528 
00529   ssize_t const bytes_read = ACE_OS::read (handle, buf, nbytes);
00530 
00531   if (bytes_read == -1)
00532     return -1;
00533 
00534   if (ACE_OS::lseek (handle,
00535                      original_position,
00536                      SEEK_SET) == -1)
00537     return -1;
00538 
00539   return bytes_read;
00540 
00541 # endif /* ACE_HAD_P_READ_WRITE */
00542 }
00543 
00544 ssize_t
00545 ACE_OS::pwrite (ACE_HANDLE handle,
00546                 const void *buf,
00547                 size_t nbytes,
00548                 ACE_OFF_T offset)
00549 {
00550 # if defined (ACE_HAS_P_READ_WRITE)
00551 #   if defined (ACE_WIN32)
00552 
00553   ACE_OS_GUARD
00554 
00555   // Remember the original file pointer position
00556   LARGE_INTEGER orig_position;
00557   orig_position.QuadPart = 0;
00558   orig_position.LowPart = ::SetFilePointer (handle,
00559                                             0,
00560                                             &orig_position.HighPart,
00561                                             FILE_CURRENT);
00562   if (orig_position.LowPart == INVALID_SET_FILE_POINTER
00563       && GetLastError () != NO_ERROR)
00564     return -1;
00565 
00566   DWORD bytes_written;
00567   LARGE_INTEGER loffset;
00568   loffset.QuadPart = offset;
00569 
00570 #     if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
00571 
00572   OVERLAPPED overlapped;
00573   overlapped.Internal = 0;
00574   overlapped.InternalHigh = 0;
00575   overlapped.Offset = loffset.LowPart;
00576   overlapped.OffsetHigh = loffset.HighPart;
00577   overlapped.hEvent = 0;
00578 
00579   BOOL result = ::WriteFile (handle,
00580                              buf,
00581                              static_cast <DWORD> (nbytes),
00582                              &bytes_written,
00583                              &overlapped);
00584 
00585   if (result == FALSE)
00586     {
00587       if (::GetLastError () != ERROR_IO_PENDING)
00588         return -1;
00589 
00590       result = ::GetOverlappedResult (handle,
00591                                       &overlapped,
00592                                       &bytes_written,
00593                                       TRUE);
00594       if (result == FALSE)
00595         return -1;
00596     }
00597 
00598 #     else /* ACE_HAS_WIN32_OVERLAPPED_IO */
00599 
00600   // Go to the correct position; if this is a Windows variant without
00601   // overlapped I/O, it probably doesn't have SetFilePointerEx either,
00602   // so manage this with SetFilePointer, changing calls based on the use
00603   // of 64 bit offsets.
00604   DWORD newpos;
00605 #       if defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
00606   newpos = ::SetFilePointer (handle,
00607                              loffset.LowPart,
00608                              &loffset.HighPart,
00609                              FILE_BEGIN);
00610 #       else
00611   newpos = ::SetFilePointer (handle,
00612                              loffset.LowPart,
00613                              0,
00614                              FILE_BEGIN);
00615 #       endif /* 64-bit file offsets */
00616   if (newpos == 0xFFFFFFFF && ::GetLastError () != NO_ERROR)
00617     {
00618       ACE_OS::set_errno_to_last_error ();
00619       return -1;
00620     }
00621 
00622   BOOL result = ::WriteFile (handle,
00623                              buf,
00624                              nbytes,
00625                              &bytes_written,
00626                              0);
00627   if (result == FALSE)
00628     return -1;
00629 
00630 #     endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
00631 
00632   // Reset the original file pointer position
00633   if (::SetFilePointer (handle,
00634                         orig_position.LowPart,
00635                         &orig_position.HighPart,
00636                         FILE_BEGIN) == INVALID_SET_FILE_POINTER
00637       && GetLastError () != NO_ERROR)
00638     return -1;
00639 
00640   return (ssize_t) bytes_written;
00641 
00642 #   else /* ACE_WIN32 */
00643 
00644   return ::pwrite (handle, buf, nbytes, offset);
00645 #   endif /* ACE_WIN32 */
00646 # else /* ACE_HAS_P_READ_WRITE */
00647 
00648   ACE_OS_GUARD
00649 
00650   // Remember the original file pointer position
00651   ACE_OFF_T original_position = ACE_OS::lseek (handle,
00652                                                0,
00653                                                SEEK_CUR);
00654   if (original_position == -1)
00655     return -1;
00656 
00657   // Go to the correct position
00658   ACE_OFF_T altered_position = ACE_OS::lseek (handle,
00659                                               offset,
00660                                               SEEK_SET);
00661   if (altered_position == -1)
00662     return -1;
00663 
00664   ssize_t const bytes_written = ACE_OS::write (handle,
00665                                                buf,
00666                                                nbytes);
00667   if (bytes_written == -1)
00668     return -1;
00669 
00670   if (ACE_OS::lseek (handle,
00671                      original_position,
00672                      SEEK_SET) == -1)
00673     return -1;
00674 
00675   return bytes_written;
00676 # endif /* ACE_HAS_P_READ_WRITE */
00677 }
00678 
00679 int
00680 ACE_OS::string_to_argv (ACE_TCHAR *buf,
00681                         int &argc,
00682                         ACE_TCHAR **&argv,
00683                         bool substitute_env_args)
00684 {
00685   // Reset the number of arguments
00686   argc = 0;
00687 
00688   if (buf == 0)
00689     return -1;
00690 
00691   ACE_TCHAR *cp = buf;
00692 
00693   // First pass: count arguments.
00694 
00695   // '#' is the start-comment token..
00696   while (*cp != ACE_TEXT ('\0') && *cp != ACE_TEXT ('#'))
00697     {
00698       // Skip whitespace..
00699       while (ACE_OS::ace_isspace (*cp))
00700         ++cp;
00701 
00702       // Increment count and move to next whitespace..
00703       if (*cp != ACE_TEXT ('\0'))
00704         ++argc;
00705 
00706       while (*cp != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*cp))
00707         {
00708           // Grok quotes....
00709           if (*cp == ACE_TEXT ('\'') || *cp == ACE_TEXT ('"'))
00710             {
00711               ACE_TCHAR quote = *cp;
00712 
00713               // Scan past the string..
00714               for (++cp; *cp != ACE_TEXT ('\0')
00715                    && (*cp != quote || cp[-1] == ACE_TEXT ('\\')); ++cp)
00716                 continue;
00717 
00718               // '\0' implies unmatched quote..
00719               if (*cp == ACE_TEXT ('\0'))
00720                 {
00721                   --argc;
00722                   break;
00723                 }
00724               else
00725                 ++cp;
00726             }
00727           else
00728             ++cp;
00729         }
00730     }
00731 
00732   // Second pass: copy arguments.
00733   ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
00734   ACE_TCHAR *argp = arg;
00735 
00736   // Make sure that the buffer we're copying into is always large
00737   // enough.
00738   if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
00739     ACE_NEW_RETURN (argp,
00740                     ACE_TCHAR[cp - buf + 1],
00741                     -1);
00742 
00743   // Make a new argv vector of argc + 1 elements.
00744   ACE_NEW_RETURN (argv,
00745                   ACE_TCHAR *[argc + 1],
00746                   -1);
00747 
00748   ACE_TCHAR *ptr = buf;
00749 
00750   for (int i = 0; i < argc; ++i)
00751     {
00752       // Skip whitespace..
00753       while (ACE_OS::ace_isspace (*ptr))
00754         ++ptr;
00755 
00756       // Copy next argument and move to next whitespace..
00757       cp = argp;
00758       while (*ptr != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*ptr))
00759         if (*ptr == ACE_TEXT ('\'') || *ptr == ACE_TEXT ('"'))
00760           {
00761             ACE_TCHAR quote = *ptr++;
00762 
00763             while (*ptr != ACE_TEXT ('\0')
00764                    && (*ptr != quote || ptr[-1] == ACE_TEXT ('\\')))
00765               {
00766                 if (*ptr == quote && ptr[-1] == ACE_TEXT ('\\')) --cp;
00767                 *cp++ = *ptr++;
00768               }
00769 
00770             if (*ptr == quote)
00771               ++ptr;
00772           }
00773         else
00774           *cp++ = *ptr++;
00775 
00776       *cp = ACE_TEXT ('\0');
00777 
00778 #if !defined (ACE_LACKS_ENV)
00779       // Check for environment variable substitution here.
00780       if (substitute_env_args) {
00781           argv[i] = ACE_OS::strenvdup (argp);
00782 
00783           if (argv[i] == 0)
00784             {
00785               if (argp != arg)
00786                 delete [] argp;
00787               errno = ENOMEM;
00788               return -1;
00789             }
00790       }
00791       else
00792 #endif /* ACE_LACKS_ENV */
00793         {
00794           argv[i] = ACE_OS::strdup (argp);
00795 
00796           if (argv[i] == 0)
00797             {
00798               if (argp != arg)
00799                 delete [] argp;
00800               errno = ENOMEM;
00801               return -1;
00802             }
00803         }
00804     }
00805 
00806   if (argp != arg)
00807     delete [] argp;
00808 
00809   argv[argc] = 0;
00810   return 0;
00811 }
00812 
00813 // Write <len> bytes from <buf> to <handle> (uses the <write>
00814 // system call on UNIX and the <WriteFile> call on Win32).
00815 
00816 ssize_t
00817 ACE_OS::write_n (ACE_HANDLE handle,
00818                  const void *buf,
00819                  size_t len,
00820                  size_t *bt)
00821 {
00822   size_t temp;
00823   size_t &bytes_transferred = bt == 0 ? temp : *bt;
00824   ssize_t n;
00825 
00826   for (bytes_transferred = 0;
00827        bytes_transferred < len;
00828        bytes_transferred += n)
00829     {
00830       n = ACE_OS::write (handle,
00831                          (char *) buf + bytes_transferred,
00832                          len - bytes_transferred);
00833 
00834       if (n == -1 || n == 0)
00835         return n;
00836     }
00837 
00838   return bytes_transferred;
00839 }
00840 
00841 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 12:05:34 2008 for ACE by doxygen 1.3.6