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