import posix
import os except sleep

## Daemonize
var
  pidFileInner: string
  fi, fo, fe: File

proc onStop(sig: cint) {.noconv.} =
  close(fi)
  close(fo)
  close(fe)
  removeFile(pidFileInner)

  quit(QuitSuccess)

proc daemonize*(pidfile, si, so, se: string, daemonMain: proc(): void): Pid =

  if fileExists(pidfile):
    raise newException(IOError, "pidfile " & pidfile & " already exists, daemon already running?")

  let pid1 = fork()

  # Are we the child process?
  if pid1 == 0:

    # Yes, so let's get ready to execute the main code given to us.
    discard chdir("/")
    discard setsid()
    discard umask(0)

    # Fork again... but I'm not sure why.
    let pid2 = fork()

    # We don't need the intermediate process, so if we are not the child this
    # time, lets just quit
    if pid2 > 0: quit(QuitSuccess)

    # If we are the grandchild let's set up our environment.
    flushFile(stdout)
    flushFile(stderr)

    if si.len > 0:
      fi = open(si, fmRead)
      discard dup2(getFileHandle(fi), getFileHandle(stdin))

    if so.len > 0:
      fo = open(so, fmAppend)
      discard dup2(getFileHandle(fo), getFileHandle(stdout))

    if se.len > 0:
      fe = open(se, fmAppend)
      discard dup2(getFileHandle(fe), getFileHandle(stderr))

    pidFileInner = pidfile

    # Add hooks to cleanup after ourselves when we're asked to die.
    signal(SIGINT, onStop)
    signal(SIGTERM, onStop)

    # Find out what our actual PID is and save it
    let childPid = getpid()
    writeFile(pidfile, $childPid)

    # Finally, execute our main
    daemonMain()

  return pid1