From b0aff891661dfa2f438a7264607a4e6e9caef026 Mon Sep 17 00:00:00 2001 From: Ophestra Umiker Date: Thu, 12 Sep 2024 20:53:33 +0900 Subject: app: handle launch method in New function Signed-off-by: Ophestra Umiker --- internal/app/run.go | 54 ++++++++++++++++++------------------------------- internal/app/setup.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++-- internal/util/early.go | 12 +++++++++++ internal/util/std.go | 16 ++++++--------- 4 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 internal/util/early.go (limited to 'internal') diff --git a/internal/app/run.go b/internal/app/run.go index b5eec825..0871e899 100644 --- a/internal/app/run.go +++ b/internal/app/run.go @@ -17,15 +17,9 @@ const ( sudoAskPass = "SUDO_ASKPASS" ) const ( - LaunchMethodSudo = iota + LaunchMethodSudo uint8 = iota + LaunchMethodBwrap LaunchMethodMachineCtl - - launchOptionLength -) - -var ( - // LaunchOptions is set in main's cli.go - LaunchOptions [launchOptionLength]bool ) func (a *App) Run() { @@ -34,34 +28,20 @@ func (a *App) Run() { a.AppendEnv(term, t) } - commandBuilder := a.commandBuilderSudo - - var toolPath string - - // dependency checks - const sudoFallback = "Falling back to 'sudo', some desktop integration features may not work" - if LaunchOptions[LaunchMethodMachineCtl] && !LaunchOptions[LaunchMethodSudo] { // sudo argument takes priority - if !util.SdBooted() { - fmt.Println("This system was not booted through systemd") - fmt.Println(sudoFallback) - } else if machineCtlPath, ok := util.Which("machinectl"); !ok { - fmt.Println("Did not find 'machinectl' in PATH") - fmt.Println(sudoFallback) - } else { - toolPath = machineCtlPath - commandBuilder = a.commandBuilderMachineCtl - } - } else if sudoPath, ok := util.Which("sudo"); !ok { - state.Fatal("Did not find 'sudo' in PATH") - } else { - toolPath = sudoPath - } - - if system.V.Verbose { - fmt.Printf("Selected launcher '%s'\n", toolPath) + var commandBuilder func() (args []string) + + switch a.launchOption { + case LaunchMethodSudo: + commandBuilder = a.commandBuilderSudo + case LaunchMethodBwrap: + commandBuilder = a.commandBuilderBwrap + case LaunchMethodMachineCtl: + commandBuilder = a.commandBuilderMachineCtl + default: + panic("unreachable") } - cmd := exec.Command(toolPath, commandBuilder()...) + cmd := exec.Command(a.toolPath, commandBuilder()...) cmd.Env = []string{} cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout @@ -122,6 +102,12 @@ func (a *App) commandBuilderSudo() (args []string) { return } +func (a *App) commandBuilderBwrap() (args []string) { + // TODO: build bwrap command + state.Fatal("bwrap") + panic("unreachable") +} + func (a *App) commandBuilderMachineCtl() (args []string) { args = make([]string, 0, 9+len(a.env)) diff --git a/internal/app/setup.go b/internal/app/setup.go index 82765dfb..d8378cfd 100644 --- a/internal/app/setup.go +++ b/internal/app/setup.go @@ -9,13 +9,19 @@ import ( "git.ophivana.moe/cat/fortify/internal/state" "git.ophivana.moe/cat/fortify/internal/system" + "git.ophivana.moe/cat/fortify/internal/util" ) type App struct { + launchOptionText string + uid int env []string command []string + launchOption uint8 + toolPath string + enablements state.Enablements *user.User @@ -23,6 +29,10 @@ type App struct { // so don't treat it as if it is } +func (a *App) LaunchOption() uint8 { + return a.launchOption +} + func (a *App) setEnablement(e state.Enablement) { if a.enablements.Has(e) { panic("enablement " + e.String() + " set twice") @@ -31,8 +41,8 @@ func (a *App) setEnablement(e state.Enablement) { a.enablements |= e.Mask() } -func New(userName string, args []string) *App { - a := &App{command: args} +func New(userName string, args []string, launchOptionText string) *App { + a := &App{command: args, launchOptionText: launchOptionText} if u, err := user.Lookup(userName); err != nil { if errors.As(err, new(user.UnknownUserError)) { @@ -57,6 +67,47 @@ func New(userName string, args []string) *App { if system.V.Verbose { fmt.Println("Running as user", a.Username, "("+a.Uid+"),", "command:", a.command) + if util.SdBootedV { + fmt.Println("System booted with systemd as init system (PID 1).") + } + } + + switch a.launchOptionText { + case "sudo": + a.launchOption = LaunchMethodSudo + if sudoPath, ok := util.Which("sudo"); !ok { + fmt.Println("Did not find 'sudo' in PATH") + os.Exit(1) + } else { + a.toolPath = sudoPath + } + case "bubblewrap": + a.launchOption = LaunchMethodBwrap + if bwrapPath, ok := util.Which("bwrap"); !ok { + fmt.Println("Did not find 'bwrap' in PATH") + os.Exit(1) + } else { + a.toolPath = bwrapPath + } + case "systemd": + a.launchOption = LaunchMethodMachineCtl + if !util.SdBootedV { + fmt.Println("System has not been booted with systemd as init system (PID 1).") + os.Exit(1) + } + + if machineCtlPath, ok := util.Which("machinectl"); !ok { + fmt.Println("Did not find 'machinectl' in PATH") + } else { + a.toolPath = machineCtlPath + } + default: + fmt.Println("invalid launch method") + os.Exit(1) + } + + if system.V.Verbose { + fmt.Println("Determined launch method to be", a.launchOptionText, "with tool at", a.toolPath) } return a diff --git a/internal/util/early.go b/internal/util/early.go new file mode 100644 index 00000000..ba7375c7 --- /dev/null +++ b/internal/util/early.go @@ -0,0 +1,12 @@ +package util + +import "fmt" + +var SdBootedV = func() bool { + if v, err := SdBooted(); err != nil { + fmt.Println("warn: read systemd marker:", err) + return false + } else { + return v + } +}() diff --git a/internal/util/std.go b/internal/util/std.go index 5c37a0d7..4f304fb6 100644 --- a/internal/util/std.go +++ b/internal/util/std.go @@ -8,7 +8,6 @@ import ( "path" "git.ophivana.moe/cat/fortify/internal/state" - "git.ophivana.moe/cat/fortify/internal/system" ) const ( @@ -22,19 +21,16 @@ const ( ) // SdBooted implements https://www.freedesktop.org/software/systemd/man/sd_booted.html -func SdBooted() bool { +func SdBooted() (bool, error) { _, err := os.Stat(systemdCheckPath) if err != nil { - if system.V.Verbose { - if errors.Is(err, fs.ErrNotExist) { - fmt.Println("System not booted through systemd") - } else { - fmt.Println("Error accessing", systemdCheckPath+":", err.Error()) - } + if errors.Is(err, fs.ErrNotExist) { + err = nil } - return false + return false, err } - return true + + return true, nil } // DiscoverPulseCookie try various standard methods to discover the current user's PulseAudio authentication cookie -- cgit v1.3.1