Apple2-IO-RPi/RaspberryPi/apple2driver/handlers/shell.go

108 lines
2.1 KiB
Go
Raw Normal View History

2022-01-11 04:00:58 +00:00
// Copyright Terence J. Boldt (c)2020-2022
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
2022-01-11 04:00:58 +00:00
// This file contains the handler for executing Linux shell
package handlers
import (
"fmt"
"io"
"os"
"os/exec"
"github.com/creack/pty"
)
// ShellCommand handles requests for the Apple II executing a Linux shell
func ShellCommand() {
cmd := exec.Command("bash", "-i")
cmd.Env = append(os.Environ(),
"TERM=vt100",
"LINES=24",
2021-11-27 05:07:14 +00:00
"COLUMNS=79",
)
var ws pty.Winsize
2021-11-27 05:07:14 +00:00
ws.Cols = 79
ws.Rows = 24
ws.X = 0
ws.Y = 0
ptmx, _ := pty.StartWithSize(cmd, &ws)
defer func() { _ = ptmx.Close() }()
outputComplete := make(chan bool)
inputComplete := make(chan bool)
userCancelled := make(chan bool)
go ptyIn(ptmx, outputComplete, inputComplete, userCancelled)
go ptyOut(ptmx, outputComplete, userCancelled)
for {
select {
case <-outputComplete:
ptmx.Close()
comm.WriteByte(0)
return
case <-userCancelled:
fmt.Printf("User cancelled, killing process\n")
ptmx.Close()
cmd.Process.Kill()
comm.WriteByte(0)
return
case <-inputComplete:
cmd.Wait()
comm.WriteByte(0)
return
}
}
}
func ptyOut(stdout io.ReadCloser, outputComplete chan bool, userCancelled chan bool) {
for {
select {
case <-userCancelled:
fmt.Printf("User Cancelled stdout\n")
stdout.Close()
return
default:
bb := make([]byte, 1)
n, err := stdout.Read(bb)
if err != nil {
stdout.Close()
outputComplete <- true
fmt.Printf("stdout closed\n")
return
2022-01-11 00:28:41 +00:00
} else if n > 0 {
b := bb[0]
comm.SendCharacter(b)
}
}
}
}
func ptyIn(stdin io.WriteCloser, done chan bool, inputComplete chan bool, userCancelled chan bool) {
for {
select {
case <-done:
stdin.Close()
inputComplete <- true
fmt.Printf("stdin closed\n")
return
default:
s, err := comm.ReadCharacter()
if err == nil {
if s == string(byte(0x00)) {
stdin.Close()
userCancelled <- true
fmt.Printf("\nUser cancelled stdin\n")
return
}
io.WriteString(stdin, string(s))
}
}
}
}