mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
167277ec11
This begins the process of renaming mshell to waveshell everywhere by making the most simple changes. There will need to be additional changes in the future, but the hope is to merge simple changes in now to reduce the number of future merge conflicts.
153 lines
4.2 KiB
Go
153 lines
4.2 KiB
Go
// Copyright 2023, Command Line Inc.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/server"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/shexec"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/wlog"
|
|
)
|
|
|
|
// this is set from build/linker flags
|
|
var BuildTime = "0"
|
|
|
|
func readFullRunPacket(packetParser *packet.PacketParser) (*packet.RunPacketType, error) {
|
|
rpb := packet.MakeRunPacketBuilder()
|
|
for pk := range packetParser.MainCh {
|
|
ok, runPacket := rpb.ProcessPacket(pk)
|
|
if runPacket != nil {
|
|
return runPacket, nil
|
|
}
|
|
if !ok {
|
|
return nil, fmt.Errorf("invalid packet '%s' sent to waveshell", pk.GetType())
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("no run packet received")
|
|
}
|
|
|
|
func handleSingle() {
|
|
packetParser := packet.MakePacketParser(os.Stdin, nil)
|
|
sender := packet.MakePacketSender(os.Stdout, nil)
|
|
defer func() {
|
|
sender.Close()
|
|
sender.WaitForDone()
|
|
}()
|
|
wlog.LogConsumer = sender.SendLogPacket
|
|
initPacket := shexec.MakeInitPacket()
|
|
sender.SendPacket(initPacket)
|
|
if len(os.Args) >= 3 && os.Args[2] == "--version" {
|
|
return
|
|
}
|
|
runPacket, err := readFullRunPacket(packetParser)
|
|
if err != nil {
|
|
sender.SendErrorResponse(runPacket.ReqId, err)
|
|
return
|
|
}
|
|
err = shexec.ValidateRunPacket(runPacket)
|
|
if err != nil {
|
|
sender.SendErrorResponse(runPacket.ReqId, err)
|
|
return
|
|
}
|
|
err = runPacket.CK.Validate("run packet")
|
|
if err != nil {
|
|
sender.SendErrorResponse(runPacket.ReqId, fmt.Errorf("run packets from server must have a CK: %v", err))
|
|
}
|
|
if runPacket.Detached {
|
|
sender.SendErrorResponse(runPacket.ReqId, fmt.Errorf("detached mode not supported"))
|
|
return
|
|
} else {
|
|
shexec.IgnoreSigPipe()
|
|
ticker := time.NewTicker(1 * time.Minute)
|
|
go func() {
|
|
for range ticker.C {
|
|
// this will let the command detect when the server has gone away
|
|
// that will then trigger cmd.SendHup() to send SIGHUP to the exec'ed process
|
|
sender.SendPacket(packet.MakePingPacket())
|
|
}
|
|
}()
|
|
defer ticker.Stop()
|
|
cmd, err := shexec.RunCommandSimple(runPacket, sender, true)
|
|
if err != nil {
|
|
sender.SendErrorResponse(runPacket.ReqId, fmt.Errorf("error running command: %w", err))
|
|
return
|
|
}
|
|
defer cmd.Close()
|
|
startPacket := cmd.MakeCmdStartPacket(runPacket.ReqId)
|
|
sender.SendPacket(startPacket)
|
|
go func() {
|
|
exitErr := sender.WaitForDone()
|
|
if exitErr != nil {
|
|
base.Logf("I/O error talking to server, sending SIGHUP to children\n")
|
|
cmd.SendSignal(syscall.SIGHUP)
|
|
}
|
|
}()
|
|
cmd.RunRemoteIOAndWait(packetParser, sender)
|
|
return
|
|
}
|
|
}
|
|
|
|
func handleUsage() {
|
|
usage := `
|
|
waveshell is a helper program for wave terminal. it is used to execute commands
|
|
|
|
Options:
|
|
--help - prints this message
|
|
--version - print version
|
|
--server - multiplexer to run multiple commands
|
|
--single - run a single command (connected to multiplexer)
|
|
--single --version - return an init packet with version info
|
|
|
|
waveshell does not open any external ports and does not require any additional permissions.
|
|
it communicates exclusively through stdin/stdout with an attached process
|
|
via a JSON packet format.
|
|
`
|
|
fmt.Printf("%s\n\n", strings.TrimSpace(usage))
|
|
}
|
|
|
|
func main() {
|
|
base.SetBuildTime(BuildTime)
|
|
if len(os.Args) == 1 {
|
|
handleUsage()
|
|
return
|
|
}
|
|
firstArg := os.Args[1]
|
|
if firstArg == "--help" {
|
|
handleUsage()
|
|
return
|
|
} else if firstArg == "--version" {
|
|
fmt.Printf("waveshell %s+%s\n", base.WaveshellVersion, base.BuildTime)
|
|
return
|
|
} else if firstArg == "--single" || firstArg == "--single-from-server" {
|
|
base.ProcessType = base.ProcessType_WaveShellSingle
|
|
wlog.GlobalSubsystem = base.ProcessType_WaveShellSingle
|
|
base.InitDebugLog("single")
|
|
handleSingle()
|
|
return
|
|
} else if firstArg == "--server" {
|
|
base.ProcessType = base.ProcessType_WaveShellServer
|
|
wlog.GlobalSubsystem = base.ProcessType_WaveShellServer
|
|
base.InitDebugLog("server")
|
|
base.EnsureRcFilesDir()
|
|
rtnCode, err := server.RunServer()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "[error] %v\n", err)
|
|
}
|
|
if rtnCode != 0 {
|
|
os.Exit(rtnCode)
|
|
}
|
|
return
|
|
} else {
|
|
handleUsage()
|
|
return
|
|
}
|
|
}
|