Logo Search packages:      
Sourcecode: inkscape version File versions

bool buildtool::MakeBase::executeCommand ( const String &  command,
const String &  inbuf,
String &  outbuf,
String &  errbuf 
) [protected, inherited]

Execute a shell command. Outbuf is a ref to a string to catch the result.

Execute a system call, using pipes to send data to the program's stdin, and reading stdout and stderr.

Definition at line 3471 of file buildtool.cpp.

References buildtool::MakeBase::error(), and buildtool::MakeBase::status().

{

    status("============ cmd ============\n%s\n=============================",
                command.c_str());

    outbuf.clear();
    errbuf.clear();
    
#ifdef __WIN32__

    /*
    I really hate having win32 code in this program, but the
    read buffer in command.com and cmd.exe are just too small
    for the large commands we need for compiling and linking.
    */

    bool ret = true;

    //# Allocate a separate buffer for safety
    char *paramBuf = new char[command.size() + 1];
    if (!paramBuf)
       {
       error("executeCommand cannot allocate command buffer");
       return false;
       }
    strcpy(paramBuf, (char *)command.c_str());

    //# Go to http://msdn2.microsoft.com/en-us/library/ms682499.aspx
    //# to see how Win32 pipes work

    //# Create pipes
    SECURITY_ATTRIBUTES saAttr; 
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 
    HANDLE stdinRead,  stdinWrite;
    HANDLE stdoutRead, stdoutWrite;
    HANDLE stderrRead, stderrWrite;
    if (!CreatePipe(&stdinRead, &stdinWrite, &saAttr, 0))
        {
        error("executeProgram: could not create pipe");
        delete[] paramBuf;
        return false;
        } 
    SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0);
    if (!CreatePipe(&stdoutRead, &stdoutWrite, &saAttr, 0))
        {
        error("executeProgram: could not create pipe");
        delete[] paramBuf;
        return false;
        } 
    SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0);
    if (!CreatePipe(&stderrRead, &stderrWrite, &saAttr, 0))
        {
        error("executeProgram: could not create pipe");
        delete[] paramBuf;
        return false;
        } 
    SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0);

    // Create the process
    STARTUPINFO siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;
    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo));
    siStartupInfo.cb = sizeof(siStartupInfo);
    siStartupInfo.hStdError   =  stderrWrite;
    siStartupInfo.hStdOutput  =  stdoutWrite;
    siStartupInfo.hStdInput   =  stdinRead;
    siStartupInfo.dwFlags    |=  STARTF_USESTDHANDLES;
   
    if (!CreateProcess(NULL, paramBuf, NULL, NULL, true,
                0, NULL, NULL, &siStartupInfo,
                &piProcessInfo))
        {
        error("executeCommand : could not create process : %s",
                    win32LastError().c_str());
        ret = false;
        }

    delete[] paramBuf;

    DWORD bytesWritten;
    if (inbuf.size()>0 &&
        !WriteFile(stdinWrite, inbuf.c_str(), inbuf.size(), 
               &bytesWritten, NULL))
        {
        error("executeCommand: could not write to pipe");
        return false;
        }    
    if (!CloseHandle(stdinWrite))
        {          
        error("executeCommand: could not close write pipe");
        return false;
        }
    if (!CloseHandle(stdoutWrite))
        {
        error("executeCommand: could not close read pipe");
        return false;
        }
    if (!CloseHandle(stderrWrite))
        {
        error("executeCommand: could not close read pipe");
        return false;
        }

    bool lastLoop = false;
    while (true)
        {
        DWORD avail;
        DWORD bytesRead;
        char readBuf[4096];

        //trace("## stderr");
        PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL);
        if (avail > 0)
            {
            bytesRead = 0;
            if (avail>4096) avail = 4096;
            ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL);
            if (bytesRead > 0)
                {
                for (unsigned int i=0 ; i<bytesRead ; i++)
                    errbuf.push_back(readBuf[i]);
                }
            }

        //trace("## stdout");
        PeekNamedPipe(stdoutRead, NULL, 0, NULL, &avail, NULL);
        if (avail > 0)
            {
            bytesRead = 0;
            if (avail>4096) avail = 4096;
            ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL);
            if (bytesRead > 0)
                {
                for (unsigned int i=0 ; i<bytesRead ; i++)
                    outbuf.push_back(readBuf[i]);
                }
            }
            
        //Was this the final check after program done?
        if (lastLoop)
            break;

        DWORD exitCode;
        GetExitCodeProcess(piProcessInfo.hProcess, &exitCode);
        if (exitCode != STILL_ACTIVE)
            lastLoop = true;

        Sleep(10);
        }    
    //trace("outbuf:%s", outbuf.c_str());
    if (!CloseHandle(stdoutRead))
        {
        error("executeCommand: could not close read pipe");
        return false;
        }
    if (!CloseHandle(stderrRead))
        {
        error("executeCommand: could not close read pipe");
        return false;
        }

    DWORD exitCode;
    GetExitCodeProcess(piProcessInfo.hProcess, &exitCode);
    //trace("exit code:%d", exitCode);
    if (exitCode != 0)
        {
        ret = false;
        }
    
    CloseHandle(piProcessInfo.hProcess);
    CloseHandle(piProcessInfo.hThread);

    return ret;

#else //do it unix-style

    String s;
    FILE *f = popen(command.c_str(), "r");
    int errnum = 0;
    if (f)
        {
        while (true)
            {
            int ch = fgetc(f);
            if (ch < 0)
                break;
            s.push_back((char)ch);
            }
        errnum = pclose(f);
        }
    outbuf = s;
    if (errnum != 0)
        {
        error("exec of command '%s' failed : %s",
             command.c_str(), strerror(errno));
        return false;
        }
    else
        return true;

#endif
} 


Generated by  Doxygen 1.6.0   Back to index