1 #ifndef CORELIB__NCBIEXEC__HPP 2 #define CORELIB__NCBIEXEC__HPP 3 4 /* $Id: ncbiexec.hpp 574926 2018-11-20 20:23:54Z ucko $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Author: Vladimir Ivanov 30 * 31 * 32 */ 33 34 /// @file ncbiexec.hpp 35 /// Defines a portable execute class. 36 37 38 #include <corelib/ncbi_process.hpp> 39 40 41 /** @addtogroup Exec 42 * 43 * @{ 44 */ 45 46 47 BEGIN_NCBI_SCOPE 48 49 50 /// Exit code type 51 typedef int TExitCode; 52 53 54 ///////////////////////////////////////////////////////////////////////////// 55 /// 56 /// CExec -- 57 /// 58 /// Define portable exec class. 59 /// 60 /// Defines the different ways a process can be spawned. 61 62 class NCBI_XNCBI_EXPORT CExec 63 { 64 public: 65 /// Modification flags for EMode. 66 /// 67 /// @note 68 /// These flags works on UNIX only, and will be ignored on MS Windows. 69 /// Also, they don't work for eOverlay/eDetach modes. 70 enum EModeFlags { 71 /// After fork() move a process to new group (assign new PGID). 72 /// This can be useful if new created process also spawns child 73 /// processes and you wish to control it using signals, or, 74 /// for example, terminate the whole process group at once. 75 fNewGroup = (1 << 8), 76 /// Mask for all master modes, all EModeFlags must be above it. 77 fModeMask = 0x0F // eOverlay | eWait | eNoWait | eDetach 78 }; 79 80 /// Which exec mode the spawned process is called with. 81 enum EMode { 82 /// Overlays calling process with new process, destroying calling 83 /// process. 84 eOverlay = 0, 85 /// Suspends calling thread until execution of new process 86 /// is complete (synchronous operation). 87 eWait = 1, 88 /// The same as eWait, but on UNIX platforms new process group 89 /// will be created and calling process become the leader of the new 90 /// process group. 91 eWaitGroup = eWait | fNewGroup, 92 /// Continues to execute calling process concurrently with new 93 /// process (asynchronous process). Do not forget to call Wait() 94 /// to get process exit code, or started process will became 95 /// a "zombie", even it has finished all work. 96 eNoWait = 2, 97 /// The same as eNoWait, but on UNIX platforms new process group 98 /// will be created and calling process become the leader of the new 99 /// process group. 100 eNoWaitGroup = eNoWait | fNewGroup, 101 /// Like eNoWait, continues to execute calling process; new process 102 /// is run in background with no access to console or keyboard. 103 /// On UNIX new created process become the leader of the new session, 104 /// the process group leader of the new process group. 105 /// Calls to Wait() against new process will fail on MS Windows, 106 /// but work on UNIX platforms. This is an asynchronous spawn. 107 eDetach = 3 108 }; 109 110 /// The result type for Spawn methods. 111 /// 112 /// In the eNoWait and eDetach modes for Spawn functions to return process 113 /// handles. On MS Windows it is a real process handle of type HANDLE. 114 /// On UNIX it is a process identifier (pid). 115 /// In the eWait mode, the spawn functions return exit code of a process. 116 /// Throws an exception if you try to get exit code instead of 117 /// stored process handle, and otherwise. 118 /// In some cases can store both - an exit code and a handle (see Wait()). 119 class NCBI_XNCBI_EXPORT CResult 120 { 121 public: 122 /// Default ctor -- zero everything CResult()123 CResult() : m_Flags(0) { memset(&m_Result, 0, sizeof(m_Result)); } 124 /// Get exit code 125 TExitCode GetExitCode (void); 126 /// Get process handle/pid 127 TProcessHandle GetProcessHandle(void); 128 // Deprecated operator for compatibility with previous 129 // versions of Spawn methods which returns integer value. 130 NCBI_DEPRECATED operator intptr_t(void) const; 131 132 private: 133 /// Flags defines what this class store 134 enum EFlags { 135 fExitCode = (1<<1), 136 fHandle = (1<<2), 137 fBoth = fExitCode | fHandle 138 }; 139 typedef int TFlags; ///< Binary OR of "EFlags" 140 struct { 141 TExitCode exitcode; 142 TProcessHandle handle; 143 } m_Result; ///< Result of Spawn*() methods 144 TFlags m_Flags; ///< What m_Result stores 145 146 friend class CExec; 147 }; 148 149 /// Execute the specified command. 150 /// 151 /// Execute the command and return the executed command's exit code. 152 /// Throw an exception if command failed to execute. If cmdline is a null 153 /// pointer, System() checks if the shell (command interpreter) exists and 154 /// is executable. If the shell is available, System() returns a non-zero 155 /// value; otherwise, it returns 0. 156 static TExitCode System(const char* cmdline); 157 158 /// Quote argument. 159 /// 160 /// Enclose argument in quotes if necessary. 161 /// Used for concatenation arguments into command line. 162 /// @note 163 /// Do not use this function with Spawn*() methods. Im most cases they 164 /// don't need it, because all parameters passes to system separately, 165 /// and automatically use more advanced and OS-specific algorithm for this 166 /// if quoting is really necessary. 167 /// @sa System 168 static string QuoteArg(const string& arg); 169 170 /// Spawn a new process with specified command-line arguments. 171 /// 172 /// In the SpawnL() version, the command-line arguments are passed 173 /// individually. SpawnL() is typically used when number of parameters to 174 /// the new process is known in advance. 175 /// 176 /// Meaning of the suffix "L" in method name: 177 /// - The letter "L" as suffix refers to the fact that command-line 178 /// arguments are passed separately as arguments. 179 /// 180 /// @param mode 181 /// Mode for running the process. 182 /// @param cmdname 183 /// Path to the process to spawn. 184 /// @param argv 185 /// First argument vector parameter. 186 /// @param ... 187 /// Argument vector. Must ends with NULL. 188 /// @return 189 /// On success, return: 190 /// - exit code - in eWait mode. 191 /// - process handle - in eNoWait and eDetach modes. 192 /// - nothing - in eOverlay mode. 193 /// Throw an exception if command failed to execute. 194 /// @sa 195 /// SpawnLE(), SpawnLP(), SpawnLPE(), SpawnV(), SpawnVE(), SpawnVP(), 196 /// SpawnVPE(). 197 static CResult 198 SpawnL(EMode mode, const char *cmdname, const char *argv, .../*, NULL */); 199 200 /// Spawn a new process with specified command-line arguments and 201 /// environment settings. 202 /// 203 /// In the SpawnLE() version, the command-line arguments and environment 204 /// pointer are passed individually. SpawnLE() is typically used when 205 /// number of parameters to the new process and individual environment 206 /// parameter settings are known in advance. 207 /// 208 /// Meaning of the suffix "LE" in method name: 209 /// - The letter "L" as suffix refers to the fact that command-line 210 /// arguments are passed separately as arguments. 211 /// - The letter "E" as suffix refers to the fact that environment pointer, 212 /// envp, is passed as an array of pointers to environment settings to 213 /// the new process. The NULL environment pointer indicates that the new 214 /// process will inherit the parents process's environment. 215 /// 216 /// @param mode 217 /// Mode for running the process. 218 /// @param cmdname 219 /// Path of file to be executed. 220 /// @param argv 221 /// First argument vector parameter. 222 /// @param ... 223 /// Argument vector. Must ends with NULL. 224 /// @param envp 225 /// Pointer to vector with environment variables which will be used 226 /// instead of current environment. Last value in vector must be NULL. 227 /// @return 228 /// On success, return: 229 /// - exit code - in eWait mode. 230 /// - process handle - in eNoWait and eDetach modes. 231 /// - nothing - in eOverlay mode. 232 /// Throw an exception if command failed to execute. 233 /// @sa 234 /// SpawnL(), SpawnLP(), SpawnLPE(), SpawnV(), SpawnVE(), SpawnVP(), 235 /// SpawnVPE(). 236 static CResult 237 SpawnLE (EMode mode, const char *cmdname, 238 const char *argv, ... /*, NULL, const char *envp[] */); 239 240 /// Spawn a new process with variable number of command-line arguments and 241 /// find file to execute from the PATH environment variable. 242 /// 243 /// In the SpawnLP() version, the command-line arguments are passed 244 /// individually and the PATH environment variable is used to find the 245 /// file to execute. SpawnLP() is typically used when number 246 /// of parameters to the new process is known in advance but the exact 247 /// path to the executable is not known. 248 /// 249 /// Meaning of the suffix "LP" in method name: 250 /// - The letter "L" as suffix refers to the fact that command-line 251 /// arguments are passed separately as arguments. 252 /// - The letter "P" as suffix refers to the fact that the PATH 253 /// environment variable is used to find file to execute - on a Unix 254 /// platform this feature works in functions without letter "P" in 255 /// function name. 256 /// 257 /// @param mode 258 /// Mode for running the process. 259 /// @param cmdname 260 /// Path of file to be executed. 261 /// @param argv 262 /// First argument vector parameter. 263 /// @param ... 264 /// Argument vector. Must ends with NULL. 265 /// @return 266 /// On success, return: 267 /// - exit code - in eWait mode. 268 /// - process handle - in eNoWait and eDetach modes. 269 /// - nothing - in eOverlay mode. 270 /// Throw an exception if command failed to execute. 271 /// @sa 272 /// SpawnL(), SpawnLE(), SpawnLPE(), SpawnV(), SpawnVE(), SpawnVP(), 273 /// SpawnVPE(). 274 static CResult 275 SpawnLP(EMode mode, const char *cmdname, const char *argv, .../*, NULL*/); 276 277 /// Spawn a new process with specified command-line arguments, 278 /// environment settings and find file to execute from the PATH 279 /// environment variable. 280 /// 281 /// In the SpawnLPE() version, the command-line arguments and environment 282 /// pointer are passed individually, and the PATH environment variable 283 /// is used to find the file to execute. SpawnLPE() is typically used when 284 /// number of parameters to the new process and individual environment 285 /// parameter settings are known in advance, but the exact path to the 286 /// executable is not known. 287 /// 288 /// Meaning of the suffix "LPE" in method name: 289 /// - The letter "L" as suffix refers to the fact that command-line 290 /// arguments are passed separately as arguments. 291 /// - The letter "P" as suffix refers to the fact that the PATH 292 /// environment variable is used to find file to execute - on a Unix 293 /// platform this feature works in functions without letter "P" in 294 /// function name. 295 /// - The letter "E" as suffix refers to the fact that environment pointer, 296 /// envp, is passed as an array of pointers to environment settings to 297 /// the new process. The NULL environment pointer indicates that the new 298 /// process will inherit the parents process's environment. 299 /// 300 /// @param mode 301 /// Mode for running the process. 302 /// @param cmdname 303 /// Path of file to be executed. 304 /// @param argv 305 /// First argument vector parameter. 306 /// @param ... 307 /// Argument vector. Must ends with NULL. 308 /// @param envp 309 /// Pointer to vector with environment variables which will be used 310 /// instead of current environment. Last value in an array must be NULL. 311 /// @return 312 /// On success, return: 313 /// - exit code - in eWait mode. 314 /// - process handle - in eNoWait and eDetach modes. 315 /// - nothing - in eOverlay mode. 316 /// Throw an exception if command failed to execute. 317 /// @sa 318 /// SpawnL(), SpawnLE(), SpawnLP(), SpawnV(), SpawnVE(), SpawnVP(), 319 /// SpawnVPE(). 320 static CResult 321 SpawnLPE(EMode mode, const char *cmdname, 322 const char *argv, ... /*, NULL, const char *envp[] */); 323 324 /// Spawn a new process with variable number of command-line arguments. 325 /// 326 /// In the SpawnV() version, the command-line arguments are a variable 327 /// number. The array of pointers to arguments must have a length of 1 or 328 /// more and you must assign parameters for the new process beginning 329 /// from 1. 330 /// 331 /// Meaning of the suffix "V" in method name: 332 /// - The letter "V" as suffix refers to the fact that the number of 333 /// command-line arguments are variable. 334 /// 335 /// @param mode 336 /// Mode for running the process. 337 /// @param cmdline 338 /// Path of file to be executed. 339 /// @param argv 340 /// Pointer to argument vector. Last value in vector must be NULL. 341 /// @return 342 /// On success, return: 343 /// - exit code - in eWait mode. 344 /// - process handle - in eNoWait and eDetach modes. 345 /// - nothing - in eOverlay mode. 346 /// Throw an exception if command failed to execute. 347 /// @sa 348 /// SpawnL(), SpawnLE(), SpawnLP(), SpawnLPE(), SpawnVE(), SpawnVP(), 349 /// SpawnVPE(). 350 static CResult 351 SpawnV(EMode mode, const char *cmdname, const char *const *argv); 352 353 /// Spawn a new process with variable number of command-line arguments 354 /// and specified environment settings. 355 /// 356 /// In the SpawnVE() version, the command-line arguments are a variable 357 /// number. The array of pointers to arguments must have a length of 1 or 358 /// more and you must assign parameters for the new process beginning from 359 /// 1. The individual environment parameter settings are known in advance 360 /// and passed explicitly. 361 /// 362 /// Meaning of the suffix "VE" in method name: 363 /// - The letter "V" as suffix refers to the fact that the number of 364 /// command-line arguments are variable. 365 /// - The letter "E" as suffix refers to the fact that environment pointer, 366 /// envp, is passed as an array of pointers to environment settings to 367 /// the new process. The NULL environment pointer indicates that the new 368 /// process will inherit the parents process's environment. 369 /// 370 /// @param mode 371 /// Mode for running the process. 372 /// @param cmdname 373 /// Path of file to be executed. 374 /// @param argv 375 /// Argument vector. Last value must be NULL. 376 /// @param envp 377 /// Pointer to vector with environment variables which will be used 378 /// instead of current environment. Last value in an array must be NULL. 379 /// @return 380 /// On success, return: 381 /// - exit code - in eWait mode. 382 /// - process handle - in eNoWait and eDetach modes. 383 /// - nothing - in eOverlay mode. 384 /// Throw an exception if command failed to execute. 385 /// @sa 386 /// SpawnL(), SpawnLE(), SpawnLP(), SpawnLPE(), SpawnV(), SpawnVP(), 387 /// SpawnVPE(). 388 static CResult 389 SpawnVE(EMode mode, const char *cmdname, 390 const char *const *argv, const char *const *envp); 391 392 /// Spawn a new process with variable number of command-line arguments and 393 /// find file to execute from the PATH environment variable. 394 /// 395 /// In the SpawnVP() version, the command-line arguments are a variable 396 /// number. The array of pointers to arguments must have a length of 1 or 397 /// more and you must assign parameters for the new process beginning from 398 /// 1. The PATH environment variable is used to find the file to execute. 399 /// 400 /// Meaning of the suffix "VP" in method name: 401 /// - The letter "V" as suffix refers to the fact that the number of 402 /// command-line arguments are variable. 403 /// - The letter "P" as suffix refers to the fact that the PATH 404 /// environment variable is used to find file to execute - on a Unix 405 /// platform this feature works in functions without letter "P" in 406 /// function name. 407 /// 408 /// @param mode 409 /// Mode for running the process. 410 /// @param cmdname 411 /// Path of file to be executed. 412 /// @param argv 413 /// Pointer to argument vector. Last value in vector must be NULL. 414 /// @return 415 /// On success, return: 416 /// - exit code - in eWait mode. 417 /// - process handle - in eNoWait and eDetach modes. 418 /// - nothing - in eOverlay mode. 419 /// Throw an exception if command failed to execute. 420 /// @sa 421 /// SpawnL(), SpawnLE(), SpawnLP(), SpawnLPE(), SpawnV(), SpawnVE(), 422 /// SpawnVPE(). 423 static CResult 424 SpawnVP(EMode mode, const char *cmdname, const char *const *argv); 425 426 /// Spawn a new process with variable number of command-line arguments 427 /// and specified environment settings, and find the file to execute 428 /// from the PATH environment variable. 429 /// 430 /// In the SpawnVPE() version, the command-line arguments are a variable 431 /// number. The array of pointers to arguments must have a length of 1 or 432 /// more and you must assign parameters for the new process beginning from 433 /// 1. The PATH environment variable is used to find the file to execute, 434 /// and the environment is passed via an environment vector pointer. 435 /// 436 /// Meaning of the suffix "VPE" in method name: 437 /// - The letter "V" as suffix refers to the fact that the number of 438 /// command-line arguments are variable. 439 /// - The letter "P" as suffix refers to the fact that the PATH 440 /// environment variable is used to find file to execute - on a Unix 441 /// platform this feature works in functions without letter "P" in 442 /// function name. 443 /// - The letter "E" as suffix refers to the fact that environment pointer, 444 /// envp, is passed as an array of pointers to environment settings to 445 /// the new process. The NULL environment pointer indicates that the new 446 /// process will inherit the parents process's environment. 447 /// 448 /// @param mode 449 /// Mode for running the process. 450 /// @param cmdname 451 /// Path of file to be executed. 452 /// @param argv 453 /// Argument vector. Last value must be NULL. 454 /// @param envp 455 /// Pointer to vector with environment variables which will be used 456 /// instead of current environment. Last value in an array must be NULL. 457 /// @return 458 /// On success, return: 459 /// - exit code - in eWait mode. 460 /// - process handle - in eNoWait and eDetach modes. 461 /// - nothing - in eOverlay mode. 462 /// Throw an exception if command failed to execute. 463 /// @sa 464 /// SpawnL(), SpawnLE(), SpawnLP(), SpawnLPE(), SpawnV(), SpawnVE(), 465 /// SpawnVP(), 466 static CResult 467 SpawnVPE(EMode mode, const char *cmdname, 468 const char *const *argv, const char *const *envp); 469 470 /// Wait until specified process terminates. 471 /// 472 /// Wait until the process with "handle" terminates, and return 473 /// immediately if the specified process has already terminated. 474 /// @param handle 475 /// Wait on process with identifier "handle", returned by one 476 /// of the Spawn* function in eNoWait and eDetach modes. 477 /// @param timeout 478 /// Time-out interval. By default it is infinite. 479 /// @return 480 /// - Exit code of the process, if no errors. 481 /// - (-1), if error has occurred. 482 /// @note 483 /// It is recommended to call this method for all processes started 484 /// in eNoWait or eDetach modes (except on Windows for eDetach), because 485 /// it release "zombie" processes, that finished working and waiting 486 /// to return it's exit status. If Wait() is not called somewhere, 487 /// the child process will be completely removed from the system only 488 /// when the parent process ends. 489 /// @sa 490 /// CProcess::Wait(), CProcess:IsAlive(), TMode 491 static TExitCode Wait(TProcessHandle handle, 492 unsigned long timeout = kInfiniteTimeoutMs); 493 494 /// Mode used to wait processes termination. 495 enum EWaitMode { 496 eWaitAny, ///< Wait any process to terminate 497 eWaitAll ///< Wait all processes to terminate 498 }; 499 500 /// Wait until any/all processes terminates. 501 /// 502 /// Wait until any/all processes from specified list terminates. 503 /// Return immediately if the specified processes has already terminated. 504 /// @param handles 505 /// List of process identifiers. Each identifier is a value returned 506 /// by one of the Spawn* function in eNoWait and eDetach modes. 507 /// Handles for terminated processes going to "result" list, and 508 /// has been removed from this one. 509 /// @param mode 510 /// Wait termination for any or all possible processes within 511 /// specified timeout. 512 /// eWaitAny - wait until at least one process terminates. 513 /// eWaitAll - wait until all processes terminates or timeout expires. 514 /// @param result 515 /// List of process handles/exitcodes of terminated processes from 516 /// the list "handles". If this list have elements, that they will 517 /// be removed. 518 /// @param timeout 519 /// Time-out interval. By default it is infinite. 520 /// @return 521 /// - Number of terminated processes (size of the "result" list), 522 /// if no errors. Regardless of timeout status. 523 /// - (-1), if error has occurred. 524 /// @sa 525 /// Wait(), CProcess::Wait(), CProcess:IsAlive() 526 static int Wait(list<TProcessHandle>& handles, 527 EWaitMode mode, 528 list<CResult>& result, 529 unsigned long timeout = kInfiniteTimeoutMs); 530 531 /// Run console application in invisible mode. 532 /// 533 /// MS Windows: 534 /// This function try to run a program in invisible mode, without 535 /// visible window. This can be used to run console program from 536 /// non-console application. If it runs from console application, 537 /// the parent's console window can be used by child process. 538 /// Executing non-console program can show theirs windows or not, 539 /// this depends. In eDetach mode the main window/console of 540 /// the running program can be visible, use eNoWait instead. 541 /// @note 542 /// If the running program cannot self-terminate, that 543 /// it can be never terminated. 544 /// Unix: 545 /// In current implementation equal to SpawnL(). 546 /// @param mode 547 /// Mode for running the process. 548 /// @param cmdname 549 /// Path to the process to spawn. 550 /// @param argv 551 /// First argument vector parameter. 552 /// @param ... 553 /// Argument vector. Must ends with NULL. 554 /// @return 555 /// On success, return: 556 /// - exit code - in eWait mode. 557 /// - process handle - in eNoWait and eDetach modes. 558 /// - nothing - in eOverlay mode. 559 /// Throw an exception if command failed to execute. 560 /// @sa 561 /// SpawnL(), TMode 562 static CResult 563 RunSilent(EMode mode, const char *cmdname, 564 const char *argv, ... /*, NULL */); 565 566 /// Check executable permissions for specified file. 567 /// 568 /// @note 569 /// This is no guarantee that the file is executable even if 570 /// the function returns TRUE. It try to get effective user 571 /// permissions for specified file, but sometimes this 572 /// is not possible. 573 /// @param path 574 /// Path to the file to check. 575 /// @return 576 /// TRUE if file is executable, FALSE otherwise. 577 /// @sa 578 /// CFile::CheckAccess 579 static bool IsExecutable(const string& path); 580 581 /// Find executable file. 582 /// 583 /// If necessary, the PATH environment variable is used 584 /// to find the file to execute 585 /// @param filename 586 /// Name of the file to search. 587 /// @return 588 /// Path to the executable file. kEmptyStr if not found, 589 /// or the file do not have executable permissions. 590 /// @sa 591 /// IsExecutable 592 static string ResolvePath(const string& filename); 593 }; 594 595 596 ///////////////////////////////////////////////////////////////////////////// 597 /// 598 /// CExecException -- 599 /// 600 /// Define exceptions generated by CExec. 601 /// 602 /// CExecException inherits its basic functionality from 603 /// CErrnoTemplException<CCoreException> and defines additional error codes 604 /// for errors generated by CExec. 605 606 class NCBI_XNCBI_EXPORT CExecException : public CErrnoTemplException<CCoreException> 607 { 608 public: 609 /// Error types that CExec can generate. 610 enum EErrCode { 611 eSystem, ///< System error 612 eSpawn, ///< Spawn error 613 eResult ///< Result interpretation error 614 }; 615 616 /// Translate from the error code value to its string representation. 617 virtual const char* GetErrCodeString(void) const override; 618 619 // Standard exception boilerplate code. 620 NCBI_EXCEPTION_DEFAULT(CExecException, 621 CErrnoTemplException<CCoreException>); 622 }; 623 624 625 END_NCBI_SCOPE 626 627 628 /* @} */ 629 630 #endif /* CORELIB__NCBIEXEC__HPP */ 631