smtpdMain :: Capacity
          -> GlobalEnv
          -> ReadHandle
          -> WriteHandle
          -> SmtpdState
          -> IO SmtpdState
smtpdMain cap theEnv hIn hOut initST = do
  let greet = do r <- trigger Greeting
                 safeReply hOut r >> safeFlush hOut
                 to <- getReadTimeout
                 sid <- mySessionID
                 return (r, to, sid)
  ((r, to, sid), st) <- runSmtpd greet theEnv initST
  st' <- case r of
    Reply (Code Success _ _) _  -> do
      let getTO  = evalState (getVarDef (mkVar "ReadTimeout") to)
          yellIO = syslogger . LogMsg sid st
          hMain  = smtpdHandler hOut theEnv
          errH e st' = yellIO (CaughtException e) >> return st'
      runLoopNB getTO errH hIn cap hMain st
    _ -> return st
  let bye = do sst <- getSessionState
               when (sst /= HaveQuit)
                 (trigger Shutdown >> return ())
  fmap snd (runSmtpd bye theEnv st')
smtpdMain :: Capacity
          -> GlobalEnv
          -> ReadHandle
          -> WriteHandle
          -> SmtpdState
          -> IO SmtpdState
smtpdMain cap theEnv hIn hOut initST = do
  let greet = do r <- trigger Greeting
                 safeReply hOut r >> safeFlush hOut
                 to <- getReadTimeout
                 sid <- mySessionID
                 return (r, to, sid)
  ((r, to, sid), st) <- runSmtpd greet theEnv initST
  st' <- case r of
    Reply (Code Success _ _) _  -> do
      let getTO  = evalState (getVarDef (mkVar "ReadTimeout") to)
          yellIO = syslogger . LogMsg sid st
          hMain  = smtpdHandler hOut theEnv
          errH e st' = yellIO (CaughtException e) >> return st'
      runLoopNB getTO errH hIn cap hMain st
    _ -> return st
  let bye = do sst <- getSessionState
               when (sst /= HaveQuit)
                 (trigger Shutdown >> return ())
  fmap snd (runSmtpd bye theEnv st')
smtpdMain cap theEnv hIn hOut initST = do
  let greet = do r <- trigger Greeting
                 safeReply hOut r >> safeFlush hOut
                 to <- getReadTimeout
                 sid <- mySessionID
                 return (r, to, sid)
  ((r, to, sid), st) <- runSmtpd greet theEnv initST
  st' <- case r of
    Reply (Code Success _ _) _  -> do
      let getTO  = evalState (getVarDef (mkVar "ReadTimeout") to)
          yellIO = syslogger . LogMsg sid st
          hMain  = smtpdHandler hOut theEnv
          errH e st' = yellIO (CaughtException e) >> return st'
      runLoopNB getTO errH hIn cap hMain st
    _ -> return st
  let bye = do sst <- getSessionState
               when (sst /= HaveQuit)
                 (trigger Shutdown >> return ())
  fmap snd (runSmtpd bye theEnv st')