00001
00002
00003 #include "ace/Process.h"
00004
00005 #if !defined (__ACE_INLINE__)
00006 #include "ace/Process.inl"
00007 #endif
00008
00009 #include "ace/ARGV.h"
00010 #include "ace/Auto_Ptr.h"
00011 #include "ace/Signal.h"
00012 #include "ace/SString.h"
00013 #include "ace/Log_Msg.h"
00014 #include "ace/OS_NS_stdio.h"
00015 #include "ace/OS_NS_stdlib.h"
00016 #include "ace/OS_NS_sys_socket.h"
00017 #include "ace/OS_NS_errno.h"
00018 #include "ace/OS_NS_string.h"
00019 #include "ace/OS_NS_unistd.h"
00020 #include "ace/OS_NS_fcntl.h"
00021 #include "ace/OS_Memory.h"
00022 #include "ace/Countdown_Time.h"
00023 #include "ace/Truncate.h"
00024 #include "ace/Vector_T.h"
00025 #include "ace/Tokenizer_T.h"
00026
00027 #if defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600) && defined (__RTP__)
00028 # include <rtpLib.h>
00029 # include <taskLib.h>
00030 #endif
00031
00032 ACE_RCSID (ace, Process, "$Id: Process.cpp 87826 2009-11-30 14:02:40Z johnnyw $")
00033
00034
00035
00036
00037 #if !defined (ACE_WIN32) && !defined(ACE_LACKS_UNIX_SIGNALS)
00038 static void
00039 sigchld_nop (int, siginfo_t *, ucontext_t *)
00040 {
00041 return;
00042 }
00043 #endif
00044
00045
00046 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00047
00048 ACE_Process::ACE_Process (void)
00049 :
00050 #if !defined (ACE_WIN32)
00051 child_id_ (ACE_INVALID_PID),
00052 #endif
00053 exit_code_ (0)
00054 {
00055 #if defined (ACE_WIN32)
00056 ACE_OS::memset ((void *) &this->process_info_,
00057 0,
00058 sizeof this->process_info_);
00059 #endif
00060 }
00061
00062 ACE_Process::~ACE_Process (void)
00063 {
00064 #if defined (ACE_WIN32)
00065
00066 ACE_OS::close (this->process_info_.hThread);
00067 ACE_OS::close (this->process_info_.hProcess);
00068 #endif
00069
00070
00071 this->close_dup_handles ();
00072 }
00073
00074 int
00075 ACE_Process::prepare (ACE_Process_Options &)
00076 {
00077 return 0;
00078 }
00079
00080 pid_t
00081 ACE_Process::spawn (ACE_Process_Options &options)
00082 {
00083 if (this->prepare (options) < 0)
00084 return ACE_INVALID_PID;
00085
00086
00087
00088
00089 ACE_Handle_Set *set_p = 0;
00090 if (options.dup_handles (this->dup_handles_))
00091 set_p = &this->dup_handles_;
00092 else if (options.passed_handles (this->handles_passed_))
00093 set_p = &this->handles_passed_;
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
00105 ACE_Process_Options::NO_EXEC))
00106 {
00107 int maxlen = 0;
00108 ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen);
00109 size_t max_len = static_cast<size_t> (maxlen);
00110 size_t curr_len = ACE_OS::strlen (cmd_line_buf);
00111 ACE_Handle_Set_Iterator h_iter (*set_p);
00112
00113
00114
00115 for (ACE_HANDLE h = h_iter ();
00116 h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
00117 h = h_iter ())
00118 {
00119 #if defined (ACE_WIN32)
00120 # if defined (ACE_WIN64)
00121 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00122 ACE_TEXT (" +H %I64p"),
00123 h);
00124 # else
00125 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00126 ACE_TEXT (" +H %p"),
00127 h);
00128 # endif
00129 #else
00130 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00131 ACE_TEXT (" +H %d"),
00132 h);
00133 #endif
00134 }
00135 }
00136
00137 #if defined (ACE_HAS_WINCE)
00138
00139
00140
00141
00142 BOOL fork_result =
00143 ACE_TEXT_CreateProcess (options.process_name(),
00144 options.command_line_buf(),
00145 options.get_process_attributes(),
00146 options.get_thread_attributes(),
00147 options.handle_inheritance(),
00148 options.creation_flags(),
00149 options.env_buf(),
00150 options.working_directory(),
00151 options.startup_info(),
00152 &this->process_info_);
00153
00154 if (fork_result)
00155 {
00156 parent (this->getpid ());
00157 return this->getpid ();
00158 }
00159 return ACE_INVALID_PID;
00160
00161 #elif defined (ACE_WIN32)
00162 void* env_buf = options.env_buf ();
00163 DWORD flags = options.creation_flags ();
00164 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
00165 wchar_t* wenv_buf = 0;
00166 if (options.use_unicode_environment ())
00167 {
00168 wenv_buf = this->convert_env_buffer (options.env_buf ());
00169 env_buf = wenv_buf;
00170 flags |= CREATE_UNICODE_ENVIRONMENT;
00171 }
00172 # endif
00173
00174 BOOL fork_result =
00175 ACE_TEXT_CreateProcess (0,
00176 options.command_line_buf (),
00177 options.get_process_attributes (),
00178 options.get_thread_attributes (),
00179 options.handle_inheritance (),
00180 flags,
00181 env_buf,
00182 options.working_directory (),
00183 options.startup_info (),
00184 &this->process_info_);
00185
00186 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
00187 if (options.use_unicode_environment ())
00188 delete wenv_buf;
00189 # endif
00190
00191 if (fork_result)
00192 {
00193 parent (this->getpid ());
00194 return this->getpid ();
00195 }
00196 return ACE_INVALID_PID;
00197
00198 #elif defined(ACE_OPENVMS)
00199 if (ACE_BIT_ENABLED (options.creation_flags (),
00200 ACE_Process_Options::NO_EXEC))
00201 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00202
00203 int saved_stdin = ACE_STDIN;
00204 int saved_stdout = ACE_STDOUT;
00205 int saved_stderr = ACE_STDERR;
00206
00207 if (options.get_stdin () != ACE_INVALID_HANDLE) {
00208 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
00209 ACE_OS::exit (errno);
00210 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
00211 ACE_OS::exit (errno);
00212 }
00213 if (options.get_stdout () != ACE_INVALID_HANDLE) {
00214 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
00215 ACE_OS::exit (errno);
00216 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
00217 ACE_OS::exit (errno);
00218 }
00219 if (options.get_stderr () != ACE_INVALID_HANDLE) {
00220 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
00221 ACE_OS::exit (errno);
00222 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
00223 ACE_OS::exit (errno);
00224 }
00225
00226 if (options.working_directory () != 0)
00227 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00228
00229 this->child_id_ = vfork();
00230 if (this->child_id_ == 0) {
00231 ACE_OS::execvp (options.process_name (),
00232 options.command_line_argv ());
00233
00234 this->child_id_ = ACE_INVALID_PID;
00235 }
00236
00237
00238 if (options.get_stdin () != ACE_INVALID_HANDLE) {
00239 if (saved_stdin == -1)
00240 ACE_OS::close (ACE_STDIN);
00241 else
00242 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
00243 }
00244 if (options.get_stdout () != ACE_INVALID_HANDLE) {
00245 if (saved_stdout == -1)
00246 ACE_OS::close (ACE_STDOUT);
00247 else
00248 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
00249 }
00250 if (options.get_stderr () != ACE_INVALID_HANDLE) {
00251 if (saved_stderr == -1)
00252 ACE_OS::close (ACE_STDERR);
00253 else
00254 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
00255 }
00256
00257 return this->child_id_;
00258 #elif (defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600)) && defined (__RTP__)
00259 if (ACE_BIT_ENABLED (options.creation_flags (),
00260 ACE_Process_Options::NO_EXEC))
00261 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00262
00263 if (options.working_directory () != 0)
00264 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00265
00266 int saved_stdin = ACE_STDIN;
00267 int saved_stdout = ACE_STDOUT;
00268 int saved_stderr = ACE_STDERR;
00269
00270 if (options.get_stdin () != ACE_INVALID_HANDLE) {
00271 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
00272 ACE_OS::exit (errno);
00273 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
00274 ACE_OS::exit (errno);
00275 }
00276 if (options.get_stdout () != ACE_INVALID_HANDLE) {
00277 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
00278 ACE_OS::exit (errno);
00279 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
00280 ACE_OS::exit (errno);
00281 }
00282 if (options.get_stderr () != ACE_INVALID_HANDLE) {
00283 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
00284 ACE_OS::exit (errno);
00285 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
00286 ACE_OS::exit (errno);
00287 }
00288
00289
00290
00291 # if defined (ACE_USES_WCHAR)
00292 wchar_t * const *wargv = options.command_line_argv ();
00293 size_t vcount, i;
00294 for (vcount = 0; wargv[vcount] != 0; ++vcount)
00295 ;
00296 char **procargv = new char *[vcount + 1];
00297 procargv[vcount] = 0;
00298 for (i = 0; i < vcount; ++i)
00299 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00300
00301 char **procenv = 0;
00302 if (options.inherit_environment ())
00303 {
00304 wargv = options.env_argv ();
00305 for (vcount = 0; wargv[vcount] != 0; ++vcount)
00306 ;
00307 procenv = new char *[vcount + 1];
00308 procenv[vcount] = 0;
00309 for (i = 0; i < vcount; ++i)
00310 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00311 }
00312 # else
00313 const char **procargv = const_cast<const char**> (options.command_line_argv ());
00314 const char **procenv = const_cast<const char**> (options.env_argv ());
00315 # endif
00316
00317 this->child_id_ = ::rtpSpawn (procargv[0],
00318 procargv,
00319 procenv,
00320 200,
00321 0x10000,
00322 0,
00323 VX_FP_TASK);
00324 int my_errno_ = errno;
00325 if (this->child_id_ == ERROR) {
00326
00327 this->child_id_ = ACE_INVALID_PID;
00328 }
00329
00330 # if defined (ACE_USES_WCHAR)
00331 if (procenv)
00332 delete procenv;
00333 # endif
00334
00335
00336 if (options.get_stdin () != ACE_INVALID_HANDLE) {
00337 if (saved_stdin == -1)
00338 ACE_OS::close (ACE_STDIN);
00339 else
00340 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
00341 }
00342 if (options.get_stdout () != ACE_INVALID_HANDLE) {
00343 if (saved_stdout == -1)
00344 ACE_OS::close (ACE_STDOUT);
00345 else
00346 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
00347 }
00348 if (options.get_stderr () != ACE_INVALID_HANDLE) {
00349 if (saved_stderr == -1)
00350 ACE_OS::close (ACE_STDERR);
00351 else
00352 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
00353 }
00354
00355 if (this->child_id_ == ACE_INVALID_PID)
00356 {
00357 errno = my_errno_;
00358 }
00359
00360 return this->child_id_;
00361 #else
00362
00363 this->child_id_ = ACE::fork (options.process_name (),
00364 options.avoid_zombies ());
00365
00366 if (this->child_id_ == 0)
00367 {
00368 # if !defined (ACE_LACKS_SETPGID)
00369
00370
00371
00372
00373 if (options.getgroup () != ACE_INVALID_PID
00374 && ACE_OS::setpgid (0,
00375 options.getgroup ()) < 0)
00376 {
00377 #if !defined (ACE_HAS_THREADS)
00378
00379
00380
00381 ACE_ERROR ((LM_ERROR,
00382 ACE_TEXT ("%p.\n"),
00383 ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
00384 #endif
00385 }
00386 # endif
00387
00388 # if !defined (ACE_LACKS_SETREGID)
00389 if (options.getrgid () != (uid_t) -1
00390 || options.getegid () != (uid_t) -1)
00391 if (ACE_OS::setregid (options.getrgid (),
00392 options.getegid ()) == -1)
00393 {
00394 #if !defined (ACE_HAS_THREADS)
00395
00396
00397
00398 ACE_ERROR ((LM_ERROR,
00399 ACE_TEXT ("%p.\n"),
00400 ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
00401 #endif
00402 }
00403 # endif
00404
00405 # if !defined (ACE_LACKS_SETREUID)
00406
00407 if (options.getruid () != (uid_t) -1
00408 || options.geteuid () != (uid_t) -1)
00409 if (ACE_OS::setreuid (options.getruid (),
00410 options.geteuid ()) == -1)
00411 {
00412 #if !defined (ACE_HAS_THREADS)
00413
00414
00415
00416 ACE_ERROR ((LM_ERROR,
00417 ACE_TEXT ("%p.\n"),
00418 ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
00419 #endif
00420 }
00421 # endif
00422
00423 this->child (ACE_OS::getppid ());
00424 }
00425 else if (this->child_id_ != -1)
00426 this->parent (this->child_id_);
00427
00428
00429 if (ACE_BIT_ENABLED (options.creation_flags (),
00430 ACE_Process_Options::NO_EXEC))
00431 return this->child_id_;
00432
00433 switch (this->child_id_)
00434 {
00435 case -1:
00436
00437 return ACE_INVALID_PID;
00438 case 0:
00439
00440 {
00441 if (options.get_stdin () != ACE_INVALID_HANDLE
00442 && ACE_OS::dup2 (options.get_stdin (),
00443 ACE_STDIN) == -1)
00444 ACE_OS::exit (errno);
00445 else if (options.get_stdout () != ACE_INVALID_HANDLE
00446 && ACE_OS::dup2 (options.get_stdout (),
00447 ACE_STDOUT) == -1)
00448 ACE_OS::exit (errno);
00449 else if (options.get_stderr () != ACE_INVALID_HANDLE
00450 && ACE_OS::dup2 (options.get_stderr (),
00451 ACE_STDERR) == -1)
00452 ACE_OS::exit (errno);
00453
00454
00455 ACE_OS::close (options.get_stdin ());
00456 ACE_OS::close (options.get_stdout ());
00457 ACE_OS::close (options.get_stderr ());
00458 if (!options.handle_inheritance ())
00459 {
00460
00461 for (int i = ACE::max_handles () - 1; i >= 0; i--)
00462 {
00463 if (i == ACE_STDIN || i == ACE_STDOUT || i == ACE_STDERR)
00464 continue;
00465 ACE_OS::fcntl (i, F_SETFD, FD_CLOEXEC);
00466 }
00467 }
00468
00469
00470
00471 if (options.working_directory () != 0)
00472 ACE_OS::chdir (options.working_directory ());
00473
00474
00475
00476 int result = 0;
00477
00478
00479
00480
00481
00482 # if defined (ACE_USES_WCHAR)
00483 ACE_Wide_To_Ascii n_procname (options.process_name ());
00484 const char *procname = n_procname.char_rep ();
00485
00486 wchar_t * const *wargv = options.command_line_argv ();
00487 size_t vcount, i;
00488 for (vcount = 0; wargv[vcount] != 0; ++vcount)
00489 ;
00490 char **procargv = new char *[vcount + 1];
00491 procargv[vcount] = 0;
00492 for (i = 0; i < vcount; ++i)
00493 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00494
00495 wargv = options.env_argv ();
00496 for (vcount = 0; wargv[vcount] != 0; ++vcount)
00497 ;
00498 char **procenv = new char *[vcount + 1];
00499 procenv[vcount] = 0;
00500 for (i = 0; i < vcount; ++i)
00501 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00502 # else
00503 const char *procname = options.process_name ();
00504 char *const *procargv = options.command_line_argv ();
00505 char *const *procenv = options.env_argv ();
00506 # endif
00507
00508 if (options.inherit_environment ())
00509 {
00510
00511
00512 for (size_t i = 0; procenv[i] != 0; i++)
00513 if (ACE_OS::putenv (procenv[i]) != 0)
00514 return ACE_INVALID_PID;
00515
00516
00517
00518 result = ACE_OS::execvp (procname, procargv);
00519 }
00520 else
00521 {
00522 # if defined (ghs)
00523
00524
00525 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00526 # else
00527 result = ACE_OS::execve (procname, procargv, procenv);
00528 # endif
00529 }
00530 if (result == -1)
00531 {
00532
00533
00534
00535
00536 ACE_OS::_exit (errno);
00537 }
00538
00539 return 0;
00540 }
00541 default:
00542
00543 return this->child_id_;
00544 }
00545 #endif
00546 }
00547
00548 void
00549 ACE_Process::parent (pid_t)
00550 {
00551
00552 }
00553
00554 void
00555 ACE_Process::child (pid_t)
00556 {
00557
00558 }
00559
00560 void
00561 ACE_Process::unmanage (void)
00562 {
00563
00564 }
00565
00566 int
00567 ACE_Process::running (void) const
00568 {
00569 #if defined (ACE_WIN32)
00570 DWORD code;
00571
00572 BOOL result = ::GetExitCodeProcess (this->gethandle (),
00573 &code);
00574 return result && code == STILL_ACTIVE;
00575 #else
00576 if (ACE_INVALID_PID == this->getpid ())
00577 return 0;
00578 else
00579 return ACE_OS::kill (this->getpid (),
00580 0) == 0
00581 || errno != ESRCH;
00582 #endif
00583 }
00584
00585 pid_t
00586 ACE_Process::wait (const ACE_Time_Value &tv,
00587 ACE_exitcode *status)
00588 {
00589 #if defined (ACE_WIN32)
00590
00591
00592 switch (::WaitForSingleObject (process_info_.hProcess,
00593 tv.msec ()))
00594 {
00595 case WAIT_OBJECT_0:
00596
00597
00598 ::GetExitCodeProcess (process_info_.hProcess,
00599 &this->exit_code_);
00600 if (status != 0)
00601 *status = this->exit_code_;
00602 return this->getpid ();
00603 case WAIT_TIMEOUT:
00604 errno = ETIME;
00605 return 0;
00606 default:
00607 ACE_OS::set_errno_to_last_error ();
00608 return -1;
00609 }
00610 #elif defined(ACE_LACKS_UNIX_SIGNALS)
00611 if (tv == ACE_Time_Value::zero)
00612 {
00613 pid_t retv =
00614 ACE_OS::waitpid (this->child_id_,
00615 &this->exit_code_,
00616 WNOHANG);
00617 if (status != 0)
00618 *status = this->exit_code_;
00619
00620 return retv;
00621 }
00622
00623 if (tv == ACE_Time_Value::max_time)
00624 # if defined (ACE_VXWORKS)
00625 {
00626 pid_t retv;
00627 while ( (retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR ) ;
00628 return retv;
00629 }
00630 # else
00631 return this->wait (status);
00632 # endif
00633
00634 pid_t pid = 0;
00635 ACE_Time_Value sleeptm (1);
00636 if (sleeptm > tv)
00637 sleeptm = tv;
00638 ACE_Time_Value tmo (tv);
00639 for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
00640 {
00641 pid = ACE_OS::waitpid (this->getpid (),
00642 &this->exit_code_,
00643 WNOHANG);
00644 if (status != 0)
00645 *status = this->exit_code_;
00646
00647 if (pid > 0 || pid == ACE_INVALID_PID)
00648 break;
00649
00650
00651
00652 ACE_OS::sleep (sleeptm);
00653 }
00654
00655 return pid;
00656 #else
00657 if (tv == ACE_Time_Value::zero)
00658 {
00659 pid_t retv =
00660 ACE_OS::waitpid (this->child_id_,
00661 &this->exit_code_,
00662 WNOHANG);
00663 if (status != 0)
00664 *status = this->exit_code_;
00665
00666 return retv;
00667 }
00668
00669 if (tv == ACE_Time_Value::max_time)
00670 return this->wait (status);
00671
00672
00673
00674
00675
00676
00677
00678 ACE_Sig_Action old_action;
00679 ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
00680 do_sigchld.register_action (SIGCHLD, &old_action);
00681
00682 pid_t pid;
00683 ACE_Time_Value tmo (tv);
00684 for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
00685 {
00686 pid = ACE_OS::waitpid (this->getpid (),
00687 &this->exit_code_,
00688 WNOHANG);
00689 if (status != 0)
00690 *status = this->exit_code_;
00691
00692 if (pid > 0 || pid == ACE_INVALID_PID)
00693 break;
00694
00695
00696
00697
00698
00699
00700 if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
00701 continue;
00702
00703 pid = 0;
00704 break;
00705 }
00706
00707
00708 old_action.register_action (SIGCHLD);
00709
00710 return pid;
00711 #endif
00712 }
00713
00714 void
00715 ACE_Process::close_dup_handles (void)
00716 {
00717 if (this->dup_handles_.num_set () > 0)
00718 {
00719 ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
00720 for (ACE_HANDLE h = h_iter ();
00721 h != ACE_INVALID_HANDLE;
00722 h = h_iter ())
00723 ACE_OS::closesocket (h);
00724 this->dup_handles_.reset ();
00725 }
00726 return;
00727 }
00728
00729 void
00730 ACE_Process::close_passed_handles (void)
00731 {
00732 if (this->handles_passed_.num_set () > 0)
00733 {
00734 ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
00735 for (ACE_HANDLE h = h_iter ();
00736 h != ACE_INVALID_HANDLE;
00737 h = h_iter ())
00738 ACE_OS::closesocket (h);
00739 this->handles_passed_.reset ();
00740 }
00741 return;
00742 }
00743
00744 #if defined (ACE_WIN32) && \
00745 defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR) && \
00746 !defined (ACE_HAS_WINCE)
00747 wchar_t*
00748 ACE_Process::convert_env_buffer (const char* env) const
00749 {
00750
00751 size_t total = 1;
00752
00753
00754
00755 ACE_Vector<wchar_t*> buffer;
00756 size_t start = 0;
00757 size_t i = 0;
00758 while (true)
00759 {
00760 if (env[i] == '\0')
00761 {
00762
00763 wchar_t* str = ACE_Ascii_To_Wide::convert (env + start);
00764
00765
00766 total += ACE_OS::strlen (str) + 1;
00767
00768
00769 buffer.push_back (str);
00770 start = ++i;
00771 if (env[start] == '\0')
00772 break;
00773 }
00774 else
00775 {
00776 i += ACE_OS::strlen (env + i);
00777 }
00778 }
00779
00780
00781
00782 start = 0;
00783 wchar_t* wenv = new wchar_t[total];
00784 size_t length = buffer.size ();
00785 for (i = 0; i < length; ++i)
00786 {
00787 ACE_OS::strcpy(wenv + start, buffer[i]);
00788 start += ACE_OS::strlen (buffer[i]) + 1;
00789 delete [] buffer[i];
00790 }
00791 wenv[start] = 0;
00792 return wenv;
00793 }
00794 #endif
00795
00796 ACE_Process_Options::ACE_Process_Options (bool inherit_environment,
00797 size_t command_line_buf_len,
00798 size_t env_buf_len,
00799 size_t max_env_args)
00800 :
00801 #if !defined (ACE_HAS_WINCE)
00802 inherit_environment_ (inherit_environment),
00803 #endif
00804 creation_flags_ (0),
00805 avoid_zombies_ (0),
00806 #if !defined (ACE_HAS_WINCE)
00807 #if defined (ACE_WIN32)
00808 environment_inherited_ (0),
00809 process_attributes_ (0),
00810 thread_attributes_ (0),
00811 #else
00812 stdin_ (ACE_INVALID_HANDLE),
00813 stdout_ (ACE_INVALID_HANDLE),
00814 stderr_ (ACE_INVALID_HANDLE),
00815 ruid_ ((uid_t) -1),
00816 euid_ ((uid_t) -1),
00817 rgid_ ((uid_t) -1),
00818 egid_ ((uid_t) -1),
00819 #endif
00820 handle_inheritance_ (true),
00821 set_handles_called_ (0),
00822 environment_buf_index_ (0),
00823 environment_argv_index_ (0),
00824 environment_buf_ (0),
00825 environment_buf_len_ (env_buf_len),
00826 max_environment_args_ (max_env_args),
00827 max_environ_argv_index_ (max_env_args - 1),
00828 #endif
00829 command_line_argv_calculated_ (false),
00830 command_line_buf_ (0),
00831 command_line_copy_ (0),
00832 command_line_buf_len_ (command_line_buf_len),
00833 process_group_ (ACE_INVALID_PID),
00834 use_unicode_environment_ (false)
00835 {
00836 ACE_NEW (command_line_buf_,
00837 ACE_TCHAR[command_line_buf_len]);
00838 command_line_buf_[0] = '\0';
00839 process_name_[0] = '\0';
00840
00841 #if defined (ACE_HAS_WINCE)
00842 ACE_UNUSED_ARG(inherit_environment);
00843 ACE_UNUSED_ARG(env_buf_len);
00844 ACE_UNUSED_ARG(max_env_args);
00845 #endif
00846
00847 #if !defined (ACE_HAS_WINCE)
00848 working_directory_[0] = '\0';
00849 ACE_NEW (environment_buf_,
00850 ACE_TCHAR[env_buf_len]);
00851 ACE_NEW (environment_argv_,
00852 ACE_TCHAR *[max_env_args]);
00853 environment_buf_[0] = '\0';
00854 environment_argv_[0] = 0;
00855 #if defined (ACE_WIN32)
00856 ACE_OS::memset ((void *) &this->startup_info_,
00857 0,
00858 sizeof this->startup_info_);
00859 this->startup_info_.cb = sizeof this->startup_info_;
00860 #endif
00861 #endif
00862 }
00863
00864 #if !defined (ACE_HAS_WINCE)
00865 #if defined (ACE_WIN32)
00866 void
00867 ACE_Process_Options::inherit_environment (void)
00868 {
00869
00870 if (environment_inherited_)
00871 return;
00872 environment_inherited_ = 1;
00873
00874
00875 ACE_TCHAR *existing_environment = 0;
00876 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
00877 WCHAR *existing_wide_env = 0;
00878 ACE_Vector<char> temp_narrow_env;
00879 if (this->use_unicode_environment_)
00880 {
00881 existing_wide_env = ::GetEnvironmentStringsW ();
00882 for (WCHAR *iter = existing_wide_env; *iter; ++iter)
00883 {
00884 ACE_Wide_To_Ascii wta (iter);
00885 size_t len = ACE_OS::strlen (wta.char_rep ());
00886 size_t idx = temp_narrow_env.size ();
00887 temp_narrow_env.resize (idx + len + 1, 0);
00888 ACE_OS::strncpy (&temp_narrow_env[idx], wta.char_rep (), len);
00889 iter += len;
00890 }
00891 temp_narrow_env.push_back (0);
00892 existing_environment = &temp_narrow_env[0];
00893 }
00894 else
00895 #endif
00896 existing_environment = ACE_OS::getenvstrings ();
00897
00898 size_t slot = 0;
00899
00900 while (existing_environment[slot] != '\0')
00901 {
00902 size_t len = ACE_OS::strlen (existing_environment + slot);
00903
00904
00905 if (this->setenv_i (existing_environment + slot, len) == -1)
00906 {
00907 ACE_ERROR ((LM_ERROR,
00908 ACE_TEXT ("%p.\n"),
00909 ACE_TEXT ("ACE_Process_Options::ACE_Process_Options")));
00910 break;
00911 }
00912
00913
00914 slot += len + 1;
00915 }
00916
00917 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
00918 if (this->use_unicode_environment_)
00919 ::FreeEnvironmentStringsW (existing_wide_env);
00920 else
00921 #endif
00922 ACE_TEXT_FreeEnvironmentStrings (existing_environment);
00923 }
00924
00925 #else
00926
00927 ACE_TCHAR * const *
00928 ACE_Process_Options::env_argv (void)
00929 {
00930 return environment_argv_;
00931 }
00932
00933 #endif
00934
00935 int
00936 ACE_Process_Options::setenv (ACE_TCHAR *envp[])
00937 {
00938 int i = 0;
00939 while (envp[i])
00940 {
00941 if (this->setenv_i (envp[i],
00942 ACE_OS::strlen (envp[i])) == -1)
00943 return -1;
00944 i++;
00945 }
00946
00947 #if defined (ACE_WIN32)
00948 if (inherit_environment_)
00949 this->inherit_environment ();
00950 #endif
00951
00952 return 0;
00953 }
00954
00955 int
00956 ACE_Process_Options::setenv (const ACE_TCHAR *format, ...)
00957 {
00958 ACE_TCHAR stack_buf[DEFAULT_COMMAND_LINE_BUF_LEN];
00959
00960
00961 va_list argp;
00962 va_start (argp, format);
00963
00964
00965 ACE_OS::vsprintf (stack_buf,
00966 format,
00967 argp);
00968
00969 va_end (argp);
00970
00971
00972 if (this->setenv_i (stack_buf,
00973 ACE_OS::strlen (stack_buf)) == -1)
00974 return -1;
00975
00976 #if defined (ACE_WIN32)
00977 if (inherit_environment_)
00978 this->inherit_environment ();
00979 #endif
00980
00981 return 0;
00982 }
00983
00984 int
00985 ACE_Process_Options::setenv (const ACE_TCHAR *variable_name,
00986 const ACE_TCHAR *format, ...)
00987 {
00988
00989
00990 size_t const buflen = ACE_OS::strlen (variable_name) + ACE_OS::strlen (format) + 2;
00991 ACE_TCHAR *newformat = 0;
00992 ACE_NEW_RETURN (newformat, ACE_TCHAR[buflen], -1);
00993 ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_newformat (newformat);
00994
00995
00996 ACE_OS::sprintf (safe_newformat.get (),
00997 ACE_TEXT ("%s=%s"),
00998 variable_name,
00999 format);
01000
01001
01002 va_list argp;
01003 va_start (argp, format);
01004
01005
01006 size_t tmp_buflen = buflen;
01007 if (DEFAULT_COMMAND_LINE_BUF_LEN > buflen)
01008 {
01009 tmp_buflen = DEFAULT_COMMAND_LINE_BUF_LEN;
01010 }
01011 int retval = 0;
01012
01013 ACE_TCHAR *stack_buf = 0;
01014 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
01015 ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_stack_buf (stack_buf);
01016
01017 do
01018 {
01019 retval = ACE_OS::vsnprintf (safe_stack_buf.get (), tmp_buflen, safe_newformat.get (), argp);
01020 if (retval > ACE_Utils::truncate_cast<int> (tmp_buflen))
01021 {
01022 tmp_buflen *= 2;
01023 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
01024 safe_stack_buf.reset (stack_buf);
01025 }
01026 else
01027 break;
01028 }
01029 while (1);
01030
01031 if (retval == -1)
01032 {
01033
01034
01035
01036 if (errno == ENOTSUP)
01037 {
01038
01039
01040
01041 retval = ACE_OS::vsprintf (safe_stack_buf.get (), safe_newformat.get (), argp);
01042 if (retval == -1)
01043
01044 return -1;
01045 }
01046 else
01047
01048 return -1;
01049 }
01050
01051
01052 va_end (argp);
01053
01054
01055 if (this->setenv_i (safe_stack_buf.get (),
01056 ACE_OS::strlen (safe_stack_buf.get ())) == -1)
01057 return -1;
01058
01059 #if defined (ACE_WIN32)
01060 if (inherit_environment_)
01061 this->inherit_environment ();
01062 #endif
01063
01064 return 0;
01065 }
01066
01067 int
01068 ACE_Process_Options::setenv_i (ACE_TCHAR *assignment,
01069 size_t len)
01070 {
01071
01072 ++len;
01073
01074
01075
01076 if (environment_argv_index_ == max_environ_argv_index_
01077 || (len + environment_buf_index_) >= environment_buf_len_)
01078 return -1;
01079
01080
01081 ACE_OS::memcpy (environment_buf_ + environment_buf_index_,
01082 assignment,
01083 len * sizeof (ACE_TCHAR));
01084
01085
01086 environment_argv_[environment_argv_index_++] =
01087 environment_buf_ + environment_buf_index_;
01088 environment_argv_[environment_argv_index_] = 0;
01089
01090
01091 environment_buf_index_ += len;
01092
01093
01094 environment_buf_[environment_buf_index_] = '\0';
01095 return 0;
01096 }
01097
01098 int
01099 ACE_Process_Options::set_handles (ACE_HANDLE std_in,
01100 ACE_HANDLE std_out,
01101 ACE_HANDLE std_err)
01102 {
01103 this->set_handles_called_ = 1;
01104 #if defined (ACE_WIN32)
01105
01106
01107 this->startup_info_.dwFlags = STARTF_USESTDHANDLES;
01108
01109 if (std_in == ACE_INVALID_HANDLE)
01110 std_in = ACE_STDIN;
01111 if (std_out == ACE_INVALID_HANDLE)
01112 std_out = ACE_STDOUT;
01113 if (std_err == ACE_INVALID_HANDLE)
01114 std_err = ACE_STDERR;
01115
01116 if (!::DuplicateHandle (::GetCurrentProcess (),
01117 std_in,
01118 ::GetCurrentProcess (),
01119 &this->startup_info_.hStdInput,
01120 0,
01121 TRUE,
01122 DUPLICATE_SAME_ACCESS))
01123 return -1;
01124
01125 if (!::DuplicateHandle (::GetCurrentProcess (),
01126 std_out,
01127 ::GetCurrentProcess (),
01128 &this->startup_info_.hStdOutput,
01129 0,
01130 TRUE,
01131 DUPLICATE_SAME_ACCESS))
01132 return -1;
01133
01134 if (!::DuplicateHandle (::GetCurrentProcess (),
01135 std_err,
01136 ::GetCurrentProcess (),
01137 &this->startup_info_.hStdError,
01138 0,
01139 TRUE,
01140 DUPLICATE_SAME_ACCESS))
01141 return -1;
01142 #else
01143 this->stdin_ = ACE_OS::dup (std_in);
01144 this->stdout_ = ACE_OS::dup (std_out);
01145 this->stderr_ = ACE_OS::dup (std_err);
01146 #endif
01147
01148 return 0;
01149 }
01150
01151
01152 void
01153 ACE_Process_Options::release_handles ()
01154 {
01155 if (set_handles_called_)
01156 {
01157 #if defined (ACE_WIN32)
01158 ACE_OS::close (startup_info_.hStdInput);
01159 ACE_OS::close (startup_info_.hStdOutput);
01160 ACE_OS::close (startup_info_.hStdError);
01161 #else
01162 ACE_OS::close (stdin_);
01163 ACE_OS::close (stdout_);
01164 ACE_OS::close (stderr_);
01165 #endif
01166 set_handles_called_ = 0;
01167 }
01168 }
01169 #endif
01170
01171
01172 ACE_Process_Options::~ACE_Process_Options (void)
01173 {
01174 #if !defined (ACE_HAS_WINCE)
01175 release_handles();
01176 delete [] environment_buf_;
01177 delete [] environment_argv_;
01178 #endif
01179 delete [] command_line_buf_;
01180 ACE::strdelete (command_line_copy_);
01181 }
01182
01183 int
01184 ACE_Process_Options::command_line (const ACE_TCHAR *const argv[])
01185 {
01186 int i = 0;
01187
01188 if (argv[i])
01189 {
01190 ACE_OS::strcat (command_line_buf_, argv[i]);
01191
01192 while (argv[++i])
01193 {
01194
01195
01196 size_t const cur_len =
01197 ACE_OS::strlen (command_line_buf_)
01198 + ACE_OS::strlen (argv[i])
01199 + 2;
01200
01201 if (cur_len > command_line_buf_len_)
01202 {
01203 ACE_ERROR_RETURN ((LM_ERROR,
01204 ACE_TEXT ("ACE_Process:command_line: ")
01205 ACE_TEXT ("command line is ")
01206 ACE_TEXT ("longer than %d\n"),
01207 command_line_buf_len_),
01208 1);
01209 }
01210
01211 ACE_OS::strcat (command_line_buf_, ACE_TEXT (" "));
01212 ACE_OS::strcat (command_line_buf_, argv[i]);
01213 }
01214 }
01215
01216 command_line_argv_calculated_ = false;
01217 return 0;
01218 }
01219
01220 int
01221 ACE_Process_Options::command_line (const ACE_TCHAR *format, ...)
01222 {
01223
01224 va_list argp;
01225 va_start (argp, format);
01226
01227 if (command_line_buf_len_ < 1)
01228 return -1;
01229
01230 #if !defined (ACE_LACKS_VSNPRINTF) || defined (ACE_HAS_TRIO)
01231
01232 ACE_OS::vsnprintf (command_line_buf_,
01233 command_line_buf_len_,
01234 format,
01235 argp);
01236 #else
01237
01238 ACE_OS::vsprintf (command_line_buf_,
01239 format,
01240 argp);
01241 #endif
01242
01243
01244 va_end (argp);
01245
01246 command_line_argv_calculated_ = false;
01247 return 0;
01248 }
01249
01250 #if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE)
01251
01252
01253
01254
01255 int
01256 ACE_Process_Options::command_line (const ACE_ANTI_TCHAR *format, ...)
01257 {
01258 ACE_ANTI_TCHAR *anti_clb = 0;
01259 ACE_NEW_RETURN (anti_clb,
01260 ACE_ANTI_TCHAR[this->command_line_buf_len_],
01261 -1);
01262
01263
01264 va_list argp;
01265 va_start (argp, format);
01266
01267
01268 ACE_OS::vsprintf (anti_clb,
01269 format,
01270 argp);
01271
01272
01273 va_end (argp);
01274
01275 ACE_OS::strcpy (this->command_line_buf_,
01276 ACE_TEXT_ANTI_TO_TCHAR (anti_clb));
01277
01278 delete [] anti_clb;
01279
01280 command_line_argv_calculated_ = false;
01281 return 0;
01282 }
01283 #endif
01284
01285 ACE_TCHAR *
01286 ACE_Process_Options::env_buf (void)
01287 {
01288 #if !defined (ACE_HAS_WINCE)
01289 if (environment_buf_[0] == '\0')
01290 return 0;
01291 else
01292 return environment_buf_;
01293 #else
01294 return 0;
01295 #endif
01296 }
01297
01298 ACE_TCHAR * const *
01299 ACE_Process_Options::command_line_argv (void)
01300 {
01301 if (!command_line_argv_calculated_)
01302 {
01303 command_line_argv_calculated_ = true;
01304
01305
01306 ACE::strdelete (command_line_copy_);
01307
01308
01309
01310 command_line_copy_ = ACE::strnew (command_line_buf_);
01311
01312
01313 ACE_Tokenizer parser (command_line_copy_);
01314 parser.delimiter_replace (' ', '\0');
01315 parser.preserve_designators ('\"', '\"');
01316 parser.preserve_designators ('\'', '\'');
01317
01318 int x = 0;
01319 do
01320 command_line_argv_[x] = parser.next ();
01321 while (command_line_argv_[x] != 0
01322
01323 && ++x < MAX_COMMAND_LINE_OPTIONS - 1);
01324
01325 command_line_argv_[x] = 0;
01326 }
01327
01328 return command_line_argv_;
01329 }
01330
01331
01332
01333 int
01334 ACE_Process_Options::pass_handle (ACE_HANDLE h)
01335 {
01336 # if defined (ACE_WIN32)
01337 # if defined (ACE_HAS_WINCE)
01338 ACE_NOTSUP_RETURN (-1);
01339 # else
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 ACE_TEXT_OSVERSIONINFO osvi;
01350 ZeroMemory (&osvi, sizeof (osvi));
01351 osvi.dwOSVersionInfoSize = sizeof (ACE_TEXT_OSVERSIONINFO);
01352
01353 if (!ACE_TEXT_GetVersionEx (&osvi) || osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
01354 {
01355 HANDLE dup_handle;
01356 if (!DuplicateHandle (GetCurrentProcess (),
01357 static_cast<HANDLE> (h),
01358 GetCurrentProcess (),
01359 &dup_handle,
01360 0,
01361 TRUE,
01362 DUPLICATE_SAME_ACCESS))
01363 return -1;
01364 dup_handles_.set_bit (static_cast<ACE_HANDLE> (dup_handle));
01365 }
01366 # endif
01367 #endif
01368
01369 this->handles_passed_.set_bit (h);
01370
01371 return 0;
01372 }
01373
01374
01375
01376 int
01377 ACE_Process_Options::dup_handles (ACE_Handle_Set &set) const
01378 {
01379 if (this->dup_handles_.num_set () == 0)
01380 return 0;
01381 set.reset ();
01382 set = this->dup_handles_;
01383 return 1;
01384 }
01385
01386
01387
01388 int
01389 ACE_Process_Options::passed_handles (ACE_Handle_Set &set) const
01390 {
01391 if (this->handles_passed_.num_set () == 0)
01392 return 0;
01393 set.reset ();
01394 set = this->handles_passed_;
01395 return 1;
01396 }
01397
01398 ACE_Managed_Process::~ACE_Managed_Process (void)
01399 {
01400 }
01401
01402 void
01403 ACE_Managed_Process::unmanage (void)
01404 {
01405 delete this;
01406 }
01407
01408 ACE_END_VERSIONED_NAMESPACE_DECL