Re: cvs commit: fptools/hslibs/posix Makefile PosixDB.lhs PosixProcEnv.lhs PosixTTY.lhs fptools/libraries/unix/System Posix.hs fptools/libraries/unix/System/Posix Terminal.hsc Time.hsc User.hsc Files.hsc IO.hsc Process.hsc Unistd.hsc ...

Alastair Reid <[email protected]> 20 Dec 2002 12:53:08 +0000
Newsgroups gmane.comp.lang.haskell.cvs.hslibs
Message-ID <[email protected]>
>   We're now about 95% complete w.r.t. the old posix library.  I've
> identified the reminaing bits to do in System/Posix.hs.

[Written on the assumption that you haven't gotten to waitpid yet]

btw When using popen, I ran into problems getting hold of process ids
because I seemed to be falling somewhere in the gap between the two
libraries.  After a bunch of searching for the Right Way, I ended up
writing the attached code.  

A few bits reflect my particular application needs (I needed something
equivalent to sh's backquote operation and was content with a
simplistic approach to error handling).  Key things in this solution
(that I'd like to see fixed):

1) I have to allocate storage to hold the result of c_waitpid - it'd
   be better to build that into waitpid.

2) The old and new libraries use different types for process ids hence
   the rather fragile 'oldPIDtoNewPID' function.

3) The result of waitpid is really a pair (triple?) masquerading as a
   single int.  It'd be better for waitpid to return a richer Haskell
   datatype.

--
Alastair

shellEx :: String -> IO a
shellEx cmd = do
  (out,err,pid) <- popen "/bin/sh" ["-c",cmd] Nothing
  prc <- malloc 

  -- force stdout, stderr and then wait for process to exit
  seq (forceSpine out) (return ())
  seq (forceSpine err) (return ())
  c_waitpid (oldPIDtoNewPID pid) prc 0

  rc <- peek prc
  free prc
  -- following line is of dubious portability
  if rc `mod` 128 == 0 && (rc `div` 256) `mod` 256 == 0
    then do
      return out
    else do
      putStrLn $ "Error while executing command " ++ cmd
      putStrLn err
      exitFailure

 where
  oldPIDtoNewPID :: ProcessID -> GHC.Posix.CPid
  oldPIDtoNewPID = fromIntegral