{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Control.Concurrent (threadDelay)
import Control.Concurrent.Chan
import Control.Exception.Extra (ignore)
import Control.Monad
import Data.Map
import DBus.Client
import System.Exit
import System.Posix.Process
main :: IO ()
main = do
-- Connect to D-Bus
client <- connectSession
-- Channel for transfering exec parameters from the callback thread
channel <- newChan
-- Export object used for launching programs
export client "/nl/dvdgiessen/DBusAppLauncher" defaultInterface
{ interfaceName = "nl.dvdgiessen.dbusapplauncher.Exec"
, interfaceMethods =
[ autoMethod "Cmd" (\ cmd -> (writeChan channel (cmd, [], Nothing)))
, autoMethod "CmdArgs" (\ cmd args -> (writeChan channel (cmd, args, Nothing)))
, autoMethod "CmdArgsEnv" (\ cmd args env -> (writeChan channel (cmd, args, Just (toList env))))
]
}
-- Register our service
requestResult <- requestName client "nl.dvdgiessen.dbusapplauncher" []
when (requestResult /= NamePrimaryOwner) $ do
putStrLn "Another service owns the \"nl.dvdgiessen.dbusapplauncher\" bus name"
exitFailure
-- Wait for the callback thread to return the exec parameters
(cmd, args, env) <- readChan channel
-- Do not accept any additional calls
unexport client "/nl/dvdgiessen/DBusAppLauncher"
-- Give the callback thread one millisecond to return its result before we kill it
threadDelay 1000
-- Disconnect from D-Bus, killing the callback thread
disconnect client
-- Make sure we are in our own process group and session
ignore (do _ <- createSession; return ())
-- Exec with the requested parameters
_ <- executeFile cmd True args env
-- Never reached
return ()