Newer version
This commit is contained in:
parent
163b0093a0
commit
a86caa7751
|
@ -1,5 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
imports = [ i[:-3] for i in os.listdir('/bin/') if i.endswith('.py') and not '__' in i ]
|
|
||||||
for module in imports:
|
|
||||||
exec(f'import bin.{module} as {module}')
|
|
|
@ -1,6 +0,0 @@
|
||||||
import circuitos
|
|
||||||
|
|
||||||
class App(circuitos.App):
|
|
||||||
def F_main(self):
|
|
||||||
self.os.launch(*self.argv[1:])
|
|
||||||
self.exit()
|
|
26
bin/init.py
26
bin/init.py
|
@ -1,16 +1,18 @@
|
||||||
import circuitos
|
|
||||||
import shlex
|
import shlex
|
||||||
|
|
||||||
class App(circuitos.App):
|
def get_app_class(template):
|
||||||
def F_main(self):
|
class App(template):
|
||||||
with open('/etc/init/start') as f:
|
def F_main(self):
|
||||||
lines = f.readlines()
|
with open('/etc/init/start') as f:
|
||||||
for line in lines:
|
lines = f.readlines()
|
||||||
if line.strip():
|
for line in lines:
|
||||||
last_pid = self.os.launch(*shlex.split(line))
|
if line.strip():
|
||||||
|
last_pid = self.os.launch(*shlex.split(line))
|
||||||
|
|
||||||
self.transfer_console(last_pid)
|
self.transfer_console(last_pid)
|
||||||
self.next_function = 'loop'
|
self.next_function = 'loop'
|
||||||
|
|
||||||
def F_loop(self):
|
def F_loop(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
return App
|
||||||
|
|
11
bin/kill.py
11
bin/kill.py
|
@ -1,6 +1,7 @@
|
||||||
import circuitos
|
def get_app_class(template):
|
||||||
|
class App(template):
|
||||||
|
def F_main(self):
|
||||||
|
self.os.kill(int(self.argv[1]))
|
||||||
|
self.exit()
|
||||||
|
|
||||||
class App(circuitos.App):
|
return App
|
||||||
def F_main(self):
|
|
||||||
self.os.kill(int(self.argv[1]))
|
|
||||||
self.exit()
|
|
||||||
|
|
19
bin/ps.py
19
bin/ps.py
|
@ -1,10 +1,11 @@
|
||||||
import circuitos
|
def get_app_class(template):
|
||||||
|
class App(template):
|
||||||
|
def F_main(self):
|
||||||
|
apps = self.os.apps
|
||||||
|
for pid, app in apps.items():
|
||||||
|
args = app.argv[1:]
|
||||||
|
name = app.name
|
||||||
|
print(f'{pid} {name} {args}')
|
||||||
|
self.exit()
|
||||||
|
|
||||||
class App(circuitos.App):
|
return App
|
||||||
def F_main(self):
|
|
||||||
apps = self.os.apps
|
|
||||||
for pid, app in apps.items():
|
|
||||||
args = app.argv[1:]
|
|
||||||
name = app.name
|
|
||||||
print(f'{pid} {name} {args}')
|
|
||||||
self.exit()
|
|
||||||
|
|
58
bin/sh.py
58
bin/sh.py
|
@ -1,33 +1,35 @@
|
||||||
import circuitos
|
import circuitos.exceptions
|
||||||
import shlex
|
import shlex
|
||||||
import console
|
import console
|
||||||
|
|
||||||
class App(circuitos.App):
|
def get_app_class(template):
|
||||||
def F_main(self):
|
class App(template):
|
||||||
self.jump('prompt')
|
def F_main(self):
|
||||||
|
|
||||||
def F_prompt(self):
|
|
||||||
self.console.write(b'CicuitOS sh # ')
|
|
||||||
self.store['buf'] = []
|
|
||||||
self.jump('input')
|
|
||||||
|
|
||||||
def F_input(self):
|
|
||||||
raw_line = console.read(self.console, self.store['buf'])
|
|
||||||
if raw_line is not None:
|
|
||||||
line = shlex.split(raw_line.decode('ascii'))
|
|
||||||
if line:
|
|
||||||
try:
|
|
||||||
if line[0] == 'bg':
|
|
||||||
self.os.launch(*line[1:])
|
|
||||||
elif line[0] == 'exit':
|
|
||||||
self.exit()
|
|
||||||
else:
|
|
||||||
pid = self.os.launch(*line)
|
|
||||||
self.wait(pid)
|
|
||||||
self.transfer_console(pid)
|
|
||||||
except circuitos.AppNotFound as e:
|
|
||||||
print('error: app not found')
|
|
||||||
self.jump('prompt')
|
self.jump('prompt')
|
||||||
|
|
||||||
def F_loop(self):
|
def F_prompt(self):
|
||||||
pass
|
self.console.write(b'CicuitOS sh # ')
|
||||||
|
self.store['buf'] = []
|
||||||
|
self.jump('input')
|
||||||
|
|
||||||
|
def F_input(self):
|
||||||
|
raw_line = console.read(self.console, self.store['buf'])
|
||||||
|
if raw_line is not None:
|
||||||
|
line = shlex.split(raw_line.decode('ascii'))
|
||||||
|
if line:
|
||||||
|
try:
|
||||||
|
if line[0] == 'bg':
|
||||||
|
self.os.launch(*line[1:])
|
||||||
|
elif line[0] == 'exit':
|
||||||
|
self.exit()
|
||||||
|
else:
|
||||||
|
pid = self.os.launch(*line)
|
||||||
|
self.wait(pid)
|
||||||
|
self.transfer_console(pid)
|
||||||
|
except circuitos.exceptions.AppNotFound as e:
|
||||||
|
print('error: app not found')
|
||||||
|
self.jump('prompt')
|
||||||
|
|
||||||
|
def F_loop(self):
|
||||||
|
pass
|
||||||
|
return App
|
||||||
|
|
106
circuitos/__init__.py
Normal file
106
circuitos/__init__.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import bin #this is at the end of the script in case any functions from bin
|
||||||
|
#depend on anything here
|
||||||
|
from circuitos.exceptions import *
|
||||||
|
from circuitos.apploader import get_app
|
||||||
|
import circuitos.apploader # apploader hack
|
||||||
|
import time
|
||||||
|
import usb_cdc
|
||||||
|
|
||||||
|
class App:
|
||||||
|
def __init__(self, os, pid, name, *argv):
|
||||||
|
self.os = os
|
||||||
|
self.pid = pid
|
||||||
|
self.name = name
|
||||||
|
self.store = {}
|
||||||
|
self.next_function = 'main'
|
||||||
|
self.run_at = -1
|
||||||
|
self.argv = (self,) + argv
|
||||||
|
self.waiting_for = -1
|
||||||
|
|
||||||
|
def iterate(self):
|
||||||
|
if time.monotonic() >= self.run_at and not self.waiting_for in self.os.apps:
|
||||||
|
getattr(self, f'F_{self.next_function}')()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def console(self):
|
||||||
|
if self.pid == self.os.controllers[-1]:
|
||||||
|
return self.os.console
|
||||||
|
else:
|
||||||
|
raise NotConsoleController(self.os.controllers[-1])
|
||||||
|
|
||||||
|
def transfer_console(self, recipient):
|
||||||
|
if self.pid == self.os.controllers[-1]:
|
||||||
|
self.os.controllers.append(recipient)
|
||||||
|
else:
|
||||||
|
raise NotConsoleController(self.os.controllers[-1])
|
||||||
|
|
||||||
|
def jump(self, function):
|
||||||
|
self.next_function = function
|
||||||
|
|
||||||
|
def sleep(self, seconds):
|
||||||
|
self.run_at = time.monotonic() + seconds
|
||||||
|
|
||||||
|
def exec(self, command, *argv):
|
||||||
|
self.os.apps[self.pid] = get_app(command)(self.os, self.pid, command, *argv)
|
||||||
|
|
||||||
|
def wait(self, pid):
|
||||||
|
self.waiting_for = pid
|
||||||
|
|
||||||
|
def end_wait(self):
|
||||||
|
self.waiting_for = -1
|
||||||
|
|
||||||
|
def on_exit(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def exit(self):
|
||||||
|
del self.os.apps[self.pid]
|
||||||
|
|
||||||
|
apploader.App = App # apploader hack
|
||||||
|
|
||||||
|
class OS:
|
||||||
|
def __init__(self):
|
||||||
|
self.apps = {}
|
||||||
|
self.next_new = 0
|
||||||
|
self.controllers = [0]
|
||||||
|
self.console = usb_cdc.console
|
||||||
|
usb_cdc.console.timeout = 0
|
||||||
|
self.next_pidi = 0
|
||||||
|
self.launch('init')
|
||||||
|
|
||||||
|
def iterate(self):
|
||||||
|
pid = list(self.apps.keys())[self.next_pidi]
|
||||||
|
function = self.apps[pid].iterate
|
||||||
|
|
||||||
|
function()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.apps[pid]
|
||||||
|
# If this succeds, the app did not exit and next_pidi should
|
||||||
|
# be incremented
|
||||||
|
self.next_pidi += 1
|
||||||
|
except KeyError:
|
||||||
|
# If self.apps[pid] failed, the app exited and next_pidi
|
||||||
|
# should not be incremented
|
||||||
|
pass
|
||||||
|
self.next_pidi = self.next_pidi % len(self.apps)
|
||||||
|
|
||||||
|
while not self.controllers[-1] in self.apps.keys():
|
||||||
|
self.controllers.pop()
|
||||||
|
|
||||||
|
def launch(self, app, *argv):
|
||||||
|
self.apps[self.next_new] = get_app(app)(self, self.next_new, app, *argv)
|
||||||
|
self.next_new += 1
|
||||||
|
return self.next_new - 1
|
||||||
|
|
||||||
|
def kill(self, pid):
|
||||||
|
try:
|
||||||
|
del self.apps[pid]
|
||||||
|
except KeyError:
|
||||||
|
raise(NoSuchProcess(pid))
|
||||||
|
|
||||||
|
def run():
|
||||||
|
os = OS()
|
||||||
|
while True:
|
||||||
|
os.iterate()
|
||||||
|
|
||||||
|
|
19
circuitos/apploader.py
Normal file
19
circuitos/apploader.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
_cache = {}
|
||||||
|
|
||||||
|
def get_app(app):
|
||||||
|
try:
|
||||||
|
return _cache[app]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
module = __import__(f'/bin/{app}')
|
||||||
|
except AttributeError:
|
||||||
|
raise AppNotFound(app)
|
||||||
|
|
||||||
|
try:
|
||||||
|
app_class = module.get_app_class(App)
|
||||||
|
except AttributeError:
|
||||||
|
raise InvalidApp(app)
|
||||||
|
|
||||||
|
_cache[app] = app_class
|
||||||
|
|
||||||
|
return app_class
|
18
circuitos/exceptions.py
Normal file
18
circuitos/exceptions.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
class CircuitOSError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NoSuchProcess(CircuitOSError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AppNotFound(CircuitOSError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidApp(AppNotFound):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NotConsoleController(CircuitOSError):
|
||||||
|
pass
|
Loading…
Reference in New Issue
Block a user