Safe HaskellNone




Probably not at all portable. Makes use of functions from the unistd.h header file.


Tidy this up, shift some of the logic out to another module.


C functions and wrappers around them

setresgid_c :: CGid -> CGid -> CGid -> IO CInt Source #

unistd funcs:

#include unistd.h

      int setresuid(uid_t ruid, uid_t euid, uid_t suid);
      int setresgid(gid_t rgid, gid_t egid, gid_t sgid);

setResGid :: CGid -> CGid -> CGid -> IO () Source #

wrapper around C func setresgid.

setResUid :: CUid -> CUid -> CUid -> IO () Source #

wrapper around C func setresuid.

low-level, Posix-specific functions

openIfNExist :: String -> IO Handle Source #

opens w/ mode 0644, but gives error if exists

i.e. -rw-r--r--

withMailFile :: String -> (Handle -> IO a) -> IO a Source #

opens and closes a file created with openIfNExist, and executes the action f on it in between.

getUserIDs :: String -> IO (UserID, GroupID) Source #

get the uid and gid for a username

getUniqueName :: IO String Source #

Return an allegedly unique filename; useful to add new mail files in a maildir. Name is of format time num hostname.


utility functions

forceEitherMsg :: Either err t -> (err -> String) -> t Source #

force either

warning :: String -> IO () Source #

emit warning to stderr

mkError :: Error a => (t -> String) -> Either t b -> Either a b Source #

for use with Either

Program config

data Config Source #

Configuration, as read from the config file.





getConfig :: String -> IO Config Source #

getConfig filename reads the config file at filename.

deal with addresses

validateAddr :: Maybe Addr -> Either String (Maybe EmailAddress) Source #

the Addr type is simply something that _might_ be an address, this validates it.

handleAddr :: (MonadError e m, Error e) => (Addr -> String -> String) -> Maybe Addr -> m (Maybe EmailAddress) Source #

wrapper around validateAddr. Pass in a func that takes in a (presumably bad) address and an error message, and spits out a string

And then, the Maybe/Either result of validation will get turned into an appropriate MonadError action we can just execute in IO.

whopping big monolithic funcs

deliverMail :: FilePath -> String -> AttCmdArgs -> IO () Source #

deliver mail to the maildir directory mailDir, owned by userName, with command-line args cmdArgs.

Creates a unique file name w/ getUniqueName. If something creates the file in between generating the name and delivering mail, an IOError will get thrown.

AttCmdArgs should never have 0 recipients

main :: IO () Source #

process args as for sendmail.

  sendmail [flags] [receipients] < message
   -f = envelop sender address
   -F = full name of sender
   -bm = read mail from stdin (default)
   -bp, -bs = we ignore these


test :: IO AttCmdArgs Source #

here for testing purposes