Initial commit with CombinedConfig and daemonize implementations.
This commit is contained in:
commit
f77efa1cd7
83
cliutils.nim
Normal file
83
cliutils.nim
Normal 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
11
cliutils.nimble
Normal 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"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user