2024-07-09 15:39:40 +09:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-09-09 03:16:54 +09:00
|
|
|
"encoding/json"
|
2024-07-15 23:29:21 +09:00
|
|
|
"errors"
|
2024-07-09 15:39:40 +09:00
|
|
|
"flag"
|
2024-07-15 23:29:21 +09:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2024-09-04 01:20:12 +09:00
|
|
|
|
2024-09-09 03:16:54 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/dbus"
|
2024-09-17 13:48:42 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal"
|
2024-09-04 01:20:12 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal/app"
|
2024-09-17 13:48:42 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal/state"
|
2024-09-12 21:07:05 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal/verbose"
|
2024-07-09 15:39:40 +09:00
|
|
|
)
|
|
|
|
|
2024-09-04 01:20:12 +09:00
|
|
|
var (
|
|
|
|
Version = "impure"
|
|
|
|
)
|
2024-07-09 15:39:40 +09:00
|
|
|
|
2024-07-16 22:07:40 +09:00
|
|
|
func tryVersion() {
|
|
|
|
if printVersion {
|
|
|
|
fmt.Println(Version)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-09 15:39:40 +09:00
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
2024-09-12 21:07:05 +09:00
|
|
|
verbose.Set(flagVerbose)
|
2024-07-15 23:29:21 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
if internal.SdBootedV {
|
|
|
|
verbose.Println("system booted with systemd as init system")
|
|
|
|
}
|
|
|
|
|
2024-09-04 01:20:12 +09:00
|
|
|
// launcher payload early exit
|
2024-09-22 00:29:36 +09:00
|
|
|
if printVersion && printLicense {
|
|
|
|
app.TryShim()
|
|
|
|
}
|
2024-07-15 23:29:21 +09:00
|
|
|
|
2024-09-04 01:20:12 +09:00
|
|
|
// version/license command early exit
|
|
|
|
tryVersion()
|
|
|
|
tryLicense()
|
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
// state query command early exit
|
|
|
|
tryState()
|
|
|
|
|
|
|
|
// prepare config
|
|
|
|
var config *app.Config
|
2024-09-04 01:20:12 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
if confPath == "nil" {
|
|
|
|
// config from flags
|
|
|
|
config = configFromFlags()
|
|
|
|
} else {
|
|
|
|
// config from file
|
|
|
|
if f, err := os.Open(confPath); err != nil {
|
|
|
|
fatalf("cannot access config file '%s': %s\n", confPath, err)
|
2024-09-09 03:16:54 +09:00
|
|
|
} else {
|
2024-09-22 00:29:36 +09:00
|
|
|
if err = json.NewDecoder(f).Decode(&config); err != nil {
|
|
|
|
fatalf("cannot parse config file '%s': %s\n", confPath, err)
|
2024-09-09 21:19:12 +09:00
|
|
|
}
|
|
|
|
}
|
2024-09-22 00:29:36 +09:00
|
|
|
}
|
2024-09-09 21:19:12 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
// invoke app
|
|
|
|
r := 1
|
|
|
|
a := app.New()
|
|
|
|
if err := a.Seal(config); err != nil {
|
|
|
|
logBaseError(err, "fortify: cannot seal app:")
|
|
|
|
} else if err = a.Start(); err != nil {
|
|
|
|
logBaseError(err, "fortify: cannot start app:")
|
|
|
|
} else if r, err = a.Wait(); err != nil {
|
|
|
|
r = 1
|
|
|
|
|
|
|
|
var e *app.BaseError
|
|
|
|
if !app.AsBaseError(err, &e) {
|
|
|
|
fmt.Println("fortify: wait failed:", err)
|
|
|
|
} else {
|
|
|
|
// Wait only returns either *app.ProcessError or *app.StateStoreError wrapped in a *app.BaseError
|
|
|
|
var se *app.StateStoreError
|
|
|
|
if !errors.As(err, &se) {
|
|
|
|
// does not need special handling
|
|
|
|
fmt.Print("fortify: " + e.Message())
|
2024-09-09 03:16:54 +09:00
|
|
|
} else {
|
2024-09-22 00:29:36 +09:00
|
|
|
// inner error are either unwrapped store errors
|
|
|
|
// or joined errors returned by *appSealTx revert
|
|
|
|
// wrapped in *app.BaseError
|
|
|
|
var ej app.RevertCompoundError
|
|
|
|
if !errors.As(se.InnerErr, &ej) {
|
|
|
|
// does not require special handling
|
|
|
|
fmt.Print("fortify: " + e.Message())
|
|
|
|
} else {
|
|
|
|
errs := ej.Unwrap()
|
|
|
|
|
|
|
|
// every error here is wrapped in *app.BaseError
|
|
|
|
for _, ei := range errs {
|
|
|
|
var eb *app.BaseError
|
|
|
|
if !errors.As(ei, &eb) {
|
|
|
|
// unreachable
|
|
|
|
fmt.Println("fortify: invalid error type returned by revert:", ei)
|
|
|
|
} else {
|
|
|
|
// print inner *app.BaseError message
|
|
|
|
fmt.Print("fortify: " + eb.Message())
|
|
|
|
}
|
|
|
|
}
|
2024-09-09 03:16:54 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-09-22 00:29:36 +09:00
|
|
|
if err := a.WaitErr(); err != nil {
|
|
|
|
fmt.Println("fortify: inner wait failed:", err)
|
|
|
|
}
|
|
|
|
os.Exit(r)
|
|
|
|
}
|
2024-09-09 03:16:54 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
func logBaseError(err error, message string) {
|
|
|
|
var e *app.BaseError
|
2024-09-04 01:20:12 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
if app.AsBaseError(err, &e) {
|
|
|
|
fmt.Print("fortify: " + e.Message())
|
2024-07-15 23:29:21 +09:00
|
|
|
} else {
|
2024-09-22 00:29:36 +09:00
|
|
|
fmt.Println(message, err)
|
2024-07-15 23:29:21 +09:00
|
|
|
}
|
2024-09-22 00:29:36 +09:00
|
|
|
}
|
2024-07-15 23:29:21 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
func configFromFlags() (config *app.Config) {
|
|
|
|
// initialise config from flags
|
|
|
|
config = &app.Config{
|
|
|
|
ID: dbusID,
|
|
|
|
User: userName,
|
|
|
|
Command: flag.Args(),
|
|
|
|
Method: launchMethodText,
|
|
|
|
}
|
2024-07-15 23:29:21 +09:00
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
// enablements from flags
|
2024-09-08 02:24:01 +09:00
|
|
|
if mustWayland {
|
2024-09-22 00:29:36 +09:00
|
|
|
config.Confinement.Enablements.Set(state.EnableWayland)
|
2024-07-15 23:29:21 +09:00
|
|
|
}
|
2024-09-08 02:24:01 +09:00
|
|
|
if mustX {
|
2024-09-22 00:29:36 +09:00
|
|
|
config.Confinement.Enablements.Set(state.EnableX)
|
2024-07-15 23:29:21 +09:00
|
|
|
}
|
2024-09-08 02:24:01 +09:00
|
|
|
if mustDBus {
|
2024-09-22 00:29:36 +09:00
|
|
|
config.Confinement.Enablements.Set(state.EnableDBus)
|
2024-07-15 23:29:21 +09:00
|
|
|
}
|
2024-09-08 02:24:01 +09:00
|
|
|
if mustPulse {
|
2024-09-22 00:29:36 +09:00
|
|
|
config.Confinement.Enablements.Set(state.EnablePulse)
|
2024-07-15 23:29:21 +09:00
|
|
|
}
|
|
|
|
|
2024-09-22 00:29:36 +09:00
|
|
|
// parse D-Bus config file from flags if applicable
|
|
|
|
if mustDBus {
|
|
|
|
if dbusConfigSession == "builtin" {
|
|
|
|
config.Confinement.SessionBus = dbus.NewConfig(dbusID, true, mpris)
|
|
|
|
} else {
|
|
|
|
if f, err := os.Open(dbusConfigSession); err != nil {
|
|
|
|
fatalf("cannot access session bus proxy config file '%s': %s\n", dbusConfigSession, err)
|
|
|
|
} else {
|
|
|
|
if err = json.NewDecoder(f).Decode(&config.Confinement.SessionBus); err != nil {
|
|
|
|
fatalf("cannot parse session bus proxy config file '%s': %s\n", dbusConfigSession, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// system bus proxy is optional
|
|
|
|
if dbusConfigSystem != "nil" {
|
|
|
|
if f, err := os.Open(dbusConfigSystem); err != nil {
|
|
|
|
fatalf("cannot access system bus proxy config file '%s': %s\n", dbusConfigSystem, err)
|
|
|
|
} else {
|
|
|
|
if err = json.NewDecoder(f).Decode(&config.Confinement.SystemBus); err != nil {
|
|
|
|
fatalf("cannot parse system bus proxy config file '%s': %s\n", dbusConfigSystem, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if dbusVerbose {
|
|
|
|
config.Confinement.SessionBus.Log = true
|
|
|
|
config.Confinement.SystemBus.Log = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func fatalf(format string, a ...any) {
|
|
|
|
fmt.Printf("fortify: "+format, a...)
|
|
|
|
os.Exit(1)
|
2024-07-15 23:29:21 +09:00
|
|
|
}
|