From bfcce3ff75017aa8a4306cae88a4f31d9cc7238c Mon Sep 17 00:00:00 2001 From: Ophestra Umiker Date: Sun, 3 Nov 2024 03:07:02 +0900 Subject: [PATCH] system/dbus: buffer xdg-dbus-proxy messages Pointing xdg-dbus-proxy to stdout/stderr makes a huge mess. This change enables app to neatly print out prefixed xdg-dbus-proxy messages after output is resumed. Signed-off-by: Ophestra Umiker --- internal/app/seal.go | 2 ++ internal/app/share.dbus.go | 4 +++- internal/app/start.go | 9 ++++++++ internal/system/dbus.go | 46 +++++++++++++++++++++++++++++++++----- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/internal/app/seal.go b/internal/app/seal.go index 502ec6e..ca7048b 100644 --- a/internal/app/seal.go +++ b/internal/app/seal.go @@ -41,6 +41,8 @@ type appSeal struct { id string // wayland mediation, disabled if nil wl *shim.Wayland + // dbus proxy message buffer retriever + dbusMsg func(f func(msgbuf []string)) // freedesktop application ID fid string diff --git a/internal/app/share.dbus.go b/internal/app/share.dbus.go index a96b1de..c80bbb9 100644 --- a/internal/app/share.dbus.go +++ b/internal/app/share.dbus.go @@ -22,8 +22,10 @@ func (seal *appSeal) shareDBus(config [2]*dbus.Config) error { sessionPath, systemPath := path.Join(seal.share, "bus"), path.Join(seal.share, "system_bus_socket") // configure dbus proxy - if err := seal.sys.ProxyDBus(config[0], config[1], sessionPath, systemPath); err != nil { + if f, err := seal.sys.ProxyDBus(config[0], config[1], sessionPath, systemPath); err != nil { return err + } else { + seal.dbusMsg = f } // share proxy sockets diff --git a/internal/app/start.go b/internal/app/start.go index 376d306..67a091c 100644 --- a/internal/app/start.go +++ b/internal/app/start.go @@ -185,6 +185,15 @@ func (a *app) Wait() (int, error) { // child process exited, resume output fmsg.Resume() + // print queued up dbus messages + if a.seal.dbusMsg != nil { + a.seal.dbusMsg(func(msgbuf []string) { + for _, msg := range msgbuf { + fmsg.Println(msg) + } + }) + } + // close wayland connection if a.seal.wl != nil { if err := a.seal.wl.Close(); err != nil { diff --git a/internal/system/dbus.go b/internal/system/dbus.go index 349963c..75f343a 100644 --- a/internal/system/dbus.go +++ b/internal/system/dbus.go @@ -1,8 +1,11 @@ package system import ( + "bytes" "errors" "os" + "strings" + "sync" "git.ophivana.moe/security/fortify/dbus" "git.ophivana.moe/security/fortify/internal/fmsg" @@ -13,14 +16,14 @@ var ( ) func (sys *I) MustProxyDBus(sessionPath string, session *dbus.Config, systemPath string, system *dbus.Config) *I { - if err := sys.ProxyDBus(session, system, sessionPath, systemPath); err != nil { + if _, err := sys.ProxyDBus(session, system, sessionPath, systemPath); err != nil { panic(err.Error()) } else { return sys } } -func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath string) error { +func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath string) (func(f func(msgbuf []string)), error) { d := new(DBus) // used by waiting goroutine to notify process exit @@ -28,7 +31,7 @@ func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath st // session bus is mandatory if session == nil { - return fmsg.WrapError(ErrDBusConfig, + return nil, fmsg.WrapError(ErrDBusConfig, "attempted to seal message bus proxy without session bus config") } @@ -61,13 +64,15 @@ func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath st sys.ops = append(sys.ops, d) // seal dbus proxy - return fmsg.WrapErrorSuffix(d.proxy.Seal(session, system), + d.out = &scanToFmsg{msg: new(strings.Builder)} + return d.out.F, fmsg.WrapErrorSuffix(d.proxy.Seal(session, system), "cannot seal message bus proxy:") } type DBus struct { proxy *dbus.Proxy + out *scanToFmsg // whether system bus proxy is enabled system bool // notification from goroutine waiting for dbus.Proxy @@ -88,7 +93,7 @@ func (d *DBus) apply(_ *I) error { ready := make(chan error, 1) // background dbus proxy start - if err := d.proxy.Start(ready, os.Stderr, true); err != nil { + if err := d.proxy.Start(ready, d.out, true); err != nil { return fmsg.WrapErrorSuffix(err, "cannot start message bus proxy:") } @@ -164,3 +169,34 @@ func (d *DBus) Path() string { func (d *DBus) String() string { return d.proxy.String() } + +type scanToFmsg struct { + msg *strings.Builder + msgbuf []string + + mu sync.RWMutex +} + +func (s *scanToFmsg) Write(p []byte) (n int, err error) { + s.mu.Lock() + defer s.mu.Unlock() + return s.write(p, 0) +} + +func (s *scanToFmsg) write(p []byte, a int) (int, error) { + if i := bytes.IndexByte(p, '\n'); i == -1 { + n, _ := s.msg.Write(p) + return a + n, nil + } else { + n, _ := s.msg.Write(p[:i]) + s.msgbuf = append(s.msgbuf, s.msg.String()) + s.msg.Reset() + return s.write(p[i+1:], a+n+1) + } +} + +func (s *scanToFmsg) F(f func(msgbuf []string)) { + s.mu.RLock() + f(s.msgbuf) + s.mu.RUnlock() +}