system-posix-redirect-1.1.0.1/0000755000000000000000000000000012241015261014313 5ustar0000000000000000system-posix-redirect-1.1.0.1/LICENSE0000644000000000000000000000276512241015261015332 0ustar0000000000000000Copyright (c)2010, Edward Z. Yang All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Edward Z. Yang nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. system-posix-redirect-1.1.0.1/Setup.hs0000644000000000000000000000005612241015261015750 0ustar0000000000000000import Distribution.Simple main = defaultMain system-posix-redirect-1.1.0.1/system-posix-redirect.cabal0000644000000000000000000000251212241015261021562 0ustar0000000000000000name: system-posix-redirect version: 1.1.0.1 synopsis: A toy module to temporarily redirect a program's stdout. description: Due to the design of POSIX, it is possible to temporarily overload the file descriptors corresponding to stdout and stderr to point to an arbitrary pipe. It is, however, tricky to get right. This module gets it right, as far as such a terrible hack can be made right. It can be used to make misbehaving third-party C libraries stop spewing to standard output. Warning: the module author has concluded that due to lack of portability, this module should not be used in any serious sytem. But, for those who like living dangerously... license: BSD3 license-file: LICENSE author: Galois Inc., Liyang HU maintainer: system-posix-redirect@liyang.hu copyright: (c) 2010 Galois Inc, 2013 Liyang HU category: System build-type: Simple extra-source-files: include/hsredirect.h cbits/hsredirect.c cabal-version: >= 1.6 source-repository head type: git location: https://github.com/liyang/system-posix-redirect library exposed-modules: System.Posix.Redirect build-depends: base >= 4 && < 5, bytestring >= 0.9, unix >= 2.4.0 ghc-options: -Wall c-sources: cbits/hsredirect.c include-dirs: include install-includes: include/hsredirect.h system-posix-redirect-1.1.0.1/System/0000755000000000000000000000000012241015261015577 5ustar0000000000000000system-posix-redirect-1.1.0.1/System/Posix/0000755000000000000000000000000012241015261016701 5ustar0000000000000000system-posix-redirect-1.1.0.1/System/Posix/Redirect.hs0000644000000000000000000001022612241015261020777 0ustar0000000000000000{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE ForeignFunctionInterface #-} {- | Module : System.Posix.Redirect Copyright : Galois, Inc. 2010 Maintainer : ezyang@galois.com Stability : experimental Portability : non-portable (POSIX, GHC) Misbehaved third-party libraries (usually not written in Haskell) may print error messages directly to stdout or stderr when we would actually like to capture them and propagate them as a normal exception. In such cases, it would be useful to temporarily override those file descriptors to point to a pipe that we control. This module is not portable and not thread safe. However, it can safely manage arbitrarily large amounts of data, as it spins off another thread to read from the pipe created; therefore, you must use -threaded to compile a program with this. If you are making a foreign call, you must ensure that the foreign call is marked safe or there is a possibility of deadlock. While this module is an interesting novelty, it is the module author's opinion that it is not a sustainable method for making C libraries behave properly, primarily due to its unportability (this trick does not appear to be possible on Windows). Use at your own risk. -} module System.Posix.Redirect ( redirectStdout , redirectStderr -- * Low-level operations , redirectWriteHandle , unsafeRedirectWriteFd ) where import Control.Concurrent import Control.Exception import Control.Monad import Data.ByteString as BS import Foreign.C.Types import Foreign.Ptr import System.IO import System.Posix.IO import System.Posix.Types -- | @'unsafeRedirectFd' fd f@ executes the computation @f@, passing as -- an argument a handle which is the read end of a pipe that -- @fd@ now points to. When the computation is done, the original file -- descriptor is restored. Use with care: if there are any file -- handles with this descriptor that have unflushed buffers, they will -- not flush to the old file descriptor, but the new file descriptor. unsafeRedirectWriteFd :: Fd -> IO a -> IO (ByteString, a) unsafeRedirectWriteFd fd f = bracket setup (hClose . fst) $ \ (outHandle, (wfd, old)) -> do -- fork a thread to consume output outMVar <- newEmptyMVar void $ forkIO (BS.hGetContents outHandle >>= putMVar outMVar) -- run the code r <- f `finally` do -- cleanup void $ dupTo old fd closeFd wfd -- wait for output out <- takeMVar outMVar return (out, r) where setup = do (rfd, wfd) <- createPipe old <- dup fd void $ dupTo wfd fd outHandle <- fdToHandle rfd return (outHandle, (wfd, old)) -- | @'redirectWriteHandle' oldFd oldHandle oldCHandle f@ executes the -- computation @f@, passing as an argument a handle which is the read -- end of a pipe that @fd@ now points to. This function appropriately -- flushes the Haskell @oldHandle@ and the C @oldCHandle@ before -- and after @f@'s execution. redirectWriteHandle :: Fd -> Handle -> Ptr FILE -> IO a -> IO (ByteString, a) redirectWriteHandle oldFd oldHandle cOldHandle f = do hFlush oldHandle hFlush stdout void $ c_fflush cOldHandle unsafeRedirectWriteFd oldFd $ do r <- f hFlush oldHandle void $ c_fflush cOldHandle return r -- | @'redirectStdout' f@ redirects standard output during the execution -- of @f@ into a pipe passed as the first argument to @f@. redirectStdout :: IO a -> IO (ByteString, a) redirectStdout f = do c_stdout <- cio_stdout redirectWriteHandle stdOutput stdout c_stdout f -- | @'redirectStderr' f@ redirects standard error during the execution -- of @f@ into a pipe passed as the first argument to @f@. redirectStderr :: IO a -> IO (ByteString, a) redirectStderr f = do c_stderr <- cio_stderr redirectWriteHandle stdError stderr c_stderr f --------------------------------------------------- -- FFI imports, since we need to flush the C buffer data FILE foreign import ccall safe "stdio.h fflush" c_fflush :: Ptr FILE -> IO CInt foreign import ccall unsafe "hsredirect.h PosixRedirect_stdout" cio_stdout :: IO (Ptr FILE) foreign import ccall unsafe "hsredirect.h PosixRedirect_stderr" cio_stderr :: IO (Ptr FILE) system-posix-redirect-1.1.0.1/cbits/0000755000000000000000000000000012241015261015417 5ustar0000000000000000system-posix-redirect-1.1.0.1/cbits/hsredirect.c0000644000000000000000000000035012241015261017715 0ustar0000000000000000#include /** * Helper functions for stdout and stderr, because I can't evaluate them * at compile/link time. */ FILE *PosixRedirect_stdout() { return stdout; } FILE *PosixRedirect_stderr() { return stderr; } system-posix-redirect-1.1.0.1/include/0000755000000000000000000000000012241015261015736 5ustar0000000000000000system-posix-redirect-1.1.0.1/include/hsredirect.h0000644000000000000000000000012012241015261020234 0ustar0000000000000000#include FILE *PosixRedirect_stdout(); FILE *PosixRedirect_stderr();