package main import ( "context" "fmt" "os" "os/signal" "path/filepath" "syscall" "github.com/adrg/xdg" "dev.mediocregopher.com/mediocre-go-lib.git/mctx" "dev.mediocregopher.com/mediocre-go-lib.git/mlog" ) // The purpose of this binary is to act as the entrypoint of the isle // process. It processes the command-line arguments which are passed in, and // then passes execution along to an appropriate binary housed in AppDir/bin // (usually a bash script, which is more versatile than a go program). func getAppDirPath() string { appDirPath := os.Getenv("APPDIR") if appDirPath == "" { appDirPath = "." } return appDirPath } func getRPCSocketDirPath() string { path, err := firstExistingDir( "/run", "/var/run", "/tmp", "/dev/shm", ) if err != nil { panic(fmt.Sprintf("Failed to find directory for RPC socket: %v", err)) } return path } // RUNTIME_DIRECTORY/STATE_DIRECTORY are used by the systemd service in // conjunction with the RuntimeDirectory/StateDirectory directives. var ( envAppDirPath = getAppDirPath() envRuntimeDirPath = envOr( "RUNTIME_DIRECTORY", func() string { return filepath.Join(xdg.RuntimeDir, "isle") }, ) envStateDirPath = envOr( "STATE_DIRECTORY", func() string { return filepath.Join(xdg.StateHome, "isle") }, ) envBinDirPath = filepath.Join(envAppDirPath, "bin") envSocketPath = envOr( "ISLE_SOCKET_PATH", func() string { return filepath.Join(getRPCSocketDirPath(), "isle-daemon.sock") }, ) ) func binPath(name string) string { return filepath.Join(envBinDirPath, name) } func main() { logger := mlog.NewLogger(&mlog.LoggerOpts{ MessageHandler: newLogMsgHandler(), MaxLevel: mlog.LevelInfo.Int(), }) defer logger.Close() ctx, cancel := context.WithCancel(context.Background()) signalCh := make(chan os.Signal, 2) signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-signalCh cancel() ctx := mctx.Annotate(ctx, "signal", sig.String()) logger.Info(ctx, "got signal, exiting gracefully") sig = <-signalCh ctx = mctx.Annotate(ctx, "signal", sig.String()) logger.FatalString(ctx, "second signal received, force quitting, there may be zombie children left behind, good luck!") }() err := subCmdCtx{ args: os.Args[1:], ctx: ctx, logger: logger, }.doSubCmd( subCmdAdmin, subCmdDaemon, subCmdGarage, subCmdHosts, subCmdNebula, subCmdVersion, ) if err != nil { logger.Fatal(ctx, "error running command", err) } }