// Simple RPC-like protocol: implementation of connection and basic actions
-// Copyright (C) 2021 Simon Ruderich
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// SPDX-License-Identifier: GPL-3.0-or-later
+// Copyright (C) 2021-2024 Simon Ruderich
package rpc
import (
"bufio"
"fmt"
+ "io/fs"
"os/exec"
"strings"
"sync"
events chan<- ConnEvent // same as Events, to publish events
eventsWg sync.WaitGroup
- debug bool
- remote string
+ debug bool
+ sshRemote string
+ sshOpts []string
+
+ remoteHelpers fs.FS
cmd *exec.Cmd
conn *safcm.GobConn
}
// NewConn creates a new connection. Events in the returned struct must be
-// regularly read or the connection will stall. This must be done before
+// regularly read or the connection will hang. This must be done before
// DialSSH is called to open a connection.
func NewConn(debug bool) *Conn {
ch := make(chan ConnEvent)
}
// Kill forcefully terminates the connection. It's safe to call Kill (and
-// Wait) multiple times.
+// Wait) multiple times. Calling it before Dial*() was called will only close
+// the Events channel.
func (c *Conn) Kill() error {
if c.cmd == nil {
+ if c.events != nil {
+ close(c.events)
+ c.events = nil
+ }
return fmt.Errorf("Dial*() not called or already terminated")
}
c.debugf("Kill: killing connection")
- c.cmd.Process.Kill()
+ c.cmd.Process.Kill() //nolint:errcheck
return c.wait()
}