[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / dep / ACE_wrappers / ace / Process.cpp
blob1871e304401ce56322173c7be2ff50aeb4be9cc9
1 // $Id: Process.cpp 82499 2008-08-04 20:01:17Z shuston $
3 #include "ace/Process.h"
5 #if !defined (__ACE_INLINE__)
6 #include "ace/Process.inl"
7 #endif /* __ACE_INLINE__ */
9 #include "ace/ARGV.h"
10 #include "ace/Auto_Ptr.h"
11 #include "ace/Signal.h"
12 #include "ace/SString.h"
13 #include "ace/Log_Msg.h"
14 #include "ace/OS_NS_stdio.h"
15 #include "ace/OS_NS_stdlib.h"
16 #include "ace/OS_NS_sys_socket.h"
17 #include "ace/OS_NS_errno.h"
18 #include "ace/OS_NS_string.h"
19 #include "ace/OS_NS_unistd.h"
20 #include "ace/OS_Memory.h"
21 #include "ace/Countdown_Time.h"
22 #include "ace/Truncate.h"
23 #include "ace/Vector_T.h"
25 #if defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600) && defined (__RTP__)
26 # include <rtpLib.h>
27 # include <taskLib.h>
28 #endif
30 ACE_RCSID (ace, Process, "$Id: Process.cpp 82499 2008-08-04 20:01:17Z shuston $")
32 // This function acts as a signal handler for SIGCHLD. We don't really want
33 // to do anything with the signal - it's just needed to interrupt a sleep.
34 // See wait() for more info.
35 #if !defined (ACE_WIN32) && !defined(ACE_LACKS_UNIX_SIGNALS)
36 static void
37 sigchld_nop (int, siginfo_t *, ucontext_t *)
39 return;
41 #endif /* ACE_WIN32 */
44 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
46 ACE_Process::ACE_Process (void)
48 #if !defined (ACE_WIN32)
49 child_id_ (ACE_INVALID_PID),
50 #endif /* !defined (ACE_WIN32) */
51 exit_code_ (0)
53 #if defined (ACE_WIN32)
54 ACE_OS::memset ((void *) &this->process_info_,
56 sizeof this->process_info_);
57 #endif /* ACE_WIN32 */
60 ACE_Process::~ACE_Process (void)
62 #if defined (ACE_WIN32)
63 // Free resources allocated in kernel.
64 ACE_OS::close (this->process_info_.hThread);
65 ACE_OS::close (this->process_info_.hProcess);
66 #endif /* ACE_WIN32 */
67 // If any handles were duplicated for the child process and
68 // still not closed, get them now.
69 this->close_dup_handles ();
72 int
73 ACE_Process::prepare (ACE_Process_Options &)
75 return 0;
78 pid_t
79 ACE_Process::spawn (ACE_Process_Options &options)
81 if (this->prepare (options) < 0)
82 return ACE_INVALID_PID;
84 // Stash the passed/duped handle sets away in this object for later
85 // closing if needed or requested. At the same time, figure out which
86 // ones to include in command line options if that's needed below.
87 ACE_Handle_Set *set_p = 0;
88 if (options.dup_handles (this->dup_handles_))
89 set_p = &this->dup_handles_;
90 else if (options.passed_handles (this->handles_passed_))
91 set_p = &this->handles_passed_;
93 // If we are going to end up running a new program (i.e. Win32, or
94 // NO_EXEC option is set) then get any handles passed in the options,
95 // and tack them onto the command line with +H <handle> options,
96 // unless the command line runs out of space.
97 // Note that we're using the knowledge that all the options, argvs, etc.
98 // passed to the options are all sitting in the command_line_buf. Any
99 // call to get the argv then splits them out. So, regardless of the
100 // platform, tack them all onto the command line buf and take it
101 // from there.
102 if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
103 ACE_Process_Options::NO_EXEC))
105 int maxlen = 0;
106 ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen);
107 size_t max_len = static_cast<size_t> (maxlen);
108 size_t curr_len = ACE_OS::strlen (cmd_line_buf);
109 ACE_Handle_Set_Iterator h_iter (*set_p);
110 // Because the length of the to-be-formatted +H option is not
111 // known, and we don't have a snprintf, guess at the space
112 // needed (20 chars), and use that as a limit.
113 for (ACE_HANDLE h = h_iter ();
114 h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
115 h = h_iter ())
117 #if defined (ACE_WIN32)
118 # if defined (ACE_WIN64)
119 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
120 ACE_TEXT (" +H %I64p"),
122 # else
123 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
124 ACE_TEXT (" +H %p"),
126 # endif /* ACE_WIN64 */
127 #else
128 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
129 ACE_TEXT (" +H %d"),
131 #endif /* ACE_WIN32 */
135 #if defined (ACE_HAS_WINCE)
136 // Note that WinCE does not have process name included in the command line as argv[0]
137 // like other OS environment. Therefore, it is user's whole responsibility to call
138 // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper
139 // process name (the execution file name with path if needed).
141 BOOL fork_result =
142 ACE_TEXT_CreateProcess (options.process_name(),
143 options.command_line_buf(),
144 options.get_process_attributes(), // must be NULL in CE
145 options.get_thread_attributes(), // must be NULL in CE
146 options.handle_inheritence(), // must be false in CE
147 options.creation_flags(), // must be NULL in CE
148 options.env_buf(), // environment variables, must be NULL in CE
149 options.working_directory(), // must be NULL in CE
150 options.startup_info(), // must be NULL in CE
151 &this->process_info_);
153 if (fork_result)
155 parent (this->getpid ());
156 return this->getpid ();
158 return ACE_INVALID_PID;
160 #elif defined (ACE_WIN32)
161 void* env_buf = options.env_buf ();
162 DWORD flags = options.creation_flags ();
163 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
164 wchar_t* wenv_buf = 0;
165 if (options.use_unicode_environment ())
167 wenv_buf = this->convert_env_buffer (options.env_buf ());
168 env_buf = wenv_buf;
169 flags |= CREATE_UNICODE_ENVIRONMENT;
171 # endif
173 BOOL fork_result =
174 ACE_TEXT_CreateProcess (0,
175 options.command_line_buf (),
176 options.get_process_attributes (),
177 options.get_thread_attributes (),
178 options.handle_inheritence (),
179 flags,
180 env_buf, // environment variables
181 options.working_directory (),
182 options.startup_info (),
183 &this->process_info_);
185 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
186 if (options.use_unicode_environment ())
187 delete wenv_buf;
188 # endif
190 if (fork_result)
192 parent (this->getpid ());
193 return this->getpid ();
195 return ACE_INVALID_PID;
197 #elif defined(ACE_OPENVMS)
198 if (ACE_BIT_ENABLED (options.creation_flags (),
199 ACE_Process_Options::NO_EXEC))
200 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
202 int saved_stdin = ACE_STDIN;
203 int saved_stdout = ACE_STDOUT;
204 int saved_stderr = ACE_STDERR;
205 // Save STD file descriptors and redirect
206 if (options.get_stdin () != ACE_INVALID_HANDLE) {
207 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
208 ACE_OS::exit (errno);
209 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
210 ACE_OS::exit (errno);
212 if (options.get_stdout () != ACE_INVALID_HANDLE) {
213 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
214 ACE_OS::exit (errno);
215 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
216 ACE_OS::exit (errno);
218 if (options.get_stderr () != ACE_INVALID_HANDLE) {
219 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
220 ACE_OS::exit (errno);
221 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
222 ACE_OS::exit (errno);
225 if (options.working_directory () != 0)
226 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
228 this->child_id_ = vfork();
229 if (this->child_id_ == 0) {
230 ACE_OS::execvp (options.process_name (),
231 options.command_line_argv ());
232 // something went wrong
233 this->child_id_ = ACE_INVALID_PID;
236 // restore STD file descriptors (if necessary)
237 if (options.get_stdin () != ACE_INVALID_HANDLE) {
238 if (saved_stdin == -1)
239 ACE_OS::close (ACE_STDIN);
240 else
241 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
243 if (options.get_stdout () != ACE_INVALID_HANDLE) {
244 if (saved_stdout == -1)
245 ACE_OS::close (ACE_STDOUT);
246 else
247 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
249 if (options.get_stderr () != ACE_INVALID_HANDLE) {
250 if (saved_stderr == -1)
251 ACE_OS::close (ACE_STDERR);
252 else
253 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
256 return this->child_id_;
257 #elif (defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600)) && defined (__RTP__)
258 if (ACE_BIT_ENABLED (options.creation_flags (),
259 ACE_Process_Options::NO_EXEC))
260 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
262 if (options.working_directory () != 0)
263 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
265 int saved_stdin = ACE_STDIN;
266 int saved_stdout = ACE_STDOUT;
267 int saved_stderr = ACE_STDERR;
268 // Save STD file descriptors and redirect
269 if (options.get_stdin () != ACE_INVALID_HANDLE) {
270 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
271 ACE_OS::exit (errno);
272 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
273 ACE_OS::exit (errno);
275 if (options.get_stdout () != ACE_INVALID_HANDLE) {
276 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
277 ACE_OS::exit (errno);
278 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
279 ACE_OS::exit (errno);
281 if (options.get_stderr () != ACE_INVALID_HANDLE) {
282 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
283 ACE_OS::exit (errno);
284 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
285 ACE_OS::exit (errno);
288 // Wide-char builds need narrow-char strings for commandline and
289 // environment variables.
290 # if defined (ACE_USES_WCHAR)
291 wchar_t * const *wargv = options.command_line_argv ();
292 size_t vcount, i;
293 for (vcount = 0; wargv[vcount] != 0; ++vcount)
295 char **procargv = new char *[vcount + 1]; // Need 0 at the end
296 procargv[vcount] = 0;
297 for (i = 0; i < vcount; ++i)
298 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
300 char **procenv = 0;
301 if (options.inherit_environment ())
303 wargv = options.env_argv ();
304 for (vcount = 0; wargv[vcount] != 0; ++vcount)
306 procenv = new char *[vcount + 1]; // Need 0 at the end
307 procenv[vcount] = 0;
308 for (i = 0; i < vcount; ++i)
309 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
311 # else
312 const char **procargv = const_cast<const char**> (options.command_line_argv ());
313 const char **procenv = const_cast<const char**> (options.env_argv ());
314 # endif /* ACE_USES_WCHAR */
316 this->child_id_ = ::rtpSpawn (procargv[0],
317 procargv,
318 procenv,
319 200, // priority
320 0x10000, // uStackSize
321 0, // options
322 VX_FP_TASK); // taskOptions
323 int my_errno_ = errno;
324 if (this->child_id_ == ERROR) {
325 // something went wrong
326 this->child_id_ = ACE_INVALID_PID;
329 # if defined (ACE_USES_WCHAR)
330 if (procenv)
331 delete procenv;
332 # endif /* ACE_USES_WCHAR */
334 // restore STD file descriptors (if necessary)
335 if (options.get_stdin () != ACE_INVALID_HANDLE) {
336 if (saved_stdin == -1)
337 ACE_OS::close (ACE_STDIN);
338 else
339 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
341 if (options.get_stdout () != ACE_INVALID_HANDLE) {
342 if (saved_stdout == -1)
343 ACE_OS::close (ACE_STDOUT);
344 else
345 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
347 if (options.get_stderr () != ACE_INVALID_HANDLE) {
348 if (saved_stderr == -1)
349 ACE_OS::close (ACE_STDERR);
350 else
351 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
354 if (this->child_id_ == ACE_INVALID_PID)
356 errno = my_errno_;
359 return this->child_id_;
360 #else /* ACE_WIN32 */
361 // Fork the new process.
362 this->child_id_ = ACE::fork (options.process_name (),
363 options.avoid_zombies ());
365 if (this->child_id_ == 0)
367 # if !defined (ACE_LACKS_SETPGID)
368 // If we're the child and the options specified a non-default
369 // process group, try to set our pgid to it. This allows the
370 // <ACE_Process_Manager> to wait for processes by their
371 // process-group.
372 if (options.getgroup () != ACE_INVALID_PID
373 && ACE_OS::setpgid (0,
374 options.getgroup ()) < 0)
376 #if !defined (ACE_HAS_THREADS)
377 // We can't emit this log message because ACE_ERROR(), etc.
378 // will invoke async signal unsafe functions, which results
379 // in undefined behavior in threaded programs.
380 ACE_ERROR ((LM_ERROR,
381 ACE_TEXT ("%p.\n"),
382 ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
383 #endif
385 # endif /* ACE_LACKS_SETPGID */
387 # if !defined (ACE_LACKS_SETREGID)
388 if (options.getrgid () != (uid_t) -1
389 || options.getegid () != (uid_t) -1)
390 if (ACE_OS::setregid (options.getrgid (),
391 options.getegid ()) == -1)
393 #if !defined (ACE_HAS_THREADS)
394 // We can't emit this log message because ACE_ERROR(), etc.
395 // will invoke async signal unsafe functions, which results
396 // in undefined behavior in threaded programs.
397 ACE_ERROR ((LM_ERROR,
398 ACE_TEXT ("%p.\n"),
399 ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
400 #endif
402 # endif /* ACE_LACKS_SETREGID */
404 # if !defined (ACE_LACKS_SETREUID)
405 // Set user and group id's.
406 if (options.getruid () != (uid_t) -1
407 || options.geteuid () != (uid_t) -1)
408 if (ACE_OS::setreuid (options.getruid (),
409 options.geteuid ()) == -1)
411 #if !defined (ACE_HAS_THREADS)
412 // We can't emit this log message because ACE_ERROR(), etc.
413 // will invoke async signal unsafe functions, which results
414 // in undefined behavior in threaded programs.
415 ACE_ERROR ((LM_ERROR,
416 ACE_TEXT ("%p.\n"),
417 ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
418 #endif
420 # endif /* ACE_LACKS_SETREUID */
422 this->child (ACE_OS::getppid ());
424 else if (this->child_id_ != -1)
425 this->parent (this->child_id_);
427 // If we're not supposed to exec, return the process id.
428 if (ACE_BIT_ENABLED (options.creation_flags (),
429 ACE_Process_Options::NO_EXEC))
430 return this->child_id_;
432 switch (this->child_id_)
434 case -1:
435 // Error.
436 return ACE_INVALID_PID;
437 case 0:
438 // Child process...exec the
440 if (options.get_stdin () != ACE_INVALID_HANDLE
441 && ACE_OS::dup2 (options.get_stdin (),
442 ACE_STDIN) == -1)
443 ACE_OS::exit (errno);
444 else if (options.get_stdout () != ACE_INVALID_HANDLE
445 && ACE_OS::dup2 (options.get_stdout (),
446 ACE_STDOUT) == -1)
447 ACE_OS::exit (errno);
448 else if (options.get_stderr () != ACE_INVALID_HANDLE
449 && ACE_OS::dup2 (options.get_stderr (),
450 ACE_STDERR) == -1)
451 ACE_OS::exit (errno);
453 // close down unneeded descriptors
454 ACE_OS::close (options.get_stdin ());
455 ACE_OS::close (options.get_stdout ());
456 ACE_OS::close (options.get_stderr ());
458 // If we must, set the working directory for the child
459 // process.
460 if (options.working_directory () != 0)
461 ACE_OS::chdir (options.working_directory ());
462 // Should check for error here!
464 // Child process executes the command.
465 int result = 0;
467 // Wide-char builds not on Windows need narrow-char strings for
468 // exec() and environment variables. Don't need to worry about
469 // releasing any of the converted string memory since this
470 // process will either exec() or exit() shortly.
471 # if defined (ACE_USES_WCHAR)
472 ACE_Wide_To_Ascii n_procname (options.process_name ());
473 const char *procname = n_procname.char_rep ();
475 wchar_t * const *wargv = options.command_line_argv ();
476 size_t vcount, i;
477 for (vcount = 0; wargv[vcount] != 0; ++vcount)
479 char **procargv = new char *[vcount + 1]; // Need 0 at the end
480 procargv[vcount] = 0;
481 for (i = 0; i < vcount; ++i)
482 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
484 wargv = options.env_argv ();
485 for (vcount = 0; wargv[vcount] != 0; ++vcount)
487 char **procenv = new char *[vcount + 1]; // Need 0 at the end
488 procenv[vcount] = 0;
489 for (i = 0; i < vcount; ++i)
490 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
491 # else
492 const char *procname = options.process_name ();
493 char *const *procargv = options.command_line_argv ();
494 char *const *procenv = options.env_argv ();
495 # endif /* ACE_USES_WCHAR */
497 if (options.inherit_environment ())
499 // Add the new environment variables to the environment
500 // context of the context before doing an <execvp>.
501 for (size_t i = 0; procenv[i] != 0; i++)
502 if (ACE_OS::putenv (procenv[i]) != 0)
503 return ACE_INVALID_PID;
505 // Now the forked process has both inherited variables and
506 // the user's supplied variables.
507 result = ACE_OS::execvp (procname, procargv);
509 else
511 # if defined (ghs)
512 // GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
513 // code. Processes aren't supported on VxWorks anyways.
514 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
515 # else
516 result = ACE_OS::execve (procname, procargv, procenv);
517 # endif /* ghs */
519 if (result == -1)
521 // If the execv fails, this child needs to exit.
523 // Exit with the errno so that the calling process can
524 // catch this and figure out what went wrong.
525 ACE_OS::_exit (errno);
527 // ... otherwise, this is never reached.
528 return 0;
530 default:
531 // Server process. The fork succeeded.
532 return this->child_id_;
534 #endif /* ACE_WIN32 */
537 void
538 ACE_Process::parent (pid_t)
540 // nothing to do
543 void
544 ACE_Process::child (pid_t)
546 // nothing to do
549 void
550 ACE_Process::unmanage (void)
552 // nothing to do
556 ACE_Process::running (void) const
558 #if defined (ACE_WIN32)
559 DWORD code;
561 BOOL result = ::GetExitCodeProcess (this->gethandle (),
562 &code);
563 return result && code == STILL_ACTIVE;
564 #else
565 if (ACE_INVALID_PID == this->getpid ())
566 return 0;
567 else
568 return ACE_OS::kill (this->getpid (),
569 0) == 0
570 || errno != ESRCH;
571 #endif /* ACE_WIN32 */
574 pid_t
575 ACE_Process::wait (const ACE_Time_Value &tv,
576 ACE_exitcode *status)
578 #if defined (ACE_WIN32)
579 // Don't try to get the process exit status if wait failed so we can
580 // keep the original error code intact.
581 switch (::WaitForSingleObject (process_info_.hProcess,
582 tv.msec ()))
584 case WAIT_OBJECT_0:
585 // The error status of <GetExitCodeProcess> is nonetheless not
586 // tested because we don't know how to return the value.
587 ::GetExitCodeProcess (process_info_.hProcess,
588 &this->exit_code_);
589 if (status != 0)
590 *status = this->exit_code_;
591 return this->getpid ();
592 case WAIT_TIMEOUT:
593 errno = ETIME;
594 return 0;
595 default:
596 ACE_OS::set_errno_to_last_error ();
597 return -1;
599 #elif defined(ACE_LACKS_UNIX_SIGNALS)
600 if (tv == ACE_Time_Value::zero)
602 pid_t retv =
603 ACE_OS::waitpid (this->child_id_,
604 &this->exit_code_,
605 WNOHANG);
606 if (status != 0)
607 *status = this->exit_code_;
609 return retv;
612 if (tv == ACE_Time_Value::max_time)
613 # if defined (ACE_VXWORKS)
615 pid_t retv;
616 while ( (retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR ) ;
617 return retv;
619 # else
620 return this->wait (status);
621 # endif
623 pid_t pid = 0;
624 ACE_Time_Value sleeptm (1); // 1 msec
625 if (sleeptm > tv) // if sleeptime > waittime
626 sleeptm = tv;
627 ACE_Time_Value tmo (tv); // Need one we can change
628 for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
630 pid = ACE_OS::waitpid (this->getpid (),
631 &this->exit_code_,
632 WNOHANG);
633 if (status != 0)
634 *status = this->exit_code_;
636 if (pid > 0 || pid == ACE_INVALID_PID)
637 break; // Got a child or an error - all done
639 // pid 0, nothing is ready yet, so wait.
640 // Do a (very) short sleep (only this thread sleeps).
641 ACE_OS::sleep (sleeptm);
644 return pid;
645 #else /* !ACE_WIN32 && !ACE_LACKS_UNIX_SIGNALS */
646 if (tv == ACE_Time_Value::zero)
648 pid_t retv =
649 ACE_OS::waitpid (this->child_id_,
650 &this->exit_code_,
651 WNOHANG);
652 if (status != 0)
653 *status = this->exit_code_;
655 return retv;
658 if (tv == ACE_Time_Value::max_time)
659 return this->wait (status);
661 // Need to wait but limited to specified time.
662 // Force generation of SIGCHLD, even though we don't want to
663 // catch it - just need it to interrupt the sleep below.
664 // If this object has a reactor set, assume it was given at
665 // open(), and there's already a SIGCHLD action set, so no
666 // action is needed here.
667 ACE_Sig_Action old_action;
668 ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
669 do_sigchld.register_action (SIGCHLD, &old_action);
671 pid_t pid;
672 ACE_Time_Value tmo (tv); // Need one we can change
673 for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
675 pid = ACE_OS::waitpid (this->getpid (),
676 &this->exit_code_,
677 WNOHANG);
678 if (status != 0)
679 *status = this->exit_code_;
681 if (pid > 0 || pid == ACE_INVALID_PID)
682 break; // Got a child or an error - all done
684 // pid 0, nothing is ready yet, so wait.
685 // Do a sleep (only this thread sleeps) til something
686 // happens. This relies on SIGCHLD interrupting the sleep.
687 // If SIGCHLD isn't delivered, we'll need to do something
688 // with sigaction to force it.
689 if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
690 continue;
691 // Timed out
692 pid = 0;
693 break;
696 // Restore the previous SIGCHLD action if it was changed.
697 old_action.register_action (SIGCHLD);
699 return pid;
700 #endif /* ACE_WIN32 */
703 void
704 ACE_Process::close_dup_handles (void)
706 if (this->dup_handles_.num_set () > 0)
708 ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
709 for (ACE_HANDLE h = h_iter ();
710 h != ACE_INVALID_HANDLE;
711 h = h_iter ())
712 ACE_OS::closesocket (h);
713 this->dup_handles_.reset ();
715 return;
718 void
719 ACE_Process::close_passed_handles (void)
721 if (this->handles_passed_.num_set () > 0)
723 ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
724 for (ACE_HANDLE h = h_iter ();
725 h != ACE_INVALID_HANDLE;
726 h = h_iter ())
727 ACE_OS::closesocket (h);
728 this->handles_passed_.reset ();
730 return;
733 #if defined (ACE_WIN32) && \
734 defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR) && \
735 !defined (ACE_HAS_WINCE)
736 wchar_t*
737 ACE_Process::convert_env_buffer (const char* env) const
739 // Total starts out at 1 due to the final block nul terminator
740 size_t total = 1;
742 // Convert each individual character string to the equivalent wide
743 // character string.
744 ACE_Vector<wchar_t*> buffer;
745 size_t start = 0;
746 size_t i = 0;
747 while (true)
749 if (env[i] == '\0')
751 // Convert the char string to wchar_t
752 wchar_t* str = ACE_Ascii_To_Wide::convert (env + start);
754 // Add the length of the string plus the nul terminator
755 total += ACE_OS::strlen (str) + 1;
757 // Save it and set up for the next string
758 buffer.push_back (str);
759 start = ++i;
760 if (env[start] == '\0')
761 break;
763 else
765 i += ACE_OS::strlen (env + i);
769 // Copy each string into the buffer leaving a nul terminator between
770 // each string and adding a second nul terminator at the end
771 start = 0;
772 wchar_t* wenv = new wchar_t[total];
773 size_t length = buffer.size ();
774 for (i = 0; i < length; ++i)
776 ACE_OS::strcpy(wenv + start, buffer[i]);
777 start += ACE_OS::strlen (buffer[i]) + 1;
778 delete [] buffer[i];
780 wenv[start] = 0;
781 return wenv;
783 #endif
785 ACE_Process_Options::ACE_Process_Options (bool inherit_environment,
786 int command_line_buf_len,
787 int env_buf_len,
788 int max_env_args)
790 #if !defined (ACE_HAS_WINCE)
791 inherit_environment_ (inherit_environment),
792 #endif /* ACE_HAS_WINCE */
793 creation_flags_ (0),
794 avoid_zombies_ (0),
795 #if !defined (ACE_HAS_WINCE)
796 #if defined (ACE_WIN32)
797 environment_inherited_ (0),
798 handle_inheritence_ (TRUE),
799 process_attributes_ (0),
800 thread_attributes_ (0),
801 #else /* ACE_WIN32 */
802 stdin_ (ACE_INVALID_HANDLE),
803 stdout_ (ACE_INVALID_HANDLE),
804 stderr_ (ACE_INVALID_HANDLE),
805 ruid_ ((uid_t) -1),
806 euid_ ((uid_t) -1),
807 rgid_ ((uid_t) -1),
808 egid_ ((uid_t) -1),
809 #endif /* ACE_WIN32 */
810 set_handles_called_ (0),
811 environment_buf_index_ (0),
812 environment_argv_index_ (0),
813 environment_buf_ (0),
814 environment_buf_len_ (env_buf_len),
815 max_environment_args_ (max_env_args),
816 max_environ_argv_index_ (max_env_args - 1),
817 #endif /* !ACE_HAS_WINCE */
818 command_line_argv_calculated_ (0),
819 command_line_buf_ (0),
820 command_line_copy_ (0),
821 command_line_buf_len_ (command_line_buf_len),
822 process_group_ (ACE_INVALID_PID),
823 use_unicode_environment_ (false)
825 ACE_NEW (command_line_buf_,
826 ACE_TCHAR[command_line_buf_len]);
827 command_line_buf_[0] = '\0';
829 #if !defined (ACE_HAS_WINCE)
830 working_directory_[0] = '\0';
831 ACE_NEW (environment_buf_,
832 ACE_TCHAR[env_buf_len]);
833 ACE_NEW (environment_argv_,
834 ACE_TCHAR *[max_env_args]);
835 environment_buf_[0] = '\0';
836 environment_argv_[0] = 0;
837 process_name_[0] = '\0';
838 #if defined (ACE_WIN32)
839 ACE_OS::memset ((void *) &this->startup_info_,
841 sizeof this->startup_info_);
842 this->startup_info_.cb = sizeof this->startup_info_;
843 #endif /* ACE_WIN32 */
844 #endif /* !ACE_HAS_WINCE */
847 #if !defined (ACE_HAS_WINCE)
848 #if defined (ACE_WIN32)
849 void
850 ACE_Process_Options::inherit_environment (void)
852 // Ensure only once execution.
853 if (environment_inherited_)
854 return;
855 environment_inherited_ = 1;
857 // Get the existing environment.
858 ACE_TCHAR *existing_environment = 0;
859 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
860 WCHAR *existing_wide_env = 0;
861 ACE_Vector<char> temp_narrow_env;
862 if (this->use_unicode_environment_)
864 existing_wide_env = ::GetEnvironmentStringsW ();
865 for (WCHAR *iter = existing_wide_env; *iter; ++iter)
867 ACE_Wide_To_Ascii wta (iter);
868 size_t len = ACE_OS::strlen (wta.char_rep ());
869 size_t idx = temp_narrow_env.size ();
870 temp_narrow_env.resize (idx + len + 1, 0);
871 ACE_OS::strncpy (&temp_narrow_env[idx], wta.char_rep (), len);
872 iter += len;
874 temp_narrow_env.push_back (0);
875 existing_environment = &temp_narrow_env[0];
877 else
878 #endif
879 existing_environment = ACE_OS::getenvstrings ();
881 size_t slot = 0;
883 while (existing_environment[slot] != '\0')
885 size_t len = ACE_OS::strlen (existing_environment + slot);
887 // Add the string to our env buffer.
888 if (this->setenv_i (existing_environment + slot, len) == -1)
890 ACE_ERROR ((LM_ERROR,
891 ACE_TEXT ("%p.\n"),
892 ACE_TEXT ("ACE_Process_Options::ACE_Process_Options")));
893 break;
896 // Skip to the next word.
897 slot += len + 1;
900 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
901 if (this->use_unicode_environment_)
902 ::FreeEnvironmentStringsW (existing_wide_env);
903 else
904 #endif
905 ACE_TEXT_FreeEnvironmentStrings (existing_environment);
908 #else /* defined ACE_WIN32 */
910 ACE_TCHAR * const *
911 ACE_Process_Options::env_argv (void)
913 return environment_argv_;
916 #endif /* ACE_WIN32 */
918 void
919 ACE_Process_Options::enable_unicode_environment (void)
921 this->use_unicode_environment_ = true;
924 void
925 ACE_Process_Options::disable_unicode_environment (void)
927 this->use_unicode_environment_ = false;
930 bool
931 ACE_Process_Options::use_unicode_environment (void) const
933 return this->use_unicode_environment_;
937 ACE_Process_Options::setenv (ACE_TCHAR *envp[])
939 int i = 0;
940 while (envp[i])
942 if (this->setenv_i (envp[i],
943 ACE_OS::strlen (envp[i])) == -1)
944 return -1;
945 i++;
948 #if defined (ACE_WIN32)
949 if (inherit_environment_)
950 this->inherit_environment ();
951 #endif /* ACE_WIN32 */
953 return 0;
957 ACE_Process_Options::setenv (const ACE_TCHAR *format, ...)
959 ACE_TCHAR stack_buf[DEFAULT_COMMAND_LINE_BUF_LEN];
961 // Start varargs.
962 va_list argp;
963 va_start (argp, format);
965 // Add the rest of the varargs.
966 ACE_OS::vsprintf (stack_buf,
967 format,
968 argp);
969 // End varargs.
970 va_end (argp);
972 // Append the string to are environment buffer.
973 if (this->setenv_i (stack_buf,
974 ACE_OS::strlen (stack_buf)) == -1)
975 return -1;
977 #if defined (ACE_WIN32)
978 if (inherit_environment_)
979 this->inherit_environment ();
980 #endif /* ACE_WIN32 */
982 return 0;
986 ACE_Process_Options::setenv (const ACE_TCHAR *variable_name,
987 const ACE_TCHAR *format, ...)
989 // To address the potential buffer overflow,
990 // we now allocate the buffer on heap with a variable size.
991 size_t const buflen = ACE_OS::strlen (variable_name) + ACE_OS::strlen (format) + 2;
992 ACE_TCHAR *newformat = 0;
993 ACE_NEW_RETURN (newformat, ACE_TCHAR[buflen], -1);
994 ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_newformat (newformat);
996 // Add in the variable name.
997 ACE_OS::sprintf (safe_newformat.get (),
998 ACE_TEXT ("%s=%s"),
999 variable_name,
1000 format);
1002 // Start varargs.
1003 va_list argp;
1004 va_start (argp, format);
1006 // Add the rest of the varargs.
1007 size_t tmp_buflen = DEFAULT_COMMAND_LINE_BUF_LEN > buflen
1008 ? static_cast<size_t> (DEFAULT_COMMAND_LINE_BUF_LEN) : buflen;
1009 int retval = 0;
1011 ACE_TCHAR *stack_buf = 0;
1012 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
1013 ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_stack_buf (stack_buf);
1017 retval = ACE_OS::vsnprintf (safe_stack_buf.get (), tmp_buflen, safe_newformat.get (), argp);
1018 if (retval > ACE_Utils::truncate_cast<int> (tmp_buflen))
1020 tmp_buflen *= 2;
1021 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
1022 safe_stack_buf.reset (stack_buf);
1024 else
1025 break;
1027 while (1);
1029 if (retval == -1)
1031 // In case that vsnprintf is not supported,
1032 // e.g., LynxOS and VxWorks 5, we have to
1033 // fall back to vsprintf.
1034 if (errno == ENOTSUP)
1036 // ALERT: Since we have to use vsprintf here, there is still a chance that
1037 // the stack_buf overflows, i.e., the length of the resulting string
1038 // can still possibly go beyond the allocated stack_buf.
1039 retval = ACE_OS::vsprintf (safe_stack_buf.get (), safe_newformat.get (), argp);
1040 if (retval == -1)
1041 // vsprintf is failed.
1042 return -1;
1044 else
1045 // vsnprintf is failed.
1046 return -1;
1049 // End varargs.
1050 va_end (argp);
1052 // Append the string to our environment buffer.
1053 if (this->setenv_i (safe_stack_buf.get (),
1054 ACE_OS::strlen (safe_stack_buf.get ())) == -1)
1055 return -1;
1057 #if defined (ACE_WIN32)
1058 if (inherit_environment_)
1059 this->inherit_environment ();
1060 #endif /* ACE_WIN32 */
1062 return 0;
1066 ACE_Process_Options::setenv_i (ACE_TCHAR *assignment,
1067 size_t len)
1069 // Add one for the null char.
1070 ++len;
1072 // If environment larger than allocated buffer return. Also check to
1073 // make sure we have enough room.
1074 if (environment_argv_index_ == max_environ_argv_index_
1075 || (len + environment_buf_index_) >= environment_buf_len_)
1076 return -1;
1078 // Copy the new environment string.
1079 ACE_OS::memcpy (environment_buf_ + environment_buf_index_,
1080 assignment,
1081 len * sizeof (ACE_TCHAR));
1083 // Update the argv array.
1084 environment_argv_[environment_argv_index_++] =
1085 environment_buf_ + environment_buf_index_;
1086 environment_argv_[environment_argv_index_] = 0;
1088 // Update our index.
1089 environment_buf_index_ += len;
1091 // Make sure the buffer is null-terminated.
1092 environment_buf_[environment_buf_index_] = '\0';
1093 return 0;
1097 ACE_Process_Options::set_handles (ACE_HANDLE std_in,
1098 ACE_HANDLE std_out,
1099 ACE_HANDLE std_err)
1101 this->set_handles_called_ = 1;
1102 #if defined (ACE_WIN32)
1104 // Tell the new process to use our std handles.
1105 this->startup_info_.dwFlags = STARTF_USESTDHANDLES;
1107 if (std_in == ACE_INVALID_HANDLE)
1108 std_in = ACE_STDIN;
1109 if (std_out == ACE_INVALID_HANDLE)
1110 std_out = ACE_STDOUT;
1111 if (std_err == ACE_INVALID_HANDLE)
1112 std_err = ACE_STDERR;
1114 if (!::DuplicateHandle (::GetCurrentProcess (),
1115 std_in,
1116 ::GetCurrentProcess (),
1117 &this->startup_info_.hStdInput,
1119 TRUE,
1120 DUPLICATE_SAME_ACCESS))
1121 return -1;
1123 if (!::DuplicateHandle (::GetCurrentProcess (),
1124 std_out,
1125 ::GetCurrentProcess (),
1126 &this->startup_info_.hStdOutput,
1128 TRUE,
1129 DUPLICATE_SAME_ACCESS))
1130 return -1;
1132 if (!::DuplicateHandle (::GetCurrentProcess (),
1133 std_err,
1134 ::GetCurrentProcess (),
1135 &this->startup_info_.hStdError,
1137 TRUE,
1138 DUPLICATE_SAME_ACCESS))
1139 return -1;
1140 #else /* ACE_WIN32 */
1141 this->stdin_ = ACE_OS::dup (std_in);
1142 this->stdout_ = ACE_OS::dup (std_out);
1143 this->stderr_ = ACE_OS::dup (std_err);
1144 #endif /* ACE_WIN32 */
1146 return 0; // Success.
1150 void
1151 ACE_Process_Options::release_handles ()
1153 if (set_handles_called_)
1155 #if defined (ACE_WIN32)
1156 ACE_OS::close (startup_info_.hStdInput);
1157 ACE_OS::close (startup_info_.hStdOutput);
1158 ACE_OS::close (startup_info_.hStdError);
1159 #else /* ACE_WIN32 */
1160 ACE_OS::close (stdin_);
1161 ACE_OS::close (stdout_);
1162 ACE_OS::close (stderr_);
1163 #endif /* ACE_WIN32 */
1164 set_handles_called_ = 0;
1167 #endif /* !ACE_HAS_WINCE */
1170 ACE_Process_Options::~ACE_Process_Options (void)
1172 #if !defined (ACE_HAS_WINCE)
1173 release_handles();
1174 delete [] environment_buf_;
1175 delete [] environment_argv_;
1176 #endif /* !ACE_HAS_WINCE */
1177 delete [] command_line_buf_;
1178 ACE::strdelete (command_line_copy_);
1182 ACE_Process_Options::command_line (const ACE_TCHAR *const argv[])
1184 // @@ Factor out the code between this
1185 int i = 0;
1187 if (argv[i])
1189 ACE_OS::strcat (command_line_buf_, argv[i]);
1190 while (argv[++i])
1192 ACE_OS::strcat (command_line_buf_,
1193 ACE_TEXT (" "));
1194 ACE_OS::strcat (command_line_buf_,
1195 argv[i]);
1199 command_line_argv_calculated_ = 0;
1200 return 0; // Success.
1204 ACE_Process_Options::command_line (const ACE_TCHAR *format, ...)
1206 // Store all ... args in argp.
1207 va_list argp;
1208 va_start (argp, format);
1210 if (command_line_buf_len_ < 1)
1211 return -1;
1213 #if !defined (ACE_LACKS_VSNPRINTF) || defined (ACE_HAS_TRIO)
1214 // vsnprintf the format and args into command_line_buf__.
1215 ACE_OS::vsnprintf (command_line_buf_,
1216 command_line_buf_len_,
1217 format,
1218 argp);
1219 #else
1220 // sprintf the format and args into command_line_buf__.
1221 ACE_OS::vsprintf (command_line_buf_,
1222 format,
1223 argp);
1224 #endif
1226 // Useless macro.
1227 va_end (argp);
1229 command_line_argv_calculated_ = 0;
1230 return 0;
1233 #if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE)
1235 * @note Not available on Windows CE because it doesn't have a char version of
1236 * vsprintf.
1239 ACE_Process_Options::command_line (const ACE_ANTI_TCHAR *format, ...)
1241 ACE_ANTI_TCHAR *anti_clb;
1242 ACE_NEW_RETURN (anti_clb,
1243 ACE_ANTI_TCHAR[this->command_line_buf_len_],
1244 -1);
1246 // Store all ... args in argp.
1247 va_list argp;
1248 va_start (argp, format);
1250 // sprintf the format and args into command_line_buf_.
1251 ACE_OS::vsprintf (anti_clb,
1252 format,
1253 argp);
1255 // Useless macro.
1256 va_end (argp);
1258 ACE_OS::strcpy (this->command_line_buf_,
1259 ACE_TEXT_ANTI_TO_TCHAR (anti_clb));
1261 delete [] anti_clb;
1263 command_line_argv_calculated_ = 0;
1264 return 0;
1266 #endif /* ACE_HAS_WCHAR && !ACE_HAS_WINCE */
1268 ACE_TCHAR *
1269 ACE_Process_Options::env_buf (void)
1271 #if !defined (ACE_HAS_WINCE)
1272 if (environment_buf_[0] == '\0')
1273 return 0;
1274 else
1275 return environment_buf_;
1276 #else
1277 return 0;
1278 #endif /* !ACE_HAS_WINCE */
1281 ACE_TCHAR * const *
1282 ACE_Process_Options::command_line_argv (void)
1284 if (command_line_argv_calculated_ == 0)
1286 command_line_argv_calculated_ = 1;
1288 // We need to free up any previous allocated memory first.
1289 ACE::strdelete (command_line_copy_);
1291 // We need to make a dynamically allocated copy here since
1292 // ACE_Tokenizer modifies its arguments.
1293 command_line_copy_ = ACE::strnew (command_line_buf_);
1294 // This tokenizer will replace all spaces with end-of-string
1295 // characters and will preserve text between "" and '' pairs.
1296 ACE_Tokenizer parser (command_line_copy_);
1297 parser.delimiter_replace (' ', '\0');
1298 parser.preserve_designators ('\"', '\"'); // "
1299 parser.preserve_designators ('\'', '\'');
1301 int x = 0;
1303 command_line_argv_[x] = parser.next ();
1304 while (command_line_argv_[x] != 0
1305 // substract one for the ending zero.
1306 && ++x < MAX_COMMAND_LINE_OPTIONS - 1);
1308 command_line_argv_[x] = 0;
1311 return command_line_argv_;
1314 // Cause the specified handle to be passed to a child process
1315 // when it's spawned.
1317 ACE_Process_Options::pass_handle (ACE_HANDLE h)
1319 # if defined (ACE_WIN32)
1320 # if defined (ACE_HAS_WINCE)
1321 ACE_NOTSUP_RETURN (-1);
1322 # else
1324 // This is oriented towards socket handles... may need some adjustment
1325 // for non-sockets.
1326 // This is all based on an MSDN article:
1327 // http://support.microsoft.com/support/kb/articles/Q150/5/23.asp
1328 // If on Win95/98, the handle needs to be duplicated for the to-be-spawned
1329 // process. On WinNT, they get inherited by the child process automatically.
1330 // If the handle is duplicated, remember the duplicate so it can be
1331 // closed later. Can't be closed now, or the child won't get it.
1332 ACE_TEXT_OSVERSIONINFO osvi;
1333 ZeroMemory (&osvi, sizeof (osvi));
1334 osvi.dwOSVersionInfoSize = sizeof (ACE_TEXT_OSVERSIONINFO);
1335 // If this is Win95/98 or we can't tell, duplicate the handle.
1336 if (!ACE_TEXT_GetVersionEx (&osvi) || osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
1338 HANDLE dup_handle;
1339 if (!DuplicateHandle (GetCurrentProcess (),
1340 static_cast<HANDLE> (h),
1341 GetCurrentProcess (),
1342 &dup_handle,
1344 TRUE, // Inheritable
1345 DUPLICATE_SAME_ACCESS))
1346 return -1;
1347 dup_handles_.set_bit (static_cast<ACE_HANDLE> (dup_handle));
1349 # endif /* ACE_HAS_WINCE */
1350 #endif /* ACE_WIN32 */
1352 this->handles_passed_.set_bit (h);
1354 return 0;
1357 // Get a copy of the handles the ACE_Process_Options duplicated
1358 // for the spawned process.
1360 ACE_Process_Options::dup_handles (ACE_Handle_Set &set) const
1362 if (this->dup_handles_.num_set () == 0)
1363 return 0;
1364 set.reset ();
1365 set = this->dup_handles_;
1366 return 1;
1369 // Get a copy of the handles passed to the spawned process. This
1370 // will be the set of handles previously passed to @arg pass_handle().
1372 ACE_Process_Options::passed_handles (ACE_Handle_Set &set) const
1374 if (this->handles_passed_.num_set () == 0)
1375 return 0;
1376 set.reset ();
1377 set = this->handles_passed_;
1378 return 1;
1381 ACE_Managed_Process::~ACE_Managed_Process (void)
1385 void
1386 ACE_Managed_Process::unmanage (void)
1388 delete this;
1391 ACE_END_VERSIONED_NAMESPACE_DECL