diff --git a/copyRootfsIntoTheImage.sh b/copyRootfsIntoTheImage.sh index 2c6a3e7..232ab5b 100755 --- a/copyRootfsIntoTheImage.sh +++ b/copyRootfsIntoTheImage.sh @@ -2,12 +2,12 @@ # we depend on a properly build rootfs if [ "$EUID" -ne 0 ] then echo "Please run as root" - exit + exit 1 fi if [ -z disk.img ] then echo "Please run createLiveImage.sh first" - exit + exit 1 fi echo "rebuilding C++ hooks" diff --git a/createLiveImage.sh b/createLiveImage.sh index dd2acb5..aae0cc7 100755 --- a/createLiveImage.sh +++ b/createLiveImage.sh @@ -47,10 +47,10 @@ arch-chroot $CHIBRAX_MOUNT_POINT grub-mkconfig -o /boot/grub/grub.cfg PARTUUID=$(lsblk $LOOP --fs | awk '{print $4}' | grep -v LABEL) -echo "menuentry 'Chibrax OS' {" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg -echo " set root='hd0,msdos1'" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg +echo "menuentry 'Chibrax OS' {" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg +echo " set root='hd0,msdos1'" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg echo " linux /boot/vmlinuz rootfstype=ext4 root=/dev/sda1 rw quiet" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg -echo "}" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg +echo "}" >> $CHIBRAX_MOUNT_POINT/boot/grub/grub.cfg umount $CHIBRAX_MOUNT_POINT losetup -d $LOOP_ROOT diff --git a/deps.sh b/deps.sh new file mode 100755 index 0000000..8659123 --- /dev/null +++ b/deps.sh @@ -0,0 +1,12 @@ +if [ -f /bin/pacman ] # btw +then + sudo pacman -S python gcc make bc +else if [ -f /bin/apt ] #deb / ubuntu +then + sudo apt-get install python3 g++ make +else if [ -f /bin/dnf ] #fedora +then + sudo dnf install python3 gcc-c++ make bc +fi +fi +fi \ No newline at end of file diff --git a/rootfs overrides/chibrax/hook.js b/rootfs overrides/chibrax/hook.js index 4c0f0cf..14546a9 100644 --- a/rootfs overrides/chibrax/hook.js +++ b/rootfs overrides/chibrax/hook.js @@ -20,8 +20,4 @@ async function fHook(path) { }) } -function rHook(path) { - -} - module.exports = { hookTo, fHook } \ No newline at end of file diff --git a/rootfs overrides/chibrax/keyboard.js b/rootfs overrides/chibrax/keyboard.js new file mode 100644 index 0000000..0e9c1db --- /dev/null +++ b/rootfs overrides/chibrax/keyboard.js @@ -0,0 +1,7 @@ +const fs = require('fs') + +function setLayOut(layout) { + +} + +fs.readFileSync('/etc/vconsole.conf') \ No newline at end of file diff --git a/rootfs overrides/etc/vconsole.conf b/rootfs overrides/etc/vconsole.conf new file mode 100644 index 0000000..fb91436 --- /dev/null +++ b/rootfs overrides/etc/vconsole.conf @@ -0,0 +1 @@ +KEYMAP=fr-pc \ No newline at end of file diff --git a/rootfs overrides/usr/bin/cat.js b/rootfs overrides/usr/bin/cat.js new file mode 100644 index 0000000..0a342bf --- /dev/null +++ b/rootfs overrides/usr/bin/cat.js @@ -0,0 +1,18 @@ +const fs = require('fs'); + +if(process.argv.length >= 3){ + try{ + const content = fs.readFileSync(process.argv[3], {encoding: 'utf-8'}); + console.log(content) + } + catch(e){ + switch(e.code){ + case "ENOENT": + console.error(`file "${file}" does not exist.`); + break; + default: + console.error(`error: code ${e.code}`) + } + } + +} \ No newline at end of file diff --git a/rootfs overrides/usr/bin/dircolors.js b/rootfs overrides/usr/bin/dircolors.js new file mode 100644 index 0000000..e69de29 diff --git a/rootfs overrides/usr/bin/echo.js b/rootfs overrides/usr/bin/echo.js index 41907fe..6694f87 100644 --- a/rootfs overrides/usr/bin/echo.js +++ b/rootfs overrides/usr/bin/echo.js @@ -1,3 +1,3 @@ if(process.argv.length >= 3){ - console.log(process.argv[3]) + console.log('\x1b[36m%s\x1b[0m', process.argv[3]) } \ No newline at end of file diff --git a/rootfs overrides/usr/bin/ip.js b/rootfs overrides/usr/bin/ip.js new file mode 100644 index 0000000..681b7dd --- /dev/null +++ b/rootfs overrides/usr/bin/ip.js @@ -0,0 +1,2 @@ +const os = require('os'); +console.log(os.networkInterfaces()); \ No newline at end of file diff --git a/rootfs overrides/usr/bin/ls.js b/rootfs overrides/usr/bin/ls.js index f2de14a..a701b78 100644 --- a/rootfs overrides/usr/bin/ls.js +++ b/rootfs overrides/usr/bin/ls.js @@ -1,14 +1,129 @@ const fs = require('fs') -let path = process.argv[3] ?? '.' -let optionsArray = process.argv.slice(4) ?? [] + +let paths = [] let options = [] -for(let option of optionsArray){ - if(option.startwith("--")) options.push(option.slice) - else if(options.startwith("-")) options.push += option.slice(1).split('').map(el => {return '-' + el}) + +for(arg of process.argv.slice(3)){ + if(arg.startsWith('--')){ + options.push(arg) + } + else if(arg.startsWith('-')){ + for(let option of arg.slice(1)){ + options.push('-' + option); + } + } + else{ + paths.push(arg) + } } -const files = fs.readdirSync(path); -const nonHiddenFiles = files.filter(file => file[0] != '.') +if(paths.length == 0){ + paths = ['.']; +} -console.log(options.includes('-a') ? files.join(' ') : nonHiddenFiles.join(' ')) \ No newline at end of file + +try{ + + listFiles(paths[0], options) +} +catch(e){ + switch(e.code){ + case "ENOENT": + console.error(`path "${paths[0]}" does not exist`); + break; + default: + console.error(`ls: ${e.code}`) + } +} + + + + +function listFiles(path, options){ + const files = ['.', '..'].concat(fs.readdirSync(paths[0])) + const nonHiddenFiles = files.filter(file => file[0] != '.') + colorList = JSON.parse(process.env.ls_color) + if(options.includes('-l')){ + console.log(`total ${options.includes('-a') ? files.length : nonHiddenFiles.length}`) + for(let file of options.includes('-a') ? files : nonHiddenFiles){ + + stats = fs.lstatSync(`${path}/${file}`); + mode = stats.mode + result = "" + let color = [] + let defaultColor = "\x1b[0m" + let fileType = "-" + if(stats.isFile()){ + fileType = "-"; + if(stats.mode & 00100){ //owner can execute + color = colorList.ex ? `\x1b[${colorList.ex[0]}m\x1b[${colorList.ex[1]}m` : "\x1b[0m" + } + } + else if (stats.isDirectory()) { + fileType = "d"; + color = colorList.di ? `\x1b[${colorList.di[0]}m\x1b[${colorList.di[1]}m` : "\x1b[0m" + } + else if (stats.isSymbolicLink()){ + fileType = "l" + color = colorList.ln ? `\x1b[${colorList.ln[0]}m\x1b[${colorList.ln[1]}m` : "\x1b[0m" + } + result += fileType; + permissions = "xwr" + for(let i=8;i>=0;i--){ + result += parseInt(Math.pow(2,i).toString(2)) & mode ? permissions[i%3] : '-' + } + if(01000 & mode){ // check sticky bit + color = "\x1b[40m\x1b[92m\x1b[7m" + } + let date = new Date(stats.mtimeMs*1000).toDateString().split(' '); + result += ` ${usernameFromUID(stats.uid)}\t${groupnameFromGID(stats.gid)}\t${stats.size}\t${date[2]} ${date[1]}. ${options.includes('--color') ? color : ""}${file}${defaultColor}` + console.log(result) + } + } + else{ + result = "" + const defaultColor = "\x1b[0m"; + if(options.includes('--color')){ + for(let file of options.includes('-a') ? files : nonHiddenFiles){ + stats = fs.lstatSync(`${path}/${file}`); + let color = defaultColor + if(stats.isDirectory()){ + color = colorList.di ? `\x1b[${colorList.di[1]}m\x1b[${colorList.di[0]}m` : defaultColor + } + else if (stats.isSymbolicLink()){ + color = colorList.ln ? `\x1b[${colorList.ln[1]}m\x1b[${colorList.ln[0]}m` : defaultColor + } + if(01000 & stats.mode){ // check sticky bit + color = "\x1b[40m\x1b[92m\x1b[7m" + } + result += color + file + defaultColor + " "; + } + console.log(result) + }else{ + console.log(options.includes('-a') ? files.join(' ') : nonHiddenFiles.join(' ')) + } + } +} + +function usernameFromUID(uid){ + const passwd = fs.readFileSync("/etc/passwd", {encoding: 'utf-8'}).split('\n'); + for(let line of passwd){ + let lineSplited = line.split(':') + if(lineSplited[2] == uid){ + return lineSplited[0]; + } + } + return uid +} + +function groupnameFromGID(uid){ + const passwd = fs.readFileSync("/etc/passwd", {encoding: 'utf-8'}).split('\n'); + for(let line of passwd){ + let lineSplited = line.split(':') + if(lineSplited[3] == uid){ + return lineSplited[0]; + } + } + return uid +} \ No newline at end of file diff --git a/rootfs overrides/usr/bin/rm.js b/rootfs overrides/usr/bin/rm.js new file mode 100644 index 0000000..22f6a51 --- /dev/null +++ b/rootfs overrides/usr/bin/rm.js @@ -0,0 +1,25 @@ +const fs = require('fs') + +if(process.argv.length >= 3){ + let filesToRemove = process.argv.slice(3).filter((arg) => !arg.startsWith('-')); + let forceDelete = process.argv.includes("--force") || process.argv.includes("-f"); + let recursiveDelete = process.argv.includes("--recursive") || process.argv.includes('-r'); + for(file of filesToRemove){ + try{ + fs.rmSync(file, {force: forceDelete, recursive: recursiveDelete}); + }catch(e){ + switch(e.code){ + case "ENOENT": + console.error(`file "${file}" does not exist.`); + break; + case "ERR_FS_EISDIR": + console.error(`cannot delete ${file} because it is a folder. Try using -r.`) + break; + default: + console.error(`error: code ${e.code}`) + console.code(`message: ${e.message}`) + } + } + } + +} \ No newline at end of file diff --git a/rootfs overrides/usr/bin/sheebr.js b/rootfs overrides/usr/bin/sheebr.js index b7928e5..3939433 100644 --- a/rootfs overrides/usr/bin/sheebr.js +++ b/rootfs overrides/usr/bin/sheebr.js @@ -1,7 +1,8 @@ const { Lexer } = require('../lib/sheebr/lexer') const { getline } = require('../lib/sheebr/utils') const fs = require('fs') -const environment = require('../lib/sheebr/environment') +let environment = require('../lib/sheebr/environment') +let aliases = require("../lib/sheebr/aliases") const readline = require('readline').createInterface({ input: process.stdin, output: process.stdout, @@ -19,6 +20,7 @@ async function start(){ while(true){ input = await getline("sheebr> "); if(input == "exit") break; + if(input == "") continue; else evaluate(input); } } @@ -26,16 +28,40 @@ async function start(){ function evaluate(input){ let lexer = new Lexer(input) args = lexer.scanTokens() - - if(args[0] == "cd"){ - if(args.length != 2){ - console.log("Wrong number of arguments"); return;} - if(!fs.existsSync(args[1])){console.log("Folder does not exist"); return;} - current_dir = args[1][0] == "/" ? args[1] : current_dir + '/' + args[1]; - console.log(current_dir) - return; + args = evaluateAliases(args) + args = evaluateEnvironmentVariables(args); + switch(args[0]){ + case "cd": + if(args.length != 2){ + console.log("Wrong number of arguments"); return;} + if(!fs.existsSync(args[1])){console.log("Folder does not exist"); return;} + current_dir = args[1][0] == "/" ? args[1] : current_dir + '/' + args[1]; + //console.log(current_dir) + break; + case "set": + environment[args[1]] = args[2]; + break; + case "alias": + if(args.length == 1) console.log(aliases); + else if(args.length == 2){ + console.error("Wrong number of argument") + } + else{ + aliases[args[1]] = args[2].split(" ") + } + break; + case "clear": + console.clear(); + break; + default: + evaluateProgram(args) } - // check for all folders in path + +} + + + +function evaluateProgram(args){ let found = false; for(let path of environment.path){ @@ -43,7 +69,7 @@ function evaluate(input){ const files = fs.readdirSync(path); if(files.includes(`${args[0]}.js`)){ found = true; - script = execSync(`node ${path + '/' + args[0]}.js ${args.map(arg => {return arg.includes(' ') ? `"${arg}"` : arg}).join(' ')}`, {cwd: current_dir}); + script = execSync(`node ${path + '/' + args[0]}.js ${args.map(arg => {return arg.includes(' ') ? `"${arg}"` : arg}).join(' ')}`, {cwd: current_dir, env: environment}); process.stdout.write(script) tobreak = true; } @@ -53,8 +79,27 @@ function evaluate(input){ if(!found){ console.log("Program not found") } - let program = args[0] } +function evaluateEnvironmentVariables(args){ + let newArgs = [] + for(let arg of args){ + if(arg.startsWith('$')){ + if (arg.slice(1) in environment) + newArgs.push(JSON.stringify(environment[arg.slice(1)])); + else + console.error(`variable ${arg.slice(1)} does not exist.`); + } + else{ + newArgs.push(arg) + } + } + return newArgs; +} - +function evaluateAliases(args){ + if(args[0] in aliases){ + return aliases[args[0]].concat(args.slice(1)) + } + return args; +} \ No newline at end of file diff --git a/rootfs overrides/usr/bin/touch.js b/rootfs overrides/usr/bin/touch.js index 9df0db5..d56689d 100644 --- a/rootfs overrides/usr/bin/touch.js +++ b/rootfs overrides/usr/bin/touch.js @@ -1,4 +1,9 @@ const fs = require('fs') if(process.argv.length >= 3){ - fs.openSync(process.argv[3], 'w'); + try{ + fs.openSync(process.argv[3], 'w'); + } + catch(e){ + console.error(e.code + '\n' + e.message); + } } \ No newline at end of file diff --git a/rootfs overrides/usr/bin/whereis.js b/rootfs overrides/usr/bin/whereis.js new file mode 100644 index 0000000..c0b6a75 --- /dev/null +++ b/rootfs overrides/usr/bin/whereis.js @@ -0,0 +1,23 @@ +const fs = require('fs'); +const { resolve } = require('path'); + +if(process.argv.length >= 3){ + // console.log(process.env.path) + for(let environmentPath of process.env.path.split(',')){ + console.log(recursiveSearch(environmentPath, process.argv[3])); + } +} + +function recursiveSearch(dir, bin){ + result = [] + const dirents = fs.readdirSync(dir, {withFileTypes: true}); + for(const dirent of dirents){ + const res = resolve(dir, dirent.name); + if(dirent.name === bin){ + result.push(res); + } + if(dirent.isDirectory()) + result = result.concat(recursiveSearch(dirent.name, bin)) + } + return result; +} \ No newline at end of file diff --git a/rootfs overrides/usr/bin/whoami.js b/rootfs overrides/usr/bin/whoami.js new file mode 100644 index 0000000..0f4ad30 --- /dev/null +++ b/rootfs overrides/usr/bin/whoami.js @@ -0,0 +1,2 @@ +let os = require('os') +console.log(os.userInfo().username); diff --git a/rootfs overrides/usr/lib/sheebr/aliases.js b/rootfs overrides/usr/lib/sheebr/aliases.js new file mode 100644 index 0000000..1e6b442 --- /dev/null +++ b/rootfs overrides/usr/lib/sheebr/aliases.js @@ -0,0 +1,5 @@ +const aliases = { + ls: ["ls", "--color"] +} + +module.exports = aliases \ No newline at end of file diff --git a/rootfs overrides/usr/lib/sheebr/environment.js b/rootfs overrides/usr/lib/sheebr/environment.js index a44043e..815d150 100644 --- a/rootfs overrides/usr/lib/sheebr/environment.js +++ b/rootfs overrides/usr/lib/sheebr/environment.js @@ -1,5 +1,10 @@ let environment = { - path: ["/usr/lib/sheebr", "/usr/bin"] + path: ["/usr/bin", "/usr/lib/sheebr"], + ls_color: JSON.stringify({ + di: [01, 34], + ln: [01, 36], + ex: [01, 32] + }) } module.exports = environment \ No newline at end of file