diff --git a/package-lock.json b/package-lock.json index 5524017..01903f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@zenfs/zip": "^0.5.1", "chalk": "^5.3.0", "jquery": "^3.7.1", - "utilium": "^0.8.2" + "utilium": "^0.8.3" }, "devDependencies": { "@eslint/js": "^9.12.0", @@ -2958,9 +2958,9 @@ } }, "node_modules/utilium": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/utilium/-/utilium-0.8.2.tgz", - "integrity": "sha512-onOj//1Hi7vuEOIehgART+Ez2G6pfRZn4+XB+lVxyyP0SR3I7L6pkMhrd20pRZeeUFu+iIpm4Xfhsk9kiUsuTg==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/utilium/-/utilium-0.8.3.tgz", + "integrity": "sha512-oeXt8a/wBNYOfdn/uI7GGv2yeKbe+r5LXOKtRS4UFtAloZFsUFHgYhH3moX7MCQjvEI2pvuL9O0u03dHzbudow==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.1" diff --git a/package.json b/package.json index d1a5231..b8b2729 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@zenfs/zip": "^0.5.1", "chalk": "^5.3.0", "jquery": "^3.7.1", - "utilium": "^0.8.2" + "utilium": "^0.8.3" }, "devDependencies": { "@eslint/js": "^9.12.0", diff --git a/src/shell.ts b/src/shell.ts index ed514f3..2507984 100644 --- a/src/shell.ts +++ b/src/shell.ts @@ -2,7 +2,8 @@ import { FitAddon } from '@xterm/addon-fit'; import { WebLinksAddon } from '@xterm/addon-web-links'; import { Terminal } from '@xterm/xterm'; import { fs } from '@zenfs/core'; -import { cd, join, resolve, cwd, basename } from '@zenfs/core/emulation/path.js'; +import { X_OK } from '@zenfs/core/emulation/constants.js'; +import * as path from '@zenfs/core/emulation/path.js'; import chalk from 'chalk'; import $ from 'jquery'; import { createShell } from 'utilium/shell.js'; @@ -13,68 +14,56 @@ terminal.loadAddon(fitAddon); terminal.loadAddon(new WebLinksAddon()); terminal.open($('#terminal-container')[0]); fitAddon.fit(); -terminal.write('\x1b[4h'); -const helpText = `Virtual FS shell.\r -Available commands: help, ls, cp, cd, mv, rm, cat, stat, pwd, mkdir, exit/quit\r -`; +terminal.writeln('Virtual FS shell.'); -terminal.writeln(helpText); +if (!fs.existsSync('/bin')) { + fs.mkdirSync('/bin'); +} + +for (const [name, script] of [ + ['help', `terminal.writeln('Some unix commands available, ls /bin to see them.');`], + ['ls', `terminal.writeln(fs.readdirSync(args[0] || '.').map(name => (fs.statSync(path.join(args[0] || '.', name)).isDirectory() ? chalk.blue(name) : name)).join(' '))`], + ['cd', `path.cd(args[0] || path.resolve('.'));`], + ['cp', `fs.cpSync(args[0], args[1]);`], + ['mv', `fs.renameSync(args[0], args[1]);`], + ['rm', `fs.unlinkSync(args[0]);`], + ['cat', String.raw`terminal.writeln(fs.readFileSync(args[0], 'utf8').replaceAll('\n', '\r\n'));`], + ['pwd', `terminal.writeln(path.cwd);`], + ['mkdir', `fs.mkdirSync(args[0]);`], + ['echo', `terminal.writeln(args.join(' '));`], + ['stat', `terminal.writeln('[work in progress]'/*inspect(fs.statSync(args[0]), { colors: true })*/)`], +]) { + fs.writeFileSync('/bin/' + name, script); + fs.chmodSync('/bin/' + name, 555); +} + +const exec_locals = { fs, path }; function exec(line: string): void { + /* eslint-disable @typescript-eslint/no-unused-vars */ + const { fs, path } = exec_locals; const [command, ...args] = line.trim().split(' '); - switch (command) { - case 'help': - terminal.writeln(helpText); - break; - case 'ls': - terminal.writeln( - fs - .readdirSync(args[0] || '.') - .map(name => (fs.statSync(join(args[0] || '.', name)).isDirectory() ? chalk.blue(name) : name)) - .join(' ') - ); - break; - case 'cd': - cd(args[0] || resolve('.')); - break; - case 'cp': - fs.cpSync(args[0], args[1]); - break; - case 'mv': - fs.renameSync(args[0], args[1]); - break; - case 'rm': - fs.unlinkSync(args[0]); - break; - case 'cat': - terminal.writeln(fs.readFileSync(args[0], 'utf8')); - break; - case 'stat': - //terminal.writeln(inspect(fs.statSync(args[0]), { colors: true })); - break; - case 'pwd': - terminal.writeln(cwd); - break; - case 'mkdir': - fs.mkdirSync(args[0]); - break; - case 'echo': - terminal.writeln(args[0]); - break; - case 'exit': - case 'quit': - close(); - return; - default: - terminal.writeln('Unknown command: ' + command); + /* eslint-enable @typescript-eslint/no-unused-vars */ + + if (!fs.existsSync('/bin/' + command)) { + terminal.writeln('Unknown command: ' + command); + return; + } + + if (!fs.statSync('/bin/' + command).hasAccess(X_OK)) { + terminal.writeln('Missing permission: ' + command); + return; } + + eval(fs.readFileSync('/bin/' + command, 'utf8')); } const shell = createShell({ terminal, get prompt(): string { - return `[${chalk.green(cwd == '/root' ? '~' : basename(cwd) || '/')}]$ `; + console.log(path.cwd); + return `[${chalk.green(path.cwd == '/root' ? '~' : path.basename(path.cwd) || '/')}]$ `; }, /** * @todo output to history file