aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/state/print.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/state/print.go')
-rw-r--r--internal/state/print.go125
1 files changed, 89 insertions, 36 deletions
diff --git a/internal/state/print.go b/internal/state/print.go
index 838cacb0..b4c74a90 100644
--- a/internal/state/print.go
+++ b/internal/state/print.go
@@ -3,69 +3,122 @@ package state
import (
"fmt"
"os"
+ "path"
"strconv"
"strings"
"text/tabwriter"
+ "time"
"git.ophivana.moe/cat/fortify/internal"
"git.ophivana.moe/cat/fortify/internal/verbose"
)
-func MustPrintLauncherStateGlobal(w **tabwriter.Writer, runDirPath string) {
- if dirs, err := os.ReadDir(runDirPath); err != nil {
- fmt.Println("Error reading runtime directory:", err)
+// MustPrintLauncherStateSimpleGlobal prints active launcher states of all simple stores
+// in an implementation-specific way.
+func MustPrintLauncherStateSimpleGlobal(w **tabwriter.Writer) {
+ sc := internal.GetSC()
+ now := time.Now().UTC()
+
+ // read runtime directory to get all UIDs
+ if dirs, err := os.ReadDir(sc.RunDirPath); err != nil {
+ fmt.Println("cannot read runtime directory:", err)
+ os.Exit(1)
} else {
for _, e := range dirs {
+ // skip non-directories
if !e.IsDir() {
- verbose.Println("Skipped non-directory entry", e.Name())
+ verbose.Println("skipped non-directory entry", e.Name())
continue
}
+ // skip non-numerical names
if _, err = strconv.Atoi(e.Name()); err != nil {
- verbose.Println("Skipped non-uid entry", e.Name())
+ verbose.Println("skipped non-uid entry", e.Name())
continue
}
- MustPrintLauncherState(w, runDirPath, e.Name())
+ // obtain temporary store
+ s := NewSimple(sc.RunDirPath, e.Name()).(*simpleStore)
+
+ // print states belonging to this store
+ s.mustPrintLauncherState(w, now)
+
+ // mustPrintLauncherState causes store activity so store needs to be closed
+ if err = s.Close(); err != nil {
+ fmt.Printf("warn: error closing store for user %s: %s\n", e.Name(), err)
+ }
}
}
}
-func MustPrintLauncherState(w **tabwriter.Writer, runDirPath, uid string) {
- launchers, err := ReadLaunchers(runDirPath, uid, true)
- if err != nil {
- fmt.Println("Error reading launchers:", err)
- os.Exit(1)
- }
+func (s *simpleStore) mustPrintLauncherState(w **tabwriter.Writer, now time.Time) {
+ var innerErr error
- if *w == nil {
- *w = tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
+ if ok, err := s.Do(func(b Backend) {
+ innerErr = func() error {
+ // read launcher states
+ states, err := b.Load()
+ if err != nil {
+ return err
+ }
- if !verbose.Get() {
- _, _ = fmt.Fprintln(*w, "\tUID\tPID\tEnablements\tLauncher\tCommand")
- } else {
- _, _ = fmt.Fprintln(*w, "\tUID\tPID\tArgv")
- }
- }
+ // initialise tabwriter if nil
+ if *w == nil {
+ *w = tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
- for _, state := range launchers {
- enablementsDescription := strings.Builder{}
- for i := internal.Enablement(0); i < internal.EnableLength; i++ {
- if state.Capability.Has(i) {
- enablementsDescription.WriteString(", " + i.String())
+ // write header when initialising
+ if !verbose.Get() {
+ _, _ = fmt.Fprintln(*w, "\tUID\tPID\tUptime\tEnablements\tLauncher\tCommand")
+ } else {
+ // argv is emitted in body when verbose
+ _, _ = fmt.Fprintln(*w, "\tUID\tPID\tArgv")
+ }
}
- }
- if enablementsDescription.Len() == 0 {
- enablementsDescription.WriteString("none")
- }
- if !verbose.Get() {
- _, _ = fmt.Fprintf(*w, "\t%s\t%d\t%s\t%s\t%s\n",
- uid, state.PID, strings.TrimPrefix(enablementsDescription.String(), ", "), state.Launcher,
- state.Command)
- } else {
- _, _ = fmt.Fprintf(*w, "\t%s\t%d\t%s\n",
- uid, state.PID, state.Argv)
+ // print each state
+ for _, state := range states {
+ // skip nil states
+ if state == nil {
+ _, _ = fmt.Fprintln(*w, "\tnil state entry")
+ continue
+ }
+
+ // build enablements string
+ ets := strings.Builder{}
+ // append enablement strings in order
+ for i := Enablement(0); i < EnableLength; i++ {
+ if state.Capability.Has(i) {
+ ets.WriteString(", " + i.String())
+ }
+ }
+ // prevent an empty string when
+ if ets.Len() == 0 {
+ ets.WriteString("(No enablements)")
+ }
+
+ if !verbose.Get() {
+ _, _ = fmt.Fprintf(*w, "\t%s\t%d\t%s\t%s\t%s\t%s\n",
+ s.path[len(s.path)-1], state.PID, now.Sub(state.Time).String(), strings.TrimPrefix(ets.String(), ", "), state.Launcher,
+ state.Command)
+ } else {
+ // emit argv instead when verbose
+ _, _ = fmt.Fprintf(*w, "\t%s\t%d\t%s\n",
+ s.path[len(s.path)-1], state.PID, state.Argv)
+ }
+ }
+
+ return nil
+ }()
+ }); err != nil {
+ fmt.Printf("cannot perform action on store '%s': %s\n", path.Join(s.path...), err)
+ if !ok {
+ fmt.Println("warn: store faulted before printing")
+ os.Exit(1)
}
}
+
+ if innerErr != nil {
+ fmt.Printf("cannot print launcher state for store '%s': %s\n", path.Join(s.path...), innerErr)
+ os.Exit(1)
+ }
}