clite.commands.data = function() { // insert commands below this line clite.commands.load('help',function(args,env,io) { var stdio = io.include('stdio'); function main(argc,argv) { stdio.printf(` Welcome to CLIte (pronounced like 'site' with an added L). Various common Unix commands are available in the CLIte shell: ls - list directory contents cat - concatenate files and print to std output or local file touch - create a new file less - simple text file viewer file - determines the file type And many more. Running any command with the argument -? will give you help for that program. As a basic guide for guests: Use ls to see what content is available, eg: ls web Use less to view the content, eg: less web/about `); return 0; } return main(args.length,args); }); clite.commands.load('ls',function(args,env,io) { var stdlib = io.include('stdlib'); var stdio = io.include('stdio'); var time = io.include('time'); var clite = io.include('clite'); var dirs = []; var long = false; var all = false; var access = false; var one = false; function help() { stdio.printf(` ls - list directory contents Usage: ls [OPTION] [FILE] Options: -? Print this help information -l Display data in long format -u Display access time in long format -a Do not ignore entries starting with . -1 Display one entry per line `); } function writeNodeData(st,fn) { if (long) { var pw = stdlib.getpwuid(st.st_uid); var gr = stdlib.getgrgid(st.st_gid); var uname = st.st_uid.toString(); var gname = st.st_gid.toString(); if (pw) uname = pw.pw_name; if (gr) gname = gr.gr_name; var tm; var t = time.time(); var tmn = time.localtime(t); if (access) { tm = time.localtime(st.st_atim.tv_sec); }else{ tm = time.localtime(st.st_mtim.tv_sec); } var d = ''; if (tm.tm_year != tmn.tm_year) { d = time.strftime('%b %d %Y',tm); }else{ d = time.strftime('%b %d %H:%M',tm); } var ms = clite.strmode(st.st_mode); if (st.type == stdio.types.FT_LINK) { var lp = '?'; var fd = stdio.open(fn,stdio.flags.O_RDONLY|stdio.flags.O_NOFOLLOW|stdio.flags.O_SYNC); if (fd) { lp = stdio.readAll(fd); stdio.close(fd); if (!lp) lp = '?'; } stdio.printf('%s%12s%12s%14s%12s -> %s\n',ms,uname,gname,d,st.name,lp); }else{ stdio.printf('%s%12s%12s%14s%12s\n',ms,uname,gname,d,st.name); } }else if (one) { stdio.printf('%s\n',st.name); }else{ stdio.printf('%s ',st.name); } } function main(argc,argv) { for (var i=1; i 1) stdio.printf('%s:\n',dir); var st = stdio.stat(dir); if (!st) { stdio.fprintf(io.stderr,'cannot read file: %s\n',dir); stdio.close(fd); return; } if (st.type != stdio.types.FT_DIR) { writeNodeData(st,dir); if (!one && !long) stdio.write(io.stdout,'\n'); return; } var fd = stdio.open(dir,stdio.flags.O_RDONLY|stdio.flags.O_SYNC); if (!fd) { stdio.fprintf(io.stderr,'cannot open directory: %s\n',dir); return; } var e; while ((e = stdio.read(fd)) != null) { if (e[0] == '.' && !all) continue; var est = stdio.lstat(dir+'/'+e,stdio.flags.AT_SYMLINK_NOFOLLOW); if (!est) { stdio.fprintf(io.stderr,'cannot read content: %s\n',dir); break; } writeNodeData(est,dir+'/'+e); } stdio.close(fd); if (!one && !long) stdio.write(io.stdout,'\n'); }); return 0; } return main(args.length,args); }); clite.commands.load('cat',function(args,env,io) { var stdlib = io.include('stdlib'); var stdio = io.include('stdio'); var clite = io.include('clite'); var files = []; var download = false; var remote = true; var pending = 0; function help() { stdio.printf(` cat - concatenate files and print to std output or local file Usage: cat [OPTION] [FILE] Options: -? Print this help information -d Download the file data, instead of printing it -l Only display files if remote data is loaded `); } function fcb(fd) { var st = stdio.fstatat(fd,stdio.flags.AT_SYMLINK_NOFOLLOW); // check if it's a directory or link if ( !st || st.type == stdio.types.FT_DIR || st.type == stdio.types.FT_LINK || st.type == stdio.types.FT_BINARY || st.type == stdio.types.FT_UNKNOWN || st.type == stdio.types.FT_IMAGE ) { if (st) { stdio.fprintf(io.stderr,'not a normal file: %s\n',st.name); }else{ stdio.write(io.stderr,'not a normal file\n'); } }else{ var d = stdio.readAll(fd); if (d != null) { if (download) { var ld = stdio.open('/dev/local',stdio.flags.O_WRONLY); if (ld) { var t = st.name+String.fromCharCode(2)+d; stdio.write(ld,t); stdio.close(ld); }else{ stdio.write(io.stderr,'can not write to local device\n'); } }else{ stdio.printf(d); } } } pending--; stdio.close(fd); if (pending <1) io.exit(0); } function main(argc,argv) { for (var i=1; i Options: -? Print this help information `); } function loadRemote(fd) { if (!fd) { stdio.fprintf(io.stderr,'unable to create file: %s\n',file); io.exit(1); return; } io.exit(0); } function main(argc,argv) { let file = null; for (var i=1; i Options: -? Print this help information `); } function showAt(line) { var start = line; var end = line+rows-1; if (end > lines.length) end = lines.length; curses.clear(); for (var i=start; i= cols) { var sects = line.match(new RegExp('(.{1,'+(cols-1)+'})','g')); lines.push.apply(lines,sects); return; } lines.push(line); }); bottomLine = (lines.length-rows); showAt(0); } function input(key) { switch (key) { case curses.key.KEY_ESCAPE: case 'q': curses.endwin(); io.exit(0); return; break; case curses.key.KEY_UP: if (topLine > 0) { topLine--; showAt(topLine); } break; case curses.key.KEY_DOWN: if (topLine < bottomLine) { topLine++; showAt(topLine); } break; case curses.key.KEY_PPAGE: if (topLine > 0) { topLine -= rows-1; if (topLine < 0) topLine = 0; showAt(topLine); } break; case curses.key.KEY_NPAGE: if (topLine < bottomLine) { topLine += rows-1; if (topLine >= bottomLine) topLine = bottomLine; showAt(topLine); } break; case curses.key.KEY_HOME: topLine = 0; showAt(topLine); break; case curses.key.KEY_END: topLine = bottomLine; showAt(topLine); break; } curses.getch(input); } function main(argc,argv) { for (var i=1; i Options: -r Remove directories and their contents recusively -f Ignore nonexistant files and arguments -? Print this help information `); } function removeFile(path) { var st = stdio.lstat(path); if (!st) { if (force) return 0; stdio.fprintf(io.stderr,'no such file or directory: %s\n',path); return 1; } var fd = stdio.open(path,stdio.flags.O_RDONLY|stdio.flags.O_NOFOLLOW|stdio.flags.O_SYNC); if (!fd) { stdio.fprintf(io.stderr,'permission denied: %s\n',path); return 1; } if (st.type == stdio.types.FT_DIR) { if (!recurse) { var i = stdio.read(fd); if (i) { stdio.close(fd); stdio.fprintf(io.stderr,'cannot remove non-empty directory: %s\n',path); return 1; } }else{ var f; while ((f = stdio.read(fd)) != null) { if (removeFile(path+'/'+f)) { stdio.close(fd); return 1; } } } } stdio.close(fd); if (st.type == stdio.types.FT_DEV) { stdio.fprintf(io.stderr,'cannot remove device files: %s\n',path); return 1; } if (!stdio.remove(path)) { stdio.fprintf(io.stderr,'permission denied: %s\n',path); return 1; } return 0; } function main(argc,argv) { for (var i=1; i Options: -p Make the full path, not just the final directory -? Print this help information `); } function main(argc,argv) { var recurse = false; var short = null; var file = null; for (var i=1; i Options: -? Print this help information `); } function getModMask(str) { var parts = str.split(','); var modmask = ['???','???','???']; if (parts.length == 1 && (str.length == 3 || str.length == 4)) { var iv = parseInt(str,10); if (iv > 0) { if (str.length == 4) str = str.substring(1); for (var i=0; i Options: -? Print this help information `); } function main(argc,argv) { var short = ''; var file = null; for (var i=1; i Options: -n N the number of lines to print (default 10) -? Print this help information `); } function writeFile(fd) { if (!fd) { stdio.fprintf(io.stderr,'could not open file\n'); io.exit(1); return; } var l; for (var i=0; i Options: -n N the number of lines to print (default 10) -c N instead of lines, print the last N characters -? Print this help information `); } function writeFile(fd) { if (!fd) { stdio.fprintf(io.stderr,'could not open file\n'); io.exit(1); return; } var d = stdio.readAll(fd); if (chars > 0) { if (d.length < chars) { stdio.write(io.stdout,d); }else{ stdio.write(io.stdout,d.substring(d.length-chars)); } }else{ var ls = d.split('\n'); if (ls[ls.length-1] == '') ls.pop(); while (ls.length > lines) { ls.shift(); } ls.forEach(function(l) { stdio.printf('%s\n',l); }); } stdio.close(fd); io.exit(0); } function main(argc,argv) { var lnext = false; var cnext = false; var short = null; var file = null; for (var i=1; i [FILE...] Options: -? Print this help information `); } // this is a no op program, it always succeeds // it exists solely because posix says it should // but does nothing because there's nothing to strip from files // "The strip utility shall remove from strippable files named by // the file operands any information the implementor deems // unnecessary for execution of those files" - doing nothing is // compliant function main(argc,argv) { for (var i=1; i Options: -? Print this help information `); } function scb(r) { io.exit(0); } function main(argc,argv) { var seconds = 0; for (var i=1; i 0) return 0; return 1; } if (argc > 5) return 1; var uargs = Array.from(argv); uargs.shift(); if (argv[0] == '[' && uargs[uargs.length-1] == ']') uargs.pop(); if (uargs[0] == '!') { negate = true; uargs.shift(); } if (uargs.length > 2 && uargs[0] == '(' && uargs[uargs.length-1] == ')') { uargs.shift(); uargs.pop(); if (uargs[0] == '!') { negate = !negate; uargs.shift(); } } if (uargs.length == 1) { if (uargs[0].length > 0) { if (negate) return 1; return 0; } if (negate) return 0; return 1; } // -primary_operator primary_operand if (uargs.length == 2) { switch (uargs[0]) { case '-b': // test for a block file var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || (st.st_mode&stdio.modes.S_IFBLK) != stdio.modes.S_IFBLK) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-c': var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || st.type != stdio.types.FT_DEV) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-d': var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || st.type != stdio.types.FT_DIR) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-e': var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-f': var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || st.type == stdio.types.FT_DIR || st.type == stdio.types.FT_DEV || st.type == stdio.types.FT_LINK) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-g': // test for set-groud-id var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || (st.st_mode&stdio.modes.S_ISGID) != stdio.modes.S_ISGID) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-h': case '-L': var p = clite.resolvePath(uargs[1]); var st = stdio.lstat(p); if (!st || st.type != stdio.types.FT_LINK) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-n': if (uargs[1].length == 0) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-p': // test for FIFO/pipe var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || (st.st_mode&stdio.modes.S_IFIFO) != stdio.modes.S_IFIFO) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-r': var p = clite.resolvePath(uargs[1]); var fd = stdio.open(p,stdio.flags.O_RDONLY|stdio.flags.O_SYNC); if (!fd || !stdio.isreadable(fd)) { if (fd) stdio.close(fd); if (negate) return 0; return 1; } if (fd) stdio.close(fd); if (negate) return 1; return 0; break; case '-S': // test for socket var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || (st.st_mode&stdio.modes.S_IFSOCK) != stdio.modes.S_IFSOCK) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-s': var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || st.st_size == 0) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-t': if (uargs[1] == '0') { // stdin if (!stdio.isatty(io.stdin)) { if (negate) return 0; return 1; } if (negate) return 1; return 0; } if (uargs[1] == '1') { // stdout if (!stdio.isatty(io.stdin)) { if (negate) return 0; return 1; } if (negate) return 1; return 0; } if (uargs[1] == '2') { // stderr if (!stdio.isatty(io.stdin)) { if (negate) return 0; return 1; } if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-u': // test for set-user-id var p = clite.resolvePath(uargs[1]); var st = stdio.stat(p); if (!st || (st.st_mode&stdio.modes.S_ISUID) != stdio.modes.S_ISUID) { if (negate) return 0; return 1; } if (negate) return 1; return 0; break; case '-w': var p = clite.resolvePath(uargs[1]); var fd = stdio.open(p,stdio.flags.O_RDONLY|stdio.flags.O_SYNC); if (!fd || !stdio.iswritable(fd)) { if (fd) stdio.close(fd); if (negate) return 0; return 1; } if (fd) stdio.close(fd); if (negate) return 1; return 0; break; case '-x': var p = clite.resolvePath(uargs[1]); var fd = stdio.open(p,stdio.flags.O_RDONLY|stdio.flags.O_SYNC); if (!fd || !stdio.isexecutable(fd)) { if (fd) stdio.close(fd); if (negate) return 0; return 1; } if (fd) stdio.close(fd); if (negate) return 1; return 0; break; case '-z': if (uargs[1].length == 0) { if (negate) return 1; return 0; } if (negate) return 0; return 1; default: return 2; } } // primary_operand -primary_operator primary_operand // primary_operand primary_operator primary_operand if (uargs.length == 3) { switch (uargs[1]) { case '=': if (uargs[0] == uargs[2]) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '!=': if (uargs[0] != uargs[2]) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-eq': if (parseInt(uargs[0]) == parseInt(uargs[2])) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-ne': if (parseInt(uargs[0]) != parseInt(uargs[2])) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-gt': if (parseInt(uargs[0]) > parseInt(uargs[2])) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-ge': if (parseInt(uargs[0]) >= parseInt(uargs[2])) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-lt': if (parseInt(uargs[0]) < parseInt(uargs[2])) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; case '-le': if (parseInt(uargs[0]) <= parseInt(uargs[2])) { if (negate) return 1; return 0; } if (negate) return 0; return 1; break; default: return 3; } } return 1; } return main(args.length,args); }); clite.commands.load('load',function(args,env,io) { var stdio = io.include('stdio'); var clite = io.include('clite'); var short = null; var file = null; function help() { stdio.printf(` load - load a text file from the local device Usage: load [OPTION] Options: -? Print this help information `); } function fcb(data) { if (data == null) { stdio.write(io.stderr,'no file received\n'); io.exit(1); return; } if (typeof data !== 'string') { stdio.write(io.stderr,'not a normal file\n'); io.exit(1); return; } var fd = stdio.open(file,stdio.flags.O_WRONLY|stdio.flags.O_CREAT|stdio.flags.O_EXCL|stdio.flags.O_SYNC); if (!fd) { stdio.write(io.stderr,'could not create file: %s\n',file); io.exit(1); return; } if (!stdio.write(fd,data)) { stdio.close(fd); stdio.write(io.stderr,'could not write file: %s\n',file); io.exit(1); return; } stdio.close(fd); io.exit(0); } function main(argc,argv) { for (var i=1; i[:GROUP] Options: -? Print this help information `); } function recurseDir(path) { let fd = stdio.open(path,stdio.flags.O_SEARCH|stdio.flags.O_DIRECTORY|stdio.flags.O_SYNC); if (!fd) { stdio.fprintf(io.stderr,'could not recurse into directory: %s\n',path); return; } let e = null; while ((e = stdio.read(fd)) != null) { let p = path+'/'+e; let r = stdio.chown(p,uid,gid); if (!r) stdio.fprintf(io.stderr,'could not change ownership of file: %s\n',path); } stdio.close(fd); } function main(argc,argv) { let files = []; let recurse = false; for (var i=1; i 1) { if (ug.length > 2) { stdio.write(io.stderr,'no valid user specified\n'); return 1; } user = ug[0]; group = ug[1]; if (user == '') user = null; if (group == '') group = null; } if (user) { let pw = stdlib.getpwnam(user); if (!pw) { stdio.write(io.stderr,'invalid user specified\n'); return 1; } uid = pw.pw_uid; } if (group) { let gr = stdlib.getgrnam(group); if (!gr) { stdio.write(io.stderr,'invalid group specified\n'); return 1; } gid = gr.gr_gid; } if (uid < 0 && gid < 0) { stdio.write(io.stderr,'no valid user or group specified\n'); return 1; } for (var i=0; i