From 3267505a4bf6c0a65bced6a9d1a812596d969fad Mon Sep 17 00:00:00 2001 From: "Dolf Schimmel (Freeaqingme)" Date: Sun, 10 Apr 2016 00:24:19 +0200 Subject: [PATCH] Initial Commit --- LICENSE | 25 ++++++++++++++++++++ log/log.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 LICENSE create mode 100644 log/log.go create mode 100644 main.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c9a7dd8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2016, Dolf Schimmel - Freeaqingme +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..b96cc50 --- /dev/null +++ b/log/log.go @@ -0,0 +1,69 @@ +package log + +import ( + logging "github.com/op/go-logging" + "log" + "log/syslog" + "os" + "syscall" +) + +type Logger struct { + *logging.Logger +} + +var ( + Log *Logger + logFile string +) + +func Open(name, logLevelStr string) *Logger { + logLevel, err := logging.LogLevel(logLevelStr) + if err != nil { + log.Fatal("Invalid log level specified") + } + + Log = &Logger { logging.MustGetLogger(name) } + + var formatStdout = logging.MustStringFormatter( + "%{color}%{time:2006-01-02T15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{color:reset} %{message}", + ) + stdout := logging.NewLogBackend(os.Stdout, "", 0) + formatter := logging.NewBackendFormatter(stdout, formatStdout) + stdoutLeveled := logging.AddModuleLevel(formatter) + stdoutLeveled.SetLevel(logLevel, "") + syslogBackend, err := logging.NewSyslogBackendPriority("cluegetter", syslog.LOG_MAIL) + if err != nil { + Log.Fatal(err) + } + + logging.SetBackend(syslogBackend, stdoutLeveled) + + return Log +} + + +func Reopen(args string) { + if logFile == "" { + Log.Notice("Asked to reopen logs but running in foreground. Ignoring.") + return + } + Log.Notice("Reopening log file per IPC request...") + logRedirectStdOutToFile(logFile) + Log.Notice("Reopened log file per IPC request") +} + +// If there are any existing fd's (e.g. we're reopening logs), we rely +// on garbage collection to clean them up for us. +func logRedirectStdOutToFile(logPath string) { + if logPath == "" { + Log.Fatal("Log Path not set") + } + + logFile, err := os.OpenFile(logPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + if err != nil { + Log.Fatal(err) + } + syscall.Dup2(int(logFile.Fd()), 1) + syscall.Dup2(int(logFile.Fd()), 2) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..eac8ca0 --- /dev/null +++ b/main.go @@ -0,0 +1,65 @@ +package GoDaemonSkeleton + +import ( + "fmt" + "os" + "strings" +) + +var ( + apps = make([]*App, 0) +) + +type App struct { + Name string + Handover *func() +} + +func GetApp() (*App, []string) { + appNames := func() []string { + out := []string{} + for _, app := range apps { + out = append(out, app.Name) + } + + return out + } + + if len(os.Args) < 2 { + fmt.Fprintf(os.Stderr, "No App specified. Must be one of: %s\n", strings.Join(appNames(), " ")) + os.Exit(1) + } + + var subAppArgs []string + var subApp *App +OuterLoop: + for i, arg := range os.Args[1:] { + for _, subAppTemp := range apps { + if arg == subAppTemp.Name { + subApp = subAppTemp + subAppArgs = os.Args[i+2:] + os.Args = os.Args[:i+1] + break OuterLoop + } + } + } + + if subApp == nil { + fmt.Fprintf(os.Stderr, "No App specified. Must be one of: %s\n", strings.Join(appNames(), " ")) + os.Exit(1) + } + + return subApp, subAppArgs +} + +func AppRegister(app *App) { + if app == nil { + panic("nil subapp supplied") + } + for _, dup := range apps { + if dup.Name == app.Name { + panic("Register called twice for subApp " + app.Name) + } + } + apps = append(apps, app) +}