-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpipevm.py
More file actions
executable file
·116 lines (93 loc) · 3.84 KB
/
Copy pathpipevm.py
File metadata and controls
executable file
·116 lines (93 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python3
from bitutil import BitStream
from devices import text, graphic, keyboard, pipeos, filesystem
from vm import Vm
import fcntl
import os
import sys
import time
class PipeCmd:
SPECIAL_CHAR = 0xff
DEVICE_SELECTOR_CHAR = 0x80
def __init__(self, vm):
# TODO: CLI arguments:
self.byteAligned = True
self.bitDictionary = None #[48, 49] # bytes that represent bit-0 and bit-1 respectively
# is ignored if byteAligned = True
self.filesystemRoot = "/tmp/pipevm/"
# for now, let all devices share the same outputBuffer
self.outputBuffer = BitStream()
self.vm = vm
filesystemDevice = filesystem.Filesystem(vm, self.outputBuffer, self.byteAligned)
filesystemDevice.setRoot(self.filesystemRoot)
self.devices = [
text.Text(vm, self.outputBuffer, self.byteAligned),
graphic.Graphic(vm, self.outputBuffer, self.byteAligned),
keyboard.Keyboard(vm, self.outputBuffer, self.byteAligned),
pipeos.Os(vm, self.outputBuffer, self.byteAligned),
filesystemDevice,
]
self.device = self.devices[0]
self.inputBuffer = BitStream()
fd = sys.stdin.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
while True:
# FIXME: improve stdin/out handling loop
# handle output (devices -> stdout)
while len(self.outputBuffer) >= 8:
c = self.outputBuffer.read(8)
sys.stdout.buffer.raw.write(c.bytes)
sys.stdout.buffer.raw.flush()
# handle input (stdin -> devices)
b = sys.stdin.buffer.raw.read(1)
if b == b'' or b is None:
continue
print("EOF", file=sys.stderr)
#quit()
# FIXME
time.sleep(0.001)
# if bitDictionary is set, read input bytes as representing an individual bit
if self.bitDictionary:
if ord(b) == self.bitDictionary[0]:
self.inputBuffer.append(BitStream(bin='0b0'))
elif ord(b) == self.bitDictionary[1]:
self.inputBuffer.append(BitStream(bin='0b1'))
else:
raise Exception(f"Invalid input byte representation of a bit: {ord(b)}")
else:
self.inputBuffer.append(BitStream(bytes=b, length=8))
# wait for at least 1 byte
if len(self.inputBuffer) < 8:
continue
c = self.inputBuffer.peek(8).uint
if c == self.SPECIAL_CHAR:
if len(self.inputBuffer) < 16:
# wait for next token
continue
c = self.inputBuffer.read(8).uint
c = self.inputBuffer.read(8).uint
if c == self.SPECIAL_CHAR:
self.device.input(BitStream(uint=c, length=8))
elif (c >= self.DEVICE_SELECTOR_CHAR
and c <= (self.DEVICE_SELECTOR_CHAR + len(self.devices))):
deviceNum = c - self.DEVICE_SELECTOR_CHAR
print(f"Selecting device {deviceNum}", file=sys.stderr)
self.setDevice(deviceNum)
else:
raise Exception(f"Invalid command: {c}")
else:
bs = self.inputBuffer.read(8)
self.device.input(bs)
def setDevice(self, deviceNum):
try:
self.device = self.devices[deviceNum]
except IndexError:
raise Exception(f"Invalid device: {deviceNum}")
def putc(self, c):
sys.stdout.input(c)
sys.stdout.flush()
if __name__ == "__main__":
vm = Vm()
vm.waitReady()
PipeCmd(vm)