Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / OS_NS_unistd.cpp
blob145a34d3b43376bdb07b904d089ff4a173577514
1 #include "ace/OS_NS_unistd.h"
3 #if !defined (ACE_HAS_INLINED_OSCALLS)
4 # include "ace/OS_NS_unistd.inl"
5 #endif /* ACE_HAS_INLINED_OSCALLS */
7 #include "ace/Base_Thread_Adapter.h"
8 #include "ace/OS_NS_stdlib.h"
9 #include "ace/OS_NS_ctype.h"
10 #include "ace/Default_Constants.h"
11 #include "ace/OS_Memory.h"
12 #include "ace/OS_NS_Thread.h"
13 #include "ace/Object_Manager_Base.h"
14 #if defined (ACE_HAS_SYSCTL)
15 # include "ace/os_include/sys/os_sysctl.h"
16 #endif /* ACE_HAS_SYSCTL */
18 #if defined ACE_HAS_VXCPULIB
19 # include "vxCpuLib.h"
20 # include "cpuset.h"
21 #endif /* ACE_HAS_VXCPULIB */
23 #include <memory>
25 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
27 int
28 ACE_OS::argv_to_string (ACE_TCHAR **argv,
29 ACE_TCHAR *&buf,
30 bool substitute_env_args,
31 bool quote_args)
33 if (argv == 0 || argv[0] == 0)
34 return 0;
36 int argc;
37 for (argc = 0; argv[argc] != 0; ++argc)
38 continue;
40 return argv_to_string (argc,
41 argv,
42 buf,
43 substitute_env_args,
44 quote_args);
47 int
48 ACE_OS::argv_to_string (int argc,
49 ACE_TCHAR **argv,
50 ACE_TCHAR *&buf,
51 bool substitute_env_args,
52 bool quote_args)
54 if (argc <= 0 || argv == 0 || argv[0] == 0)
55 return 0;
57 size_t buf_len = 0;
59 // Determine the length of the buffer.
61 ACE_TCHAR **argv_p = argv;
63 for (int i = 0; i < argc; ++i)
65 // Account for environment variables.
66 if (substitute_env_args
67 && ACE_OS::strchr (argv[i], ACE_TEXT ('$')) != 0)
69 if (argv_p == argv)
71 #if defined (ACE_HAS_ALLOC_HOOKS)
72 argv_p = (ACE_TCHAR **) ACE_Allocator::instance()->malloc (argc * sizeof (ACE_TCHAR *));
73 #else
74 argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
75 #endif /* ACE_HAS_ALLOC_HOOKS */
76 if (argv_p == 0)
78 errno = ENOMEM;
79 return 0;
81 ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
83 argv_p[i] = ACE_OS::strenvdup (argv[i]);
84 if (argv_p[i] == 0)
86 #if defined (ACE_HAS_ALLOC_HOOKS)
87 ACE_Allocator::instance()->free (argv_p);
88 #else
89 ACE_OS::free (argv_p);
90 #endif /* ACE_HAS_ALLOC_HOOKS */
91 errno = ENOMEM;
92 return 0;
95 // If must quote, we only do it if the arg contains spaces, or
96 // is empty. Perhaps a check for other c | ord(c) <= 32 is in
97 // order?
98 if (quote_args
99 && (ACE_OS::strchr (argv_p[i], ACE_TEXT (' ')) != 0
100 || ACE_OS::strchr (argv_p[i], ACE_TEXT ('\t')) != 0
101 || ACE_OS::strchr (argv_p[i], ACE_TEXT ('\n')) != 0
102 || *argv_p[i] == 0))
104 if (argv_p == argv)
106 #if defined (ACE_HAS_ALLOC_HOOKS)
107 argv_p = (ACE_TCHAR **) ACE_Allocator::instance()->malloc (argc * sizeof (ACE_TCHAR *));
108 #else
109 argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
110 #endif /* ACE_HAS_ALLOC_HOOKS */
111 if (argv_p == 0)
113 errno = ENOMEM;
114 return 0;
116 ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
118 int quotes = 0;
119 ACE_TCHAR *temp = argv_p[i];
120 if (ACE_OS::strchr (temp, ACE_TEXT ('"')) != 0)
122 for (int j = 0; temp[j] != 0; ++j)
123 if (temp[j] == ACE_TEXT ('"'))
124 ++quotes;
126 argv_p[i] =
127 #if defined (ACE_HAS_ALLOC_HOOKS)
128 (ACE_TCHAR *) ACE_Allocator::instance()->malloc ((ACE_OS::strlen (temp) + quotes + 3)
129 * sizeof (ACE_TCHAR));
130 #else
131 (ACE_TCHAR *) ACE_OS::malloc ((ACE_OS::strlen (temp) + quotes + 3)
132 * sizeof (ACE_TCHAR));
133 #endif /* ACE_HAS_ALLOC_HOOKS */
134 if (argv_p[i] == 0)
136 #if defined (ACE_HAS_ALLOC_HOOKS)
137 ACE_Allocator::instance()->free (argv_p);
138 #else
139 ACE_OS::free (argv_p);
140 #endif /* ACE_HAS_ALLOC_HOOKS */
141 errno = ENOMEM;
142 return 0;
144 ACE_TCHAR *end = argv_p[i];
146 *end++ = ACE_TEXT ('"');
148 if (quotes > 0)
150 for (ACE_TCHAR *p = temp;
151 *p != 0;
152 *end++ = *p++)
153 if (*p == ACE_TEXT ('"'))
154 *end++ = ACE_TEXT ('\\');
156 *end++ = ACE_TEXT ('\0');
158 else
159 end = ACE_OS::strecpy (end, temp);
161 end[-1] = ACE_TEXT ('"');
163 *end = ACE_TEXT ('\0');
164 if (temp != argv[i])
165 #if defined (ACE_HAS_ALLOC_HOOKS)
166 ACE_Allocator::instance()->free (temp);
167 #else
168 ACE_OS::free (temp);
169 #endif /* ACE_HAS_ALLOC_HOOKS */
171 buf_len += ACE_OS::strlen (argv_p[i]);
173 // Add one for the extra space between each string.
174 buf_len++;
177 // Step through all argv params and copy each one into buf; separate
178 // each param with white space.
180 #if defined (ACE_HAS_ALLOC_HOOKS)
181 ACE_ALLOCATOR_RETURN (buf,
182 static_cast<ACE_TCHAR*>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR) * (buf_len + 1))),
184 #else
185 ACE_NEW_RETURN (buf,
186 ACE_TCHAR[buf_len + 1],
188 #endif /* ACE_HAS_ALLOC_HOOKS */
190 // Initial null charater to make it a null string.
191 buf[0] = ACE_TEXT ('\0');
192 ACE_TCHAR *end = buf;
194 for (int i = 0; i < argc; ++i)
196 end = ACE_OS::strecpy (end, argv_p[i]);
197 if (argv_p[i] != argv[i])
198 #if defined (ACE_HAS_ALLOC_HOOKS)
199 ACE_Allocator::instance()->free (argv_p[i]);
200 #else
201 ACE_OS::free (argv_p[i]);
202 #endif /* ACE_HAS_ALLOC_HOOKS */
204 // Replace the null char that strecpy put there with white
205 // space.
206 end[-1] = ACE_TEXT (' ');
208 // Null terminate the string.
209 *end = ACE_TEXT ('\0');
211 if (argv_p != argv)
212 #if defined (ACE_HAS_ALLOC_HOOKS)
213 ACE_Allocator::instance()->free (argv_p);
214 #else
215 ACE_OS::free (argv_p);
216 #endif /* ACE_HAS_ALLOC_HOOKS */
218 // The number of arguments.
219 return argc;
223 ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...)
225 ACE_OS_TRACE ("ACE_OS::execl");
226 ACE_NOTSUP_RETURN (-1);
227 // Need to write this code.
228 // return ::execv (path, argv);
232 ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...)
234 ACE_OS_TRACE ("ACE_OS::execle");
235 ACE_NOTSUP_RETURN (-1);
236 // Need to write this code.
237 // return ::execve (path, argv, envp);
241 ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...)
243 ACE_OS_TRACE ("ACE_OS::execlp");
244 ACE_NOTSUP_RETURN (-1);
245 // Need to write this code.
246 // return ::execvp (file, argv);
249 pid_t
250 ACE_OS::fork (const ACE_TCHAR *program_name)
252 ACE_OS_TRACE ("ACE_OS::fork");
253 # if defined (ACE_LACKS_FORK)
254 ACE_UNUSED_ARG (program_name);
255 ACE_NOTSUP_RETURN (pid_t (-1));
256 # else
257 pid_t const pid = ::fork ();
259 #if !defined (ACE_HAS_MINIMAL_ACE_OS) && !defined (ACE_HAS_THREADS)
261 // ACE_Base_Thread_Adapter::sync_log_msg() is used to update the
262 // program name and process id in ACE's log framework. However, we
263 // can't invoke it from (the child process of) threaded programs
264 // because it calls async signal unsafe functions, which will result
265 // in undefined behavior (only async signal safe functions can be
266 // called after fork() until an exec()).
268 // This is no great loss. Using the ACE log framework in the child
269 // process will undoubtedly call async signal unsafe functions too.
270 // So it doesn't really matter that the program name and process id
271 // will not be updated.
273 if (pid == 0)
274 ACE_Base_Thread_Adapter::sync_log_msg (program_name);
276 #else
278 ACE_UNUSED_ARG (program_name);
280 #endif /* ! ACE_HAS_MINIMAL_ACE_OS && !ACE_HAS_THREADS */
282 return pid;
283 # endif /* ACE_WIN32 */
286 // Create a contiguous command-line argument buffer with each arg
287 // separated by spaces.
289 pid_t
290 ACE_OS::fork_exec (ACE_TCHAR *argv[])
292 # if defined (ACE_WIN32)
294 ACE_TCHAR *buf = 0;
295 std::unique_ptr<ACE_TCHAR[]> safe_ptr (buf);
296 if (ACE_OS::argv_to_string (argv, buf) != -1)
298 PROCESS_INFORMATION process_info;
299 ACE_TEXT_STARTUPINFO startup_info;
300 ACE_OS::memset ((void *) &startup_info,
302 sizeof startup_info);
303 startup_info.cb = sizeof startup_info;
305 if (ACE_TEXT_CreateProcess (0,
306 buf,
307 0, // No process attributes.
308 0, // No thread attributes.
309 TRUE, // Allow handle inheritance.
310 0, // Don't create a new console window.
311 0, // No environment.
312 0, // No current directory.
313 &startup_info,
314 &process_info))
316 // Free resources allocated in kernel.
317 ACE_OS::close (process_info.hThread);
318 ACE_OS::close (process_info.hProcess);
319 // Return new process id.
320 return process_info.dwProcessId;
324 // CreateProcess failed.
325 return -1;
326 # else
327 pid_t const result = ACE_OS::fork ();
329 # if defined (ACE_USES_WCHAR)
330 // Wide-char builds need to convert the command-line args to
331 // narrow char strings for execv ().
332 char **cargv = 0;
333 int arg_count;
334 # endif /* ACE_HAS_WCHAR */
336 switch (result)
338 case static_cast<pid_t>(-1):
339 // Error.
340 return -1;
341 case 0:
342 // Child process.
343 # if defined (ACE_USES_WCHAR)
344 for (arg_count = 0; argv[arg_count] != 0; ++arg_count)
346 ++arg_count; // Need a 0-pointer end-of-array marker
347 ACE_NEW_NORETURN (cargv, char*[arg_count]);
348 if (cargv == 0)
349 ACE_OS::exit (errno);
350 --arg_count; // Back to 0-indexed
351 cargv[arg_count] = 0;
352 while (--arg_count >= 0)
353 cargv[arg_count] = ACE_Wide_To_Ascii::convert (argv[arg_count]);
354 // Don't worry about freeing the cargv or the strings it points to.
355 // Either the process will be replaced, or we'll exit.
356 if (ACE_OS::execv (cargv[0], cargv) == -1)
357 ACE_OS::exit (errno);
358 # else
359 if (ACE_OS::execv (argv[0], argv) == -1)
361 // The OS layer should not print stuff out
362 // ACELIB_ERROR ((LM_ERROR,
363 // "%p Exec failed\n"));
365 // If the execv fails, this child needs to exit.
366 ACE_OS::exit (errno);
368 # endif /* ACE_HAS_WCHAR */
369 return result;
370 default:
371 // Server process. The fork succeeded.
372 return result;
374 # endif /* ACE_WIN32 */
377 long
378 ACE_OS::num_processors ()
380 ACE_OS_TRACE ("ACE_OS::num_processors");
382 #if defined (ACE_WIN32)
383 SYSTEM_INFO sys_info;
384 ::GetSystemInfo (&sys_info);
385 return sys_info.dwNumberOfProcessors;
386 #elif defined (ACE_HAS_VXCPULIB)
387 return vxCpuConfiguredGet();
388 #elif defined (_SC_NPROCESSORS_CONF)
389 return ::sysconf (_SC_NPROCESSORS_CONF);
390 #elif defined (ACE_HAS_SYSCTL)
391 int num_processors = 0;
392 int mib[2] = { CTL_HW, HW_NCPU };
393 size_t len = sizeof (num_processors);
394 if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
395 return num_processors;
396 else
397 return -1;
398 #else
399 ACE_NOTSUP_RETURN (-1);
400 #endif
403 long
404 ACE_OS::num_processors_online ()
406 ACE_OS_TRACE ("ACE_OS::num_processors_online");
408 #if defined (ACE_WIN32)
409 SYSTEM_INFO sys_info;
410 ::GetSystemInfo (&sys_info);
411 long active_processors = 0;
412 DWORD_PTR mask = sys_info.dwActiveProcessorMask;
413 while (mask != 0)
415 if (mask & 1)
416 ++active_processors;
417 mask >>= 1;
419 return active_processors;
420 #elif defined (ACE_HAS_VXCPULIB)
421 long num_cpu = 0;
422 cpuset_t cpuset;
423 CPUSET_ZERO (cpuset);
424 cpuset = vxCpuEnabledGet();
425 unsigned int const maxcpu = vxCpuConfiguredGet();
426 for (unsigned int i =0; i < maxcpu; i++)
428 if (CPUSET_ISSET (cpuset, i))
430 ++num_cpu;
433 return num_cpu;
434 #elif defined (_SC_NPROCESSORS_ONLN)
435 return ::sysconf (_SC_NPROCESSORS_ONLN);
436 #elif defined (ACE_HAS_SYSCTL)
437 int num_processors;
438 int mib[2] = { CTL_HW, HW_NCPU };
439 size_t len = sizeof (num_processors);
440 if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
441 return num_processors;
442 else
443 return -1;
444 #else
445 ACE_NOTSUP_RETURN (-1);
446 #endif
449 ssize_t
450 ACE_OS::read_n (ACE_HANDLE handle,
451 void *buf,
452 size_t len,
453 size_t *bt)
455 size_t temp;
456 size_t &bytes_transferred = bt == 0 ? temp : *bt;
457 ssize_t n = 0;
459 for (bytes_transferred = 0;
460 bytes_transferred < len;
461 bytes_transferred += n)
463 n = ACE_OS::read (handle,
464 (char *) buf + bytes_transferred,
465 len - bytes_transferred);
467 if (n == -1 || n == 0)
469 return n;
473 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
476 ssize_t
477 ACE_OS::pread (ACE_HANDLE handle,
478 void *buf,
479 size_t nbytes,
480 ACE_OFF_T offset)
482 # if defined (ACE_HAS_P_READ_WRITE)
483 # if defined (ACE_WIN32)
485 ACE_OS_GUARD
487 // Remember the original file pointer position
488 LONG original_high_position = 0;
489 DWORD original_low_position = ::SetFilePointer (handle,
491 &original_high_position,
492 FILE_CURRENT);
494 if (original_low_position == INVALID_SET_FILE_POINTER
495 && GetLastError () != NO_ERROR)
497 ACE_OS::set_errno_to_last_error ();
498 return -1;
501 // Go to the correct position
502 LONG low_offset = ACE_LOW_PART (offset);
503 LONG high_offset = ACE_HIGH_PART (offset);
504 DWORD altered_position = ::SetFilePointer (handle,
505 low_offset,
506 &high_offset,
507 FILE_BEGIN);
508 if (altered_position == INVALID_SET_FILE_POINTER
509 && GetLastError () != NO_ERROR)
511 ACE_OS::set_errno_to_last_error ();
512 return -1;
515 DWORD bytes_read;
517 # if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
519 OVERLAPPED overlapped;
520 overlapped.Internal = 0;
521 overlapped.InternalHigh = 0;
522 overlapped.Offset = low_offset;
523 overlapped.OffsetHigh = high_offset;
524 overlapped.hEvent = 0;
526 BOOL result = ::ReadFile (handle,
527 buf,
528 static_cast <DWORD> (nbytes),
529 &bytes_read,
530 &overlapped);
532 if (result == FALSE)
534 if (::GetLastError () != ERROR_IO_PENDING)
535 return -1;
537 else
539 result = ::GetOverlappedResult (handle,
540 &overlapped,
541 &bytes_read,
542 TRUE);
543 if (result == FALSE)
544 return -1;
548 # else /* ACE_HAS_WIN32_OVERLAPPED_IO */
550 BOOL result = ::ReadFile (handle,
551 buf,
552 nbytes,
553 &bytes_read,
555 if (result == FALSE)
556 return -1;
558 # endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
560 // Reset the original file pointer position
561 if (::SetFilePointer (handle,
562 original_low_position,
563 &original_high_position,
564 FILE_BEGIN) == INVALID_SET_FILE_POINTER
565 && GetLastError () != NO_ERROR)
567 ACE_OS::set_errno_to_last_error ();
568 return -1;
571 return (ssize_t) bytes_read;
573 # else /* ACE_WIN32 */
575 return ::pread (handle, buf, nbytes, offset);
577 # endif /* ACE_WIN32 */
579 # else /* ACE_HAS_P_READ_WRITE */
581 ACE_OS_GUARD
583 // Remember the original file pointer position
584 ACE_OFF_T original_position = ACE_OS::lseek (handle,
586 SEEK_CUR);
588 if (original_position == -1)
589 return -1;
591 // Go to the correct position
592 ACE_OFF_T altered_position = ACE_OS::lseek (handle, offset, SEEK_SET);
594 if (altered_position == -1)
595 return -1;
597 ssize_t const bytes_read = ACE_OS::read (handle, buf, nbytes);
599 if (bytes_read == -1)
600 return -1;
602 if (ACE_OS::lseek (handle,
603 original_position,
604 SEEK_SET) == -1)
605 return -1;
607 return bytes_read;
609 # endif /* ACE_HAS_P_READ_WRITE */
612 ssize_t
613 ACE_OS::pwrite (ACE_HANDLE handle,
614 const void *buf,
615 size_t nbytes,
616 ACE_OFF_T offset)
618 # if defined (ACE_HAS_P_READ_WRITE)
619 # if defined (ACE_WIN32)
621 ACE_OS_GUARD
623 // Remember the original file pointer position
624 LONG original_high_position = 0;
625 DWORD original_low_position = ::SetFilePointer (handle,
627 &original_high_position,
628 FILE_CURRENT);
630 if (original_low_position == INVALID_SET_FILE_POINTER
631 && GetLastError () != NO_ERROR)
633 ACE_OS::set_errno_to_last_error ();
634 return -1;
637 DWORD bytes_written;
638 LONG low_offset = ACE_LOW_PART (offset);
639 LONG high_offset = ACE_HIGH_PART (offset);
641 # if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
643 OVERLAPPED overlapped;
644 overlapped.Internal = 0;
645 overlapped.InternalHigh = 0;
646 overlapped.Offset = low_offset;
647 overlapped.OffsetHigh = high_offset;
648 overlapped.hEvent = 0;
650 BOOL result = ::WriteFile (handle,
651 buf,
652 static_cast <DWORD> (nbytes),
653 &bytes_written,
654 &overlapped);
656 if (result == FALSE)
658 if (::GetLastError () != ERROR_IO_PENDING)
660 return -1;
662 else
664 result = ::GetOverlappedResult (handle,
665 &overlapped,
666 &bytes_written,
667 TRUE);
668 if (result == FALSE)
669 return -1;
673 # else /* ACE_HAS_WIN32_OVERLAPPED_IO */
675 if (::SetFilePointer (handle,
676 low_offset,
677 &high_offset,
678 FILE_BEGIN) == INVALID_SET_FILE_POINTER
679 && ::GetLastError () != NO_ERROR)
681 ACE_OS::set_errno_to_last_error ();
682 return -1;
685 BOOL result = ::WriteFile (handle,
686 buf,
687 nbytes,
688 &bytes_written,
690 if (result == FALSE)
691 return -1;
693 # endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
695 // Reset the original file pointer position
696 if (::SetFilePointer (handle,
697 original_low_position,
698 &original_high_position,
699 FILE_BEGIN) == INVALID_SET_FILE_POINTER
700 && GetLastError () != NO_ERROR)
702 ACE_OS::set_errno_to_last_error ();
703 return -1;
706 return (ssize_t) bytes_written;
708 # else /* ACE_WIN32 */
709 # if defined (ACE_HAS_NON_CONST_PWRITE)
710 return ::pwrite (handle, const_cast<void*> (buf), nbytes, offset);
711 # else
712 return ::pwrite (handle, buf, nbytes, offset);
713 # endif
714 # endif /* ACE_WIN32 */
715 # else /* ACE_HAS_P_READ_WRITE */
717 ACE_OS_GUARD
719 // Remember the original file pointer position
720 ACE_OFF_T original_position = ACE_OS::lseek (handle,
722 SEEK_CUR);
723 if (original_position == -1)
724 return -1;
726 // Go to the correct position
727 ACE_OFF_T altered_position = ACE_OS::lseek (handle,
728 offset,
729 SEEK_SET);
730 if (altered_position == -1)
731 return -1;
733 ssize_t const bytes_written = ACE_OS::write (handle,
734 buf,
735 nbytes);
736 if (bytes_written == -1)
737 return -1;
739 if (ACE_OS::lseek (handle,
740 original_position,
741 SEEK_SET) == -1)
742 return -1;
744 return bytes_written;
745 # endif /* ACE_HAS_P_READ_WRITE */
749 ACE_OS::string_to_argv (ACE_TCHAR *buf,
750 int &argc,
751 ACE_TCHAR **&argv,
752 bool substitute_env_args)
754 // Reset the number of arguments
755 argc = 0;
757 if (buf == 0)
758 return -1;
760 ACE_TCHAR *cp = buf;
762 // First pass: count arguments.
764 // '#' is the start-comment token..
765 while (*cp != ACE_TEXT ('\0') && *cp != ACE_TEXT ('#'))
767 // Skip whitespace..
768 while (ACE_OS::ace_isspace (*cp))
769 ++cp;
771 // Increment count and move to next whitespace..
772 if (*cp != ACE_TEXT ('\0'))
773 ++argc;
775 while (*cp != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*cp))
777 // Grok quotes....
778 if (*cp == ACE_TEXT ('\'') || *cp == ACE_TEXT ('"'))
780 ACE_TCHAR quote = *cp;
782 // Scan past the string..
783 for (++cp; *cp != ACE_TEXT ('\0')
784 && (*cp != quote || cp[-1] == ACE_TEXT ('\\')); ++cp)
785 continue;
787 // '\0' implies unmatched quote..
788 if (*cp == ACE_TEXT ('\0'))
790 --argc;
791 break;
793 else
794 ++cp;
796 else
797 ++cp;
801 // Second pass: copy arguments.
802 ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
803 ACE_TCHAR *argp = arg;
805 // Make sure that the buffer we're copying into is always large
806 // enough.
807 if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
808 #if defined (ACE_HAS_ALLOC_HOOKS)
809 ACE_ALLOCATOR_RETURN(argp,
810 static_cast<ACE_TCHAR *>(ACE_Allocator::instance()->malloc(sizeof (ACE_TCHAR) * (cp - buf + 1))),
811 -1);
812 #else
813 ACE_NEW_RETURN (argp,
814 ACE_TCHAR[cp - buf + 1],
815 -1);
816 #endif /* ACE_HAS_ALLOC_HOOKS */
818 // Make a new argv vector of argc + 1 elements.
819 #if defined (ACE_HAS_ALLOC_HOOKS)
820 ACE_ALLOCATOR_RETURN(argv,
821 static_cast<ACE_TCHAR **>(ACE_Allocator::instance()->malloc(sizeof (ACE_TCHAR*) * (argc + 1))),
822 -1);
823 #else
824 ACE_NEW_RETURN (argv,
825 ACE_TCHAR *[argc + 1],
826 -1);
827 #endif /* ACE_HAS_ALLOC_HOOKS */
829 ACE_TCHAR *ptr = buf;
831 for (int i = 0; i < argc; ++i)
833 // Skip whitespace..
834 while (ACE_OS::ace_isspace (*ptr))
835 ++ptr;
837 // Copy next argument and move to next whitespace..
838 cp = argp;
839 while (*ptr != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*ptr))
840 if (*ptr == ACE_TEXT ('\'') || *ptr == ACE_TEXT ('"'))
842 ACE_TCHAR quote = *ptr++;
844 while (*ptr != ACE_TEXT ('\0')
845 && (*ptr != quote || ptr[-1] == ACE_TEXT ('\\')))
847 if (*ptr == quote && ptr[-1] == ACE_TEXT ('\\')) --cp;
848 *cp++ = *ptr++;
851 if (*ptr == quote)
852 ++ptr;
854 else
855 *cp++ = *ptr++;
857 *cp = ACE_TEXT ('\0');
859 // Check for environment variable substitution here.
860 if (substitute_env_args) {
861 argv[i] = ACE_OS::strenvdup (argp);
863 if (argv[i] == 0)
865 if (argp != arg)
866 #if defined (ACE_HAS_ALLOC_HOOKS)
867 ACE_Allocator::instance()->free(argp);
868 #else
869 delete [] argp;
870 #endif /* ACE_HAS_ALLOC_HOOKS */
871 errno = ENOMEM;
872 return -1;
875 else
877 argv[i] = ACE_OS::strdup (argp);
879 if (argv[i] == 0)
881 if (argp != arg)
883 #if defined (ACE_HAS_ALLOC_HOOKS)
884 ACE_Allocator::instance()->free(argp);
885 #else
886 delete [] argp;
887 #endif /* ACE_HAS_ALLOC_HOOKS */
890 errno = ENOMEM;
891 return -1;
896 if (argp != arg)
898 #if defined (ACE_HAS_ALLOC_HOOKS)
899 ACE_Allocator::instance()->free(argp);
900 #else
901 delete [] argp;
902 #endif /* ACE_HAS_ALLOC_HOOKS */
905 argv[argc] = 0;
906 return 0;
909 // Write <len> bytes from <buf> to <handle> (uses the <write>
910 // system call on UNIX and the <WriteFile> call on Win32).
912 ssize_t
913 ACE_OS::write_n (ACE_HANDLE handle,
914 const void *buf,
915 size_t len,
916 size_t *bt)
918 size_t temp;
919 size_t &bytes_transferred = bt == 0 ? temp : *bt;
920 ssize_t n;
922 for (bytes_transferred = 0;
923 bytes_transferred < len;
924 bytes_transferred += n)
926 n = ACE_OS::write (handle,
927 (char *) buf + bytes_transferred,
928 len - bytes_transferred);
930 if (n == -1 || n == 0)
932 return n;
936 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
939 ACE_END_VERSIONED_NAMESPACE_DECL