diff --git a/main.go b/main.go index 2cc9d03..7a37722 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,7 @@ var tcpAddr = flag.String("tcp", "", "also listen on TCP address (e.g. :564)") var strict = flag.Bool("strict", false, "only allow tool steps; reject inline code") var yolo = flag.Bool("yolo", false, "skip landrun sandbox for execute_code") var nodbus = flag.Bool("nodbus", false, "disable D-Bus adapter (for headless/container use)") +var no9p = flag.Bool("no9p", false, "disable 9P listener (D-Bus only mode)") // ModelCache caches the list of models from all backends. type ModelCache struct { @@ -189,6 +190,9 @@ func daemonize(pidPath string) { if *nodbus { args = append(args, "-nodbus") } + if *no9p { + args = append(args, "-no9p") + } cmd := exec.Command(exe, args...) cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true} if err := cmd.Start(); err != nil { @@ -217,9 +221,17 @@ func stopServer(sockPath, pidPath string) { func runServer(sockPath, pidPath string) { env.EnsureDefaults() + // -no9p requires D-Bus (otherwise there's no interface at all) + if *no9p && *nodbus { + fmt.Fprintln(os.Stderr, "error: -no9p and -nodbus are mutually exclusive") + os.Exit(1) + } + // Remove stale socket - if _, err := os.Stat(sockPath); err == nil { - os.Remove(sockPath) //nolint:errcheck + if !*no9p { + if _, err := os.Stat(sockPath); err == nil { + os.Remove(sockPath) //nolint:errcheck + } } // Write PID file @@ -240,7 +252,7 @@ func runServer(sockPath, pidPath string) { Sink: sink, Strict: *strict, Yolo: *yolo, - NoMount: *tcpAddr != "", + NoMount: *no9p || *tcpAddr != "", InvalidateModels: modelCache.Invalidate, OnSessionCreated: func(id string, sess *session.Session) { if dbusAdapter != nil { @@ -259,43 +271,58 @@ func runServer(sockPath, pidPath string) { }, }) - srv := server.New(server.Config{ - Sink: sink, - SessionMgr: mgr, - RootStore: NewRootStore(), - InvalidateModels: modelCache.Invalidate, - }) + var srv *server.Server + if !*no9p { + srv = server.New(server.Config{ + Sink: sink, + SessionMgr: mgr, + RootStore: NewRootStore(), + InvalidateModels: modelCache.Invalidate, + }) + } - // Start D-Bus adapter (best-effort; pure 9P still works without it). + // Start D-Bus adapter. // -tcp implies -nodbus (remote/headless deployments have no session bus). - if !*nodbus && *tcpAddr == "" { + // -no9p forces D-Bus on (it's the only interface). + if !*nodbus && (*no9p || *tcpAddr == "") { dbusAdapter = startDBus(mgr) - dbusAdapter.WatchExisting() + if dbusAdapter != nil { + dbusAdapter.WatchExisting() + } + if *no9p && dbusAdapter == nil { + fmt.Fprintln(os.Stderr, "error: -no9p mode requires D-Bus but session bus is unavailable") + os.Exit(1) + } } // Prefetch models asynchronously at startup go modelCache.Refresh() - listener, err := net.Listen("unix", sockPath) - if err != nil { - fmt.Fprintf(os.Stderr, "listen: %v\n", err) - os.Exit(1) + var listener net.Listener + if !*no9p { + var err error + listener, err = net.Listen("unix", sockPath) + if err != nil { + fmt.Fprintf(os.Stderr, "listen: %v\n", err) + os.Exit(1) + } + + go func() { + for { + conn, err := listener.Accept() + if err != nil { + return + } + go srv.Serve(conn) + } + }() + + fmt.Printf("olliesrv listening on %s\n", sockPath) } - go func() { - for { - conn, err := listener.Accept() - if err != nil { - return - } - go srv.Serve(conn) - } - }() - - fmt.Printf("olliesrv listening on %s\n", sockPath) - var tcpListener net.Listener - if *tcpAddr != "" { + if !*no9p && *tcpAddr != "" { + var err error tcpListener, err = net.Listen("tcp", *tcpAddr) if err != nil { fmt.Fprintf(os.Stderr, "tcp listen: %v\n", err) @@ -313,21 +340,33 @@ func runServer(sockPath, pidPath string) { fmt.Printf("olliesrv listening on tcp %s\n", *tcpAddr) } + if *no9p { + fmt.Println("olliesrv running in D-Bus only mode") + } + sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) <-sigChan - srv.InterruptAll() + if srv != nil { + srv.InterruptAll() + } fmt.Println("shutting down") if dbusAdapter != nil { dbusAdapter.Close() } - srv.Shutdown() - listener.Close() //nolint:errcheck + if srv != nil { + srv.Shutdown() + } + if listener != nil { + listener.Close() //nolint:errcheck + } if tcpListener != nil { tcpListener.Close() //nolint:errcheck } - os.Remove(sockPath) + if !*no9p { + os.Remove(sockPath) + } os.Remove(pidPath) sink.Flush() }