aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/app/setup.go
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-09-22 00:29:36 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-09-22 01:15:39 +0900
commit62cb8a91b603546314034ded1e9d6ddfbd6ef106 (patch)
tree981d0c6daf04595e0118f8a48c0898cdd6d44e05 /internal/app/setup.go
parent11832a937924030699a6304a3ba9b5884532b730 (diff)
app: clean up interactions and handle all application state and setup/teardown
There was an earlier attempt of cleaning up the app package however it ended up creating even more of a mess and the code structure largely still looked like Ego with state setup scattered everywhere and a bunch of ugly hacks had to be implemented to keep track of all of them. In this commit the entire app package is rewritten to track everything that has to do with an app in one thread safe value. In anticipation of the client/server split also made changes: - Console messages are cleaned up to be consistent - State tracking is fully rewritten to be cleaner and usable for multiple process and client/server - Encapsulate errors to easier identify type of action causing the error as well as additional info - System-level setup operations is grouped in a way that can be collectively committed/reverted and gracefully handles errors returned by each operation - Resource sharing is made more fine-grained with PID-scoped resources whenever possible, a few remnants (X11, Wayland, PulseAudio) will be addressed when a generic proxy is available - Application setup takes a JSON-friendly config struct and deterministically generates system setup operations Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'internal/app/setup.go')
-rw-r--r--internal/app/setup.go150
1 files changed, 0 insertions, 150 deletions
diff --git a/internal/app/setup.go b/internal/app/setup.go
deleted file mode 100644
index c13468a0..00000000
--- a/internal/app/setup.go
+++ /dev/null
@@ -1,150 +0,0 @@
-package app
-
-import (
- "errors"
- "fmt"
- "os"
- "os/user"
- "path"
- "strconv"
-
- "git.ophivana.moe/cat/fortify/internal"
- "git.ophivana.moe/cat/fortify/internal/util"
- "git.ophivana.moe/cat/fortify/internal/verbose"
-)
-
-const (
- xdgRuntimeDir = "XDG_RUNTIME_DIR"
-)
-
-type App struct {
- uid int // assigned
- env []string // modified via AppendEnv
- command []string // set on initialisation
-
- exit *internal.ExitState // assigned
-
- launchOptionText string // set on initialisation
- launchOption uint8 // assigned
-
- sharePath string // set on initialisation
- runtimePath string // assigned
- runDirPath string // assigned
- toolPath string // assigned
-
- enablements internal.Enablements // set via setEnablement
- *user.User // assigned
-
- // absolutely *no* method of this type is thread-safe
- // so don't treat it as if it is
-}
-
-func (a *App) LaunchOption() uint8 {
- return a.launchOption
-}
-
-func (a *App) RunDir() string {
- return a.runDirPath
-}
-
-func (a *App) setEnablement(e internal.Enablement) {
- if a.enablements.Has(e) {
- panic("enablement " + e.String() + " set twice")
- }
-
- a.enablements |= e.Mask()
-}
-
-func (a *App) SealExit(exit *internal.ExitState) {
- if a.exit != nil {
- panic("application exit state sealed twice")
- }
- a.exit = exit
-}
-
-func New(userName string, args []string, launchOptionText string) *App {
- a := &App{
- command: args,
- launchOptionText: launchOptionText,
- sharePath: path.Join(os.TempDir(), "fortify."+strconv.Itoa(os.Geteuid())),
- }
-
- // runtimePath, runDirPath
- if r, ok := os.LookupEnv(xdgRuntimeDir); !ok {
- fmt.Println("Env variable", xdgRuntimeDir, "unset")
-
- // too early for fatal
- os.Exit(1)
- } else {
- a.runtimePath = r
- a.runDirPath = path.Join(a.runtimePath, "fortify")
- verbose.Println("Runtime directory at", a.runDirPath)
- }
-
- // *user.User
- if u, err := user.Lookup(userName); err != nil {
- if errors.As(err, new(user.UnknownUserError)) {
- fmt.Println("unknown user", userName)
- } else {
- // unreachable
- panic(err)
- }
-
- // too early for fatal
- os.Exit(1)
- } else {
- a.User = u
- }
-
- // uid
- if u, err := strconv.Atoi(a.Uid); err != nil {
- // usually unreachable
- panic("uid parse")
- } else {
- a.uid = u
- }
-
- verbose.Println("Running as user", a.Username, "("+a.Uid+"),", "command:", a.command)
- if internal.SdBootedV {
- verbose.Println("System booted with systemd as init system (PID 1).")
- }
-
- // launchOption, toolPath
- 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 !internal.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)
- }
-
- verbose.Println("Determined launch method to be", a.launchOptionText, "with tool at", a.toolPath)
-
- return a
-}