Use override/default for RTPortableServer
[ACE_TAO.git] / ACE / ace / Process.cpp
blobafa7a0da98d5b818a888a2c7209a8e6db40af8a1
1 #include "ace/Process.h"
3 #if !defined (__ACE_INLINE__)
4 #include "ace/Process.inl"
5 #endif /* __ACE_INLINE__ */
7 #include "ace/ARGV.h"
8 #include "ace/Signal.h"
9 #include "ace/SString.h"
10 #include "ace/Log_Category.h"
11 #include "ace/OS_NS_stdio.h"
12 #include "ace/OS_NS_stdlib.h"
13 #include "ace/OS_NS_sys_socket.h"
14 #include "ace/OS_NS_errno.h"
15 #include "ace/OS_NS_string.h"
16 #include "ace/OS_NS_unistd.h"
17 #include "ace/OS_NS_fcntl.h"
18 #include "ace/OS_Memory.h"
19 #include "ace/Countdown_Time.h"
20 #include "ace/Truncate.h"
21 #include "ace/Vector_T.h"
22 #include "ace/Tokenizer_T.h"
24 #if defined (ACE_VXWORKS) && defined (__RTP__)
25 # include <rtpLib.h>
26 # include <taskLib.h>
27 #endif
29 #include <memory>
31 // This function acts as a signal handler for SIGCHLD. We don't really want
32 // to do anything with the signal - it's just needed to interrupt a sleep.
33 // See wait() for more info.
34 #if !defined (ACE_WIN32) && !defined(ACE_LACKS_UNIX_SIGNALS)
35 static void sigchld_nop (int, siginfo_t *, ucontext_t *)
37 return;
39 #endif /* ACE_WIN32 */
41 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
43 ACE_Process::ACE_Process ()
45 #if !defined (ACE_WIN32)
46 child_id_ (ACE_INVALID_PID),
47 #endif /* !defined (ACE_WIN32) */
48 exit_code_ (0)
50 #if defined (ACE_WIN32)
51 ACE_OS::memset ((void *) &this->process_info_,
53 sizeof this->process_info_);
54 #endif /* ACE_WIN32 */
57 ACE_Process::~ACE_Process ()
59 #if defined (ACE_WIN32)
60 // Free resources allocated in kernel.
61 ACE_OS::close (this->process_info_.hThread);
62 ACE_OS::close (this->process_info_.hProcess);
63 #endif /* ACE_WIN32 */
64 // If any handles were duplicated for the child process and
65 // still not closed, get them now.
66 this->close_dup_handles ();
69 int
70 ACE_Process::prepare (ACE_Process_Options &)
72 return 0;
75 pid_t
76 ACE_Process::spawn (ACE_Process_Options &options)
78 if (this->prepare (options) < 0)
79 return ACE_INVALID_PID;
81 // Stash the passed/duped handle sets away in this object for later
82 // closing if needed or requested. At the same time, figure out which
83 // ones to include in command line options if that's needed below.
84 ACE_Handle_Set *set_p = 0;
85 if (options.dup_handles (this->dup_handles_))
86 set_p = &this->dup_handles_;
87 else if (options.passed_handles (this->handles_passed_))
88 set_p = &this->handles_passed_;
90 // If we are going to end up running a new program (i.e. Win32, or
91 // NO_EXEC option is set) then get any handles passed in the options,
92 // and tack them onto the command line with +H <handle> options,
93 // unless the command line runs out of space.
94 // Note that we're using the knowledge that all the options, argvs, etc.
95 // passed to the options are all sitting in the command_line_buf. Any
96 // call to get the argv then splits them out. So, regardless of the
97 // platform, tack them all onto the command line buf and take it
98 // from there.
99 if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
100 ACE_Process_Options::NO_EXEC))
102 size_t max_len = 0;
103 ACE_TCHAR *cmd_line_buf = options.command_line_buf (&max_len);
104 size_t curr_len = ACE_OS::strlen (cmd_line_buf);
105 ACE_Handle_Set_Iterator h_iter (*set_p);
106 // Because the length of the to-be-formatted +H option is not
107 // known, and we don't have a snprintf, guess at the space
108 // needed (20 chars), and use that as a limit.
109 for (ACE_HANDLE h = h_iter ();
110 h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
111 h = h_iter ())
113 #if defined (ACE_WIN32)
114 # if defined (ACE_WIN64)
115 // silence warnings coming from MinGW64 compilers
116 # if defined (__GNUC__)
117 # pragma GCC diagnostic push
118 # pragma GCC diagnostic ignored "-Wformat"
119 # pragma GCC diagnostic ignored "-Wformat-extra-args"
120 # endif /* __GNUC__ */
121 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
122 ACE_TEXT (" +H %I64p"),
124 # if defined (__GNUC__)
125 # pragma GCC diagnostic pop
126 # endif /* __GNUC__ */
127 # else
128 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
129 ACE_TEXT (" +H %p"),
131 # endif /* ACE_WIN64 */
132 #else
133 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
134 ACE_TEXT (" +H %d"),
136 #endif /* ACE_WIN32 */
140 #if defined (ACE_WIN32)
141 void* env_buf = options.env_buf ();
142 DWORD flags = options.creation_flags ();
143 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
144 wchar_t* wenv_buf = 0;
145 if (options.use_unicode_environment ())
147 wenv_buf = this->convert_env_buffer (options.env_buf ());
148 env_buf = wenv_buf;
149 flags |= CREATE_UNICODE_ENVIRONMENT;
151 # endif
153 BOOL fork_result;
154 if (options.get_user_token () == ACE_INVALID_HANDLE)
156 fork_result = ACE_TEXT_CreateProcess (0,
157 options.command_line_buf (),
158 options.get_process_attributes (),
159 options.get_thread_attributes (),
160 options.handle_inheritance (),
161 flags,
162 env_buf, // environment variables
163 options.working_directory (),
164 options.startup_info (),
165 &this->process_info_);
167 else
169 fork_result = ACE_TEXT_CreateProcessAsUser (options.get_user_token (),
171 options.command_line_buf (),
172 options.get_process_attributes (),
173 options.get_thread_attributes (),
174 options.handle_inheritance (),
175 flags,
176 env_buf, // environment variables
177 options.working_directory (),
178 options.startup_info (),
179 &this->process_info_);
182 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
183 if (options.use_unicode_environment ())
184 delete wenv_buf;
185 # endif
187 if (fork_result)
189 parent (this->getpid ());
190 return this->getpid ();
192 return ACE_INVALID_PID;
193 #elif defined (ACE_VXWORKS) && defined (__RTP__)
194 if (ACE_BIT_ENABLED (options.creation_flags (),
195 ACE_Process_Options::NO_EXEC))
196 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
198 if (options.working_directory () != 0)
199 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
201 int saved_stdin = ACE_STDIN;
202 int saved_stdout = ACE_STDOUT;
203 int saved_stderr = ACE_STDERR;
204 // Save STD file descriptors and redirect
205 if (options.get_stdin () != ACE_INVALID_HANDLE) {
206 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
207 ACE_OS::exit (errno);
208 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
209 ACE_OS::exit (errno);
211 if (options.get_stdout () != ACE_INVALID_HANDLE) {
212 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
213 ACE_OS::exit (errno);
214 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
215 ACE_OS::exit (errno);
217 if (options.get_stderr () != ACE_INVALID_HANDLE) {
218 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
219 ACE_OS::exit (errno);
220 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
221 ACE_OS::exit (errno);
224 // Wide-char builds need narrow-char strings for commandline and
225 // environment variables.
226 # if defined (ACE_USES_WCHAR)
227 wchar_t * const *wargv = options.command_line_argv ();
228 size_t vcount, i;
229 for (vcount = 0; wargv[vcount] != 0; ++vcount)
231 char **procargv = new char *[vcount + 1]; // Need 0 at the end
232 procargv[vcount] = 0;
233 for (i = 0; i < vcount; ++i)
234 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
236 char **procenv = 0;
237 if (options.inherit_environment ())
239 wargv = options.env_argv ();
240 for (vcount = 0; wargv[vcount] != 0; ++vcount)
242 procenv = new char *[vcount + 1]; // Need 0 at the end
243 procenv[vcount] = 0;
244 for (i = 0; i < vcount; ++i)
245 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
247 # else
248 const char **procargv = const_cast<const char**> (options.command_line_argv ());
249 const char **procenv = const_cast<const char**> (options.env_argv ());
250 # endif /* ACE_USES_WCHAR */
252 this->child_id_ = ::rtpSpawn (procargv[0],
253 procargv,
254 procenv,
255 200, // priority
256 0x10000, // uStackSize
257 0, // options
258 VX_FP_TASK); // taskOptions
259 int my_errno_ = errno;
260 if (this->child_id_ == ERROR) {
261 // something went wrong
262 this->child_id_ = ACE_INVALID_PID;
265 # if defined (ACE_USES_WCHAR)
266 if (procenv)
267 delete [] procenv;
268 # endif /* ACE_USES_WCHAR */
270 // restore STD file descriptors (if necessary)
271 if (options.get_stdin () != ACE_INVALID_HANDLE) {
272 if (saved_stdin == -1)
273 ACE_OS::close (ACE_STDIN);
274 else
275 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
277 if (options.get_stdout () != ACE_INVALID_HANDLE) {
278 if (saved_stdout == -1)
279 ACE_OS::close (ACE_STDOUT);
280 else
281 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
283 if (options.get_stderr () != ACE_INVALID_HANDLE) {
284 if (saved_stderr == -1)
285 ACE_OS::close (ACE_STDERR);
286 else
287 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
290 if (this->child_id_ == ACE_INVALID_PID)
292 errno = my_errno_;
295 return this->child_id_;
296 #else /* ACE_WIN32 */
297 // Fork the new process.
298 this->child_id_ = ACE::fork (options.process_name (),
299 options.avoid_zombies ());
301 if (this->child_id_ == 0)
303 # if !defined (ACE_LACKS_SETPGID)
304 // If we're the child and the options specified a non-default
305 // process group, try to set our pgid to it. This allows the
306 // <ACE_Process_Manager> to wait for processes by their
307 // process-group.
308 if (options.getgroup () != ACE_INVALID_PID
309 && ACE_OS::setpgid (0,
310 options.getgroup ()) < 0)
312 #if !defined (ACE_HAS_THREADS)
313 // We can't emit this log message because ACELIB_ERROR(), etc.
314 // will invoke async signal unsafe functions, which results
315 // in undefined behavior in threaded programs.
316 ACELIB_ERROR ((LM_ERROR,
317 ACE_TEXT ("%p.\n"),
318 ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
319 #endif
321 # endif /* ACE_LACKS_SETPGID */
323 # if !defined (ACE_LACKS_SETREGID)
324 if (options.getrgid () != (gid_t) -1
325 || options.getegid () != (gid_t) -1)
326 if (ACE_OS::setregid (options.getrgid (),
327 options.getegid ()) == -1)
329 #if !defined (ACE_HAS_THREADS)
330 // We can't emit this log message because ACELIB_ERROR(), etc.
331 // will invoke async signal unsafe functions, which results
332 // in undefined behavior in threaded programs.
333 ACELIB_ERROR ((LM_ERROR,
334 ACE_TEXT ("%p.\n"),
335 ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
336 #endif
338 # endif /* ACE_LACKS_SETREGID */
340 # if !defined (ACE_LACKS_SETREUID)
341 // Set user and group id's.
342 if (options.getruid () != (uid_t) -1
343 || options.geteuid () != (uid_t) -1)
344 if (ACE_OS::setreuid (options.getruid (),
345 options.geteuid ()) == -1)
347 #if !defined (ACE_HAS_THREADS)
348 // We can't emit this log message because ACELIB_ERROR(), etc.
349 // will invoke async signal unsafe functions, which results
350 // in undefined behavior in threaded programs.
351 ACELIB_ERROR ((LM_ERROR,
352 ACE_TEXT ("%p.\n"),
353 ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
354 #endif
356 # endif /* ACE_LACKS_SETREUID */
358 this->child (ACE_OS::getppid ());
360 else if (this->child_id_ != -1)
361 this->parent (this->child_id_);
363 // If we're not supposed to exec, return the process id.
364 if (ACE_BIT_ENABLED (options.creation_flags (),
365 ACE_Process_Options::NO_EXEC))
366 return this->child_id_;
368 switch (this->child_id_)
370 case static_cast<pid_t>(-1):
371 // Error.
372 return ACE_INVALID_PID;
373 case 0:
374 // Child process...exec the
376 if (options.get_stdin () != ACE_INVALID_HANDLE
377 && ACE_OS::dup2 (options.get_stdin (),
378 ACE_STDIN) == -1)
379 ACE_OS::exit (errno);
380 else if (options.get_stdout () != ACE_INVALID_HANDLE
381 && ACE_OS::dup2 (options.get_stdout (),
382 ACE_STDOUT) == -1)
383 ACE_OS::exit (errno);
384 else if (options.get_stderr () != ACE_INVALID_HANDLE
385 && ACE_OS::dup2 (options.get_stderr (),
386 ACE_STDERR) == -1)
387 ACE_OS::exit (errno);
389 // close down unneeded descriptors
390 ACE_OS::close (options.get_stdin ());
391 ACE_OS::close (options.get_stdout ());
392 ACE_OS::close (options.get_stderr ());
393 if (!options.handle_inheritance ())
395 // Set close-on-exec for all FDs except standard handles
396 for (int i = ACE::max_handles () - 1; i >= 0; i--)
398 if (i == ACE_STDIN || i == ACE_STDOUT || i == ACE_STDERR)
399 continue;
400 ACE_OS::fcntl (i, F_SETFD, FD_CLOEXEC);
404 // If we must, set the working directory for the child
405 // process.
406 if (options.working_directory () != 0)
407 ACE_OS::chdir (options.working_directory ());
408 // Should check for error here!
410 // Child process executes the command.
411 int result = 0;
413 // Wide-char builds not on Windows need narrow-char strings for
414 // exec() and environment variables. Don't need to worry about
415 // releasing any of the converted string memory since this
416 // process will either exec() or exit() shortly.
417 # if defined (ACE_USES_WCHAR)
418 ACE_Wide_To_Ascii n_procname (options.process_name ());
419 const char *procname = n_procname.char_rep ();
421 wchar_t * const *wargv = options.command_line_argv ();
422 size_t vcount, i;
423 for (vcount = 0; wargv[vcount] != 0; ++vcount)
425 char **procargv = new char *[vcount + 1]; // Need 0 at the end
426 procargv[vcount] = 0;
427 for (i = 0; i < vcount; ++i)
428 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
430 wargv = options.env_argv ();
431 for (vcount = 0; wargv[vcount] != 0; ++vcount)
433 char **procenv = new char *[vcount + 1]; // Need 0 at the end
434 procenv[vcount] = 0;
435 for (i = 0; i < vcount; ++i)
436 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
437 # else
438 const char *procname = options.process_name ();
439 char *const *procargv = options.command_line_argv ();
440 char *const *procenv = options.env_argv ();
441 # endif /* ACE_USES_WCHAR */
443 if (options.inherit_environment ())
445 // Add the new environment variables to the environment
446 // context of the context before doing an <execvp>.
447 for (size_t i = 0; procenv[i] != 0; i++)
448 if (ACE_OS::putenv (procenv[i]) != 0)
449 return ACE_INVALID_PID;
451 // Now the forked process has both inherited variables and
452 // the user's supplied variables.
453 # ifdef ACE_LACKS_EXECVP
454 result = ACE_OS::execv (procname, procargv);
455 # else
456 result = ACE_OS::execvp (procname, procargv);
457 # endif
459 else
461 result = ACE_OS::execve (procname, procargv, procenv);
463 if (result == -1)
465 // If the execv fails, this child needs to exit.
467 // Exit with the errno so that the calling process can
468 // catch this and figure out what went wrong.
469 ACE_OS::_exit (errno);
471 // ... otherwise, this is never reached.
472 return 0;
474 default:
475 // Server process. The fork succeeded.
476 return this->child_id_;
478 #endif /* ACE_WIN32 */
481 void
482 ACE_Process::parent (pid_t)
484 // nothing to do
487 void
488 ACE_Process::child (pid_t)
490 // nothing to do
493 void
494 ACE_Process::unmanage ()
496 // nothing to do
500 ACE_Process::running () const
502 #if defined (ACE_WIN32)
503 DWORD code;
505 BOOL result = ::GetExitCodeProcess (this->gethandle (),
506 &code);
507 return result && code == STILL_ACTIVE;
508 #else
509 if (ACE_INVALID_PID == this->getpid ())
510 return 0;
511 else
512 return ACE_OS::kill (this->getpid (),
513 0) == 0
514 || errno != ESRCH;
515 #endif /* ACE_WIN32 */
518 pid_t
519 ACE_Process::wait (const ACE_Time_Value &tv,
520 ACE_exitcode *status)
522 #if defined (ACE_WIN32)
523 // Don't try to get the process exit status if wait failed so we can
524 // keep the original error code intact.
525 switch (::WaitForSingleObject (process_info_.hProcess,
526 tv.msec ()))
528 case WAIT_OBJECT_0:
529 // The error status of <GetExitCodeProcess> is nonetheless not
530 // tested because we don't know how to return the value.
531 ::GetExitCodeProcess (process_info_.hProcess,
532 &this->exit_code_);
533 if (status != 0)
534 *status = this->exit_code_;
535 return this->getpid ();
536 case WAIT_TIMEOUT:
537 errno = ETIME;
538 return 0;
539 default:
540 ACE_OS::set_errno_to_last_error ();
541 return -1;
543 #elif defined(ACE_LACKS_UNIX_SIGNALS)
544 if (tv == ACE_Time_Value::zero)
546 pid_t retv =
547 ACE_OS::waitpid (this->child_id_,
548 &this->exit_code_,
549 WNOHANG);
550 if (status != 0)
551 *status = this->exit_code_;
553 return retv;
556 if (tv == ACE_Time_Value::max_time)
557 # if defined (ACE_VXWORKS)
559 pid_t retv;
560 while ((retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR) ;
561 return retv;
563 # else
564 return this->wait (status);
565 # endif
567 pid_t pid = 0;
568 ACE_Time_Value sleeptm (1); // 1 msec
569 if (sleeptm > tv) // if sleeptime > waittime
570 sleeptm = tv;
571 ACE_Time_Value tmo (tv); // Need one we can change
572 for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
574 pid = ACE_OS::waitpid (this->getpid (),
575 &this->exit_code_,
576 WNOHANG);
577 if (status != 0)
578 *status = this->exit_code_;
580 if (pid > 0 || pid == ACE_INVALID_PID)
581 break; // Got a child or an error - all done
583 // pid 0, nothing is ready yet, so wait.
584 // Do a (very) short sleep (only this thread sleeps).
585 ACE_OS::sleep (sleeptm);
588 return pid;
589 #else /* !ACE_WIN32 && !ACE_LACKS_UNIX_SIGNALS */
590 if (tv == ACE_Time_Value::zero)
592 pid_t retv =
593 ACE_OS::waitpid (this->child_id_,
594 &this->exit_code_,
595 WNOHANG);
596 if (status != 0)
597 *status = this->exit_code_;
599 return retv;
602 if (tv == ACE_Time_Value::max_time)
603 return this->wait (status);
605 // Need to wait but limited to specified time.
606 // Force generation of SIGCHLD, even though we don't want to
607 // catch it - just need it to interrupt the sleep below.
608 // If this object has a reactor set, assume it was given at
609 // open(), and there's already a SIGCHLD action set, so no
610 // action is needed here.
611 ACE_Sig_Action old_action;
612 ACE_Sig_Handler_Ex sigchld_nop_ptr = sigchld_nop;
613 ACE_Sig_Action do_sigchld (reinterpret_cast<ACE_SignalHandler> (reinterpret_cast<void*> (sigchld_nop_ptr)));
614 do_sigchld.register_action (SIGCHLD, &old_action);
616 pid_t pid;
617 ACE_Time_Value tmo (tv); // Need one we can change
618 for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
620 pid = ACE_OS::waitpid (this->getpid (),
621 &this->exit_code_,
622 WNOHANG);
623 if (status != 0)
624 *status = this->exit_code_;
626 if (pid > 0 || pid == ACE_INVALID_PID)
627 break; // Got a child or an error - all done
629 // pid 0, nothing is ready yet, so wait.
630 // Do a sleep (only this thread sleeps) til something
631 // happens. This relies on SIGCHLD interrupting the sleep.
632 // If SIGCHLD isn't delivered, we'll need to do something
633 // with sigaction to force it.
634 if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
635 continue;
636 // Timed out
637 pid = 0;
638 break;
641 // Restore the previous SIGCHLD action if it was changed.
642 old_action.register_action (SIGCHLD);
644 return pid;
645 #endif /* ACE_WIN32 */
648 void
649 ACE_Process::close_dup_handles ()
651 if (this->dup_handles_.num_set () > 0)
653 ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
654 for (ACE_HANDLE h = h_iter ();
655 h != ACE_INVALID_HANDLE;
656 h = h_iter ())
657 ACE_OS::closesocket (h);
658 this->dup_handles_.reset ();
660 return;
663 void
664 ACE_Process::close_passed_handles ()
666 if (this->handles_passed_.num_set () > 0)
668 ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
669 for (ACE_HANDLE h = h_iter ();
670 h != ACE_INVALID_HANDLE;
671 h = h_iter ())
672 ACE_OS::closesocket (h);
673 this->handles_passed_.reset ();
675 return;
678 #if defined (ACE_WIN32) && \
679 defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
680 wchar_t*
681 ACE_Process::convert_env_buffer (const char* env) const
683 // Total starts out at 1 due to the final block nul terminator
684 size_t total = 1;
686 // Convert each individual character string to the equivalent wide
687 // character string.
688 ACE_Vector<wchar_t*> buffer;
689 size_t start = 0;
690 size_t i = 0;
691 while (true)
693 if (env[i] == '\0')
695 // Convert the char string to wchar_t
696 wchar_t* str = ACE_Ascii_To_Wide::convert (env + start);
698 // Add the length of the string plus the nul terminator
699 total += ACE_OS::strlen (str) + 1;
701 // Save it and set up for the next string
702 buffer.push_back (str);
703 start = ++i;
704 if (env[start] == '\0')
705 break;
707 else
709 i += ACE_OS::strlen (env + i);
713 // Copy each string into the buffer leaving a nul terminator between
714 // each string and adding a second nul terminator at the end
715 start = 0;
716 wchar_t* wenv = new wchar_t[total];
717 size_t length = buffer.size ();
718 for (i = 0; i < length; ++i)
720 ACE_OS::strcpy(wenv + start, buffer[i]);
721 start += ACE_OS::strlen (buffer[i]) + 1;
722 delete [] buffer[i];
724 wenv[start] = 0;
725 return wenv;
727 #endif
729 ACE_Process_Options::ACE_Process_Options (bool inherit_environment,
730 size_t command_line_buf_len,
731 size_t env_buf_len,
732 size_t max_env_args,
733 size_t max_cmdline_args)
735 inherit_environment_ (inherit_environment),
736 creation_flags_ (0),
737 avoid_zombies_ (0),
738 #if defined (ACE_WIN32)
739 environment_inherited_ (0),
740 process_attributes_ (0),
741 thread_attributes_ (0),
742 user_token_ (ACE_INVALID_HANDLE),
743 close_user_token_ (false),
744 #else /* ACE_WIN32 */
745 stdin_ (ACE_INVALID_HANDLE),
746 stdout_ (ACE_INVALID_HANDLE),
747 stderr_ (ACE_INVALID_HANDLE),
748 ruid_ ((uid_t) -1),
749 euid_ ((uid_t) -1),
750 rgid_ ((gid_t) -1),
751 egid_ ((gid_t) -1),
752 #endif /* ACE_WIN32 */
753 handle_inheritance_ (true),
754 set_handles_called_ (0),
755 environment_buf_index_ (0),
756 environment_argv_index_ (0),
757 environment_buf_ (0),
758 environment_buf_len_ (env_buf_len),
759 max_environment_args_ (max_env_args),
760 max_environ_argv_index_ (max_env_args - 1),
761 command_line_argv_calculated_ (false),
762 command_line_buf_ (0),
763 command_line_copy_ (0),
764 command_line_buf_len_ (command_line_buf_len),
765 max_command_line_args_ (max_cmdline_args),
766 command_line_argv_ (0),
767 process_group_ (ACE_INVALID_PID),
768 use_unicode_environment_ (false)
770 #if defined (ACE_HAS_ALLOC_HOOKS)
771 ACE_ALLOCATOR (command_line_buf_,
772 static_cast<ACE_TCHAR*>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR) * command_line_buf_len)));
773 #else
774 ACE_NEW (command_line_buf_,
775 ACE_TCHAR[command_line_buf_len]);
776 #endif /* ACE_HAS_ALLOC_HOOKS */
777 command_line_buf_[0] = '\0';
778 process_name_[0] = '\0';
780 working_directory_[0] = '\0';
781 #if defined (ACE_HAS_ALLOC_HOOKS)
782 ACE_ALLOCATOR (environment_buf_,
783 static_cast<ACE_TCHAR*>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR) * env_buf_len)));
784 #else
785 ACE_NEW (environment_buf_,
786 ACE_TCHAR[env_buf_len]);
787 #endif /* ACE_HAS_ALLOC_HOOKS */
788 #if defined (ACE_HAS_ALLOC_HOOKS)
789 ACE_ALLOCATOR (environment_argv_,
790 static_cast<ACE_TCHAR**>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR*) * max_env_args)));
791 #else
792 ACE_NEW (environment_argv_,
793 ACE_TCHAR *[max_env_args]);
794 #endif /* ACE_HAS_ALLOC_HOOKS */
795 environment_buf_[0] = '\0';
796 environment_argv_[0] = 0;
797 #if defined (ACE_WIN32)
798 ACE_OS::memset ((void *) &this->startup_info_,
800 sizeof this->startup_info_);
801 this->startup_info_.cb = sizeof this->startup_info_;
802 #endif /* ACE_WIN32 */
803 #if defined (ACE_HAS_ALLOC_HOOKS)
804 ACE_ALLOCATOR (command_line_argv_,
805 static_cast<ACE_TCHAR**>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR*) * max_cmdline_args)));
806 #else
807 ACE_NEW (command_line_argv_,
808 ACE_TCHAR *[max_cmdline_args]);
809 #endif /* ACE_HAS_ALLOC_HOOKS */
812 #if defined (ACE_WIN32)
813 void
814 ACE_Process_Options::inherit_environment ()
816 // Ensure only once execution.
817 if (environment_inherited_)
818 return;
819 environment_inherited_ = 1;
821 // Get the existing environment.
822 ACE_TCHAR *existing_environment = 0;
823 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
824 WCHAR *existing_wide_env = 0;
825 ACE_Vector<char> temp_narrow_env;
826 if (this->use_unicode_environment_)
828 existing_wide_env = ::GetEnvironmentStringsW ();
829 for (WCHAR *iter = existing_wide_env; *iter; ++iter)
831 ACE_Wide_To_Ascii wta (iter);
832 size_t const len = ACE_OS::strlen (wta.char_rep ());
833 size_t const idx = temp_narrow_env.size ();
834 temp_narrow_env.resize (idx + len + 1, 0);
835 ACE_OS::strncpy (&temp_narrow_env[idx], wta.char_rep (), len);
836 iter += len;
838 temp_narrow_env.push_back (0);
839 existing_environment = &temp_narrow_env[0];
841 else
842 #endif
843 existing_environment = ACE_OS::getenvstrings ();
845 size_t slot = 0;
847 while (existing_environment[slot] != '\0')
849 size_t const len = ACE_OS::strlen (existing_environment + slot);
851 // Add the string to our env buffer.
852 if (this->setenv_i (existing_environment + slot, len) == -1)
854 ACELIB_ERROR ((LM_ERROR,
855 ACE_TEXT ("%p.\n"),
856 ACE_TEXT ("ACE_Process_Options::ACE_Process_Options")));
857 break;
860 // Skip to the next word.
861 slot += len + 1;
864 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
865 if (this->use_unicode_environment_)
866 ::FreeEnvironmentStringsW (existing_wide_env);
867 else
868 #endif
869 ACE_TEXT_FreeEnvironmentStrings (existing_environment);
872 #else /* defined ACE_WIN32 */
874 ACE_TCHAR * const *
875 ACE_Process_Options::env_argv ()
877 return environment_argv_;
879 #endif /* ACE_WIN32 */
882 ACE_Process_Options::setenv (ACE_TCHAR *envp[])
884 int i = 0;
885 while (envp[i])
887 if (this->setenv_i (envp[i], ACE_OS::strlen (envp[i])) == -1)
888 return -1;
889 i++;
892 #if defined (ACE_WIN32)
893 if (inherit_environment_)
894 this->inherit_environment ();
895 #endif /* ACE_WIN32 */
897 return 0;
900 #ifndef ACE_LACKS_VA_FUNCTIONS
902 ACE_Process_Options::setenv (const ACE_TCHAR *format, ...)
904 ACE_TCHAR stack_buf[DEFAULT_COMMAND_LINE_BUF_LEN];
906 // Start varargs.
907 va_list argp;
908 va_start (argp, format);
910 // Add the rest of the varargs.
911 int status = ACE_OS::vsnprintf (stack_buf, DEFAULT_COMMAND_LINE_BUF_LEN, format, argp);
912 // End varargs.
913 va_end (argp);
915 if (status == -1)
916 return -1;
918 // Append the string to are environment buffer.
919 if (this->setenv_i (stack_buf, ACE_OS::strlen (stack_buf)) == -1)
920 return -1;
922 #if defined (ACE_WIN32)
923 if (inherit_environment_)
924 this->inherit_environment ();
925 #endif /* ACE_WIN32 */
927 return 0;
931 ACE_Process_Options::setenv (const ACE_TCHAR *variable_name,
932 const ACE_TCHAR *format, ...)
934 // To address the potential buffer overflow,
935 // we now allocate the buffer on heap with a variable size.
936 size_t const buflen = ACE_OS::strlen (variable_name) + ACE_OS::strlen (format) + 2;
937 ACE_TCHAR *newformat = 0;
938 ACE_NEW_RETURN (newformat, ACE_TCHAR[buflen], -1);
939 std::unique_ptr<ACE_TCHAR[]> safe_newformat (newformat);
941 // Add in the variable name.
942 ACE_OS::snprintf (safe_newformat.get (), buflen,
943 ACE_TEXT ("%") ACE_TEXT_PRIs ACE_TEXT ("=%") ACE_TEXT_PRIs,
944 variable_name, format);
946 // Add the rest of the varargs.
947 size_t tmp_buflen = buflen;
948 if (DEFAULT_COMMAND_LINE_BUF_LEN > buflen)
950 tmp_buflen = DEFAULT_COMMAND_LINE_BUF_LEN;
952 int retval = 0;
954 ACE_TCHAR *stack_buf = 0;
955 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
956 std::unique_ptr<ACE_TCHAR[]> safe_stack_buf (stack_buf);
960 // Must restart varargs on each time through this loop,
961 va_list argp;
962 va_start (argp, format);
964 retval = ACE_OS::vsnprintf (safe_stack_buf.get (), tmp_buflen, safe_newformat.get (), argp);
966 // End varargs.
967 va_end (argp);
969 if (retval > ACE_Utils::truncate_cast<int> (tmp_buflen))
971 tmp_buflen *= 2;
972 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
973 safe_stack_buf.reset (stack_buf);
975 else
976 break;
978 while (1);
980 if (retval == -1)
982 // In case that vsnprintf is not supported,
983 // e.g., LynxOS and VxWorks 5, we have to
984 // fall back to vsprintf.
985 if (errno == ENOTSUP)
987 // ALERT: Since we have to use vsprintf here, there is still a chance that
988 // the stack_buf overflows, i.e., the length of the resulting string
989 // can still possibly go beyond the allocated stack_buf.
990 va_list argp;
991 va_start (argp, format);
992 retval = ACE_OS::vsprintf (safe_stack_buf.get (), safe_newformat.get (), argp);
993 va_end (argp);
994 if (retval == -1)
995 // vsprintf is failed.
996 return -1;
998 else
999 // vsnprintf is failed.
1000 return -1;
1003 // Append the string to our environment buffer.
1004 if (this->setenv_i (safe_stack_buf.get (),
1005 ACE_OS::strlen (safe_stack_buf.get ())) == -1)
1006 return -1;
1008 #if defined (ACE_WIN32)
1009 if (inherit_environment_)
1010 this->inherit_environment ();
1011 #endif /* ACE_WIN32 */
1013 return 0;
1015 #endif // ACE_LACKS_VA_FUNCTIONS
1018 ACE_Process_Options::setenv_i (ACE_TCHAR *assignment,
1019 size_t len)
1021 // Add one for the null char.
1022 ++len;
1024 // If environment larger than allocated buffer return. Also check to
1025 // make sure we have enough room.
1026 if (environment_argv_index_ == max_environ_argv_index_
1027 || (len + environment_buf_index_) >= environment_buf_len_)
1028 return -1;
1030 // Copy the new environment string.
1031 ACE_OS::memcpy (environment_buf_ + environment_buf_index_,
1032 assignment,
1033 len * sizeof (ACE_TCHAR));
1035 // Update the argv array.
1036 environment_argv_[environment_argv_index_++] = environment_buf_ + environment_buf_index_;
1037 environment_argv_[environment_argv_index_] = 0;
1039 // Update our index.
1040 environment_buf_index_ += len;
1042 // Make sure the buffer is null-terminated.
1043 environment_buf_[environment_buf_index_] = '\0';
1044 return 0;
1048 ACE_Process_Options::set_handles (ACE_HANDLE std_in,
1049 ACE_HANDLE std_out,
1050 ACE_HANDLE std_err)
1052 this->set_handles_called_ = 1;
1053 #if defined (ACE_WIN32)
1055 // Tell the new process to use our std handles.
1056 this->startup_info_.dwFlags = STARTF_USESTDHANDLES;
1058 if (std_in == ACE_INVALID_HANDLE)
1059 std_in = ACE_STDIN;
1060 if (std_out == ACE_INVALID_HANDLE)
1061 std_out = ACE_STDOUT;
1062 if (std_err == ACE_INVALID_HANDLE)
1063 std_err = ACE_STDERR;
1065 // STD handles may have value 0 (not ACE_INVALID_HANDLE) if there is no such
1066 // handle in the process. This was observed to occur for stdin in console
1067 // processes that were launched from services. In this case we need to make
1068 // sure not to return -1 from setting std_in so that we can process std_out
1069 // and std_err.
1070 if (std_in)
1072 if (!::DuplicateHandle (::GetCurrentProcess (),
1073 std_in,
1074 ::GetCurrentProcess (),
1075 &this->startup_info_.hStdInput,
1077 TRUE,
1078 DUPLICATE_SAME_ACCESS))
1079 return -1;
1082 if (std_out)
1084 if (!::DuplicateHandle (::GetCurrentProcess (),
1085 std_out,
1086 ::GetCurrentProcess (),
1087 &this->startup_info_.hStdOutput,
1089 TRUE,
1090 DUPLICATE_SAME_ACCESS))
1091 return -1;
1094 if (std_err)
1096 if (!::DuplicateHandle (::GetCurrentProcess (),
1097 std_err,
1098 ::GetCurrentProcess (),
1099 &this->startup_info_.hStdError,
1101 TRUE,
1102 DUPLICATE_SAME_ACCESS))
1103 return -1;
1105 #else /* ACE_WIN32 */
1106 this->stdin_ = ACE_OS::dup (std_in);
1107 this->stdout_ = ACE_OS::dup (std_out);
1108 this->stderr_ = ACE_OS::dup (std_err);
1109 #endif /* ACE_WIN32 */
1111 return 0; // Success.
1115 void
1116 ACE_Process_Options::release_handles ()
1118 if (set_handles_called_)
1120 #if defined (ACE_WIN32)
1121 ACE_OS::close (startup_info_.hStdInput);
1122 ACE_OS::close (startup_info_.hStdOutput);
1123 ACE_OS::close (startup_info_.hStdError);
1124 #else /* ACE_WIN32 */
1125 ACE_OS::close (stdin_);
1126 ACE_OS::close (stdout_);
1127 ACE_OS::close (stderr_);
1128 #endif /* ACE_WIN32 */
1129 set_handles_called_ = 0;
1133 ACE_Process_Options::~ACE_Process_Options ()
1135 release_handles();
1136 #if defined (ACE_HAS_ALLOC_HOOKS)
1137 ACE_Allocator::instance()->free(environment_buf_);
1138 ACE_Allocator::instance()->free(environment_argv_);
1139 #else
1140 delete [] environment_buf_;
1141 delete [] environment_argv_;
1142 #endif /* ACE_HAS_ALLOC_HOOKS */
1143 #if defined (ACE_HAS_ALLOC_HOOKS)
1144 ACE_Allocator::instance()->free(command_line_buf_);
1145 #else
1146 delete [] command_line_buf_;
1147 #endif /* ACE_HAS_ALLOC_HOOKS */
1148 ACE::strdelete (command_line_copy_);
1149 #if defined (ACE_HAS_ALLOC_HOOKS)
1150 ACE_Allocator::instance()->free(command_line_argv_);
1151 #else
1152 delete [] command_line_argv_;
1153 #endif /* ACE_HAS_ALLOC_HOOKS */
1155 #if defined (ACE_WIN32)
1156 if (user_token_ != ACE_INVALID_HANDLE && close_user_token_)
1158 ::CloseHandle(user_token_);
1160 #endif /* ACE_WIN32 */
1164 ACE_Process_Options::command_line (const ACE_TCHAR *const argv[])
1166 int i = 0;
1168 if (argv[i])
1170 ACE_OS::strcat (command_line_buf_, argv[i]);
1172 while (argv[++i])
1174 // Check to see if the next argument will overflow the
1175 // command_line buffer.
1176 size_t const cur_len =
1177 ACE_OS::strlen (command_line_buf_)
1178 + ACE_OS::strlen (argv[i])
1179 + 2;
1181 if (cur_len > command_line_buf_len_)
1183 ACELIB_ERROR_RETURN ((LM_ERROR,
1184 ACE_TEXT ("ACE_Process:command_line: ")
1185 ACE_TEXT ("command line is ")
1186 ACE_TEXT ("longer than %d\n"),
1187 command_line_buf_len_),
1191 ACE_OS::strcat (command_line_buf_, ACE_TEXT (" "));
1192 ACE_OS::strcat (command_line_buf_, argv[i]);
1196 command_line_argv_calculated_ = false;
1197 return 0; // Success.
1200 #ifndef ACE_LACKS_VA_FUNCTIONS
1202 ACE_Process_Options::command_line (const ACE_TCHAR *format, ...)
1204 // Store all ... args in argp.
1205 va_list argp;
1206 va_start (argp, format);
1208 if (command_line_buf_len_ < 1)
1210 va_end (argp);
1211 return -1;
1214 ACE_OS::vsnprintf (command_line_buf_,
1215 command_line_buf_len_,
1216 format,
1217 argp);
1218 // Useless macro.
1219 va_end (argp);
1221 command_line_argv_calculated_ = false;
1222 return 0;
1225 #if defined (ACE_HAS_WCHAR)
1227 ACE_Process_Options::command_line (const ACE_ANTI_TCHAR *format, ...)
1229 ACE_ANTI_TCHAR *anti_clb = 0;
1230 ACE_NEW_RETURN (anti_clb,
1231 ACE_ANTI_TCHAR[this->command_line_buf_len_],
1232 -1);
1234 // Store all ... args in argp.
1235 va_list argp;
1236 va_start (argp, format);
1238 // sprintf the format and args into command_line_buf_.
1239 ACE_OS::vsnprintf (anti_clb, this->command_line_buf_len_, format, argp);
1241 // Useless macro.
1242 va_end (argp);
1244 ACE_OS::strcpy (this->command_line_buf_,
1245 ACE_TEXT_ANTI_TO_TCHAR (anti_clb));
1247 delete [] anti_clb;
1249 command_line_argv_calculated_ = false;
1250 return 0;
1252 #endif /* ACE_HAS_WCHAR */
1253 #endif // ACE_LACKS_VA_FUNCTIONS
1255 ACE_TCHAR *
1256 ACE_Process_Options::env_buf ()
1258 if (environment_buf_[0] == '\0')
1259 return 0;
1260 else
1261 return environment_buf_;
1264 ACE_TCHAR * const *
1265 ACE_Process_Options::command_line_argv ()
1267 if (!command_line_argv_calculated_)
1269 command_line_argv_calculated_ = true;
1271 // We need to free up any previous allocated memory first.
1272 ACE::strdelete (command_line_copy_);
1274 // We need to make a dynamically allocated copy here since
1275 // ACE_Tokenizer modifies its arguments.
1276 command_line_copy_ = ACE::strnew (command_line_buf_);
1277 // This tokenizer will replace all spaces with end-of-string
1278 // characters and will preserve text between "" and '' pairs.
1279 ACE_Tokenizer parser (command_line_copy_);
1280 parser.delimiter_replace (' ', '\0');
1281 parser.preserve_designators ('\"', '\"'); // "
1282 parser.preserve_designators ('\'', '\'');
1284 unsigned int x = 0;
1286 command_line_argv_[x] = parser.next ();
1287 while (command_line_argv_[x] != 0
1288 // subtract one for the ending zero.
1289 && ++x < max_command_line_args_ - 1);
1291 command_line_argv_[x] = 0;
1294 return command_line_argv_;
1297 // Cause the specified handle to be passed to a child process
1298 // when it's spawned.
1300 ACE_Process_Options::pass_handle (ACE_HANDLE h)
1302 this->handles_passed_.set_bit (h);
1303 return 0;
1306 // Get a copy of the handles the ACE_Process_Options duplicated
1307 // for the spawned process.
1309 ACE_Process_Options::dup_handles (ACE_Handle_Set &set) const
1311 if (this->dup_handles_.num_set () == 0)
1312 return 0;
1313 set.reset ();
1314 set = this->dup_handles_;
1315 return 1;
1318 // Get a copy of the handles passed to the spawned process. This
1319 // will be the set of handles previously passed to @arg pass_handle().
1321 ACE_Process_Options::passed_handles (ACE_Handle_Set &set) const
1323 if (this->handles_passed_.num_set () == 0)
1324 return 0;
1325 set.reset ();
1326 set = this->handles_passed_;
1327 return 1;
1330 ACE_ALLOC_HOOK_DEFINE(ACE_Managed_Process)
1332 void
1333 ACE_Managed_Process::unmanage ()
1335 delete this;
1338 #if defined (ACE_WIN32)
1339 void
1340 ACE_Process_Options::set_user_token (HANDLE token, bool close_token)
1342 if (user_token_ != ACE_INVALID_HANDLE && close_user_token_)
1344 ::CloseHandle(user_token_);
1347 user_token_ = token;
1348 close_user_token_ = close_token;
1350 #endif /* ACE_WIN32 */
1352 ACE_END_VERSIONED_NAMESPACE_DECL