// -*- C++ -*- //============================================================================= /** * @file Process.h * * @author Tim Harrison */ //============================================================================= #ifndef ACE_PROCESS_H #define ACE_PROCESS_H #include /**/ "ace/pre.h" #include /**/ "ace/ACE_export.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Handle_Set.h" #include "ace/Global_Macros.h" #include "ace/os_include/sys/os_types.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL // Forward declaration class ACE_Time_Value; /** * @class ACE_Process_Options * * @brief Process Options * * This class controls the options passed to (or * and ). * Notice that on Windows CE, creating a process merely means * instantiating a new process. You can't set the handles (since * there's no stdin, stdout and stderr,) specify process/thread * options, set environment,... So, basically, this class only * set the command line and nothing else. * Notice that on UNIX platforms, if the is used, the * is using the system call. It means that the * should include a full path to the program file * ( does not search the PATH). If is not used * then, the is using the which searches for the * program file in the PATH variable. */ class ACE_Export ACE_Process_Options { public: enum { DEFAULT_COMMAND_LINE_BUF_LEN = 1024, // UNIX process creation flags. #if defined (ACE_WIN32) NO_EXEC = 0 #else NO_EXEC = 1 #endif /* ACE_WIN32 */ }; protected: // = Default settings not part of public Interface. // /// @todo These sizes should be taken from the appropriate /// POSIX/system header files and/or defined dynamically. enum { MAX_COMMAND_LINE_OPTIONS = 128, ENVIRONMENT_BUFFER = 16 * 1024, // 16K MAX_ENVIRONMENT_ARGS = 512 // }; public: /** * If @a inherit_environment == true, the new process will inherit the * environment of the current process. @a command_line_buf_len is the * max strlen for command-line arguments. */ ACE_Process_Options (bool inherit_environment = true, size_t command_line_buf_len = DEFAULT_COMMAND_LINE_BUF_LEN, size_t env_buf_len = ENVIRONMENT_BUFFER, size_t max_env_args = MAX_ENVIRONMENT_ARGS, size_t max_cmdline_args = MAX_COMMAND_LINE_OPTIONS); /// Destructor. ~ACE_Process_Options (); // = Methods to set process creation options portably. /** * Set the standard handles of the new process to the respective * handles. If you want to affect a subset of the handles, make * sure to set the others to ACE_INVALID_HANDLE. * * @note Any handle passed as ACE_INVALID_HANDLE will be changed to * a duplicate of the current associated handle. For example, passing * ACE_INVALID_HANDLE for @a std_in will cause ACE_STDIN to be * duplicated and set in this object. * * @note Windows: The implementation of set_handles() uses DuplicateHandle * on Windows. DuplicateHandle cannot be used to pass a socket handle * on Windows. Socket handles require an alternate mechanism to pass; * see http://msdn.microsoft.com/en-us/library/ms741565(v=VS.85).aspx * * @return 0 on success, -1 on failure. */ int set_handles (ACE_HANDLE std_in, ACE_HANDLE std_out = ACE_INVALID_HANDLE, ACE_HANDLE std_err = ACE_INVALID_HANDLE); /// Release the standard handles previously set with set_handles; void release_handles (); #ifndef ACE_LACKS_VA_FUNCTIONS /// @param format must be of the form "VARIABLE=VALUE". There can not be /// any spaces between VARIABLE and the equal sign. int setenv (const ACE_TCHAR *format, ...) #if !defined (ACE_USES_WCHAR) ACE_GCC_FORMAT_ATTRIBUTE (printf, 2, 3) #endif /* !ACE_USES_WCHAR */ ; /** * Set a single environment variable, @a variable_name. Since * different platforms separate each environment variable * differently, you must call this method once for each variable. * @a format can be any printf format string. So options->setenv * ("FOO","one + two = %s", "three") will result in "FOO=one + two = * three". */ int setenv (const ACE_TCHAR *variable_name, const ACE_TCHAR *format, ...) #if !defined (ACE_USES_WCHAR) ACE_GCC_FORMAT_ATTRIBUTE (printf, 3, 4) #endif /* !ACE_USES_WCHAR */ ; #endif // ACE_LACKS_VA_FUNCTIONS /// Same as above with argv format. @a envp must be null terminated. int setenv (ACE_TCHAR *envp[]); /// Set the working directory for the process. strlen of @a wd must /// be <= MAXPATHLEN. void working_directory (const char *wd); #if defined (ACE_HAS_WCHAR) /// wchar_t version of working_directory void working_directory (const wchar_t *wd); #endif /* ACE_HAS_WCHAR */ #ifndef ACE_LACKS_VA_FUNCTIONS /** * Set the command-line arguments. @a format can use any printf * formats. The first token in @a format should be the path to the * application. This can either be a full path, relative path, or * just an executable name. If an executable name is used, we rely * on the platform's support for searching paths. Since we need a * path to run a process, this method *must* be called! Returns 0 * on success, -1 on failure. */ int command_line (const ACE_TCHAR *format, ...) #if !defined (ACE_USES_WCHAR) ACE_GCC_FORMAT_ATTRIBUTE (printf, 2, 3) #endif /* !ACE_USES_WCHAR */ ; #if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE) /// Anti-TChar version of command_line () int command_line (const ACE_ANTI_TCHAR *format, ...); #endif /* ACE_HAS_WCHAR && !ACE_HAS_WINCE */ #endif // ACE_LACKS_VA_FUNCTIONS /// Same as above in argv format. @a argv must be null terminated. int command_line (const ACE_TCHAR * const argv[]); /** * Specify the full path or relative path, or just the executable * name for the process. If this is set, then @a name will be used to * create the process instead of argv[0] set in the command * line. This is here so that you can supply something other than * executable name as argv[0]. */ void process_name (const ACE_TCHAR *name); /// Return the process_name. If the set /// method is not called, this method will return argv[0]. const ACE_TCHAR *process_name (); /// Get the creation flags. u_long creation_flags () const; /** * Set the creation flags to affect how a new process is spawned. * The only ACE-defined flag is @c NO_EXEC which prevents the new process * from executing a new program image; this is a simple POSIX fork(). * The @c NO_EXEC option has no affect on Windows; on other platforms where * a POSIX fork is not possible, specifying @c NO_EXEC will cause * ACE_Process::spawn() to fail. * * On Windows, the value of creation_flags is passed to the @c CreateProcess * system call as the value of the @c dwCreationFlags parameter. */ void creation_flags (u_long); /// Current working directory. Returns "" if nothing has been set. ACE_TCHAR *working_directory (); /// Buffer of command-line options. Returns a pointer to a buffer that /// contains the list of command line options. Prior to a call to /// command_line_argv(), this is a single string of space separated /// arguments independent of which form of command_line() was used to /// create it. After a call to command_line_argv(), this is a list of /// strings each terminated by '\0'. [Note: spawn() will call /// command_line_argv().] The total length of all these strings is the /// same as the single string in the prior case and can be obtained by /// providing max_len. @arg max_len, if non-zero, provides a location /// into which the total length of the command line buffer is returned. ACE_TCHAR *command_line_buf (size_t *max_len = 0); /** * argv-style command-line options. Parses and modifies the string * created from . All spaces not in quotes ("" or * '') are replaced with null (\0) bytes. An argv array is built * and returned with each entry pointing to the start of * null-terminated string. Returns { 0 } if nothing has been set. */ ACE_TCHAR * const *command_line_argv (); /** * Null-terminated buffer of null terminated strings. Each string * is an environment assignment "VARIABLE=value". This buffer * should end with two null characters. */ ACE_TCHAR *env_buf (); /// Get the process group. On UNIX, these methods are used by the /// ACE_Process_Manager to manage groups of processes. pid_t getgroup () const; /// Set the process group. On UNIX, these methods are used by the /// ACE_Process_Manager to manage groups of processes. pid_t setgroup (pid_t pgrp); /// Allows disabling of handle inheritance, default is TRUE. /// /// @remarks @b Windows: the handle_inheritance value is passed as the /// bInheritHandles value to the CreateProcess() system function. Therefore, /// if you redirect standard input, output, or error via /// ACE_Process_Options::set_handles() you must not call /// handle_inheritance(false). Doing so will prevent the duplicated handles /// from surviving in the created process. int handle_inheritance (); void handle_inheritance (int); /// Cause the specified handle to be passed to a child process /// when it runs a new program image. /** * The specified handle value will be included in the spawned * process's command line as @arg +H @arg handle, if a new * program is spawned (always on Win32; else if NO_EXEC is not * set in creation flags). The passed handle value will be * duplicated if on Win32 less capable than NT. * @return 0 if success, -1 if failure. */ int pass_handle (ACE_HANDLE); /// Get a copy of the handles the ACE_Process_Options duplicated /// for the spawned process. /** * Any handles created through duplication of those passed into * @arg pass_handle are returned in @arg set. * @return 0 if there were no handles to return; 1 if there were. */ int dup_handles (ACE_Handle_Set &set) const; /// Get a copy of the handles passed to the spawned process. This /// will be the set of handles previously passed to @arg pass_handle(). /** * Any handles previously passed to @arg pass_handle are returned * in @arg set. * @return 0 if there were no handles to return; 1 if there were. */ int passed_handles (ACE_Handle_Set &set) const; /// Set value for avoid_zombies (has no real effect except on *nix). void avoid_zombies (int); /// Get current value for avoid_zombies. int avoid_zombies (); /// Enable the use of a Unicode environment. This only makes sense /// for Win32 when ACE_USES_WCHAR is not defined. void enable_unicode_environment (); /// Disable the use of a Unicode environment. void disable_unicode_environment (); /// Return the unicode environment status bool use_unicode_environment () const; #if defined (ACE_WIN32) // = Non-portable accessors for when you "just have to use them." /// Used for setting and getting. ACE_TEXT_STARTUPINFO *startup_info (void); /// Get the process_attributes. Returns NULL if /// set_process_attributes has not been set. LPSECURITY_ATTRIBUTES get_process_attributes () const; /// If this is called, a non-null process attributes is sent to /// CreateProcess. LPSECURITY_ATTRIBUTES set_process_attributes (void); /// Get the thread_attributes. Returns NULL if set_thread_attributes /// has not been set. LPSECURITY_ATTRIBUTES get_thread_attributes () const; /// If this is called, a non-null thread attributes is sent to /// CreateProcess. LPSECURITY_ATTRIBUTES set_thread_attributes (void); /// Get user token. Return ACE_INVALID_HANDLE if it has not been set. HANDLE get_user_token () const; /// Set user token for creating process as user. /// @param token the user token is passed to \c ::CreateProcessAsUser. /// @param close_token whether to close the user token when destructing. void set_user_token (HANDLE token, bool close_token = false); #else /* All things not WIN32 */ /// argv-style array of environment settings. ACE_TCHAR *const *env_argv (); // = Accessors for the standard handles. ACE_HANDLE get_stdin () const; ACE_HANDLE get_stdout () const; ACE_HANDLE get_stderr () const; // = Set/get real & effective user & group id associated with user. int setreugid (const ACE_TCHAR* user); void setruid (uid_t id); void seteuid (uid_t id); void setrgid (uid_t id); void setegid (uid_t id); uid_t getruid () const; uid_t geteuid () const; uid_t getrgid () const; uid_t getegid () const; /** * Get the inherit_environment flag. */ bool inherit_environment () const; /** * Set the inherit_environment flag. */ void inherit_environment (bool nv); #endif /* ACE_WIN32 */ protected: #if !defined (ACE_HAS_WINCE) /// Add @a assignment to environment_buf_ and adjust /// environment_argv_. @a len is the strlen of @a assignment. int setenv_i (ACE_TCHAR *assignment, size_t len); /// Whether the child process inherits the current process /// environment. bool inherit_environment_; #endif /* !ACE_HAS_WINCE */ /// Default 0. u_long creation_flags_; /// Avoid zombies for spawned processes. int avoid_zombies_; #if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) /// Helper function to grab win32 environment and stick it in /// environment_buf_ using this->setenv_i. void inherit_environment (void); /// Ensures once only call to inherit environment. int environment_inherited_; ACE_TEXT_STARTUPINFO startup_info_; /// Pointer to security_buf1_. LPSECURITY_ATTRIBUTES process_attributes_; /// Pointer to security_buf2_. LPSECURITY_ATTRIBUTES thread_attributes_; /// Data for process_attributes_. SECURITY_ATTRIBUTES security_buf1_; /// Data for thread_attributes_. SECURITY_ATTRIBUTES security_buf2_; /// User token for \a CreateProcessAsUser HANDLE user_token_; /// Keeps track of whether we need to close user token. bool close_user_token_; #else /* !ACE_WIN32 */ ACE_HANDLE stdin_; ACE_HANDLE stdout_; ACE_HANDLE stderr_; // = Real & effective user & group id's. // These should be set to -1 to leave unchanged (default). uid_t ruid_; uid_t euid_; uid_t rgid_; uid_t egid_; #endif /* ACE_WIN32 */ /// Default true. bool handle_inheritance_; #if !defined (ACE_HAS_WINCE) /// Is 1 if stdhandles was called. int set_handles_called_; /// Pointer into environment_buf_. This should point to the next /// free spot. size_t environment_buf_index_; /// Pointer to environment_argv_. size_t environment_argv_index_; /// Pointer to buffer of the environment settings. ACE_TCHAR *environment_buf_; /// Size of the environment buffer. Configurable size_t environment_buf_len_; /// Pointers into environment_buf_. ACE_TCHAR **environment_argv_; /// Maximum number of environment variables. Configurable size_t max_environment_args_; /// Maximum index of environment_argv_ buffer size_t max_environ_argv_index_; /// The current working directory. ACE_TCHAR working_directory_[MAXPATHLEN + 1]; #endif /* !ACE_HAS_WINCE */ /// Ensures command_line_argv is only calculated once. bool command_line_argv_calculated_; /// Pointer to buffer of command-line arguments. E.g., "-f foo -b bar". ACE_TCHAR *command_line_buf_; /// Pointer to copy of command-line arguments, which is needed when /// converting a command-line string into a command-line argv. ACE_TCHAR *command_line_copy_; /// Max length of command_line_buf_ size_t command_line_buf_len_; /// Maximum number of command-line arguments. Configurable size_t max_command_line_args_; /// Argv-style command-line arguments. ACE_TCHAR **command_line_argv_; /// Process-group on Unix; unused on Win32. pid_t process_group_; /// Set of handles that were passed in pass_handle (). ACE_Handle_Set handles_passed_; /// Results of duplicating handles passed in pass_handle (). ACE_Handle_Set dup_handles_; /// Pathname for the process. Relative path or absolute path or just /// the program name. ACE_TCHAR process_name_[MAXPATHLEN + 1]; /// Indicate if a Unicode environment should be used bool use_unicode_environment_; }; //class ACE_Process_Manager; /** * @class ACE_Process * * @brief A portable encapsulation for creating and managing new processes. * * ACE_Process provides a convenient way to: * - Spawn child processes, with convenient hooks for pre- and post-spawn * actions * - Check if a spawned process is still running * - Kill a spawned child process * - Wait for a spawned child process to exit. * * @see ACE_Process_Options because it is used to * pass options when spawning child processes. * * @see ACE_Process_Manager for additional ways to manage spawned * processes. */ class ACE_Export ACE_Process { public: friend class ACE_Process_Manager; /// Default construction. Use ACE_Process::spawn() to start a process. ACE_Process (); /// Destructor. virtual ~ACE_Process (); /** * Called back from spawn() just before spawning the child. If this * returns non-zero, the spawn is aborted (and returns ACE_INVALID_PID). * The default returns zero. */ virtual int prepare (ACE_Process_Options &options); /** * Launch a new process as described by @a options. * * @retval -1 on failure; check @c errno for error code. * @retval 1 on success if the option @c avoid_zombies is set. * @retval other the process id of the newly spawned child. * * @note The return value 1 may be changed in future versions of ACE to be * the process id of the child will be returned regardless of the * @c avoid_zombies option. * * @note On UNIX platforms, spawn() uses the execvp() system call if * ACE_Process_Options::inherit_environment() returns true (which is the * default) and execve() if not. Since execve() does not search PATH, the * ACE_Process_Options::command_line() should include a full path to the * program file. */ virtual pid_t spawn (ACE_Process_Options &options); /// Called back from spawn() in the parent's context just after forking, /// if the fork succeeds. The default simply returns. virtual void parent (pid_t child); /** * Called back from spawn() in the child's context just after forking. The * default does nothing. * * @note This function is *not* called on Windows * because the process-creation scheme does not allow it. */ virtual void child (pid_t parent); /// Called by a ACE_Process_Manager that is removing this object from /// its table of managed processes. Default is to do nothing. virtual void unmanage (); /** * Wait for a previously spawned process to exit. * * @arg status Points to a location to receive the exit status of the * spawned process. Ignored if the value is 0. * @arg wait_options If @c WNOHANG then return 0 and don't block if the * child process hasn't exited yet. * * @retval -1 the wait operation failed; consult @c errno for details. * @retval other the child process id is returned on success. */ pid_t wait (ACE_exitcode *status = 0, int wait_options = 0); /** * Timed wait for a previously spawned process to exit. * * @arg tv A relative amount of time to wait for the process to exit. * @arg status Points to a location to receive the exit status of the * spawned process. Ignored if the value is 0. * * @retval 0 the specified time period elapsed before the process exited. * @retval -1 the wait operation failed; consult @c errno for details. * @retval other the child process id is returned on success. * * @note On UNIX platforms this function uses @c ualarm(), i.e., it * overwrites any existing alarm. In addition, it steals all * @c SIGCHLD signals during the timeout period, which will break another * ACE_Process_Manager in the same process that's expecting * @c SIGCHLD to kick off process reaping. */ pid_t wait (const ACE_Time_Value &tv, ACE_exitcode *status = 0); /// Send the process a signal. This only has an effect on operating /// systems that support signals, such as UNIX/POSIX. int kill (int signum = SIGINT); /** * Terminate the process abruptly using ACE::terminate_process(). * This call doesn't give the process a chance to cleanup, so use it * with caution. */ int terminate (); /// Return the process id of the new child process. pid_t getpid () const; /// Return the handle of the process, if it has one. ACE_HANDLE gethandle () const; /// Return 1 if running; 0 otherwise. int running () const; /// Return the process's exit code. This method returns the raw /// exit status returned from system APIs (such as @c wait() or /// @c waitpid() ). This value is system dependent. ACE_exitcode exit_code () const; /// Return the process's return value. This method returns the /// actual return value that a child process returns or exits with. int return_value () const; /// Close all the handles in the set obtained from the /// @a ACE_Process_Options::dup_handles object used to spawn /// the process. void close_dup_handles (); /// Close all the passed handles in the set obtained from the /// ACE_Process_Options object used to spawn the process. void close_passed_handles (); #if defined (ACE_WIN32) PROCESS_INFORMATION process_info (void); #endif /* ACE_WIN32 */ private: ACE_Process (const ACE_Process &) = delete; void operator= (const ACE_Process &) = delete; ACE_Process (ACE_Process &&) = delete; void operator= (ACE_Process &&) = delete; protected: /// Set this process's exit code. ACE_Process_Manager uses this /// method to set the exit code after successfully waiting for /// this process to exit. void exit_code (ACE_exitcode code); #if defined (ACE_WIN32) PROCESS_INFORMATION process_info_; #else /* ACE_WIN32 */ /// Process id of the child. pid_t child_id_; #endif /* ACE_WIN32 */ ACE_exitcode exit_code_; /// Set of handles that were passed to the child process. ACE_Handle_Set handles_passed_; /// Handle duplicates made for the child process. ACE_Handle_Set dup_handles_; private: #if defined (ACE_WIN32) && \ defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR) && \ !defined (ACE_HAS_WINCE) wchar_t* convert_env_buffer (const char* env) const; #endif }; /** * @class ACE_Managed_Process * * @brief A process easily managed by ACE_Process_Manager. * * @arg ACE_Managed_Process is just an @arg ACE_Process with an * @arg unmanage() method that deletes the instance. * This class is only valid for use as a dynamically-allocated object! */ class ACE_Export ACE_Managed_Process : public ACE_Process { public: /// Cleanup by deleting @c this. virtual void unmanage (); ACE_ALLOC_HOOK_DECLARE; protected: /// Make sure that we're allocated dynamically! virtual ~ACE_Managed_Process (); }; ACE_END_VERSIONED_NAMESPACE_DECL #if defined (__ACE_INLINE__) #include "ace/Process.inl" #endif /* __ACE_INLINE__ */ #include /**/ "ace/post.h" #endif /* ACE_PROCESS_H */