Skip to content

Commit ccad59b

Browse files
full telnet implementation with virtual terminals
1 parent 1bba997 commit ccad59b

7 files changed

Lines changed: 223 additions & 44 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ollieos",
3-
"version": "2.2.4",
3+
"version": "2.2.5",
44
"description": "",
55
"main": "server.js",
66
"scripts": {

src/kernel/index.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,10 @@ export class Kernel {
260260
* @param explicit_args Ignored if cmd_or_parse is a {@link ParsedCommandLine}. Otherwise, the explicit arguments to pass to the command.
261261
* @param shell The shell that is spawning this process, if any.
262262
* @param start_privileged Whether to start the process with privileged kernel access. The process will not need to use {@link request_privilege} if this is true!!!
263+
* @param term_override An optional {@link AbstractTerminal} to use for this process instead of the default kernel terminal. This is useful for daemons running virtual terminals.
263264
* @returns A {@link SpawnResult} containing the process context and a promise for its completion. You are responsible for terminating the process on an error or after execution.
264265
*/
265-
spawn = (cmd_or_parse: string | ParsedCommandLine, explicit_args?: string[], shell?: AbstractShell, start_privileged?: boolean): SpawnResult => {
266+
spawn = (cmd_or_parse: string | ParsedCommandLine, explicit_args?: string[], shell?: AbstractShell, start_privileged?: boolean, term_override?: AbstractTerminal): SpawnResult => {
266267
// TODO: is passing shell around annoying? how can it be alleviated without affecting separation of concerns?
267268
// TODO: replace the above with process ownership :)
268269

@@ -316,8 +317,11 @@ export class Kernel {
316317
throw new Error(`Program ${program.name} is not compatible with OllieOS 2. (Add compat: "2.0.0" to the program object to mark it as ported.)`);
317318
}
318319

320+
// select the terminal to assign to the process
321+
const term = term_override || this.#term;
322+
319323
// create new process context
320-
const process = this.#process_manager.create_process(parsed_line, shell);
324+
const process = this.#process_manager.create_process(term, parsed_line, shell);
321325

322326
// protect from pollution
323327
const data = Object.create(null) as ProgramMainData<unknown>;
@@ -331,7 +335,7 @@ export class Kernel {
331335
data.process = process.create_userspace_proxy();
332336
}
333337

334-
data.term = this.#term;
338+
data.term = term;
335339
data.args = args;
336340
data.shell = shell;
337341
data.unsubbed_args = parsed_line.unsubbed_args;
@@ -384,8 +388,21 @@ export class Kernel {
384388
// remove last NEWLINE
385389
process_info = process_info.trimEnd();
386390

391+
// collect all terminals in use
392+
const terminals = new Set<AbstractTerminal>();
393+
terminals.add(this.#term);
394+
395+
for (const pid of pids) {
396+
const proc = proc_mgr.get_process(pid);
397+
terminals.add(proc.terminal);
398+
}
399+
400+
// tell all terminals to panic
401+
for (const term of terminals) {
402+
term.handle_kernel_panic(message, process_info, debug_info);
403+
}
404+
387405
proc_mgr.dispose_all();
388-
this.#term.handle_kernel_panic(message, process_info, debug_info);
389406

390407
if (this.#after_panic) {
391408
this.#after_panic(message, debug_info);
@@ -617,8 +634,9 @@ export class Kernel {
617634
get_ipc: { value: () => proc_mgr_proxy.ipc_manager, enumerable: true },
618635
get_env_info: { value: () => self.get_env_info(), enumerable: true },
619636
spawn: {
637+
// force the process to pass its own terminal as the one to use
620638
value: (command: string | ParsedCommandLine, args?: string[], shell?: AbstractShell) =>
621-
self.spawn(command, args, shell, false),
639+
self.spawn(command, args, shell, false, process.terminal),
622640
enumerable: true
623641
},
624642
request_privilege: {

src/kernel/processes.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
UserspaceClientSocket,
99
UserspaceServerSocket
1010
} from "./network";
11+
import {AbstractTerminal} from "./term_ctl";
1112

1213
export interface IPCMessage {
1314
from: number;
@@ -307,6 +308,7 @@ export interface UserspaceOtherProcessContext {
307308
}
308309

309310
export interface UserspaceProcessContext extends UserspaceOtherProcessContext {
311+
readonly terminal: AbstractTerminal;
310312
detach(silently?: boolean): void;
311313
kill(exit_code?: number): void;
312314
add_exit_listener(listener: (exit_code: number) => Promise<void> | void): void;
@@ -326,6 +328,7 @@ export class ProcessContext {
326328
readonly #pid: number;
327329
readonly #manager: ProcessManager;
328330

331+
readonly #terminal: AbstractTerminal;
329332
readonly #source_command: ParsedCommandLine;
330333
readonly #created_at: Date = new Date();
331334
readonly #shell: AbstractShell | undefined;
@@ -346,8 +349,9 @@ export class ProcessContext {
346349
readonly #port_map: Map<number, AbstractServerSocket> = new Map();
347350
readonly #network_clients: Set<AbstractClientSocket> = new Set();
348351

349-
constructor(pid: number, source_command: ParsedCommandLine, registry: ProcessManager, shell?: AbstractShell) {
352+
constructor(pid: number, terminal: AbstractTerminal, source_command: ParsedCommandLine, registry: ProcessManager, shell?: AbstractShell) {
350353
this.#pid = pid;
354+
this.#terminal = terminal;
351355
this.#source_command = source_command;
352356
this.#manager = registry;
353357

@@ -363,6 +367,11 @@ export class ProcessContext {
363367
get pid(): number {
364368
return this.#pid;
365369
}
370+
371+
get terminal(): AbstractTerminal {
372+
return this.#terminal;
373+
}
374+
366375
get source_command(): ParsedCommandLine {
367376
return this.#source_command;
368377
}
@@ -616,6 +625,7 @@ export class ProcessContext {
616625

617626
Object.defineProperties(proxy, {
618627
pid: { get: () => self.pid, enumerable: true },
628+
terminal: { get: () => self.terminal, enumerable: true },
619629
created_at: { get: () => self.created_at, enumerable: true },
620630
is_detached: { get: () => self.is_detached, enumerable: true },
621631
is_background: { get: () => self.is_background, enumerable: true },
@@ -689,9 +699,9 @@ export class ProcessManager {
689699
this.#processes.clear();
690700
}
691701

692-
create_process(source_command: ParsedCommandLine, shell?: AbstractShell): ProcessContext {
702+
create_process(terminal: AbstractTerminal, source_command: ParsedCommandLine, shell?: AbstractShell): ProcessContext {
693703
const pid = this.#next_pid++;
694-
const context = new ProcessContext(pid, source_command, this, shell);
704+
const context = new ProcessContext(pid, terminal, source_command, this, shell);
695705
this.#processes.set(pid, context);
696706
return context;
697707
}

src/kernel/term_ctl.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ export abstract class AbstractTerminal {
131131
return ANSI_UNESCAPED_REGEX;
132132
}
133133

134-
abstract write(text: string | Uint8Array, callback?: () => void): void;
135-
abstract writeln(text: string | Uint8Array, callback?: () => void): void;
134+
abstract write(data: string | Uint8Array, callback?: () => void): void;
135+
abstract writeln(data: string | Uint8Array, callback?: () => void): void;
136136

137137
abstract clear(): void;
138138
abstract reset(): void;

0 commit comments

Comments
 (0)