NCBI C++ ToolKit
exec.cpp
Go to the documentation of this file.
00001 /*  $Id: exec.cpp 16579 2008-04-02 13:20:08Z dicuccio $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors:  Josh Cherry
00027  *
00028  * File Description:  execute another program, capturing output in strings
00029  *
00030  */
00031 
00032 
00033 #include <ncbi_pch.hpp>
00034 #include <gui/utils/exec.hpp>
00035 
00036 #include <corelib/ncbitime.hpp>
00037 #include <connect/ncbi_pipe.hpp>
00038 
00039 BEGIN_NCBI_SCOPE
00040 
00041 // run an executable using strings for std*
00042 int CExecute::Exec(const string& cmd,
00043                    const vector<string>& args,
00044                    const string& std_in,
00045                    string& std_out,
00046                    string& std_err,
00047                    STimeout *timeout)
00048 {
00049     // open a pipe, with text mode for std_in, std_out, and std_err
00050     CPipe pipe;
00051 
00052     // set up timeout, if requested
00053     CStopWatch sw;
00054     double max_time = 0;  // initialize to avoid compiler warning
00055     if (timeout) {
00056         pipe.SetTimeout(eIO_Open, timeout);
00057         pipe.SetTimeout(eIO_Close, timeout);
00058         max_time = timeout->sec + timeout->usec / 1000000.0;
00059     }
00060     sw.Start();
00061 
00062     pipe.Open(cmd.c_str(), args, CPipe::fStdErr_Open);
00063 
00064     STimeout short_time = {0, 1};
00065     pipe.SetTimeout(eIO_Read, &short_time);
00066     pipe.SetTimeout(eIO_Write, &short_time);
00067 
00068     size_t bytes_written;
00069     size_t total_bytes_written = 0;
00070     bool out_done = false;
00071     bool err_done = false;
00072 
00073     const size_t buf_size = 4096;
00074     char buf[buf_size];
00075 
00076     while (!out_done || !err_done) {
00077 
00078         // write stdin
00079         if (total_bytes_written < std_in.size()) {
00080             pipe.Write(std_in.c_str() + total_bytes_written,
00081                        std_in.size() - total_bytes_written,
00082                        &bytes_written);
00083             total_bytes_written += bytes_written;
00084             if (total_bytes_written == std_in.size()) {
00085                 pipe.CloseHandle(CPipe::eStdIn);
00086             }
00087         }
00088 
00089         EIO_Status rstatus;
00090         size_t bytes_read;
00091 
00092         // read stdout
00093         if (!out_done) {
00094             rstatus = pipe.Read(buf, buf_size, &bytes_read);
00095             std_out.append(buf, bytes_read);
00096             if (rstatus != eIO_Success && rstatus != eIO_Timeout) {
00097                 out_done = true;
00098             }
00099         }
00100 
00101         // read stderr
00102         if (!err_done) {
00103             rstatus = pipe.Read(buf, buf_size, &bytes_read, CPipe::eStdErr);
00104             std_err.append(buf, bytes_read);
00105             if (rstatus != eIO_Success && rstatus != eIO_Timeout) {
00106                 err_done = true;
00107             }
00108         }
00109 
00110         // check whether total time (timeout paramater) exceeded
00111         if (timeout) {
00112             if (sw.Elapsed() > max_time) {
00113                 pipe.SetTimeout(eIO_Close, &short_time);
00114                 break;
00115             }
00116         }
00117     }
00118 
00119     int exit_value;
00120     pipe.Close(&exit_value);
00121 
00122     // return the value with which the process exited
00123     return exit_value;
00124 }
00125 
00126 
00127 END_NCBI_SCOPE
Modified on Wed May 23 13:14:26 2012 by modify_doxy.py rev. 337098