/** @file * IPRT - Process Management. */ /* * Copyright (C) 2006-2024 Oracle and/or its affiliates. * * This file is part of VirtualBox base platform packages, as * available from https://www.virtualbox.org. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, in version 3 of the * License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included * in the VirtualBox distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. * * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 */ #ifndef IPRT_INCLUDED_process_h #define IPRT_INCLUDED_process_h #ifndef RT_WITHOUT_PRAGMA_ONCE # pragma once #endif #include #include RT_C_DECLS_BEGIN /** @defgroup grp_rt_process RTProc - Process Management * @ingroup grp_rt * @{ */ /** * Process priority. * * The process priority is used to select how scheduling properties * are assigned to the different thread types (see THREADTYPE). * * In addition to using the policy assigned to the process at startup (DEFAULT) * it is possible to change the process priority at runtime. This allows for * a GUI, resource manager or admin to adjust the general priority of a task * without upsetting the fine-tuned priority of the threads within. */ typedef enum RTPROCPRIORITY { /** Invalid priority. */ RTPROCPRIORITY_INVALID = 0, /** Default priority. * Derive the scheduling policy from the priority of the RTR3Init() * and RTProcSetPriority() callers and the rights the process have * to alter its own priority. */ RTPROCPRIORITY_DEFAULT, /** Flat priority. * Assumes a scheduling policy which puts the process at the default priority * and with all thread at the same priority. */ RTPROCPRIORITY_FLAT, /** Low priority. * Assumes a scheduling policy which puts the process mostly below the * default priority of the host OS. */ RTPROCPRIORITY_LOW, /** Normal priority. * Assume a scheduling policy which shares the CPU resources fairly with * other processes running with the default priority of the host OS. */ RTPROCPRIORITY_NORMAL, /** High priority. * Assumes a scheduling policy which puts the task above the default * priority of the host OS. This policy might easily cause other tasks * in the system to starve. */ RTPROCPRIORITY_HIGH, /** Last priority, used for validation. */ RTPROCPRIORITY_LAST } RTPROCPRIORITY; /** * Get the current process identifier. * * @returns Process identifier. */ RTDECL(RTPROCESS) RTProcSelf(void); #ifdef IN_RING0 /** * Get the current process handle. * * @returns Ring-0 process handle. */ RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void); #endif /** * Translate a signal number to a short name on the form SIGXXXX. * * If the signal is not known, it will be formatted as a number into one of * several static buffers. This means that there could be concurrency issues if * this suddenly happens on multiple threads, though that is unlikely. * * @returns Readonly string naming the signal. * @param iSignal The signal to name. */ RTDECL(const char *) RTProcSignalName(int iSignal); #ifdef IN_RING3 /** * Attempts to alter the priority of the current process. * * @returns iprt status code. * @param enmPriority The new priority. */ RTR3DECL(int) RTProcSetPriority(RTPROCPRIORITY enmPriority); /** * Gets the current priority of this process. * * @returns The priority (see RTPROCPRIORITY). */ RTR3DECL(RTPROCPRIORITY) RTProcGetPriority(void); /** * Create a child process. * * @returns iprt status code. * @param pszExec Executable image to use to create the child process. * @param papszArgs Pointer to an array of arguments to the child. The array terminated by an entry containing NULL. * @param Env Handle to the environment block for the child. * @param fFlags Flags, one of the RTPROC_FLAGS_* defines. * @param pProcess Where to store the process identifier on successful return. * The content is not changed on failure. NULL is allowed. */ RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess); /** * Create a child process. * * @returns IPRT status code. * * @param pszExec Executable image to use to create the child process. * @param papszArgs Pointer to an array of arguments to the child. The * array terminated by an entry containing NULL. * @param hEnv Handle to the environment block for the child. Pass * RTENV_DEFAULT to use the environment of the current * process. * @param fFlags Flags, one of the RTPROC_FLAGS_* defines. * @param phStdIn The standard in handle to assign the new process. Pass * NULL to use the same as the current process. If the * handle is NIL, we'll close the standard input of the * guest. * @param phStdOut The standard out handle to assign the new process. Pass * NULL to use the same as the current process. If the * handle is NIL, we'll close the standard output of the * guest. * @param phStdErr The standard error handle to assign the new process. Pass * NULL to use the same as the current process. If the * handle is NIL, we'll close the standard error of the * guest. * @param pszAsUser User to run the process as. Pass NULL to use the same * user as the current process. * Windows: Use user\@domain (UPN, User Principal Name) * format to specify a domain. * @param pszPassword Password to use to authenticate @a pszAsUser. Must be * NULL wif pszAsUser is NULL. Whether this is actually * used or not depends on the platform. * @param pvExtraData Points to additional data as per @a fFlags: * - RTPROC_FLAGS_DESIRED_SESSION_ID: Pointing to a * uint32_t variable with the desired session ID. * - RTPROC_FLAGS_CWD: Pointing to a string constant * with the directory to chdir() to under the final * execution ID, before starting the process. * - These flags cannot be used in the same call. * @param phProcess Where to store the process handle on successful return. * The content is not changed on failure. NULL is allowed. * * @remarks The handles does not have to be created as inheritable, but it * doesn't hurt if they are as it may avoid race conditions on some * platforms. * * @remarks The as-user feature isn't supported/implemented on all platforms and * will cause a-yet-to-be-determined-error-status on these. */ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser, const char *pszPassword, void *pvExtraData, PRTPROCESS phProcess); /** @name RTProcCreate and RTProcCreateEx flags * @{ */ /** Detach the child process from the parents process tree and process group, * session or/and console (depends on the platform what's done applicable). * * The new process will not be a direct decendent of the parent and it will not * be possible to wait for it, i.e. @a phProcess shall be NULL. */ #define RTPROC_FLAGS_DETACHED RT_BIT(0) /** Don't show the started process. * This is a Windows (and maybe OS/2) concept, do not use on other platforms. */ #define RTPROC_FLAGS_HIDDEN RT_BIT(1) /** Use special code path for starting child processes from a service (daemon). * This is a windows concept for dealing with the so called "Session 0" * isolation which was introduced with Windows Vista. Do not use on other * platforms. */ #define RTPROC_FLAGS_SERVICE RT_BIT(2) /** Suppress changing the process contract id for the child process * on Solaris. Without this flag the contract id is always changed, as that's * the more frequently used case. */ #define RTPROC_FLAGS_SAME_CONTRACT RT_BIT(3) /** Load user profile data when executing a process. * This redefines the meaning of RTENV_DEFAULT to the profile environment. See * also RTPROC_FLAGS_ONLY_BASIC_PROFILE */ #define RTPROC_FLAGS_PROFILE RT_BIT(4) /** Create process without a console window. * This is a Windows (and OS/2) concept, do not use on other platforms. */ #define RTPROC_FLAGS_NO_WINDOW RT_BIT(5) /** Search the PATH for the executable. */ #define RTPROC_FLAGS_SEARCH_PATH RT_BIT(6) /** Don't quote and escape arguments on Windows and similar platforms where a * command line is passed to the child process instead of an argument vector, * just join up argv with a space between each. Ignored on platforms * passing argument the vector. */ #define RTPROC_FLAGS_UNQUOTED_ARGS RT_BIT(7) /** Consider hEnv an environment change record to be applied to RTENV_DEFAULT. * If hEnv is RTENV_DEFAULT, the flag has no effect. */ #define RTPROC_FLAGS_ENV_CHANGE_RECORD RT_BIT(8) /** Create process using the current impersonated thread token. * Caller should also specify RTPROC_FLAGS_SERVICE and RTPROC_FLAGS_PROFILE. * Windows only flag, ignored everywhere else. */ #define RTPROC_FLAGS_AS_IMPERSONATED_TOKEN RT_BIT(9) /** Hint that we don't expect to ever want to wait on the process. */ #define RTPROC_FLAGS_NO_WAIT RT_BIT(10) /** For use with RTPROC_FLAGS_SERVICE to specify a desired session ID * (Windows only, ignored elsewhere). The @a pvExtraData argument points to * a uint32_t containing the session ID, UINT32_MAX means any session. * Cannot be set with RTPROC_FLAGS_TOKEN_SUPPLIED or RTPROC_FLAGS_CWD. */ #define RTPROC_FLAGS_DESIRED_SESSION_ID RT_BIT(11) /** This is a modifier to RTPROC_FLAGS_PROFILE on unix systems that makes it * skip trying to dump the environment of a login shell. */ #define RTPROC_FLAGS_ONLY_BASIC_PROFILE RT_BIT(12) /** Don't translate arguments to the (guessed) child process codeset. * This is ignored on Windows as it is using UTF-16. */ #define RTPROC_FLAGS_UTF8_ARGV RT_BIT_32(13) /** Create process using supplied token. The @a pvExtraData argument points to * a HANDLE containing the token used as user credentials for process creation. * Cannot be set with RTPROC_FLAGS_DESIRED_SESSION_ID or RTPROC_FLAGS_CWD. * Windows only flag, ignored everywhere else. */ #define RTPROC_FLAGS_TOKEN_SUPPLIED RT_BIT(14) /** The @a pvExtraData argument points to a string containing the directory * to chdir() to, under the final execution ID, before starting the process. * Cannot be set with RTPROC_FLAGS_DESIRED_SESSION_ID or * RTPROC_FLAGS_TOKEN_SUPPLIED. */ #define RTPROC_FLAGS_CWD RT_BIT(15) /** Valid flag mask. */ #define RTPROC_FLAGS_VALID_MASK UINT32_C(0xffff) /** @} */ /** * Process exit reason. */ typedef enum RTPROCEXITREASON { /** Normal exit. iStatus contains the exit code. */ RTPROCEXITREASON_NORMAL = 1, /** Any abnormal exit. iStatus is undefined. */ RTPROCEXITREASON_ABEND, /** Killed by a signal. The iStatus field contains the signal number. */ RTPROCEXITREASON_SIGNAL } RTPROCEXITREASON; /** * Process exit status. */ typedef struct RTPROCSTATUS { /** The process exit status if the exit was a normal one. */ int iStatus; /** The reason the process terminated. */ RTPROCEXITREASON enmReason; } RTPROCSTATUS; /** Pointer to a process exit status structure. */ typedef RTPROCSTATUS *PRTPROCSTATUS; /** Pointer to a const process exit status structure. */ typedef const RTPROCSTATUS *PCRTPROCSTATUS; /** Flags for RTProcWait(). * @{ */ /** Block indefinitly waiting for the process to exit. */ #define RTPROCWAIT_FLAGS_BLOCK 0 /** Don't block, just check if the process have exited. */ #define RTPROCWAIT_FLAGS_NOBLOCK 1 /** @} */ /** * Waits for a process, resumes on interruption. * * @returns VINF_SUCCESS when the status code for the process was collected and * put in *pProcStatus. * @returns VERR_PROCESS_NOT_FOUND if the specified process wasn't found. * @returns VERR_PROCESS_RUNNING when the RTPROCWAIT_FLAGS_NOBLOCK and the * process haven't exited yet. * * @param Process The process to wait for. * @param fFlags The wait flags, any of the RTPROCWAIT_FLAGS_ \#defines. * @param pProcStatus Where to store the exit status on success. * Optional. */ RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus); /** * Waits for a process, returns on interruption. * * @returns VINF_SUCCESS when the status code for the process was collected and * put in *pProcStatus. * @returns VERR_PROCESS_NOT_FOUND if the specified process wasn't found. * @returns VERR_PROCESS_RUNNING when the RTPROCWAIT_FLAGS_NOBLOCK and the * process haven't exited yet. * @returns VERR_INTERRUPTED when the wait was interrupted by the arrival of a * signal or other async event. * * @param Process The process to wait for. * @param fFlags The wait flags, any of the RTPROCWAIT_FLAGS_ \#defines. * @param pProcStatus Where to store the exit status on success. * Optional. */ RTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus); /** * Terminates (kills) a running process. * * @returns IPRT status code. * @param Process The process to terminate. */ RTR3DECL(int) RTProcTerminate(RTPROCESS Process); /** * Gets the processor affinity mask of the current process. * * @returns The affinity mask. */ RTR3DECL(uint64_t) RTProcGetAffinityMask(void); /** * Gets the short process name. * * @returns Pointer to read-only name string. * @note IPRT must've been initialized or the string will be empty. */ RTR3DECL(const char *) RTProcShortName(void); /** * Gets the path to the executable image of the current process. * * @returns Pointer to read-only path string. * @note IPRT must've been initialized or the string will be empty. */ RTR3DECL(const char *) RTProcExecutablePath(void); /** * Gets a copy of the path to the executable image of the current process. * * @returns pszExecPath on success. NULL on buffer overflow or other errors. * * @param pszExecPath Where to store the path. * @param cbExecPath The size of the buffer. * @note IPRT must've been initialized or the string will be empty. */ RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath); /** * Daemonize the current process, making it a background process. * * The way this work is that it will spawn a detached / backgrounded / * daemonized / call-it-what-you-want process that isn't a direct child of the * current process. The spawned will have the same arguments a the caller, * except that the @a pszDaemonizedOpt is appended to prevent that the new * process calls this API again. * * The new process will have the standard handles directed to/from the * bitbucket. * * @returns IPRT status code. On success it is normal for the caller to exit * the process by returning from main(). * * @param papszArgs The argument vector of the calling process. * @param pszDaemonizedOpt The daemonized option. This is appended to the * end of the parameter list of the daemonized process. */ RTR3DECL(int) RTProcDaemonize(const char * const *papszArgs, const char *pszDaemonizedOpt); /** * Daemonize the current process, making it a background process. The current * process will exit if daemonizing is successful. * * @returns IPRT status code. On success it will only return in the child * process, the parent will exit. On failure, it will return in the * parent process and no child has been spawned. * * @param fNoChDir Pass false to change working directory to "/". * @param fNoClose Pass false to redirect standard file streams to the null device. * @param pszPidfile Path to a file to write the process id of the daemon * process to. Daemonizing will fail if this file already * exists or cannot be written. May be NULL. */ RTR3DECL(int) RTProcDaemonizeUsingFork(bool fNoChDir, bool fNoClose, const char *pszPidfile); /** * Check if the given process is running on the system. * * This check is case sensitive on most systems, except for Windows, OS/2 and * Darwin. * * @returns true if the process is running & false otherwise. * @param pszName Process name to search for. If no path is given only the * filename part of the running process set will be * matched. If a path is specified, the full path will be * matched. */ RTR3DECL(bool) RTProcIsRunningByName(const char *pszName); /** * Queries the parent process ID. * * @returns IPRT status code * @param hProcess The process to query the parent of. * @param phParent Where to return the parent process ID. */ RTR3DECL(int) RTProcQueryParent(RTPROCESS hProcess, PRTPROCESS phParent); /** * Query the username of the given process. * * @returns IPRT status code. * @retval VERR_BUFFER_OVERFLOW if the given buffer size is to small for the username. * @param hProcess The process handle to query the username for. * NIL_PROCESS is an alias for the current process. * @param pszUser Where to store the user name on success. * @param cbUser The size of the user name buffer. * @param pcbUser Where to store the username length on success * or the required buffer size if VERR_BUFFER_OVERFLOW * is returned. */ RTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser, size_t *pcbUser); /** * Query the username of the given process allocating the string for the username. * * @returns IPRT status code. * @param hProcess The process handle to query the username for. * @param ppszUser Where to store the pointer to the string containing * the username on success. Free with RTStrFree(). */ RTR3DECL(int) RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser); #endif /* IN_RING3 */ /** @} */ RT_C_DECLS_END #endif /* !IPRT_INCLUDED_process_h */