packages feed

hsshellscript 3.1.0 → 3.2.0

raw patch · 18 files changed

+624/−116 lines, 18 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- HsShellScript: pipe_from2 :: IO a -> IO (String, ProcessStatus)
+ HsShellScript: pipe_from2 :: IO a -> IO String
- HsShellScript.ProcErr: pipe_from2 :: IO a -> IO (String, ProcessStatus)
+ HsShellScript.ProcErr: pipe_from2 :: IO a -> IO String

Files

Makefile view
@@ -8,7 +8,9 @@ 	cabal haddock 	cabal install -dist/build/libHShsshellscript-3.0.0.a :: +build :: dist/build/libHShsshellscript-3.2.0.a++dist/build/libHShsshellscript-3.2.0.a ::  	cabal build  dist ::@@ -22,3 +24,6 @@ uninstall-manual :: 	rm -rf /usr/local/share/hsshellscript/manual 	rmdir --ignore-fail-on-non-empty /usr/local/share/hsshellscript ++doc ::+	cabal haddock
hsshellscript.cabal view
@@ -1,5 +1,5 @@ Name:                hsshellscript-Version:             3.1.0+Version:             3.2.0 Synopsis:            Haskell for Unix shell scripting tasks Description:         A Haskell-library for tasks which are usually done in                      shell scripts. This includes parsing command line@@ -15,7 +15,7 @@ Copyright:           (c)2004-2011 by Volker Wysk Category:            System Build-type:          Simple-Extra-source-files:  README, manual/*.html, manual/LICENSE, Makefile+Extra-source-files:  README, manual/*.html, manual/LICENSE, Makefile, test/*.hs  cabal-version:       >= 1.6 @@ -44,5 +44,3 @@    -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.   Build-tools:       c2hs >= 0.15.1--
manual/index.html view
@@ -8,7 +8,7 @@ <H1>HsShellScript User Manual</H1>  <P>This is the user manual for the <A HREF="http://www.volker-wysk.de/hsshellscript">HsShellScript</A>-Haskell shell scripting library, version 3.1.0. It has been released 2012-04-02. The API+Haskell shell scripting library, version 3.2.0. It has been released 2012-08-28. The API documentation is in a separate document.</P> <P>HsShellScript is a library which makes things easy to program in Haskell, which are typically done by shell scripts on Unix-like@@ -23,6 +23,6 @@ <BR><A HREF="LICENSE">License</A></P>  <P STYLE="border-top: 1px solid #000000; border-bottom: none; border-left: none; border-right: none; padding-top: 0.05cm; padding-bottom: 0cm; padding-left: 0cm; padding-right: 0cm">-<small>Last changed 2012-04-02</small></P>+<small>Last changed 2012-08-28</small></P> </BODY> </HTML>
manual/install.html view
@@ -17,7 +17,7 @@ <p>In order to install, unpack the source distribution somewhere. Go to the   directory, and call <tt>make</tt>. This will compile and install the library,   locally, as a user package. The location of the API documentation-  is <tt>~/.cabal/share/doc/hsshellscript-3.1.0/html/index.html</tt>.+  is <tt>~/.cabal/share/doc/hsshellscript-3.2.0/html/index.html</tt>.  <p>Cabal's Simple Build Infrastructure doesn't provide any means to add extra   documenation to a project. Therefore the user manual isn't installed by default.
src/HsShellScript.hs view
@@ -126,7 +126,7 @@                       putStrLn $ "\n" ++ (argerror_usageinfo argerror)                       exitFailure               , Handler $ \(processstatus :: ProcessStatus) ->-                   do errm $ "Process error. process status = " ++ show ( processstatus :: ProcessStatus )+                   do errm $ "Process error. Process status = " ++ show ( processstatus :: ProcessStatus )                       exitFailure               , Handler $ \(runerror :: RunError) ->                    do errm (show_runerror runerror)@@ -232,7 +232,7 @@    duplicated. When the child process uses that handle, that data gets written    twice. -   The functions which fork a child process ('call', 'spawn', 'silently',+   The functions which fork a child process ('subproc', 'spawn', 'silently',    'pipe_to' etc.) flush @stdout@ and @stderr@ (should be unbuffered) before the    fork. So the child process can use them. The pipe functions also take care of    @stdin@, which is used to read from the pipe. But they don't know about any@@ -282,8 +282,8 @@    might have changed, see "HsShellScript#exec"). They are also reset to    blocking mode. All others are closed when the exec succeeds. -   /You can't use/ @executeFile@ /directly, unless you take care of the things-   outlined at/ "HsShellScript#exec" /and/ 'execute_file' /by yourself./+   /You can't use/ @executeFile@ /directly, unless you take care of the things/+   /outlined at/ "HsShellScript#exec" /and/ 'execute_file' /by yourself./     If replacing the process fails (for instance, because the program wasn't    found), then everything is restored to original state, and an @IOError@ is
src/HsShellScript/ProcErr.chs view
@@ -1,4 +1,3 @@--- Ausnahme in child, Exception -- #hide module HsShellScript.ProcErr where @@ -65,26 +64,42 @@ -- Execute an IO action as a separate process, and wait for it to finish. -- Report errors as exceptions. ----- The program forks a child process and performs the specified action.--- Then it waits for the child process to finish. If it exits in any way--- which indicates an error, the @ProcessStatus@ is thrown as an--- exception.+-- This forks a child process, which performs the specified IO action.+-- In+-- case the child process has been stopped by a signal, the parent blocks. ----- When the action throws an @IOError@, it is transmitted to the parent.+-- If the action throws an @IOError@, it is transmitted to the parent. -- It is then raised there, as if it happened locally. The child then aborts -- quietly with an exit code of 0. --+-- Exceptions in+-- the child process, other than @IOError@s, result in an error message on @stderr@, and a+-- @ProcessStatus@ exception in the parent, with the value of @Exited+-- (ExitFailure 1)@. The following exceptions are understood by @subproc@, and+-- result in corresponding messages: @ArgError@, @ProcessStatus@, @RunError@,+-- @IOError@ and @ExitCode@. Other exceptions result in the generic message, as+-- produced by @show@.+--+-- If the child process exits with an exit code other than zero, or it is+-- terminated by a signal, the corresponding @ProcessStatus@ is raised as an+-- exception in the parent program. Only @IOError@s are transmitted to the parent.+-- -- When used in conjunction with an @exec@ variant, this means that the parent -- process can tell the difference between failure of the @exec@ call itself,--- and failure of the program being executed. You get the @IOError@, which--- happened in the child when calling @executeFile@ (GHC hierarchical--- libraries). Of course, the action can prevent this form happening, by--- itself catching @IOError@s.+-- and failure of the child program being executed after a successful call of+-- the @exec@ variant. In case of failure of the @exec@+-- call, You get the @IOError@, which+-- happened in the child when calling @executeFile@ (from the GHC hierarchical+-- libraries). In case of the called program failing, you get the @ProcessStatus@. ----- The parent process waits for the child process, if it has been stopped by a--- signal.+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally (unless it throws an+-- @IOError@). The child process is then properly terminated by @subproc@, such+-- that no resources, which have been duplicated by the fork, cause problems.+-- See "HsShellScript#subr" for details. ----- See "HsShellScript#subr" for further details.+-- If you want to run an external program, by calling one of the @exec@+-- variants in the child action, you might want to call @runprog@ instead of @subproc@. -- -- -- Examples:@@ -233,7 +248,7 @@   -{- | An error which occured when calling an external program via 'runprog'.+{- | An error which occured when calling an external program.    The fields specifiy the details of the call.     See 'show_runerror', 'to_ioe', 'as_ioe', @System.Posix.ProcessStatus@.@@ -333,7 +348,8 @@  -- | -- Run an external program, and report errors as exceptions. The executable is--- searched via the @PATH@.+-- searched via the @PATH@. In case the child process has been stopped by a+-- signal, the parent blocks. -- -- In case the program exits in an way which indicates an error, or is -- terminated by a signal, a @RunError@ is thrown. It@@ -343,7 +359,9 @@ -- -- In case of starting the program itself failed, an @IOError@ is thrown. ----- @runprog prog par@ is essentially @subproc (execp prog par)@.+-- @runprog prog par@ is a simple front end to @subproc@. It is essentially+-- @subproc (execp prog par)@, apart from building a @RunError@ from a+-- @ProcessStatus@. -- -- Example 1: --@@ -379,8 +397,7 @@                              , re_env   = env                              , re_wd    = wd                              , re_ps    = ps-                             , re_errno = if c_errno /= (0::CInt) then Just c_errno-                                                                  else Nothing+                             , re_errno = if c_errno /= (0::CInt) then Just c_errno else Nothing                              }))  @@ -883,13 +900,51 @@             return (Just h)  --- | Run an IO action as a separate process, and pipe some text to its @stdin@.--- Then close the pipe and wait for the child process to finish. If it--- exits in a way which indicates an error, the @ProcessStatus@ is thrown.+-- |+-- Run an IO action as a separate process, and pipe some text to its @stdin@.+-- Then close the pipe and wait for the child process to finish. ----- Example: @pipe_to \"blah\" $ exec \"\/usr\/bin\/foo\" [\"bar\"]@+-- This forks a child process, which executes the specified action. The specified+-- text is sent to the action's @stdin@ through a pipe. Then the pipe is closed.+-- In case the action replaces the process by calling an @exec@ variant, it is+-- made sure that the process gets the text on it's file descriptor 0. ----- See 'subproc', 'runprog', '-<-', 'h_pipe_to'. See "HsShellScript#fdpipes" for more details.+-- In case the action fails (exits with an exit status other than 0, or is+-- terminated by a signal), the @ProcessStatus@ is thrown, such as reported by+-- 'System.Posix.getProcessStatus'. No attempt is made to create more meaningful+-- exceptions, like it is done by @runprog@/@subproc@.+--+-- Exceptions in the action result in an error message on @stderr@, and the+-- termination of the child. The parent gets a @ProcessStatus@ exception, with+-- the value of @Exited (ExitFailure 1)@. The following exceptions are+-- understood, and result in corresponding messages: @ArgError@,+-- @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other exceptions+-- result in the generic message, as produced by @show@.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally.+-- The child process is then properly terminated, such+-- that no resources, which have been duplicated by the fork, cause problems.+-- See "HsShellScript#subr" for details.+--+-- Example:+--+-- >pipe_to "blah" (exec "/usr/bin/foo" ["bar"])+--+-- Example: Access both @stdin@ and @stdout@ of an external program.+--+-- >import HsShellScript+-- >+-- >main = mainwrapper $ do+-- >+-- >   res <- pipe_from $+-- >      pipe_to "2\n3\n1" $+-- >         exec "/usr/bin/sort" []+-- >+-- >   putStrLn res+--+--+-- See 'subproc', 'runprog', '-<-', 'h_pipe_to'. pipe_to :: String       -- ^ Text to pipe         -> IO a         -- ^ Action to run as a separate process, and to pipe to         -> IO ()@@ -903,11 +958,46 @@        else throw ps  --- | Run an IO action as a separate process, and connect to its @stdin@--- with a pipe.+-- |+-- Run an IO action as a separate process, and get a connection (a pipe) to+-- its @stdin@ as a file handle. ----- Example: @h \<- h_pipe_to $ exec \"\/usr\/bin\/foo\" [\"bar\"]@+-- This forks a subprocess, which executes the specified action. A file handle,+-- which is connected to its @stdin@, is returned. The child's @ProcessID@+-- is returned as well. If the action replaces the child process, by calling an+-- @exec@ variant, it is made sure that its file descriptor 0 is connected to+-- the returned file handle. --+-- This gives you full control of the pipe, and of the forked process. But you+-- must cope with the child process by yourself. +--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally.+-- The child process is then properly terminated, such+-- that no resources, which have been duplicated by the fork, cause problems.+-- See "HsShellScript#subr" for details.+--+-- Errors can only be detected by examining the child's process status (using+-- 'System.Posix.Process.getProcessStatus'). If the child action throws an+-- exception, an error message is printed on @stderr@, and the child process+-- exits with a @ProcessStatus@ of @Exited+-- (ExitFailure 1)@. The following exceptions are understood, and+-- result in corresponding messages: @ArgError@, @ProcessStatus@, @RunError@,+-- @IOError@ and @ExitCode@. Other exceptions result in the generic message, as+-- produced by @show@.+--+-- If the child process exits in a way which signals an error, the+-- corresponding @ProcessStatus@ is returned by @getProcessStatus@. See+-- 'System.Posix.Process.getProcessStatus' for details.+--+-- Example:+--+-- >(handle, pid) <- h_pipe_to $ exec "/usr/bin/foo" ["bar"]+-- >hPutStrLn handle "Some text to go through the pipe"+-- >(Just ps) <- getProcessStatus True False pid+-- >when (ps /= Exited ExitSuccess) $+-- >   throw ps+-- -- See '-<-', 'pipe_to', 'pipe_from', 'pipe_from2'. See "HsShellScript#fdpipes" for more details. h_pipe_to :: IO a                       -- ^ Action to run as a separate process, and to pipe to           -> IO (Handle, ProcessID)     -- ^ Returns handle connected to the standard input of the child process, and the child's process ID@@ -916,70 +1006,181 @@    return (h, pid)  --- | Run an IO action as a separate process, and read its @stdout@--- strictly. Then wait for the child process to finish. This is like the--- backquote feature of shells.+-- | Run an IO action as a separate process, and read its @stdout@ strictly.+-- Then wait for the child process to finish. This is like the backquote feature+-- of shells. ----- If the child process exits with a non-zero exit code, the--- @ProcessStatus@ is thrown.+-- This forks a child process, which executes the specified action. The output+-- of the child is read from its standard output. In case it replaces the+-- process by calling an @exec@ variant, it is make sure that the output is+-- read from the new process' file descriptor 1. ----- The whole output is returned, no trailing newline character is removed, like the shell does with backquotes. You may want to apply @chomp@--- to the result.+-- The end of the child's output is reached when either the standard output is+-- closed, or the child process exits. The program blocks until the action+-- exits, even if the child closes its standard output earlier. So the parent+-- process always notices a failure of the action (when it exits in a way which+-- indicates an error). --+-- When the child action exits in a way which indicates an error, the+-- corresponding @ProcessStatus@ is thrown. See+-- 'System.Posix.Process.getProcessStatus'. No attempt is made to create more+-- meaningful exceptions, like it is done by @runprog@/@subproc@.+--+-- Exceptions in the action result in an error message on @stderr@, and the+-- proper termination of the child. The parent gets a @ProcessStatus@ exception, with+-- the value of @Exited (ExitFailure 1)@. The following exceptions are+-- understood, and result in corresponding messages: @ArgError@,+-- @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other exceptions+-- result in the generic message, as produced by @show@.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally. The child process is+-- then properly terminated, such that no resources, which have been duplicated+-- by the fork, cause problems. See "HsShellScript#subr" for details.+--+-- Unlike shells\' backquote feature, @pipe_from@ does not remove any trailing+-- newline characters. The entire output of the action is returned. You might want+-- to apply @chomp@ to the result.+-- -- Example: ----- >output <- pipe_from $ exec "/bin/foo" ["bar"]+-- >output <- pipe_from $ exec "/bin/mount" [] ----- See 'exec', 'pipe_to', 'pipe_from2', 'h_pipe_from', 'lazy_pipe_from', 'chomp', 'silently'. See "HsShellScript#fdpipes" for more details.-pipe_from :: IO a               -- ^ Action to run as a separate process-          -> IO String          -- ^ The called program's standard output+-- Example: Access both @stdin@ and @stdout@ of an external program.+--+-- >import HsShellScript+-- >+-- >main = mainwrapper $ do+-- >+-- >   res <- pipe_from $+-- >      pipe_to "2\n3\n1" $+-- >         exec "/usr/bin/sort" []+-- >+-- >   putStrLn res+--+-- See 'exec', 'pipe_to', 'pipe_from2', 'h_pipe_from', 'lazy_pipe_from', 'chomp', 'silently'.+pipe_from :: IO a               -- ^ Action to run as a separate process. Its+                                -- return value is ignored.+          -> IO String          -- ^ The action's standard output pipe_from io = do    (h, pid) <- h_pipe_from io    txt <- hGetContents h    seq (length txt) (hClose h)-   (Just ps) <- getProcessStatus True False pid+   (Just ps) <- System.Posix.getProcessStatus True False pid    if ps == Exited ExitSuccess        then return txt        else throw ps  --- | Run an IO action as a separate process, and read its @stderr@--- strictly. Then wait for the child process to finish, and return the text--- along with its exit code.+-- | Run an IO action as a separate process, and read its standard error output+-- strictly. Then wait for the child process to finish. This is like the+-- backquote feature of shells. This function is exactly the same as+-- @pipe_from@, except that the standard error output is read, instead of the+-- standard output. --+-- This forks a child process, which executes the specified action. The error output+-- of the child is read from its standard error output. In case it replaces the+-- process by calling an @exec@ variant, it is made sure that the output is+-- read from the new process' file descriptor 2.+--+-- The end of the child's error output is reached when either the standard error+-- output is closed, or the child process exits. The program blocks until the+-- action exits, even if the child closes its standard error output earlier. So+-- the parent process always notices a failure of the action (which means it+-- exits in a way which indicates an error).+--+-- When the child action exits in a way which indicates an error, the+-- corresponding @ProcessStatus@ is thrown. See+-- 'System.Posix.Process.getProcessStatus'.+-- No attempt is made to create+-- more meaningful exceptions, like it is done by @runprog@/@subproc@.+--+--+-- Exceptions in the action result in an error message on @stderr@, and the+-- proper termination of the child. This means that the error message is sent+-- through the pipe, to the parent process. The message can be found in the text+-- which has been read from the child process. It doesn't appear on the console.+--+-- The parent gets a @ProcessStatus@ exception, with+-- the value of @Exited (ExitFailure 1)@. The following exceptions are+-- understood, and result in corresponding messages: @ArgError@,+-- @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other exceptions+-- result in the generic message, as produced by @show@.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally. The child process is+-- then properly terminated, such that no resources, which have been duplicated+-- by the fork, cause problems. See "HsShellScript#subr" for details.+--+-- Unlike shells\' backquote feature, @pipe_from2@ does not remove any trailing+-- newline characters. The entire error output of the action is returned. You might want+-- to apply @chomp@ to the result.+-- -- Example: ----- >(errmsg, ec) <- pipe_from2 $ exec "/bin/foo" ["bar"] ->- "/dev/null"+-- >output <- pipe_from $ exec "/bin/mount" []+--+-- Example: Access both @stdin@ and @stdout@ of an external program.+--+-- >import HsShellScript -- >--- >when (ec /= Exited ExitSuccess) $ do--- >   errm errmsg--- >   ...+-- >main = mainwrapper $ do+-- >+-- >   res <- pipe_from $+-- >      pipe_to "2\n3\n1" $+-- >         exec "/usr/bin/sort" []+-- >+-- >   putStrLn res -- -- See 'exec', 'pipe_to', 'pipe_from', 'h_pipe_from2', 'lazy_pipe_from2', 'silently'. See "HsShellScript#fdpipes" for more details.-pipe_from2 :: IO a                              -- ^ Action to run as a separate process-           -> IO (String, ProcessStatus)        -- ^ The called program's standard output+pipe_from2 :: IO a              -- ^ Action to run as a separate process+           -> IO String         -- ^ The action's standard error output pipe_from2 io = do    (h, pid) <- h_pipe_from2 io    txt <- hGetContents h    seq (length txt) (hClose h)-   (Just ps) <- getProcessStatus True False pid-   return (txt, ps)+   (Just ps) <- System.Posix.getProcessStatus True False pid+   if ps == Exited ExitSuccess+       then return txt+       else throw ps   -- | Run an IO action as a separate process, and connect to its @stdout@--- with a pipe.+-- with a file handle.+-- This is like the backquote feature of shells. ----- A handle connected to the child process, and the process ID--- of the child are returned. The process ID can be used with--- @System.Posix.getProcessStatus@ to get the child's exit code. You must either--- ensure that all data has been read, or close the handle, before calling--- @getProcessStatus@ blockingly. Otherwise you'll get a deadlock. When you--- close the handle before all data has been read, then the child gets a--- @SIGPIPE@ signal.+-- This forks a subprocess, which executes the specified action. A file handle,+-- which is connected to its @stdout@, is returned. The child's @ProcessID@+-- is returned as well. If the action replaces the child process, by calling an+-- @exec@ variant, it is made sure that its file descriptor 1 is connected to+-- the returned file handle. --+-- This gives you full control of the pipe, and of the forked process. But you+-- must cope with the child process by yourself. +--+-- When you call @getProcessStatus@ blockingly, you must first ensure that all+-- data has been read, or close the handle. Otherwise you'll get a deadlock.+-- When you close the handle before all data has been read, then the child gets+-- a @SIGPIPE@ signal.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally.+-- The child process is then properly terminated, such+-- that no resources, which have been duplicated by the fork, cause problems.+-- See "HsShellScript#subr" for details.+--+-- Errors can only be detected by examining the child's process status (using+-- 'System.Posix.Process.getProcessStatus'). No attempt is made to create more+-- meaningful exceptions, like it is done by @runprog@/@subproc@. If the child+-- action throws an exception, an error message is printed on @stderr@, and the+-- child process exits with a @ProcessStatus@ of @Exited (ExitFailure 1)@. The+-- following exceptions are understood, and result in corresponding messages:+-- @ArgError@, @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other+-- exceptions result in the generic message, as produced by @show@.+-- -- Example: ----- >h <- h_pipe_from $ exec "/usr/bin/foo" ["bar"]+-- >(h,pid) <- h_pipe_from $ exec "/usr/bin/foo" ["bar"] -- -- See 'exec', 'pipe_to', 'h_pipe_from2', 'pipe_from', 'lazy_pipe_from', 'chomp', 'silently'. See "HsShellScript#fdpipes" for more details. h_pipe_from :: IO a                             -- ^ Action to run as a separate process, and to pipe from@@ -990,22 +1191,43 @@   -- | Run an IO action as a separate process, and connect to its @stderr@--- with a pipe.+-- with a file handle. ----- A handle connected to the child process' standard error output, and the process ID--- of the child are returned. The process ID can be used with--- @System.Posix.getProcessStatus@ to get the child's exit code. You must either--- ensure that all data has been read, or close the handle, before calling--- @getProcessStatus@ blockingly. Otherwise you'll get a deadlock. When you--- close the handle before all data has been read, then the child gets a--- @SIGPIPE@ signal. Of course, you can also use the process ID to kill the--- child process.+-- This forks a subprocess, which executes the specified action. A file handle,+-- which is connected to its @stderr@, is returned. The child's @ProcessID@+-- is returned as well. If the action replaces the child process, by calling an+-- @exec@ variant, it is made sure that its file descriptor 2 is connected to+-- the returned file handle. --+-- This gives you full control of the pipe, and of the forked process. But you+-- must cope with the child process by yourself. +--+-- When you call @getProcessStatus@ blockingly, you must first ensure that all+-- data has been read, or close the handle. Otherwise you'll get a deadlock.+-- When you close the handle before all data has been read, then the child gets+-- a @SIGPIPE@ signal.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally. The child process is+-- then properly terminated, such that no resources, which have been duplicated+-- by the fork, cause problems. See "HsShellScript#subr" for details.+--+-- Errors can only be detected by examining the child's process status (using+-- 'System.Posix.Process.getProcessStatus'). No attempt is made to create more+-- meaningful exceptions, like it is done by @runprog@/@subproc@. If the child+-- action throws an exception, an error message is printed on @stderr@. This+-- means that the message goes through the pipe to the parent process. Then the+-- child process exits with a @ProcessStatus@ of @Exited (ExitFailure 1)@. The+-- following exceptions are understood, and result in corresponding messages:+-- @ArgError@, @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other+-- exceptions result in the generic message, as produced by @show@.+-- -- Example: ----- >h <- h_pipe_from2 $ exec "/usr/bin/foo" ["bar"]+-- >(h,pid) <- h_pipe_from $ exec "/usr/bin/foo" ["bar"] ----- See 'exec', 'pipe_to', 'h_pipe_from', 'pipe_from2', 'lazy_pipe_from2', 'chomp', 'silently'. See "HsShellScript#fdpipes" for more details.+-- See 'exec', 'pipe_from', 'pipe_from2', 'h_pipe_from', 'pipe_to',+-- 'lazy_pipe_from', 'chomp', 'silently'. h_pipe_from2 :: IO a                             -- ^ Action to run as a separate process, and to pipe from              -> IO (Handle, ProcessID)           -- ^ Returns handle connected to the standard output of the child process, and the child's process ID h_pipe_from2 io = do@@ -1013,28 +1235,90 @@    return (h, pid)  --- | Run an IO action as a separate process, and read its @stdout@,--- This is like the backquote feature of shells. The output is read--- lazily, as the returned string is evaluated.+++-- | Run an IO action in a separate process, and read its standard output, The output+-- is read lazily, as the returned string is evaluated. The child's output along+-- with its process ID are returned.+-- +-- This forks a child process, which executes the specified action. The output+-- of the child is read lazily through a pipe, which connncts to its standard+-- output. In case the child replaces the process by calling an @exec@ variant,+-- it is make sure that the output is read from the new process' file descriptor+-- 1. ----- The child's output along with its process ID are returned. The process ID can--- be used with @System.Posix.getProcessStatus@ to get the child process' exit--- code. Be aware that you must evaluate the whole string, before calling--- @getProcessStatus@ blockingly, or you'll get a deadlock.+-- @lazy_pipe_from@ calls 'System.IO.hGetContents', in order to read the pipe+-- lazily. This means that the file handle goes to semi-closed state. The handle+-- holds a file descriptor, and as long as the string isn't fully evaluated,+-- this file descriptor won't be closed. For the file descriptor to be closed,+-- first its standard output needs to be closed on the child side. This happens+-- when the child explicitly closes it, or the child process exits. When+-- afterwards the string on the parent side is completely evaluated, the handle,+-- along with the file descritor it holds, are closed and freed. ----- The whole output is returned, no trailing newline character is removed, like--- the shell does with backquotes. You'll possibly want to apply 'chomp' to the--- result.+-- If you use the string in such a way that you only access the beginning of the+-- string, the handle will remain in semi-closed state, holding a file+-- descriptor, even when the pipe is closed on the child side. When you do that+-- repeatedly, you may run out of file descriptors. ----- Example:+-- Unless you're sure that your program will reach the string's end, you should +-- take care for it explicitly, by doing something like this: ----- >(txt, pid) <- lazy_pipe_from $ exec "/usr/bin/foo" ["bar"]+-- >(output, pid) <- lazy_pipe_from (exec "\/usr\/bin\/foobar" []) -- >...--- >-- Done, but must read the rest of the output--- >seq (length txt) (return ())--- >(Just ps) <- getProcessStatus True False pid+-- >seq (length output) (return ())    ----- See 'exec', 'pipe_to', 'pipe_from', 'h_pipe_from', 'lazy_pipe_from2', 'silently'. See "HsShellScript#fdpipes" for more details.+-- This will read the entire standard output of the child, even if it isn't+-- needed. You can't cut the child process' output short, when you use+-- @lazy_pipe_from@. If you need to do this, you should use @h_pipe_from@, which +-- gives you the handle, which can then be closed by 'System.IO.hClose', even +-- if the child's output isn't completed:+--+-- >(h, pid) <- h_pipe_from io+-- >+-- >-- Lazily read io's output+-- >output <- hGetContents h+-- >...+-- >-- Not eveyting read yet, but cut io short.+-- >hClose h   +-- >+-- >-- Wait for io to finish, and detect errors+-- >(Just ps) <- System.Posix.getProcessStatus True False pid+-- >when (ps /= Exited ExitSuccess) $+-- >   throw ps+--   +-- When you close the handle before all data has been read, then the child gets+-- a @SIGPIPE@ signal.+-- +-- After all the output has been read, you should call @getProcessStatus@ on the+-- child's process ID, in order to detect errors. Be aware that you must+-- evaluate the whole string, before calling @getProcessStatus@ blockingly, or+-- you'll get a deadlock.+--   +-- You won't get an exception, if the child action exits in a way which +-- indicates an error. Errors occur asynchronously, when the output string is +-- evaluated. You must detect errors by yourself, by calling +-- 'System.Posix.Process.getProcessStatus'.+--+-- In case the action doesn't replace the child process with an external+-- program, an exception may be thrown out of the action. This results in an error+-- message on @stderr@, and the proper termination of the child. The+-- @ProcessStatus@, which can be accessed in the parent process by+-- @getProcessStatus@, is @Exited (ExitFailure 1)@. The following exceptions are+-- understood, and result in corresponding messages: @ArgError@,+-- @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other exceptions+-- result in the generic message, as produced by @show@.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally. The child process is+-- then properly terminated, such that no resources, which have been duplicated+-- by the fork, cause problems. See "HsShellScript#subr" for details.+--+-- Unlike shells\' backquote feature, @lazy_pipe_from@ does not remove any trailing+-- newline characters. The entire output of the action is returned. You might want+-- to apply @chomp@ to the result.+--   +-- See 'exec', 'pipe_to', 'pipe_from', 'h_pipe_from', 'lazy_pipe_from2', 'silently'. lazy_pipe_from :: IO a                          -- ^ Action to run as a separate process                -> IO (String, ProcessID)        -- ^ The action's lazy output and the process ID of the child process lazy_pipe_from io = do@@ -1043,31 +1327,97 @@    return (txt, pid)  --- | Run an IO action as a separate process, and read its @stderr@. The output--- is read lazily, as the returned string is evaluated.++-- | Run an IO action in a separate process, and read its standard error output, The output+-- is read lazily, as the returned string is evaluated. The child's error output along+-- with its process ID are returned.+-- +-- This forks a child process, which executes the specified action. The error output+-- of the child is read lazily through a pipe, which connncts to its standard error+-- output. In case the child replaces the process by calling an @exec@ variant,+-- it is make sure that the output is read from the new process' file descriptor+-- 1. ----- The child's error output along with its process ID are returned. The process--- ID can be used with @System.Posix.getProcessStatus@ to get the child process'--- exit code. Be aware that you must evaluate the whole string, before calling--- @getProcessStatus@ blockingly, or you'll get a deadlock.+-- @lazy_pipe_from@ calls 'System.IO.hGetContents', in order to read the pipe+-- lazily. This means that the file handle goes to semi-closed state. The handle+-- holds a file descriptor, and as long as the string isn't fully evaluated,+-- this file descriptor won't be closed. For the file descriptor to be closed,+-- first its standard error output needs to be closed on the child side. This happens+-- when the child explicitly closes it, or the child process exits. When+-- afterwards the string on the parent side is completely evaluated, the handle,+-- along with the file descritor it holds, are closed and freed. ----- Example:+-- If you use the string in such a way that you only access the beginning of the+-- string, the handle will remain in semi-closed state, holding a file+-- descriptor, even when the pipe is closed on the child side. When you do that+-- repeatedly, you may run out of file descriptors. ----- >(errmsg, pid) <- lazy_pipe_from2 $ exec "/usr/bin/foo" ["bar"] ->- "/dev/null"+-- Unless you're sure that your program will reach the string's end, you should +-- take care for it explicitly, by doing something like this:+--+-- >(errmsg, pid) <- lazy_pipe_from2 (exec "/usr/bin/foobar" []) -- >...--- >-- Read enough error messages, terminate the child.--- >signalProcess killProcess pid+-- >seq (length errmsg) (return ())   +--+-- This will read the entire standard error output of the child, even if it isn't+-- needed. You can't cut the child process' output short, when you use+-- @lazy_pipe_from@. If you need to do this, you should use @h_pipe_from@, which +-- gives you the handle, which can then be closed by 'System.IO.hClose', even +-- if the child's output isn't completed:+--+-- >(h, pid) <- h_pipe_from io -- >--- >-- Make sure the file descriptor gets closed, or you may run out of file descriptors.--- >seq (length errmsg) (return ())+-- >-- Lazily read io's output+-- >output <- hGetContents h+-- >...+-- >-- Not eveyting read yet, but cut io short.+-- >hClose h   +-- >+-- >-- Wait for io to finish, and detect errors+-- >(Just ps) <- System.Posix.getProcessStatus True False pid+-- >when (ps /= Exited ExitSuccess) $+-- >   throw ps+--   +-- When you close the handle before all data has been read, then the child gets+-- a @SIGPIPE@ signal.+-- +-- After all the output has been read, you should call @getProcessStatus@ on the+-- child's process ID, in order to detect errors. Be aware that you must+-- evaluate the whole string, before calling @getProcessStatus@ blockingly, or+-- you'll get a deadlock.+--   +-- You won't get an exception, if the child action exits in a way which +-- indicates an error. Errors occur asynchronously, when the output string is +-- evaluated. You must detect errors by yourself, by calling +-- 'System.Posix.Process.getProcessStatus'. ----- See 'exec', 'pipe_to', 'pipe_from2', 'h_pipe_from2', 'lazy_pipe_from', 'silently'. See "HsShellScript#fdpipes" for more details.+-- In case the action doesn't replace the child process with an external+-- program, an exception may be thrown out of the action. This results in an+-- error message on @stderr@. This means that the message is sent through the+-- pipe, to the parent process. Then the child process is properly terminated.+-- The @ProcessStatus@, which can be accessed in the parent process by+-- @getProcessStatus@, is @Exited (ExitFailure 1)@. The following exceptions are+-- understood, and result in corresponding messages: @ArgError@,+-- @ProcessStatus@, @RunError@, @IOError@ and @ExitCode@. Other exceptions+-- result in the generic message, as produced by @show@.+--+-- Unless you replace the child process, calling an @exec@ variant, the child+-- should let the control flow leave the action normally. The child process is+-- then properly terminated, such that no resources, which have been duplicated+-- by the fork, cause problems. See "HsShellScript#subr" for details.+--+-- Unlike shells\' backquote feature, @lazy_pipe_from@ does not remove any trailing+-- newline characters. The entire output of the action is returned. You might want+-- to apply @chomp@ to the result.+--   +-- See 'exec', 'pipe_to', 'pipe_from2', 'h_pipe_from2', 'lazy_pipe_from', 'silently'. lazy_pipe_from2 :: IO a                          -- ^ Action to run as a separate process                 -> IO (String, ProcessID)        -- ^ The action's lazy output and the process ID of the child process lazy_pipe_from2 io = do-   (_, Just h, _, pid) <- pipe_fork_dup io False True False+   (_, _, Just h, pid) <- pipe_fork_dup io False False True    txt <- hGetContents h    return (txt, pid)+      -- | Run an IO action as a separate process, and optionally connect to its@@ -1335,7 +1685,7 @@       -> IO b           -- Never returns child io = do    (io `finally` flush_outerr)-      `catches` +      `catches`       [ Handler $ (\argerror -> do                       errm $ "In child process:\n" ++ argerror_message argerror                       _exit 1@@ -1344,11 +1694,15 @@                       errm $ "Process error in child process. Process status = " ++ show ( processstatus :: ProcessStatus )                       _exit 1                   )+      , Handler $ (\(runerror::RunError) -> do+                      errm $ (show_runerror runerror)+                      _exit 1+                  )       , Handler $ (\(ioe::IOError) -> do                       errm ("In child process:\n   " ++ show_ioerror ioe)                       _exit 1                   )-      , Handler $ (\(e::ExitCode) -> do +      , Handler $ (\(e::ExitCode) -> do                       -- Child process is a subroutine that has terminated normally.                       errm "Warning! Child process tries to shut down normally. This is a bug. It should\n\                            \terminate with _exit (or catch the ExitException yourself). See section\n\"\@@ -1777,7 +2131,7 @@    typeOf = const tyCon_ProcessStatus  -- GHC 6.4-tyCon_ProcessStatus = mkTyConApp (mkTyCon3 "hsshellscript"              +tyCon_ProcessStatus = mkTyConApp (mkTyCon3 "hsshellscript"                                            "HsShellScript.ProcErr"                                            "Posix.ProcessStatus") [] 
src/cbits/hsshellscript.c view
@@ -48,8 +48,6 @@   int ret;   buf->gl_pathv = 0; -  printf("pattern = >%s<\n", pattern);  /***/-   ret = glob(pattern, GLOB_ERR, 0, buf);    switch (ret) {
+ test/IOError.hs view
@@ -0,0 +1,36 @@+to_ioe :: RunError -> IOError+to_ioe re =+   GHC.IO.Exception.IOError { ioe_handle      = Nothing,+                              ioe_type        = GHC.IO.Exception.SystemError,+                              ioe_location    = "runprog",+                              ioe_description = show_runerror re,+                              ioe_filename    = Just (shell_command (re_prog re) (re_pars re)),+                              ioe_errno       = re_errno re+                            }+      +{-+ FilePath -> IOErrorSource+                                +   GHC.IO.Exception.IOError { +                              +                              +                              ioe_description = show_runerror re,+                              ioe_filename    = +                              ioe_errno       = re_errno re+                            }+-}+{-+to_ioe re =+   System.IO.Error.ioeSetErrorString +      ( System.IO.Error.mkIOError GHC.IO.Exception.SystemError       -- Type+                                  "runprog"                          -- Location+                                  Nothing                            -- handle +                                  (Just (shell_command (re_prog re) (re_pars re)))   -- file name+      )+      (show_runerror re)+      { +-}++++-- In ProcErr.hs:317
+ test/as_ioe.hs view
@@ -0,0 +1,16 @@+import Control.Exception+import Prelude hiding (catch)+import HsShellScript++main = mainwrapper $ do+   outm "RunError:"+   runprog "/bin/false" []+     `catch` (\(re::RunError) -> +                 outm (show re))+   +   outm "\n\nIOError:" +   (as_ioe $ runprog "/bin/false" [])+     `catch` (\(ioe::IOError) -> +                 outm (show ioe))++   outm "\n\nEnd."
+ test/bug.hs view
@@ -0,0 +1,16 @@+import Foreign.C+import Foreign.Ptr+++main = +  aufruf "äöü"+++aufruf :: String -> IO ()+aufruf str =+  withCString str $ \ptr -> c_aufruf ptr+++foreign import ccall safe "test/glob.chs.h c_aufruf"+  c_aufruf :: ((Ptr CChar) -> (IO ()))+
+ test/child.hs view
@@ -0,0 +1,5 @@+import HsShellScript+++main = mainwrapper $ do+   pipe_to "bla" (exec "/bin/false" [])
+ test/glob.hs view
@@ -0,0 +1,6 @@+import HsShellScript++main = do+   l <- glob "*"+   mapM_ outm l+   
+ test/h_pipe_to.hs view
@@ -0,0 +1,14 @@+import System.Posix+import HsShellScript+++main = mainwrapper $ do+  (h,pid) <- h_pipe_to (exec "/fooble" [])+  (Just ps) <- getProcessStatus True False pid+  print (ps::ProcessStatus)+  +  +{- +     getProcessStatus block stopped pid+                      - Ob getProcessStatus blockieren soll+-}
+ test/path_exists'.hs view
@@ -0,0 +1,16 @@+import HsShellScript+import System.Posix.Files++main = do +  createSymbolicLink "/frooble" "symlink"+  +  outm_ "Symlink exists: "+  ex <- path_exists' "symlink"+  outm (show ex)+  +  outm_ "Path exists: "+  ex <- path_exists "symlink"+  outm (show ex)++  removeLink "symlink"+  
+ test/pipe.hs view
@@ -0,0 +1,9 @@+import HsShellScript++main = mainwrapper $ do++   erg <- pipe_from $+      pipe_to "2\n3\n1" $+         exec "/usr/bin/sort" []++   putStrLn erg
+ test/run.hs view
@@ -0,0 +1,12 @@+import HsShellScript+import Control.Exception+import Prelude hiding (catch)++main = do+   outm "run:"+   (mainwrapper $ run "/frooble" [])+      `catch` (\(e::SomeException) -> print e)++   outm "\n\nrunprog:"+   (mainwrapper $ runprog "/frooble" [])+      `catch` (\(e::SomeException) -> print e)
+ test/subproc.hs view
@@ -0,0 +1,12 @@+import HsShellScript+import Control.Exception+import Data.Typeable++data Ausnahme = Ausnahme+   deriving (Show, Typeable)++instance Exception Ausnahme+++main = mainwrapper $ do+   subproc (throw Ausnahme)
+ test/test.hs view
@@ -0,0 +1,11 @@++import HsShellScript++main = do+  outm "-1-"+  subproc (outm "Durch die Röhre" -|- exec "/bin/cat" [])+  outm "-2-"++  mount <- pipe_from (exec "/bin/mount" [])+  outm "Mount:"+  outm mount