-- |A place to collect and hopefully retire all the random ways of-- running shell commands that have accumulated over the years.moduleSystem.Unix.ProcessExtrawhereimportControl.Exception(ErrorCall(ErrorCall),try)importControl.Monad.Trans(liftIO)importqualifiedData.ByteString.Lazy.Char8asLimportqualifiedData.ByteStringasBimportData.List(intercalate)importSystem.ExitimportqualifiedSystem.IOasIOimportSystem.Unix.Process(Output(..),lazyCommand,collectOutput,lazyProcess)cmdOutput::String->IO(EitherErrorCallL.ByteString)cmdOutputcmd=do(out,err,code)<-lazyCommandcmdL.empty>>=return.collectOutputcasecodeofExitSuccess->return(Rightout)_->return.Left.ErrorCall$"Failure: "++showcmd++" -> "++showcode++"\n\nstdpout:\n\n"++show(L.unpackout)++"\n\nstderr:\n\n"++show(L.unpackerr)cmdOutputStrict::String->IO(EitherErrorCallB.ByteString)cmdOutputStrictcmd=do(out,err,code)<-lazyCommandcmdL.empty>>=return.f.collectOutputcasecodeofExitSuccess->return(Rightout)_->return.Left.ErrorCall$"Failure: "++showcmd++" -> "++showcode++"\n\nstdpout:\n\n"++show(B.unpackout)++"\n\nstderr:\n\n"++show(B.unpackerr)wheref::(L.ByteString,L.ByteString,ExitCode)->(B.ByteString,B.ByteString,ExitCode)f(o,e,c)=(toStricto,toStricte,c)toLazy::B.ByteString->L.ByteStringtoLazyb=L.fromChunks[b]toStrict::L.ByteString->B.ByteStringtoStrictb=B.concat(L.toChunksb)echoCommand::String->L.ByteString->IO[Output]echoCommandcommandinput=ePutStrBl("# "++command)>>liftIO(lazyCommandcommandinput)-- |Echo the process arguments and then run the processechoProcess::FilePath->[String]->L.ByteString->IO[Output]echoProcessexecargsinput=ePutStrBl(intercalate" "("#":exec:args))>>liftIO(lazyProcessexecargsNothingNothinginput)ePutStrBl::String->IO()ePutStrBls=IO.hPutStrLnIO.stderrs