mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-11 21:51:50 +09:00
more coreutils
This commit is contained in:
@@ -7,23 +7,43 @@ import java.io.OutputStream
|
||||
/**
|
||||
* Created by minjaesong on 2022-05-23.
|
||||
*/
|
||||
class SerialStdioHost(val hostVM: VM) : BlockTransferInterface(true, true) {
|
||||
class SerialStdioHost(val runnerVM: VM) : BlockTransferInterface(true, true) {
|
||||
|
||||
/**
|
||||
* - IDLE: Initial status
|
||||
* - HOST: Usually the server computer
|
||||
* - TERMINAL: Usually the user computer that connects to the host
|
||||
* - PRINTSTREAM: When set, any received bytes will go into the monitor
|
||||
* - INPUTSTREAM: When set, any received bytes will be handled internally (usually, when host sets the terminal to this mode, the host will interpret any data sent from the terminal as input by the human behind the terminal)
|
||||
*/
|
||||
enum class Mode {
|
||||
IDLE, HOST, CLIENT, PRINTSTREAM, INPUTSTREAM
|
||||
}
|
||||
|
||||
var otherVM: VM? = null
|
||||
|
||||
private var mode: Mode = Mode.IDLE
|
||||
private var stream: Mode = Mode.IDLE
|
||||
|
||||
override fun attachDevice(device: BlockTransferInterface?) {
|
||||
if (device !is SerialStdioHost) throw IllegalArgumentException("Other device is not SerialStdioHost: ${device?.javaClass?.canonicalName}")
|
||||
super.attachDevice(device)
|
||||
otherVM = device.hostVM
|
||||
otherVM = device.runnerVM
|
||||
}
|
||||
|
||||
private fun getOthersFirstGPU(): GraphicsAdapter? {
|
||||
return otherVM!!.findPeribyType(VM.PERITYPE_GPU_AND_TERM)?.peripheral as? GraphicsAdapter
|
||||
private fun getOthersFirstGPU(): GraphicsAdapter {
|
||||
return otherVM!!.findPeribyType(VM.PERITYPE_GPU_AND_TERM)?.peripheral as GraphicsAdapter
|
||||
}
|
||||
|
||||
private fun getHostsFirstGPU(): GraphicsAdapter {
|
||||
return runnerVM.findPeribyType(VM.PERITYPE_GPU_AND_TERM)?.peripheral as GraphicsAdapter
|
||||
}
|
||||
|
||||
// sends a byte to client's GPU
|
||||
val out = object : OutputStream() {
|
||||
override fun write(p0: Int) {
|
||||
getOthersFirstGPU()?.writeOut(p0.toByte())
|
||||
if ((recipient as SerialStdioHost).readyToBePossessed)
|
||||
getOthersFirstGPU().writeOut(p0.toByte())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,29 +52,34 @@ class SerialStdioHost(val hostVM: VM) : BlockTransferInterface(true, true) {
|
||||
private val SGI_RESET = byteArrayOf(0x1B, 0x5B, 0x6D)
|
||||
|
||||
override fun write(p0: Int) {
|
||||
getOthersFirstGPU()?.let { g ->
|
||||
SGI_RED.forEach { g.writeOut(it) }
|
||||
g.writeOut(p0.toByte())
|
||||
SGI_RESET.forEach { g.writeOut(it) }
|
||||
if ((recipient as SerialStdioHost).readyToBePossessed) {
|
||||
getOthersFirstGPU().let { g ->
|
||||
SGI_RED.forEach { g.writeOut(it) }
|
||||
g.writeOut(p0.toByte())
|
||||
SGI_RESET.forEach { g.writeOut(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(p0: ByteArray) {
|
||||
getOthersFirstGPU()?.let { g ->
|
||||
SGI_RED.forEach { g.writeOut(it) }
|
||||
p0.forEach { g.writeOut(it) }
|
||||
SGI_RESET.forEach { g.writeOut(it) }
|
||||
if ((recipient as SerialStdioHost).readyToBePossessed) {
|
||||
getOthersFirstGPU().let { g ->
|
||||
SGI_RED.forEach { g.writeOut(it) }
|
||||
p0.forEach { g.writeOut(it) }
|
||||
SGI_RESET.forEach { g.writeOut(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sends a byte from the client to the host
|
||||
val `in` = object : InputStream() {
|
||||
init {
|
||||
otherVM?.getIO()?.mmio_write(38L, 1)
|
||||
}
|
||||
|
||||
override fun read(): Int {
|
||||
if (otherVM != null) {
|
||||
if (otherVM != null && (recipient as SerialStdioHost).readyToBePossessed) {
|
||||
var key: Byte
|
||||
do {
|
||||
Thread.sleep(4L) // if spinning rate is too fast, this function will fail.
|
||||
@@ -77,13 +102,84 @@ class SerialStdioHost(val hostVM: VM) : BlockTransferInterface(true, true) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
private var readyToBePossessed = false
|
||||
|
||||
/**
|
||||
* Commands:
|
||||
*
|
||||
* - "LISTEN": when idle, sets the device to TERMINAL mode
|
||||
* - "HOST": when idle, sets the device to HOST mode
|
||||
* - \x14: hangs up the connection and routes stdio back to the TERMINAL's GraphicsAdapter
|
||||
*
|
||||
* // NOTE TO SELF: are these necessary?
|
||||
*
|
||||
* - \x11: tells TERMINAL to enter printstream mode (routes stdio to this device)
|
||||
* - \x12: tells TERMINAL to enter datastream mode
|
||||
* - \x13: tells TERMINAL to enter keyboard-read mode
|
||||
*/
|
||||
override fun writeoutImpl(inputData: ByteArray) {
|
||||
TODO("Not yet implemented")
|
||||
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||
|
||||
if (mode == Mode.IDLE) {
|
||||
if (inputString.startsWith("LISTEN")) {
|
||||
mode = Mode.CLIENT
|
||||
readyToBePossessed = true
|
||||
}
|
||||
else if (inputString.startsWith("HOST")) {
|
||||
mode = Mode.HOST
|
||||
hijackHostPrint()
|
||||
hijackClientRead()
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mode == Mode.HOST) {
|
||||
when (inputData[0]) {
|
||||
DC_HUP -> {
|
||||
releaseHostPrint()
|
||||
releaseClientRead()
|
||||
mode = Mode.IDLE
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode == Mode.CLIENT) {
|
||||
when (inputData[0]) {
|
||||
DC_HUP -> {
|
||||
mode = Mode.IDLE
|
||||
readyToBePossessed = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hijackHostPrint() {
|
||||
runnerVM.getPrintStream = { this.out }
|
||||
runnerVM.getErrorStream = { this.err }
|
||||
}
|
||||
|
||||
private fun hijackClientRead() {
|
||||
otherVM!!.getInputStream = { this.`in` }
|
||||
}
|
||||
|
||||
private fun releaseHostPrint() {
|
||||
getHostsFirstGPU().let {
|
||||
runnerVM.getPrintStream = { it.getPrintStream() }
|
||||
runnerVM.getErrorStream = { it.getErrorStream() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun releaseClientRead() {
|
||||
otherVM!!.getInputStream = { getOthersFirstGPU().getInputStream() }
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
|
||||
private companion object {
|
||||
const val DC_PRINT = 0x11.toByte()
|
||||
const val DC_DATA = 0x12.toByte()
|
||||
const val DC_INPUT = 0x13.toByte()
|
||||
const val DC_HUP = 0x14.toByte()
|
||||
}
|
||||
}
|
||||
@@ -215,6 +215,23 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
|
||||
}
|
||||
blockSendCount = 0
|
||||
}
|
||||
else if (inputString.startsWith("DELETE")) {
|
||||
if (!fileOpen) {
|
||||
statusCode = STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
try {
|
||||
file.delete()
|
||||
}
|
||||
catch (e: SecurityException) {
|
||||
statusCode = STATE_CODE_SYSTEM_SECURITY_ERROR
|
||||
return
|
||||
}
|
||||
catch (e1: IOException) {
|
||||
statusCode = STATE_CODE_SYSTEM_IO_ERROR
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("LISTFILES")) {
|
||||
// TODO temporary behaviour to ignore any arguments
|
||||
resetBuf()
|
||||
|
||||
Reference in New Issue
Block a user