/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library 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 Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ #include "domainjoin.h" void WaitTimeout(int val) { } void FreeProcInfo( PPROCINFO pProcInfo ) { CTFreeProcInfo(pProcInfo); } CENTERROR DJSpawnProcessWithEnvironment( PCSTR pszCommand, const PSTR* ppszArgs, const PSTR* ppszEnv, int dwFdIn, int dwFdOut, int dwFdErr, PPROCINFO* ppProcInfo ) { return CTSpawnProcessWithEnvironment( pszCommand, ppszArgs, ppszEnv, dwFdIn, dwFdOut, dwFdErr, ppProcInfo ); } CENTERROR DJSpawnProcess( PCSTR pszCommand, const PSTR* ppszArgs, PPROCINFO* ppProcInfo ) { return DJSpawnProcessWithEnvironment(pszCommand, ppszArgs, NULL, -1, -1, -1, ppProcInfo); } #ifdef NOT_YET CENTERROR DJSpawnProcessCaptureOutput( PCSTR pszCommand, PSTR* ppszArgs, PPROCINFO* ppProcInfo, PSTR* ppszStdout, PSTR* ppszStderr) { CENTERROR ceError = CENTERROR_SUCCESS; BOOLEAN bFirst = FALSE; PPROCINFO pProcInfo = NULL; PROCBUFFER procBuffer; DWORD iOutBufIdx = 0; DWORD dwOutBufLen = 0; DWORD dwOutBufAvailable = 0; PSTR pszOutBuffer = NULL; DWORD iErrBufIdx = 0; DWORD dwErrBufLen = 0; DWORD dwErrBufAvailable = 0; PSTR pszErrBuffer = NULL; ceError = DJSpawnProcess(pszCommand, ppszArgs, ppProcInfo); BAIL_ON_CENTERIS_ERROR(ceError); pProcInfo = *ppProcInfo; do { if (!bFirst) { ceError = DJReadData(pProcInfo, &procBuffer); BAIL_ON_CENTERIS_ERROR(ceError); } bFirst = FALSE; if (procBuffer.dwOutBytesRead) { while (1) { if (procBuffer.dwOutBytesRead < dwOutBufAvailable) { memcpy(pszOutBuffer+iOutBufIdx, procBuffer.szOutBuf, procBuffer.dwOutBytesRead ); iOutBufIdx+= procBuffer.dwOutBytesRead; dwOutBufAvailable -= procBuffer.dwOutBytesRead; *(pszOutBuffer+iOutBufIdx+1) = '\0'; break; } else { /* * TODO: Limit the amount of memory acquired */ ceError = CTReallocMemory(pszOutBuffer, (PVOID*)&pszOutBuffer, dwOutBufLen+1024); BAIL_ON_CENTERIS_ERROR(ceError); dwOutBufLen += 1024; dwOutBufAvailable += 1024; } } } if (procBuffer.dwErrBytesRead) { while (1) { if (procBuffer.dwErrBytesRead < dwErrBufAvailable) { memcpy(pszErrBuffer+iErrBufIdx, procBuffer.szErrBuf, procBuffer.dwErrBytesRead ); iErrBufIdx+= procBuffer.dwErrBytesRead; dwErrBufAvailable -= procBuffer.dwErrBytesRead; *(pszErrBuffer+iErrBufIdx+1) = '\0'; break; } else { /* * TODO: Limit the amount of memory acquired */ ceError = CTReallocMemory(pszErrBuffer, (PVOID*)&pszErrBuffer, dwErrBufLen+1024); BAIL_ON_CENTERIS_ERROR(ceError); dwErrBufLen += 1024; dwErrBufAvailable += 1024; } } } } while (!procBuffer.bEndOfFile); ceError = CTAllocateString(pszOutBuffer, ppszStdout); BAIL_ON_CENTERIS_ERROR(ceError); CT_SAFE_FREE_STRING(pszOutBuffer); ceError = CTAllocateString(pszErrBuffer, ppszStderr); BAIL_ON_CENTERIS_ERROR(ceError); CT_SAFE_FREE_STRING(pszErrBuffer); error: if (pszOutBuffer) { *ppszStdout = pszOutBuffer; } if (pszErrBuffer) { *ppszStderr = pszErrBuffer; } return ceError; } #endif /* NOT_YET */ CENTERROR DJSpawnProcessWithFds( PCSTR pszCommand, PSTR* ppszArgs, int dwFdIn, int dwFdOut, int dwFdErr, PPROCINFO* ppProcInfo ) { return CTSpawnProcessWithFds(pszCommand, ppszArgs, dwFdIn, dwFdOut, dwFdErr, ppProcInfo); } CENTERROR DJSpawnProcessSilent( PCSTR pszCommand, PSTR* ppArgs, PPROCINFO* ppProcInfo ) { int dwFdIn = -1, dwFdOut = -1, dwFdErr = -1; CENTERROR ceError = CENTERROR_SUCCESS; dwFdIn = open("/dev/zero", O_RDONLY); if (dwFdIn < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } dwFdOut = open("/dev/null", O_WRONLY); if (dwFdOut < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } dwFdErr = open("/dev/null", O_WRONLY); if (dwFdErr < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } ceError = DJSpawnProcessWithFds(pszCommand, ppArgs, dwFdIn, dwFdOut, dwFdErr, ppProcInfo); BAIL_ON_CENTERIS_ERROR(ceError); error: if(dwFdIn != -1) close(dwFdIn); if(dwFdOut != -1) close(dwFdOut); if(dwFdErr != -1) close(dwFdErr); return ceError; } CENTERROR DJSpawnProcessOutputToFile( PCSTR pszCommand, PSTR* ppArgs, PCSTR file, PPROCINFO* ppProcInfo ) { int dwFdIn = -1, dwFdOut = -1, dwFdErr = -1; CENTERROR ceError = CENTERROR_SUCCESS; dwFdIn = open("/dev/zero", O_RDONLY); if (dwFdIn < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } dwFdOut = open(file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR ); if (dwFdOut < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } dwFdErr = open("/dev/null", O_WRONLY); if (dwFdErr < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } ceError = DJSpawnProcessWithFds(pszCommand, ppArgs, dwFdIn, dwFdOut, dwFdErr, ppProcInfo); BAIL_ON_CENTERIS_ERROR(ceError); error: if(dwFdIn != -1) close(dwFdIn); if(dwFdOut != -1) close(dwFdOut); if(dwFdErr != -1) close(dwFdErr); return ceError; } CENTERROR DJTimedReadData( PPROCINFO pProcInfo, PPROCBUFFER pProcBuffer, DWORD dwTimeoutSecs, PBOOLEAN pbTimedout ) { CENTERROR ceError = CENTERROR_SUCCESS; PSTR pszBuf = NULL; DWORD dwBytesRead = 0; int maxfd; fd_set read_fd_set; int select_status; int fd = 0; int iFd = 0; struct timeval timeout; timeout.tv_sec = dwTimeoutSecs; timeout.tv_usec = 0; pProcBuffer->dwOutBytesRead = 0; pProcBuffer->dwErrBytesRead = 0; pProcBuffer->bEndOfFile = FALSE; FD_ZERO(&read_fd_set); while (!pProcBuffer->dwOutBytesRead && !pProcBuffer->dwErrBytesRead && !pProcBuffer->bEndOfFile) { if (pProcInfo->fdout >= 0) { FD_SET(pProcInfo->fdout, &read_fd_set); } if (pProcInfo->fderr >= 0) { FD_SET(pProcInfo->fderr, &read_fd_set); } maxfd = (pProcInfo->fdout > pProcInfo->fderr ? pProcInfo->fdout+1 : pProcInfo->fderr + 1); select_status = select(maxfd, &read_fd_set, NULL /* write_fds */, NULL /* except_fds */, &timeout); if (select_status < 0) { if (errno == EINTR) continue; ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } else if (select_status == 0) { /* timed out */ } else { for (iFd = 0; iFd < 2; iFd++) { fd = (iFd == 0 ? pProcInfo->fdout : pProcInfo->fderr); if (fd < 0) { continue; } pszBuf = (iFd == 0 ? pProcBuffer->szOutBuf : pProcBuffer->szErrBuf); if (FD_ISSET(fd, &read_fd_set)) { dwBytesRead = read(fd, pszBuf, MAX_PROC_BUF_LEN); if (dwBytesRead < 0) { if (errno != EAGAIN && errno != EINTR) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } } else if (dwBytesRead == 0) { pProcBuffer->bEndOfFile = TRUE; } else { if (iFd == 0) pProcBuffer->dwOutBytesRead = dwBytesRead; else pProcBuffer->dwErrBytesRead = dwBytesRead; } } } } } error: return (ceError); } CENTERROR DJReadData( PPROCINFO pProcInfo, PPROCBUFFER pProcBuffer ) { BOOLEAN bTimedout = FALSE; return DJTimedReadData(pProcInfo, pProcBuffer, 5, &bTimedout); } CENTERROR DJWriteData( DWORD dwFd, PSTR pszBuf, DWORD dwLen ) { CENTERROR ceError = CENTERROR_SUCCESS; DWORD nWritten = 0; DWORD dwRemaining = 0; PSTR pStr; dwRemaining = dwLen; pStr = pszBuf; while (dwRemaining > 0) { nWritten = write(dwFd, pStr, dwRemaining); if (nWritten < 0) { if (errno != EAGAIN && errno != EINTR) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } } else { dwRemaining -= nWritten; pStr += nWritten; } } error: return (ceError); } CENTERROR DJGetProcessStatus( PPROCINFO pProcInfo, PLONG plstatus ) { CENTERROR ceError = CENTERROR_SUCCESS; int status = 0; do { if (waitpid(pProcInfo->pid, &status, 0) < 0) { if (errno == EINTR) continue; ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } if (WIFEXITED(status)) { *plstatus = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { DJ_LOG_ERROR("Process [%d] killed by signal %d\n", pProcInfo->pid, WTERMSIG(status)); } else if (WIFSTOPPED(status)) { DJ_LOG_ERROR("Process [%d] stopped by signal %d\n", pProcInfo->pid, WSTOPSIG(status)); } else { DJ_LOG_ERROR("Process [%d] unknown status 0x%x\n", pProcInfo->pid, status); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); error: return ceError; } CENTERROR DJKillProcess( PPROCINFO pProcInfo ) { CENTERROR ceError = CENTERROR_SUCCESS; DWORD dwFlag = 0; DWORD dwTimeout = 30; int status = 0; BOOLEAN oldhandlerset = FALSE; #ifdef HAVE_SIGPROCMASK sigset_t oldset; sigset_t newset; #else sighandler_t oldhandler = 0; #endif #ifdef HAVE_SIGPROCMASK if(sigemptyset(&newset) < 0 || sigaddset(&newset, SIGALRM) < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } if(sigprocmask(SIG_BLOCK, &newset, &oldset) < 0) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } #else if((long)(oldhandler = sigset(SIGALRM, WaitTimeout)) == -1) { ceError = CTMapSystemError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } #endif oldhandlerset = TRUE; alarm(dwTimeout); while ((waitpid(pProcInfo->pid, &status, 0) < 0) && errno == EINTR) { alarm(0); if (dwFlag == 0) { kill(pProcInfo->pid, SIGTERM); } else if (dwFlag == 1) { kill(pProcInfo->pid, SIGKILL); break; } dwFlag++; alarm(dwTimeout); } alarm(0); error: if(oldhandlerset) { #ifdef HAVE_SIGPROCMASK if(sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 && CENTERROR_IS_OK(ceError)) { ceError = CTMapSystemError(errno); } #else if(sigset(SIGALRM, oldhandler) == -1 && CENTERROR_IS_OK(ceError)) { ceError = CTMapSystemError(errno); } #endif } return ceError; }