Next step might actually be the TUI! Or maybe the raw proxy, it would be nice to be able to just run the proxy.
67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"termtap.dev/internal/model"
|
|
"termtap.dev/internal/process"
|
|
)
|
|
|
|
func StartProcess(cmd model.Command, addr string, ch chan<- model.Message, sigCh <-chan os.Signal) {
|
|
ch <- model.Message{
|
|
Type: model.MessageTypeProcessStarting,
|
|
Body: fmt.Sprintf("spawning process '%s'", process.CommandString(cmd)),
|
|
}
|
|
|
|
proc := process.NewProcess(cmd, addr, ch)
|
|
|
|
if err := proc.Exec.Start(); err != nil {
|
|
ch <- model.Message{
|
|
Type: model.MessageTypeProcessExited,
|
|
Body: fmt.Sprintf("%q", err),
|
|
}
|
|
return
|
|
}
|
|
process.UpdateStatus(proc, true, ch)
|
|
|
|
// Listen for SIGTERM from main process
|
|
go func() {
|
|
sig := <-sigCh
|
|
|
|
ch <- model.Message{
|
|
Type: model.MessageTypeProcessSignaled,
|
|
Body: fmt.Sprintf("process with pid '%d' is being killed", proc.Exec.Process.Pid),
|
|
PID: proc.Exec.Process.Pid,
|
|
}
|
|
|
|
if proc.Exec != nil {
|
|
_ = proc.Exec.Process.Signal(sig)
|
|
process.UpdateStatus(proc, false, ch)
|
|
}
|
|
}()
|
|
|
|
if err := proc.Exec.Wait(); err != nil {
|
|
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok {
|
|
ch <- model.Message{
|
|
Type: model.MessageTypeProcessExited,
|
|
Body: fmt.Sprintf("process pid '%d' exited by itself", proc.Exec.Process.Pid),
|
|
PID: proc.Exec.Process.Pid,
|
|
ExitCode: exitErr.ExitCode(),
|
|
}
|
|
process.UpdateStatus(proc, false, ch)
|
|
return
|
|
}
|
|
|
|
ch <- model.Message{
|
|
Type: model.MessageTypeFatal,
|
|
Body: fmt.Sprintf("%q", err),
|
|
}
|
|
process.UpdateStatus(proc, false, ch)
|
|
return
|
|
}
|
|
|
|
}
|