ncbiexec.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:11k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbiexec.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:09:04  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbiexec.cpp,v 1000.1 2004/06/01 19:09:04 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Vladimir Ivanov
  35.  *
  36.  */
  37. #include <ncbi_pch.hpp>
  38. #include <stdio.h>
  39. #include <stdarg.h>
  40. #include <corelib/ncbiexec.hpp>
  41. #include <corelib/ncbi_process.hpp>
  42. #if defined(NCBI_OS_MSWIN)
  43. #  include <process.h>
  44. #elif defined(NCBI_OS_UNIX)
  45. #  include <unistd.h>
  46. #  include <sys/types.h>
  47. #  include <sys/wait.h>
  48. #  include <errno.h>
  49. #elif defined(NCBI_OS_MAC)
  50. #  error "Class CExec defined only for MS Windows and UNIX platforms"
  51. #endif
  52. BEGIN_NCBI_SCOPE
  53. #if defined(NCBI_OS_MSWIN)
  54. // Convert CExec class mode to the real mode
  55. static int s_GetRealMode(CExec::EMode mode)
  56. {
  57.     static const int s_Mode[] =  { 
  58.         P_OVERLAY, P_WAIT, P_NOWAIT, P_DETACH 
  59.     };
  60.     int x_mode = (int) mode;
  61.     _ASSERT(0 <= x_mode  &&  x_mode < sizeof(s_Mode)/sizeof(s_Mode[0]));
  62.     return s_Mode[x_mode];
  63. }
  64. #endif
  65. #if defined(NCBI_OS_UNIX)
  66. // Type function to call
  67. enum ESpawnFunc {eV, eVE, eVP, eVPE};
  68. static int s_SpawnUnix(ESpawnFunc func, CExec::EMode mode, 
  69.                        const char *cmdname, const char *const *argv, 
  70.                        const char *const *envp = 0)
  71. {
  72.     // Empty environment for Spawn*E
  73.     const char* empty_env[] = { 0 };
  74.     if ( !envp ) {
  75.         envp = empty_env;
  76.     }
  77.     // Replace the current process image with a new process image.
  78.     if (mode == CExec::eOverlay) {
  79.         switch (func) {
  80.         case eV:
  81.             return execv(cmdname, const_cast<char**>(argv));
  82.         case eVP:
  83.             return execvp(cmdname, const_cast<char**>(argv));
  84.         case eVE:
  85.         case eVPE:
  86.             return execve(cmdname, const_cast<char**>(argv), 
  87.                           const_cast<char**>(envp));
  88.         }
  89.         return -1;
  90.     }
  91.     // Fork child process
  92.     pid_t pid;
  93.     switch (pid = fork()) {
  94.     case -1:
  95.         // fork failed
  96.         return -1;
  97.     case 0:
  98.         // Here we're the child
  99.         if (mode == CExec::eDetach) {
  100.             fclose(stdin);
  101.             fclose(stdout);
  102.             fclose(stderr);
  103.             setsid();
  104.         }
  105.         int status =-1;
  106.         switch (func) {
  107.         case eV:
  108.             status = execv(cmdname, const_cast<char**>(argv));
  109.             break;
  110.         case eVP:
  111.             status = execvp(cmdname, const_cast<char**>(argv));
  112.             break;
  113.         case eVE:
  114.         case eVPE:
  115.             status = execve(cmdname, const_cast<char**>(argv),
  116.                             const_cast<char**>(envp));
  117.             break;
  118.         }
  119.         _exit(status);
  120.     }
  121.     // The "pid" contains the childs pid
  122.     if ( mode == CExec::eWait ) {
  123.         return CExec::Wait(pid);
  124.     }
  125.     return pid;
  126. }
  127. #endif
  128. // Get exec arguments
  129. #define GET_EXEC_ARGS 
  130.     int xcnt = 2; 
  131.     va_list vargs; 
  132.     va_start(vargs, argv); 
  133.     while ( va_arg(vargs, const char*) ) xcnt++; 
  134.     va_end(vargs); 
  135.     const char **args = new const char*[xcnt+1]; 
  136.     typedef ArrayDeleter<const char*> TArgsDeleter; 
  137.     AutoPtr<const char*, TArgsDeleter> p_args(args); 
  138.     if ( !args ) return -1; 
  139.     args[0] = cmdname; 
  140.     args[1] = argv; 
  141.     va_start(vargs, argv); 
  142.     int xi = 1; 
  143.     while ( xi < xcnt ) { 
  144.         xi++; 
  145.         args[xi] = va_arg(vargs, const char*); 
  146.     } 
  147.     args[xi] = 0
  148. int CExec::System(const char *cmdline)
  149.     int status;
  150. #if defined(NCBI_OS_MSWIN)
  151.     status = system(cmdline); 
  152. #elif defined(NCBI_OS_UNIX)
  153.     status = system(cmdline);
  154. #endif
  155.     if (status == -1) {
  156.         NCBI_THROW(CExecException,eSystem,
  157.                    "CExec::System: call to system failed");
  158.     }
  159. #if defined(NCBI_OS_UNIX)
  160.     return cmdline ? WEXITSTATUS(status) : status;
  161. #else
  162.     return status;
  163. #endif
  164. }
  165. int CExec::SpawnL(EMode mode, const char *cmdname, const char *argv, ...)
  166. {
  167.     int status;
  168. #if defined(NCBI_OS_MSWIN)
  169.     status = spawnv(s_GetRealMode(mode), cmdname, &cmdname);
  170. #elif defined(NCBI_OS_UNIX)
  171.     GET_EXEC_ARGS;
  172.     status = s_SpawnUnix(eV, mode, cmdname, args);
  173. #endif
  174.     if (status == -1) {
  175.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnL");
  176.     }
  177.     return status;
  178. }
  179. int CExec::SpawnLE(EMode mode, const char *cmdname,  const char *argv, ...)
  180. {
  181.     int status;
  182.     GET_EXEC_ARGS;
  183.     char** envp = va_arg(vargs, char**);
  184. #if defined(NCBI_OS_MSWIN)
  185.     status = spawnve(s_GetRealMode(mode), cmdname, args, envp);
  186. #elif defined(NCBI_OS_UNIX)
  187.     status = s_SpawnUnix(eVE, mode, cmdname, args, envp);
  188. #endif
  189.     if (status == -1) {
  190.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnLE");
  191.     }
  192.     return status;
  193. }
  194. int CExec::SpawnLP(EMode mode, const char *cmdname, const char *argv, ...)
  195. {
  196.     int status;
  197. #if defined(NCBI_OS_MSWIN)
  198.     status = spawnvp(s_GetRealMode(mode), cmdname, &cmdname);
  199. #elif defined(NCBI_OS_UNIX)
  200.     GET_EXEC_ARGS;
  201.     status = s_SpawnUnix(eVP, mode, cmdname, args);
  202. #endif
  203.     if (status == -1) {
  204.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnLP");
  205.     }
  206.     return status;
  207. }
  208. int CExec::SpawnLPE(EMode mode, const char *cmdname, const char *argv, ...)
  209. {
  210.     int status;
  211.     GET_EXEC_ARGS;
  212.     char** envp = va_arg(vargs, char**);
  213. #if defined(NCBI_OS_MSWIN)
  214.     status = spawnve(s_GetRealMode(mode), cmdname, args, envp);
  215. #elif defined(NCBI_OS_UNIX)
  216.     status = s_SpawnUnix(eVPE, mode, cmdname, args, envp);
  217. #endif
  218.     if (status == -1 ) {
  219.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnLPE");
  220.     }
  221.     return status;
  222. }
  223. int CExec::SpawnV(EMode mode, const char *cmdname, const char *const *argv)
  224. {
  225.     int status;
  226.     char** argp = const_cast<char**>(argv);
  227.     argp[0] = const_cast<char*>(cmdname);
  228. #if defined(NCBI_OS_MSWIN)
  229.     status = spawnv(s_GetRealMode(mode), cmdname, argv);
  230. #elif defined(NCBI_OS_UNIX)
  231.     status = s_SpawnUnix(eV, mode, cmdname, argv);
  232. #endif
  233.     if (status == -1 ) {
  234.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnV");
  235.     }
  236.     return status;
  237. }
  238. int CExec::SpawnVE(EMode mode, const char *cmdname, 
  239.                    const char *const *argv, const char * const *envp)
  240. {
  241.     int status;
  242.     char** argp = const_cast<char**>(argv);
  243.     argp[0] = const_cast<char*>(cmdname);
  244. #if defined(NCBI_OS_MSWIN)
  245.     status = spawnve(s_GetRealMode(mode), cmdname, argv, envp);
  246. #elif defined(NCBI_OS_UNIX)
  247.     status = s_SpawnUnix(eVE, mode, cmdname, argv, envp);
  248. #endif
  249.     if (status == -1 ) {
  250.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnVE");
  251.     }
  252.     return status;
  253. }
  254. int CExec::SpawnVP(EMode mode, const char *cmdname, const char *const *argv)
  255. {
  256.     int status;
  257.     char** argp = const_cast<char**>(argv);
  258.     argp[0] = const_cast<char*>(cmdname);
  259. #if defined(NCBI_OS_MSWIN)
  260.     status = spawnvp(s_GetRealMode(mode), cmdname, argv);
  261. #elif defined(NCBI_OS_UNIX)
  262.     status = s_SpawnUnix(eVP, mode, cmdname, argv);
  263. #endif
  264.     if (status == -1 ) {
  265.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnVP");
  266.     }
  267.     return status;
  268. }
  269. int CExec::SpawnVPE(EMode mode, const char *cmdname,
  270.                     const char *const *argv, const char * const *envp)
  271. {
  272.     int status;
  273.     char** argp = const_cast<char**>(argv);
  274.     argp[0] = const_cast<char*>(cmdname);
  275. #if defined(NCBI_OS_MSWIN)
  276.     status = spawnvpe(s_GetRealMode(mode), cmdname, argv, envp);
  277. #elif defined(NCBI_OS_UNIX)
  278.     status = s_SpawnUnix(eVPE, mode, cmdname, argv, envp);
  279. #endif
  280.     if (status == -1 ) {
  281.         NCBI_THROW(CExecException,eSpawn, "CExec::SpawnVPE");
  282.     }
  283.     return status;
  284. }
  285. int CExec::Wait(int handle, unsigned long timeout)
  286. {
  287.     return CProcess(handle, CProcess::eHandle).Wait(timeout);
  288. }
  289. END_NCBI_SCOPE
  290. /*
  291.  * ===========================================================================
  292.  * $Log: ncbiexec.cpp,v $
  293.  * Revision 1000.1  2004/06/01 19:09:04  gouriano
  294.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  295.  *
  296.  * Revision 1.17  2004/05/14 13:59:27  gorelenk
  297.  * Added include of ncbi_pch.hpp
  298.  *
  299.  * Revision 1.16  2003/10/01 20:22:05  ivanov
  300.  * Formal code rearrangement
  301.  *
  302.  * Revision 1.15  2003/09/25 17:02:20  ivanov
  303.  * CExec::Wait():  replaced all code with CProcess::Wait() call
  304.  *
  305.  * Revision 1.14  2003/09/16 17:48:08  ucko
  306.  * Remove redundant "const"s from arguments passed by value.
  307.  *
  308.  * Revision 1.13  2003/08/12 16:57:55  ivanov
  309.  * s_SpawnUnix(): use execv() instead execvp() for the eV-mode
  310.  *
  311.  * Revision 1.12  2003/04/23 21:02:48  ivanov
  312.  * Removed redundant NCBI_OS_MAC preprocessor directives
  313.  *
  314.  * Revision 1.11  2003/02/24 19:56:05  gouriano
  315.  * use template-based exceptions instead of errno and parse exceptions
  316.  *
  317.  * Revision 1.10  2002/08/15 18:26:29  ivanov
  318.  * Changed s_SpawnUnix() -- empty environment, setsid() for eDetach mode
  319.  *
  320.  * Revision 1.9  2002/07/17 15:12:34  ivanov
  321.  * Changed method of obtaining parameters in the SpawnLE/LPE functions
  322.  * under MS Windows
  323.  *
  324.  * Revision 1.8  2002/07/16 15:04:22  ivanov
  325.  * Fixed warning about uninitialized variable in s_SpawnUnix()
  326.  *
  327.  * Revision 1.7  2002/07/15 16:38:50  ivanov
  328.  * Fixed bug in macro GET_EXEC_ARGS -- write over array bound
  329.  *
  330.  * Revision 1.6  2002/07/11 14:18:26  gouriano
  331.  * exceptions replaced by CNcbiException-type ones
  332.  *
  333.  * Revision 1.5  2002/06/30 03:22:14  vakatov
  334.  * s_GetRealMode() -- formal code rearrangement to avoid a warning
  335.  *
  336.  * Revision 1.4  2002/06/11 19:28:31  ivanov
  337.  * Use AutoPtr<char*> for exec arguments in GET_EXEC_ARGS
  338.  *
  339.  * Revision 1.3  2002/06/04 19:43:20  ivanov
  340.  * Done s_ThrowException static
  341.  *
  342.  * Revision 1.2  2002/05/31 20:49:33  ivanov
  343.  * Removed excrescent headers
  344.  *
  345.  * Revision 1.1  2002/05/30 16:29:13  ivanov
  346.  * Initial revision
  347.  *
  348.  * ===========================================================================
  349.  */