signal-cli-http/subprocess/subprocess.go

95 lines
No EOL
2.1 KiB
Go

package subprocess
/* This file manages calling signal-cli */
import (
"bufio"
"encoding/json"
"errors"
"os"
"os/exec"
"os/signal"
"sync"
"syscall"
"github.com/creack/pty"
)
var cmd *exec.Cmd;
var cmdStarted = false;
var f *os.File;
var fLock sync.RWMutex;
var reader *bufio.Scanner;
func SetupCMD(binaryLocation string) error {
// Avoid double set-up
if cmdStarted {return errors.New("cmd already started")};
// Create cmd object
cmd = exec.Command(binaryLocation, "jsonRpc");
if cmd == nil {return errors.New("Creating process failed!")}
// Start it
file, err := pty.Start(cmd);
f = file;
if err != nil {return err}
// Set up reader object and loop
reader = bufio.NewScanner(f);
go readCMD();
// Make sure cmd is killed when this program is
go catchKillSignal();
// No problem
return nil;
}
/* Catch signals from this program to kill child */
func catchKillSignal() {
signalCatcher := make(chan os.Signal, 1)
signal.Notify(signalCatcher, syscall.SIGINT, syscall.SIGTERM, syscall.SIGILL)
<- signalCatcher;
cmd.Process.Kill();
os.Exit(0); // Without this the process never exits
}
/* Continuously reads the next line up to 40960 bytes and forwards it to response */
func readCMD() {
var maxCapacity int = 40960;
buf := make([]byte, maxCapacity);
reader.Buffer(buf, maxCapacity);
for reader.Scan() {
// Read the line
line := reader.Text();
// Unmarshal the JSON
var unmarshaledJSON any;
if err := json.Unmarshal([]byte(line), &unmarshaledJSON); err != nil {continue}
// Make sure it's a JSON map
unmarshaledJSONMap, ok := unmarshaledJSON.(map[string]any)
if !ok {continue}
// Get method
method, ok := unmarshaledJSONMap["method"];
if !ok {continue}
// Redirect to handlers based off method
if method == "receive" {
handleIncoming(line, unmarshaledJSONMap);
} else {
handleResponse(line, unmarshaledJSONMap);
}
}
}
/* Write a line into the subprocess */
func writeCMD(line string) (ok bool) {
fLock.Lock();
if line[len(line)-1] != '\n' {line += "\n"}
f.WriteString(line);
fLock.Unlock();
return true;
}