Initial commit with CombinedConfig and daemonize implementations.

This commit is contained in:
Jonathan Bernard 2016-11-04 16:30:06 -05:00
commit f77efa1cd7
2 changed files with 94 additions and 0 deletions

83
cliutils.nim Normal file
View File

@ -0,0 +1,83 @@
import docopt, json, posix, nre, strutils
import os except sleep
type
CombinedConfig* = object
docopt*: Table[string, Value]
json*: JsonNode
proc getVal*(cfg: CombinedConfig, key, default: string): string =
let argKey = "--" & key
let envKey = key.replace('-', '_').toUpper
let jsonKey = key.replace(re"(-\w)", proc (m: RegexMatch): string = ($m)[1..1].toUpper)
if cfg.docopt[argKey]: return $cfg.docopt[argKey]
elif existsEnv(envKey): return getEnv(envKey)
elif cfg.json.hasKey(jsonKey): return cfg.json[jsonKey].getStr
else: return default
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): int =
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 not si.isNil and si != "":
fi = open(si, fmRead)
discard dup2(getFileHandle(fi), getFileHandle(stdin))
if not so.isNil and so != "":
fo = open(so, fmAppend)
discard dup2(getFileHandle(fo), getFileHandle(stdout))
if not se.isNil and so != "":
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

11
cliutils.nimble Normal file
View File

@ -0,0 +1,11 @@
# Package
version = "0.1.0"
author = "Jonathan Bernard"
description = "Helper functions for writing command line interfaces."
license = "MIT"
# Dependencies
requires @["nim >= 0.15.3", "docopt"]