Yesterday i wrote a little xinetd exercise for my students: make a reverse echo program.
To learn something new, i tried to implement a Haskell solution. The trivial main = forever $ interact reverse
does not work. I went through this question and made a corrected version:
import Control.Monad
import System.IO
main = forever $ interact revLines
revLines = unlines . map (reverse) . lines
But this corrected version also doesn't work. I read the buffering documentation and played with the various settings.
If i set NoBuffering
or LineBuffering
, my program works correctly. Finally i printed out the default buffering modes for stdin and stdout
import System.IO
main = do
hGetBuffering stdin >>= print
hGetBuffering stdout >>= print
I've got BlockBuffering Nothing
if i run my program from xinetd(echo "test" | nc localhost 7
) but from cli i've got LineBuffering
- What is the difference between a xinetd tcp service and a cli program, regards to buffering?
- Do i have to set manually the buffering if i want to write a working program with both running method?
Edit: Thank you all for the helpful answers.
I accept the answer which was given by blaze, he give me a hint with isatty(3). I went through again the System.IO documentation and found the hIsTerminalDevice function, with wich i am able to check the connection of the handle.
For the record, here is my final program:
{-# OPTIONS_GHC -W #-}
import System.IO
main = do
hSetBuffering stdin LineBuffering
hSetBuffering stdout LineBuffering
interact revLines
revLines = unlines . map (reverse) . lines