CurryInfo: cpns-3.0.0 / Network.CPNSD

classes:

              
documentation:
------------------------------------------------------------------------
--- This is the main program of the CPNS demon.
---
--- @author Michael Hanus
--- @version March 2021
------------------------------------------------------------------------
name:
Network.CPNSD
operations:
main putErrLn startServer startServerIfNecessary stopServer
sourcecode:
module Network.CPNSD
 where

import Control.Monad      ( unless )
import System.Environment ( getArgs )

import Data.Time          ( calendarTimeToString, getLocalTime )
import System.Directory   ( doesFileExist )
import System.IO          ( hFlush, hPutStrLn, stderr )
import System.Process     ( getPID, system )

import Network.CPNS
import Network.CPNS.Config

--- Main function for CPNS demon. Check arguments and execute command.
main :: IO ()
main = do
  args <- getArgs
  case args of
   ["serve"]   -> cpnsStart
   ["start"]   -> startServerIfNecessary
   ["stop"]    -> stopServer
   ["status"]  -> cpnsStatus
   ["log"]     -> do logfile <- getLogFile
                     readFile logfile >>= putStr
   _ -> putErrLn $ "ERROR: Illegal arguments: " ++ unwords args ++ "\n" ++
                    "Allowed arguments: start | stop | serve | status | log"

--- Start the Curry Port Name Server demon, if it is not already
--- started on this machine:
startServerIfNecessary :: IO ()
startServerIfNecessary = do
  alive <- cpnsAlive "localhost"
  unless alive $ do
    putErrLn "CPNS demon seems to be aborted. I try to restart it..."
    startServer

startServer :: IO ()
startServer = do
  lockfile <- getStartupLockFile
  lfc <- system $ "lockfile-create --lock-name " ++ lockfile
  if lfc == 0
    then do
      putErrLn "Starting demon for Curry Port Name Server..."
      logfile <- getLogFile
      exlogfile <- doesFileExist logfile
      unless exlogfile $ do
        -- create log file with correct access rights:
        system $ "touch " ++ logfile
        -- make log file accessible for everybody:
        system $ "chmod -f 666 " ++ logfile
        return ()
      putErrLn $ "Log information in file '" ++ logfile ++ "'"
      ctime <- getLocalTime
      appendFile logfile $
        "CPNS demon started at " ++ calendarTimeToString ctime ++ "\n"
      -- start CPNSD in server mode:
      cpnsbin <- getCPNSD
      system $ "nohup \"" ++ cpnsbin ++ "\" serve >> " ++ logfile ++ " 2>&1  &"
      lockFileCreateAndRemove lockfile
      putErrLn "CPNS demon started."
    else do
      putErrLn "CPNS demon seems already started by another process"
      putErrLn $ "If this is not the case, delete file '" ++ lockfile ++ "'"
      lockFileCreateAndRemove lockfile
 where
  -- wait for lockfile deletion by CPNS demon startup:
  lockFileCreateAndRemove lockfile = do
    system $ "lockfile-create --lock-name " ++ lockfile
    system $ "lockfile-remove --lock-name " ++ lockfile
    return ()

--- Terminate the Curry Port Name Server demon, if it is not already terminated.
stopServer :: IO ()
stopServer = do
  lockfile <- getStartupLockFile
  system $ "/bin/rm -f " ++ lockfile -- just to be sure
  -- test whether the server process is still alive:
  alive <- cpnsAlive "localhost"
  if alive then cpnsStop
           else putErrLn "CPNS demon does not seem to be alive"

putErrLn :: String -> IO ()
putErrLn s = hPutStrLn stderr s >> hFlush stderr
types:

              
unsafe:
safe