Add process manager
This commit is contained in:
@@ -146,6 +146,22 @@ duk_ret_t native_word_out(duk_context *ctx)
|
||||
// Global context for IRQ handlers
|
||||
duk_context *global_ctx = NULL;
|
||||
|
||||
// Pending heaps to destroy
|
||||
duk_context *pending_heaps[16];
|
||||
int pending_heaps_count = 0;
|
||||
|
||||
void process_pending_heaps()
|
||||
{
|
||||
for (int i = 0; i < pending_heaps_count; i++)
|
||||
{
|
||||
if (pending_heaps[i] != NULL)
|
||||
{
|
||||
duk_destroy_heap(pending_heaps[i]);
|
||||
}
|
||||
}
|
||||
pending_heaps_count = 0;
|
||||
}
|
||||
|
||||
// JavaScript IRQ wrapper
|
||||
void js_irq_callback(registers_t *r)
|
||||
{
|
||||
@@ -187,6 +203,9 @@ void js_irq_callback(registers_t *r)
|
||||
}
|
||||
|
||||
duk_pop(global_ctx); // Pop stash
|
||||
|
||||
// Process any pending heaps
|
||||
process_pending_heaps();
|
||||
}
|
||||
|
||||
// Native function to register IRQ from JavaScript
|
||||
@@ -616,10 +635,29 @@ duk_ret_t native_isolated_exec(duk_context *ctx)
|
||||
// duk_destroy_heap(isolated_ctx);
|
||||
|
||||
// Return success/failure
|
||||
duk_push_boolean(ctx, success);
|
||||
// Return the heap pointer as a number (uint32_t)
|
||||
duk_push_uint(ctx, (duk_uint_t)isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Native function to destroy an isolated heap
|
||||
duk_ret_t native_destroy_isolated_heap(duk_context *ctx)
|
||||
{
|
||||
// Get the heap pointer
|
||||
duk_uint_t heap_ptr = duk_require_uint(ctx, 0);
|
||||
duk_context *isolated_ctx = (duk_context *)heap_ptr;
|
||||
|
||||
if (isolated_ctx != NULL)
|
||||
{
|
||||
if (pending_heaps_count < 16)
|
||||
{
|
||||
pending_heaps[pending_heaps_count++] = isolated_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kmain()
|
||||
{
|
||||
// Initialize IDT and ISRs
|
||||
@@ -674,6 +712,10 @@ void kmain()
|
||||
duk_push_c_function(ctx, native_isolated_exec, 1);
|
||||
duk_put_global_string(ctx, "$isolatedExec");
|
||||
|
||||
// Register native isolated heap destruction function
|
||||
duk_push_c_function(ctx, native_destroy_isolated_heap, 1);
|
||||
duk_put_global_string(ctx, "$destroyIsolatedHeap");
|
||||
|
||||
// Enable interrupts before JavaScript execution
|
||||
__asm__ volatile("sti");
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ export function devfs_driver(): KFilesystemDriver {
|
||||
stat(path: string): KFilesystemStat | null {
|
||||
return devfs_statEntity(path);
|
||||
},
|
||||
rm(path: string): void {
|
||||
throw new Error("Cannot remove objects in devfs.")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,9 @@ export function fat32_driver(driver: any, data: any): KFilesystemDriver {
|
||||
directRead(path: string, count: number, offset: number) {
|
||||
return fat32_directRead(state, path, count, offset);
|
||||
},
|
||||
rm(path: string): void {
|
||||
throw new Error("Cannot remove objects in fat32.");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
168
src/os/src/kernel/filesystem/procfs.ts
Normal file
168
src/os/src/kernel/filesystem/procfs.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import { Logger } from "../../lib/libstd/logger/logger.kmod";
|
||||
import { Path } from "../../lib/libstd/path";
|
||||
import type {
|
||||
KFilesystemDriver,
|
||||
KFilesystemEntity,
|
||||
KFilesystemMemdata,
|
||||
KFilesystemStat,
|
||||
} from "../../types/filesystem/fs";
|
||||
|
||||
const procfs_data: KFilesystemMemdata = [];
|
||||
|
||||
export function procfs_driver(): KFilesystemDriver {
|
||||
return {
|
||||
id: "procfs",
|
||||
init: procfs_init,
|
||||
listDir(path: string): KFilesystemEntity[] | null {
|
||||
return procfs_listDir(path);
|
||||
},
|
||||
readFile(path: string): unknown {
|
||||
return procfs_readFile(path);
|
||||
},
|
||||
writeFile(path: string, content: unknown): void {
|
||||
throw new Error("Cannot write files in procfs.");
|
||||
},
|
||||
createFile(path: string, content: unknown): void {
|
||||
throw new Error("Cannot create files in procfs.");
|
||||
},
|
||||
mkdir(path: string): void {
|
||||
throw new Error("Cannot make directories in procfs.");
|
||||
},
|
||||
stat(path: string): KFilesystemStat | null {
|
||||
return procfs_statEntity(path);
|
||||
},
|
||||
rm(path: string): void {
|
||||
procfs_rm(path);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function procfs_init(): void {
|
||||
procfs_data.push({
|
||||
name: "root",
|
||||
path: "/",
|
||||
type: "folder",
|
||||
size: 0,
|
||||
contents: null,
|
||||
});
|
||||
}
|
||||
|
||||
export function procfs_getEntity(path: string): KFilesystemEntity | null {
|
||||
for (let i = 0; i < procfs_data.length; i++) {
|
||||
const entity = procfs_data[i]!;
|
||||
|
||||
if (entity.path === path) return entity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function procfs_statEntity(path: string): KFilesystemStat | null {
|
||||
const entity = procfs_getEntity(path);
|
||||
if (!entity) return null;
|
||||
|
||||
return {
|
||||
name: entity.name,
|
||||
type: entity.type,
|
||||
size: entity.size,
|
||||
};
|
||||
}
|
||||
|
||||
export function procfs_mkdir(path: string): void {
|
||||
if (procfs_getEntity(path)) return;
|
||||
|
||||
const parent = Path.dirname(path);
|
||||
if (!procfs_getEntity(parent)) return;
|
||||
|
||||
procfs_data.push({
|
||||
name: Path.filename(path),
|
||||
path,
|
||||
type: "folder",
|
||||
size: 0,
|
||||
contents: null,
|
||||
});
|
||||
}
|
||||
|
||||
export function procfs_createFile(path: string, content: unknown): void {
|
||||
if (procfs_getEntity(path)) return;
|
||||
|
||||
const parent = Path.dirname(path);
|
||||
if (!procfs_getEntity(parent)) return;
|
||||
|
||||
const size = String(content).length;
|
||||
|
||||
procfs_data.push({
|
||||
name: Path.filename(path),
|
||||
path,
|
||||
type: "file",
|
||||
size,
|
||||
contents: content,
|
||||
});
|
||||
}
|
||||
|
||||
export function procfs_writeFile(path: string, content: unknown): void {
|
||||
const entity = procfs_getEntity(path);
|
||||
if (!entity) return procfs_createFile(path, content);
|
||||
|
||||
if (entity.type !== "file") return;
|
||||
|
||||
entity.contents = content;
|
||||
entity.size = String(content).length;
|
||||
}
|
||||
|
||||
export function procfs_readFile(path: string): unknown {
|
||||
const entity = procfs_getEntity(path);
|
||||
if (!entity) return null;
|
||||
|
||||
if (entity.type !== "file") return null;
|
||||
|
||||
return entity.contents;
|
||||
}
|
||||
|
||||
export function procfs_listDir(path: string): KFilesystemEntity[] | null {
|
||||
const entity = procfs_getEntity(path);
|
||||
if (!entity) return null;
|
||||
|
||||
if (entity.type !== "folder") return null;
|
||||
|
||||
const contents: KFilesystemEntity[] = [];
|
||||
|
||||
for (let i = 0; i < procfs_data.length; i++) {
|
||||
const e = procfs_data[i]!;
|
||||
|
||||
if (Path.dirname(e.path) === path) {
|
||||
contents.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
export function procfs_rm(path: string): void {
|
||||
const entity = procfs_getEntity(path);
|
||||
if (!entity) return;
|
||||
|
||||
if (entity.type === "file") {
|
||||
const index = procfs_data.indexOf(entity);
|
||||
|
||||
if (index !== -1) procfs_data.splice(index, 1);
|
||||
} else if (entity.type === "folder") {
|
||||
const entitiesToRemove: KFilesystemEntity[] = [];
|
||||
const pathPrefix = path === "/" ? "/" : path + "/";
|
||||
|
||||
for (let i = 0; i < procfs_data.length; i++) {
|
||||
const e = procfs_data[i]!;
|
||||
|
||||
if (e.path === path || e.path.startsWith(pathPrefix)) {
|
||||
entitiesToRemove.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < entitiesToRemove.length; i++) {
|
||||
const toRemove = entitiesToRemove[i]!;
|
||||
const index = procfs_data.indexOf(toRemove);
|
||||
|
||||
if (index !== -1) procfs_data.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,9 @@ export function sysfs_driver(): KFilesystemDriver {
|
||||
stat(path: string): KFilesystemStat | null {
|
||||
return sysfs_statEntity(path);
|
||||
},
|
||||
rm(path: string): void {
|
||||
throw new Error("Cannot remove objects in sysfs.");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from "./drivers/etc/serial";
|
||||
import { devfs_driver, devfs_getDevice } from "./filesystem/devfs";
|
||||
import { fat32_driver } from "./filesystem/fat32";
|
||||
import { procfs_driver } from "./filesystem/procfs";
|
||||
import { sysfs_driver, sysfs_readFile } from "./filesystem/sysfs";
|
||||
import { kmod_app_init, kmod_app_run } from "./modules/app/app.kmod";
|
||||
import { kmod_disks_detectDisks } from "./modules/disks/disks.kmod";
|
||||
@@ -48,6 +49,7 @@ export function kmain() {
|
||||
kmod_filesystem_init();
|
||||
kmod_filesystem_mount("/sys", sysfs_driver);
|
||||
kmod_filesystem_mount("/dev", devfs_driver);
|
||||
kmod_filesystem_mount("/proc", procfs_driver);
|
||||
|
||||
Logger.log("[Kernel] Initializing terminal module...");
|
||||
kmod_terminal_input_init();
|
||||
@@ -60,7 +62,7 @@ export function kmain() {
|
||||
|
||||
const dev = devfs_getDevice("/hda1");
|
||||
if (!dev) throw new Error("System drive not found");
|
||||
|
||||
|
||||
kmod_filesystem_mount("/disk", function () {
|
||||
return fat32_driver(dev.driver, dev.data);
|
||||
});
|
||||
@@ -72,5 +74,5 @@ export function kmain() {
|
||||
|
||||
const shell = uiarrtostr(kmod_filesystem_readFile("/disk/ushellc")!);
|
||||
|
||||
kmod_app_run(shell);
|
||||
kmod_app_run(shell, "");
|
||||
}
|
||||
|
||||
@@ -9,12 +9,21 @@ import {
|
||||
} from "../filesystem/filesystem.kmod";
|
||||
import { oskrnl_register } from "../../../oskrnl";
|
||||
import { getPathEnv } from "../../../lib/sys/env";
|
||||
import {
|
||||
procfs_mkdir,
|
||||
procfs_readFile,
|
||||
procfs_rm,
|
||||
procfs_writeFile,
|
||||
} from "../../filesystem/procfs";
|
||||
|
||||
const exitListeners: { [pid: string]: (() => void)[] } = {};
|
||||
const heapHandles: { [pid: string]: number } = {};
|
||||
|
||||
export function kmod_app_init() {
|
||||
oskrnl_register();
|
||||
}
|
||||
|
||||
export function kmod_app_run(path: string) {
|
||||
export function kmod_app_run(path: string, args: string) {
|
||||
const appPath = kmod_app_resolve(path);
|
||||
if (!appPath) throw new Error("App not found");
|
||||
|
||||
@@ -27,7 +36,15 @@ export function kmod_app_run(path: string) {
|
||||
const entrypoint = Path.join(appPath, meta["app:entrypoint"]);
|
||||
const code = uiarrtostr(kmod_filesystem_readFile(entrypoint)!);
|
||||
|
||||
iexec(code);
|
||||
const pid = kmod_app_proc_generateId().toString();
|
||||
|
||||
kmod_app_proc_init(pid, meta["app:name"]!, args);
|
||||
kmod_app_proc_registerHandle(pid, "app");
|
||||
const heapHandle = iexec("var __oskrnl_procd_pid = " + pid + ";\n" + code);
|
||||
if (heapHandle) heapHandles[pid] = heapHandle;
|
||||
kmod_app_proc_unregisterHandle(pid, "app");
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
export function kmod_app_resolve(path: string): string | null {
|
||||
@@ -43,3 +60,93 @@ export function kmod_app_resolve(path: string): string | null {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function kmod_app_proc_generateId(): number {
|
||||
return Math.floor(Math.random() * 0xffffffff);
|
||||
}
|
||||
|
||||
export function kmod_app_proc_init(id: string, name: string, args: string) {
|
||||
const root = "/" + id;
|
||||
procfs_mkdir(root);
|
||||
procfs_writeFile(Path.join(root, "name"), name);
|
||||
procfs_writeFile(Path.join(root, "args"), args);
|
||||
procfs_writeFile(Path.join(root, "pid"), id);
|
||||
procfs_writeFile(Path.join(root, "handles"), "");
|
||||
}
|
||||
|
||||
export function kmod_app_proc_getArgs(pid: string): string {
|
||||
const res = procfs_readFile(Path.join("/" + pid, "args"));
|
||||
return res as string;
|
||||
}
|
||||
|
||||
export function kmod_app_proc_registerHandle(
|
||||
pid: string,
|
||||
handle: string
|
||||
): string {
|
||||
const handles = procfs_readFile(Path.join("/" + pid, "handles")) as string;
|
||||
|
||||
const handlesArr = handles == "" ? [] : handles.split(",");
|
||||
handlesArr.push(handle);
|
||||
|
||||
procfs_writeFile(Path.join("/" + pid, "handles"), handlesArr.join(","));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
export function kmod_app_proc_unregisterHandle(
|
||||
pid: string,
|
||||
handle: string
|
||||
): void {
|
||||
const handles = procfs_readFile(Path.join("/" + pid, "handles")) as string;
|
||||
if (handles == "") return;
|
||||
|
||||
const handlesArr = handles.split(",");
|
||||
handlesArr.splice(handlesArr.indexOf(handle), 1);
|
||||
|
||||
procfs_writeFile(Path.join("/" + pid, "handles"), handlesArr.join(","));
|
||||
|
||||
if (handlesArr.length < 1) kmod_app_proc_handleExit(pid);
|
||||
}
|
||||
|
||||
export function kmod_app_proc_generateHandle(): string {
|
||||
return Math.floor(Math.random() * 0xffffffff).toString();
|
||||
}
|
||||
|
||||
export function kmod_app_proc_handleExit(pid: string): void {
|
||||
procfs_writeFile(Path.join("/", pid + "/handles"), "");
|
||||
procfs_rm("/" + pid);
|
||||
|
||||
if (exitListeners[pid]) {
|
||||
for (let i = 0; i < exitListeners[pid].length; i++) {
|
||||
exitListeners[pid][i]!();
|
||||
}
|
||||
}
|
||||
|
||||
exitListeners[pid] = [];
|
||||
delete exitListeners[pid];
|
||||
|
||||
if (heapHandles[pid]) {
|
||||
$destroyIsolatedHeap(heapHandles[pid]!);
|
||||
delete heapHandles[pid];
|
||||
}
|
||||
}
|
||||
|
||||
export function kmod_app_proc_running(pid: string): boolean {
|
||||
const handles = procfs_readFile(Path.join("/" + pid, "handles")) as string;
|
||||
|
||||
if (handles === null || handles === undefined) return false;
|
||||
|
||||
return handles !== "";
|
||||
}
|
||||
|
||||
export function kmod_app_proc_addExitListener(
|
||||
pid: string,
|
||||
listener: () => void
|
||||
): void {
|
||||
if (!exitListeners[pid]) exitListeners[pid] = [];
|
||||
exitListeners[pid].push(listener);
|
||||
}
|
||||
|
||||
export function kmod_app_proc_exit(pid: string): void {
|
||||
kmod_app_proc_handleExit(pid);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,15 @@ export function kmod_terminal_input_init(): void {}
|
||||
|
||||
export function kmod_terminal_input_onKeyboardInput(
|
||||
handler: (keycode: keyof typeof Keycode) => void
|
||||
) {
|
||||
): () => void {
|
||||
kmod_terminal_input_keyboardInputHandlers.push(handler);
|
||||
|
||||
return function () {
|
||||
const index = kmod_terminal_input_keyboardInputHandlers.indexOf(handler);
|
||||
if (index !== -1) {
|
||||
kmod_terminal_input_keyboardInputHandlers.splice(index, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function kmod_terminal_input_handleKeyboardInput(
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export function iexec(code: string) {
|
||||
$isolatedExec(code);
|
||||
}
|
||||
return $isolatedExec(code);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { kmod_app_run } from "../../kernel/modules/app/app.kmod";
|
||||
|
||||
export function oskrnl_app_launcher_run(path: string, args: string) {
|
||||
if ((globalThis as any).__oskrnl) {
|
||||
(globalThis as any).__oskrnl.app_args = args;
|
||||
}
|
||||
kmod_app_run(path);
|
||||
return kmod_app_run(path, args);
|
||||
}
|
||||
|
||||
25
src/os/src/oskrnl/app/proc.ts
Normal file
25
src/os/src/oskrnl/app/proc.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import {
|
||||
kmod_app_proc_addExitListener,
|
||||
kmod_app_proc_exit,
|
||||
kmod_app_proc_getArgs,
|
||||
kmod_app_proc_running,
|
||||
} from "../../kernel/modules/app/app.kmod";
|
||||
|
||||
export function oskrnl_app_proc_getArgs(pid: string): string {
|
||||
return kmod_app_proc_getArgs(pid);
|
||||
}
|
||||
|
||||
export function oskrnl_app_proc_addExitListener(
|
||||
pid: string,
|
||||
listener: () => void
|
||||
): void {
|
||||
kmod_app_proc_addExitListener(pid, listener);
|
||||
}
|
||||
|
||||
export function oskrnl_app_proc_exit(pid: string): void {
|
||||
kmod_app_proc_exit(pid);
|
||||
}
|
||||
|
||||
export function oskrnl_app_proc_running(pid: string): boolean {
|
||||
return kmod_app_proc_running(pid);
|
||||
}
|
||||
@@ -1,13 +1,22 @@
|
||||
import { oskrnl_app_launcher_run } from "./app/launcher";
|
||||
import {
|
||||
oskrnl_app_proc_addExitListener,
|
||||
oskrnl_app_proc_exit,
|
||||
oskrnl_app_proc_getArgs,
|
||||
oskrnl_app_proc_running,
|
||||
} from "./app/proc";
|
||||
import { oskrnl_console_log, oskrnl_console_update } from "./console/console";
|
||||
import { oskrnl_input_onKeyPress } from "./input/input";
|
||||
|
||||
export function oskrnl_register() {
|
||||
(globalThis as any).__oskrnl = {
|
||||
app_args: null,
|
||||
console_log: oskrnl_console_log,
|
||||
console_update: oskrnl_console_update,
|
||||
input_onKeyPress: oskrnl_input_onKeyPress,
|
||||
app_launcher_run: oskrnl_app_launcher_run,
|
||||
app_proc_getArgs: oskrnl_app_proc_getArgs,
|
||||
app_proc_addExitListener: oskrnl_app_proc_addExitListener,
|
||||
app_proc_exit: oskrnl_app_proc_exit,
|
||||
app_proc_running: oskrnl_app_proc_running,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
import {
|
||||
kmod_app_proc_generateHandle,
|
||||
kmod_app_proc_registerHandle,
|
||||
kmod_app_proc_running,
|
||||
kmod_app_proc_addExitListener,
|
||||
} from "../../kernel/modules/app/app.kmod";
|
||||
import { kmod_terminal_input_onKeyboardInput } from "../../kernel/modules/terminal/input";
|
||||
|
||||
export function oskrnl_input_onKeyPress(handler: (key: string) => void) {
|
||||
kmod_terminal_input_onKeyboardInput(handler);
|
||||
export function oskrnl_input_onKeyPress(
|
||||
pid: string,
|
||||
handler: (key: string) => void
|
||||
) {
|
||||
kmod_app_proc_registerHandle(pid, kmod_app_proc_generateHandle());
|
||||
const removeHandler = kmod_terminal_input_onKeyboardInput(function (
|
||||
key: string
|
||||
) {
|
||||
const running = kmod_app_proc_running(pid);
|
||||
if (!running) return;
|
||||
|
||||
handler(key);
|
||||
});
|
||||
|
||||
kmod_app_proc_addExitListener(pid, removeHandler);
|
||||
}
|
||||
|
||||
4
src/os/src/types/c/bindings.d.ts
vendored
4
src/os/src/types/c/bindings.d.ts
vendored
@@ -11,5 +11,5 @@ declare const $irqregister: (
|
||||
irq: number,
|
||||
handler: (irqNum: number) => void
|
||||
) => boolean;
|
||||
declare function $isolatedExec(code: string): void;
|
||||
|
||||
declare function $isolatedExec(code: string): number;
|
||||
declare function $destroyIsolatedHeap(handle: number): void;
|
||||
|
||||
@@ -17,6 +17,7 @@ export type KFilesystemDriver = {
|
||||
writeFile(path: string, content: unknown): void;
|
||||
createFile(path: string, content: unknown): void;
|
||||
mkdir(path: string): void;
|
||||
rm(path: string): void;
|
||||
stat(path: string): KFilesystemStat | null;
|
||||
directRead?(
|
||||
path: string,
|
||||
|
||||
@@ -1 +1 @@
|
||||
__oskrnl.console_log(__oskrnl.app_args);
|
||||
__oskrnl.console_log(__oskrnl.app_proc_getArgs(__oskrnl_procd_pid));
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
__oskrnl.console_log("> ");
|
||||
|
||||
var input = "";
|
||||
var inputActive = true;
|
||||
var pid = "";
|
||||
|
||||
__oskrnl.input_onKeyPress(function (key) {
|
||||
if (!inputActive) return;
|
||||
__oskrnl.input_onKeyPress(__oskrnl_procd_pid, function (key) {
|
||||
if (pid != "" && __oskrnl.app_proc_running(pid)) return;
|
||||
|
||||
if (key == "Backspace") input = input.slice(0, -1);
|
||||
else if (key == "Enter") {
|
||||
inputActive = false;
|
||||
process();
|
||||
return;
|
||||
} else input += key.toLowerCase();
|
||||
@@ -19,5 +18,14 @@ __oskrnl.input_onKeyPress(function (key) {
|
||||
function process() {
|
||||
var app = input.split(" ")[0];
|
||||
var args = input.split(" ").slice(1);
|
||||
__oskrnl.app_launcher_run(app, args.join(" "));
|
||||
pid = __oskrnl.app_launcher_run(app, args.join(" "));
|
||||
__oskrnl.app_proc_addExitListener(pid, function () {
|
||||
input = "";
|
||||
__oskrnl.console_log("> ");
|
||||
});
|
||||
|
||||
if (!__oskrnl.app_proc_running(pid)) {
|
||||
input = "";
|
||||
__oskrnl.console_log("> ");
|
||||
}
|
||||
}
|
||||
|
||||
6
test-hdd/apps/wfkey/index.js
Normal file
6
test-hdd/apps/wfkey/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
__oskrnl.input_onKeyPress(__oskrnl_procd_pid, function (key) {
|
||||
if (key == __oskrnl.app_proc_getArgs(__oskrnl_procd_pid)[0].toUpperCase()) {
|
||||
__oskrnl.app_proc_exit(__oskrnl_procd_pid);
|
||||
return;
|
||||
}
|
||||
});
|
||||
5
test-hdd/apps/wfkey/meta.lam
Normal file
5
test-hdd/apps/wfkey/meta.lam
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"app:name": "wfkey",
|
||||
"app:version": "1.0.0",
|
||||
"app:entrypoint": "index.js"
|
||||
}
|
||||
Reference in New Issue
Block a user