mirror of
https://codeberg.org/TicklishHoneyBee/CLIte.git
synced 2026-03-11 09:04:37 +00:00
2367 lines
48 KiB
JavaScript
2367 lines
48 KiB
JavaScript
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'l':
|
|
long = true;
|
|
break;
|
|
case 'u':
|
|
access = true;
|
|
break;
|
|
case 'a':
|
|
all = true;
|
|
break;
|
|
case '1':
|
|
one = true;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
dirs.push(clite.resolvePath(argv[i],false));
|
|
}
|
|
}
|
|
|
|
if (dirs.length < 1)
|
|
dirs.push(env.PWD);
|
|
|
|
dirs.forEach(function(dir,index) {
|
|
if (dirs.length > 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> [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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'd':
|
|
download = true;
|
|
break;
|
|
case 'l':
|
|
remote = false;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
files.push(clite.resolvePath(argv[i],false));
|
|
}
|
|
}
|
|
|
|
if (files.length < 1)
|
|
return 1;
|
|
pending = files.length;
|
|
|
|
// check if we're on a webserver
|
|
if (!remote) {
|
|
var u = stdlib.uname();
|
|
if (u && u.nodename != 'localhost')
|
|
remote = true;
|
|
}
|
|
|
|
files.forEach(function(file,index) {
|
|
var st = stdio.stat(file);
|
|
// 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
|
|
) {
|
|
stdio.fprintf(io.stderr,'not a normal file: %s\n',file);
|
|
pending--;
|
|
return;
|
|
}
|
|
if (!remote && st.type == stdio.types.FT_REMOTE) {
|
|
pending--;
|
|
return;
|
|
}
|
|
var fd = stdio.open(file,stdio.flags.O_RDONLY,fcb);
|
|
if (!fd) {
|
|
stdio.fprintf(io.stderr,'cannot open file: %s\n',file);
|
|
pending--;
|
|
return;
|
|
}
|
|
});
|
|
|
|
if (pending <1)
|
|
return 0;
|
|
return null;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('touch',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
touch - create a new empty file
|
|
Usage: touch [OPTION] <FILE>
|
|
|
|
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
file = clite.resolvePath(argv[i],false);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
if (!stdio.creat(file)) {
|
|
var fd = stdio.open(file,stdio.flags.O_RDONLY,loadRemote);
|
|
return null;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('less',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
var term = io.include('term');
|
|
var curses = io.include('curses');
|
|
var clite = io.include('clite');
|
|
|
|
var file = null;
|
|
var cols;
|
|
var rows;
|
|
var lines = [];
|
|
var topLine = 0;
|
|
var bottomLine = 0;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
less - text file viewer
|
|
Usage: less [OPTION] <FILE>
|
|
|
|
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<end; i++) {
|
|
curses.printw("%s\n",lines[i]);
|
|
}
|
|
}
|
|
|
|
function prepFile(fd) {
|
|
if (!fd) {
|
|
stdio.fprintf(io.stderr,'could not open file: %s\n',file);
|
|
io.exit(1);
|
|
return;
|
|
}
|
|
var st = stdio.fstatat(fd,0);
|
|
if ( !st || (st.type != stdio.types.FT_TEXT && st.type != stdio.types.FT_SCRIPT)) {
|
|
stdio.write(io.stderr,'can not read files of this type\n');
|
|
io.exit(1);
|
|
return;
|
|
}
|
|
var txt = stdio.readAll(fd);
|
|
stdio.close(fd);
|
|
|
|
var parts = txt.split('\n');
|
|
parts.forEach(function(line) {
|
|
if (line.length >= 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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
file = clite.resolvePath(argv[i],false);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
let fd = null;
|
|
|
|
if (file == null) {
|
|
if (stdio.isatty(io.stdin)) {
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
fd = io.stdin;
|
|
io.stdin = stdio.open('/dev/tty',stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
|
|
stdlib.sleep(2,function() {
|
|
prepFile(fd);
|
|
});
|
|
}else{
|
|
fd = stdio.open(file,stdio.flags.O_RDONLY,prepFile);
|
|
if (!fd) {
|
|
stdio.fprintf(io.stderr,'could not open file: %s\n',file);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
curses.initscr();
|
|
cols = curses.getmaxx();
|
|
rows = curses.getmaxy();
|
|
curses.cbreak();
|
|
curses.noecho();
|
|
curses.printw('Loading...');
|
|
|
|
curses.getch(input);
|
|
|
|
return null;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('rm',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
var recurse = false;
|
|
var force = false;
|
|
var short = null;
|
|
var file = null;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
rm - remove files or directories
|
|
Usage: rm [OPTION] <FILE>
|
|
|
|
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case 'r':
|
|
recurse = true;
|
|
break;
|
|
case 'f':
|
|
force = true;
|
|
break;
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
short = argv[i];
|
|
file = clite.resolvePath(argv[i],false);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.fprintf(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
return removeFile(file);
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('mkdir',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var stdlib = io.include('stdlib');
|
|
var clite = io.include('clite');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
mkdir - remove files or directories
|
|
Usage: mkdir [OPTION] <DIRECTORY>
|
|
|
|
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case 'p':
|
|
recurse = true;
|
|
break;
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
short = argv[i];
|
|
file = clite.resolvePath(argv[i]);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.fprintf(io.stderr,'no path specified\n');
|
|
return 1;
|
|
}
|
|
|
|
var st = stdio.lstat(file);
|
|
if (st) {
|
|
stdio.fprintf(io.stderr,'already exists: %s\n',short);
|
|
return 1;
|
|
}
|
|
|
|
if (!stdio.mkdir(file)) {
|
|
if (!recurse) {
|
|
stdio.fprintf(io.stderr,'persmission denied: %s\n',short);
|
|
return 1;
|
|
}
|
|
|
|
var parts = file.split('/');
|
|
var path = '';
|
|
for (var i=0; i<parts.length; i++) {
|
|
path += '/'+parts[i];
|
|
st = stdio.stat(path);
|
|
if (st) {
|
|
if (st.type != stdio.types.FT_DIR) {
|
|
stdio.fprintf(io.stderr,'permission denied: %s\n',path);
|
|
return 1;
|
|
}
|
|
continue;
|
|
}
|
|
if (!stdio.mkdir(path)) {
|
|
stdio.fprintf(io.stderr,'permission denied: %s\n',path);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('chmod',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
var recurse = false;
|
|
var modmask = null;
|
|
var short = '';
|
|
var file = null;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
chmod - change file mode bits
|
|
Usage: chmod [OPTION] <MODE> <FILE>
|
|
|
|
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<str.length; i++) {
|
|
switch(str[i]) {
|
|
case '0':
|
|
modmask[i] = '---';
|
|
break;
|
|
case '1':
|
|
modmask[i] = '--x';
|
|
break;
|
|
case '2':
|
|
modmask[i] = '-w-';
|
|
break;
|
|
case '3':
|
|
modmask[i] = '-wx';
|
|
break;
|
|
case '4':
|
|
modmask[i] = 'r--';
|
|
break;
|
|
case '5':
|
|
modmask[i] = 'r-x';
|
|
break;
|
|
case '6':
|
|
modmask[i] = 'rw-';
|
|
break;
|
|
case '7':
|
|
modmask[i] = 'rwx';
|
|
break;
|
|
}
|
|
}
|
|
return modmask.join('');
|
|
}
|
|
}
|
|
parts.forEach(function(p) { // [who]op[perm]
|
|
var u = false;
|
|
var g = false;
|
|
var o = false;
|
|
var op = null;
|
|
var s = 0;
|
|
for (var i=0; i<p.length; i++) {
|
|
if (s == 0) {
|
|
switch (p[i]) {
|
|
case 'u':
|
|
u = true;
|
|
break;
|
|
case 'g':
|
|
g = true;
|
|
break;
|
|
case 'o':
|
|
o = true;
|
|
break;
|
|
case 'a':
|
|
u = true;
|
|
g = true;
|
|
o = true;
|
|
break;
|
|
case '=':
|
|
case '+':
|
|
case '-':
|
|
op = p[i];
|
|
s = 1;
|
|
if (!u && !g && !o) {
|
|
u = true;
|
|
g = true;
|
|
o = true;
|
|
}
|
|
if (op == '=') {
|
|
if (u)
|
|
modmask[0] = '---';
|
|
if (g)
|
|
modmask[1] = '---';
|
|
if (o)
|
|
modmask[2] = '---';
|
|
}
|
|
break;
|
|
}
|
|
}else if (s == 1) {
|
|
switch (p[i]) {
|
|
case 'r':
|
|
if (u) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[0] = 'r'+modmask[0][1]+modmask[0][2];
|
|
}else if (op = '-') {
|
|
modmask[0] = '-'+modmask[0][1]+modmask[0][2];
|
|
}
|
|
}
|
|
if (g) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[1] = 'r'+modmask[1][1]+modmask[1][2];
|
|
}else if (op = '-') {
|
|
modmask[1] = '-'+modmask[1][1]+modmask[1][2];
|
|
}
|
|
}
|
|
if (o) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[2] = 'r'+modmask[2][1]+modmask[2][2];
|
|
}else if (op = '-') {
|
|
modmask[2] = '-'+modmask[2][1]+modmask[2][2];
|
|
}
|
|
}
|
|
break;
|
|
case 'w':
|
|
if (u) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[0] = modmask[0][0]+'w'+modmask[0][2];
|
|
}else if (op = '-') {
|
|
modmask[0] = modmask[0][0]+'-'+modmask[0][2];
|
|
}
|
|
}
|
|
if (g) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[1] = modmask[1][0]+'w'+modmask[1][2];
|
|
}else if (op = '-') {
|
|
modmask[1] = modmask[1][0]+'-'+modmask[1][2];
|
|
}
|
|
}
|
|
if (o) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[2] = modmask[2][0]+'w'+modmask[2][2];
|
|
}else if (op = '-') {
|
|
modmask[2] = modmask[2][0]+'-'+modmask[2][2];
|
|
}
|
|
}
|
|
break;
|
|
case 'x':
|
|
if (u) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[0] = modmask[0][0]+modmask[0][1]+'x';
|
|
}else if (op = '-') {
|
|
modmask[0] = modmask[0][1]+modmask[0][1]+'-';
|
|
}
|
|
}
|
|
if (g) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[1] = modmask[1][0]+modmask[1][1]+'x';
|
|
}else if (op = '-') {
|
|
modmask[1] = modmask[1][0]+modmask[1][1]+'-';
|
|
}
|
|
}
|
|
if (o) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[2] = modmask[2][0]+modmask[2][1]+'x';
|
|
}else if (op = '-') {
|
|
modmask[2] = modmask[2][0]+modmask[2][1]+'-';
|
|
}
|
|
}
|
|
break;
|
|
case 'X':
|
|
if (u) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[0] = modmask[0][0]+modmask[0][1]+'X';
|
|
}else if (op = '-') {
|
|
modmask[0] = modmask[0][1]+modmask[0][1]+'Y';
|
|
}
|
|
}
|
|
if (g) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[1] = modmask[1][0]+modmask[1][1]+'X';
|
|
}else if (op = '-') {
|
|
modmask[1] = modmask[1][0]+modmask[1][1]+'Y';
|
|
}
|
|
}
|
|
if (o) {
|
|
if (op == '=' || op == '+') {
|
|
modmask[2] = modmask[2][0]+modmask[2][1]+'X';
|
|
}else if (op = '-') {
|
|
modmask[2] = modmask[2][0]+modmask[2][1]+'Y';
|
|
}
|
|
}
|
|
break;
|
|
case 'u':
|
|
if (g)
|
|
modmask[1] = modmask[0];
|
|
if (o)
|
|
modmask[2] = modmask[0];
|
|
s = 0;
|
|
break;
|
|
case 'g':
|
|
if (u)
|
|
modmask[0] = modmask[1];
|
|
if (o)
|
|
modmask[2] = modmask[1];
|
|
s = 0;
|
|
break;
|
|
case 'o':
|
|
if (u)
|
|
modmask[0] = modmask[2];
|
|
if (g)
|
|
modmask[1] = modmask[2];
|
|
s = 0;
|
|
break;
|
|
}
|
|
}else{ // ?
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
|
|
return modmask.join('');
|
|
}
|
|
|
|
function getMode(mode,isdir) {
|
|
if (modmask[0] == 'r') {
|
|
mode |= stdio.modes.S_IRUSR;
|
|
}else if (modmask[0] == '-') {
|
|
mode &= ~stdio.modes.S_IRUSR;
|
|
}
|
|
if (modmask[1] == 'w') {
|
|
mode |= stdio.modes.S_IWUSR;
|
|
}else if (modmask[1] == '-') {
|
|
mode &= ~stdio.modes.S_IWUSR;
|
|
}
|
|
if (modmask[2] == 'x' || (isdir && modmask[2] == 'X')) {
|
|
mode |= stdio.modes.S_IXUSR;
|
|
mode &= ~stdio.modes.S_ISUID;
|
|
}else if (modmask[2] == 's') {
|
|
mode |= stdio.modes.S_IXUSR;
|
|
mode |= stdio.modes.S_ISUID;
|
|
}else if (modmask[2] == 'S') {
|
|
mode &= ~stdio.modes.S_IXUSR;
|
|
mode |= stdio.modes.S_ISUID;
|
|
}else if (modmask[2] == '-' || (isdir && modmask[2] == 'Y')) {
|
|
mode &= ~stdio.modes.S_IXUSR;
|
|
mode &= ~stdio.modes.S_ISUID;
|
|
}
|
|
|
|
if (modmask[3] == 'r') {
|
|
mode |= stdio.modes.S_IRGRP;
|
|
}else if (modmask[3] == '-') {
|
|
mode &= ~stdio.modes.S_IRGRP;
|
|
}
|
|
if (modmask[4] == 'w') {
|
|
mode |= stdio.modes.S_IWGRP;
|
|
}else if (modmask[4] == '-') {
|
|
mode &= ~stdio.modes.S_IWGRP;
|
|
}
|
|
if (modmask[5] == 'x' || (isdir && modmask[5] == 'X')) {
|
|
mode |= stdio.modes.S_IXGRP;
|
|
mode &= ~stdio.modes.S_ISGID;
|
|
}else if (modmask[5] == 's') {
|
|
mode |= stdio.modes.S_IXGRP;
|
|
mode |= stdio.modes.S_ISGID;
|
|
}else if (modmask[5] == 'S') {
|
|
mode &= ~stdio.modes.S_IXGRP;
|
|
mode |= stdio.modes.S_ISGID;
|
|
}else if (modmask[5] == '-' || (isdir && modmask[5] == 'Y')) {
|
|
mode &= ~stdio.modes.S_IXGRP;
|
|
mode &= ~stdio.modes.S_ISGID;
|
|
}
|
|
|
|
if (modmask[6] == 'r') {
|
|
mode |= stdio.modes.S_IROTH;
|
|
}else if (modmask[6] == '-') {
|
|
mode &= ~stdio.modes.S_IROTH;
|
|
}
|
|
if (modmask[7] == 'w') {
|
|
mode |= stdio.modes.S_IWOTH;
|
|
}else if (modmask[7] == '-') {
|
|
mode &= ~stdio.modes.S_IWOTH;
|
|
}
|
|
if (!isdir) {
|
|
if (modmask[8] == 'x') {
|
|
mode |= stdio.modes.S_IXOTH;
|
|
}else if (modmask[8] == '-') {
|
|
mode &= ~stdio.modes.S_IXOTH;
|
|
}
|
|
}else{
|
|
if (modmask[8] == 'x' || modmask[8] == 'X') {
|
|
mode |= stdio.modes.S_IXOTH;
|
|
mode &= ~stdio.modes.S_ISVTX;
|
|
}else if (modmask[8] == 't') {
|
|
mode |= stdio.modes.S_IXOTH;
|
|
mode |= stdio.modes.S_ISVTX;
|
|
}else if (modmask[8] == 'T') {
|
|
mode &= ~stdio.modes.S_IXOTH;
|
|
mode |= stdio.modes.S_ISVTX;
|
|
}else if (modmask[8] == '-' || modmask[8] == 'Y') {
|
|
mode &= ~stdio.modes.S_IXOTH;
|
|
mode &= ~stdio.modes.S_ISVTX;
|
|
}
|
|
}
|
|
|
|
return mode;
|
|
}
|
|
|
|
function getPerms(str,isdir) {
|
|
var n = str.substring(1);
|
|
for (var i=0; i<9; i++) {
|
|
if (modmask[i] == '?')
|
|
continue;
|
|
if (modmask[i] == n[i])
|
|
continue;
|
|
if (modmask[i] == 'X') {
|
|
if (isdir)
|
|
n = n.substring(0,i)+'x'+n.substring(i+1);
|
|
}else if (modmask[i] == 'Y') {
|
|
if (isdir)
|
|
n = n.substring(0,i)+'-'+n.substring(i+1);
|
|
}else{
|
|
n = n.substring(0,i)+modmask[i]+n.substring(i+1);
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
if (argc == 3) { // name mode file
|
|
modmask = getModMask(argv[1]);
|
|
short = argv[2];
|
|
file = clite.resolvePath(short);
|
|
}else if (argc == 4) { // name option mode file
|
|
if (argv[1][0] != '-') {
|
|
stdio.write(io.stderr,'invalid arguments\n');
|
|
return 1;
|
|
}
|
|
for (var j=1; j<argv[1].length; j++) {
|
|
switch (argv[1][j]) {
|
|
case 'R':
|
|
recurse = true;
|
|
break;
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
modmask = getModMask(argv[2]);
|
|
short = argv[3];
|
|
file = clite.resolvePath(short);
|
|
}else if (argc == 2 && argv[1] == '-?') {
|
|
help();
|
|
return 0;
|
|
}else{
|
|
stdio.write(io.stderr,'invalid arguments\n');
|
|
return 1;
|
|
}
|
|
|
|
if (modmask == null || modmask == '?????????') {
|
|
stdio.write(io.stderr,'invalid mode\n');
|
|
return 1;
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
var st = stdio.lstat(file);
|
|
if (!st) {
|
|
stdio.fprintf(io.stderr,'cannot open file: %s\n',short);
|
|
return 1;
|
|
}
|
|
|
|
var mode = getMode(st.st_mode,(st.type == stdio.types.FT_DIR));
|
|
|
|
if (!stdio.chmod(file,mode)) {
|
|
stdio.fprintf(io.stderr,'cannot write file: %s\n',short);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('file',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
file - determine the file type
|
|
Usage: file [OPTION] <FILE>
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
var short = '';
|
|
var file = null;
|
|
|
|
for (var i=1; i<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
short = argv[i];
|
|
file = clite.resolvePath(argv[i],false);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
var st = stdio.lstat(file);
|
|
|
|
var txt = short+': ';
|
|
if (!st) {
|
|
stdio.fprintf(io.stderr,'cannot open file: %s\n',file);
|
|
return 1;
|
|
}else{
|
|
switch (st.type) {
|
|
case stdio.types.FT_TEXT:
|
|
txt += 'Plain Text';
|
|
break;
|
|
case stdio.types.FT_BINARY:
|
|
txt += 'CLIte Executable';
|
|
break;
|
|
case stdio.types.FT_DIR:
|
|
txt += 'Directory';
|
|
break;
|
|
case stdio.types.FT_LINK:
|
|
txt += 'Link';
|
|
break;
|
|
case stdio.types.FT_DEV:
|
|
txt += 'Device File';
|
|
break;
|
|
case stdio.types.FT_REMOTE:
|
|
txt += 'Unloaded Remote Data';
|
|
break;
|
|
case stdio.types.FT_SCRIPT:
|
|
txt += 'Shell Script';
|
|
break;
|
|
case stdio.types.FT_IMAGE:
|
|
txt += 'Image';
|
|
break;
|
|
case stdio.types.FT_LIBRARY:
|
|
txt += 'Shared Object';
|
|
break;
|
|
default:
|
|
txt += 'Unknown Data';
|
|
break;
|
|
}
|
|
}
|
|
|
|
stdio.printf('%s\n',txt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('reboot',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
reboot - reboot the system, forcing reload of all code
|
|
Usage: reboot [OPTION]
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
for (var i=1; i<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
var fd = stdio.open('/dev/initctl',stdio.flags.O_WRONLY|stdio.flags.O_SYNC);
|
|
if (!fd)
|
|
return 1;
|
|
stdio.write(fd,'6'); // switch to runlevel 6, reboot
|
|
stdio.close(fd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('uname',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var stdlib = io.include('stdlib');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
uname - print system information
|
|
Usage: uname [OPTION]
|
|
|
|
Options:
|
|
-a All, equivalent to -mnrsv
|
|
-m Print the hardware info (User Agent)
|
|
-n Print the network name
|
|
-r Print the operating system release
|
|
-s Print the operating system name
|
|
-v Print the operating system version
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
var sysname = false;
|
|
var nodename = false;
|
|
var release = false;
|
|
var version = false;
|
|
var machine = false;
|
|
for (var i=1; i<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'a':
|
|
machine = true;
|
|
nodename = true;
|
|
release = true;
|
|
sysname = true;
|
|
version = true;
|
|
break;
|
|
case 'm':
|
|
machine = true;
|
|
break;
|
|
case 'n':
|
|
nodename = true;
|
|
break;
|
|
case 'r':
|
|
release = true;
|
|
break;
|
|
case 's':
|
|
sysname = true;
|
|
break;
|
|
case 'v':
|
|
version = true;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (!machine && !nodename && !release && !sysname && !version)
|
|
sysname = true;
|
|
|
|
var ut = stdlib.uname();
|
|
|
|
var txt = '';
|
|
if (sysname)
|
|
txt += ut.sysname+' ';
|
|
if (nodename)
|
|
txt += ut.nodename+' ';
|
|
if (release)
|
|
txt += ut.release+' ';
|
|
if (version)
|
|
txt += ut.version+' ';
|
|
if (machine)
|
|
txt += ut.machine;
|
|
|
|
stdio.printf('%s\n',txt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('date',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var time = io.include('time');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
date - print system time and date
|
|
Usage: date [OPTION] [FORMAT]
|
|
|
|
Options:
|
|
-u use UTC instead of local time
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
//tm_sec:0, // seconds (0-60)
|
|
//tm_min:0, // minutes (0-59)
|
|
//tm_hour:0, // hour (0-23)
|
|
//tm_mday:0, // day of month (0-31)
|
|
//tm_mon:0, // month of year (0-11)
|
|
//tm_year:0, // years since 1900
|
|
//tm_wday:0, // day of week (0-6, sunday = 0)
|
|
//tm_yday:0, // day of year (0-365)
|
|
//tm_isdst:0 // 1 if daylight savings
|
|
|
|
function main(argc,argv) {
|
|
var utc = false;
|
|
var format = '%a %d %b %Y %T %Z';
|
|
for (var i=1; i<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'u':
|
|
utc = true;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (argv[i][0] == '+') {
|
|
format = argv[i].substring(1);
|
|
}else{
|
|
// TODO: set time
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
var t = time.time();
|
|
var tm = null;
|
|
if (utc) {
|
|
tm = time.gmtime(t);
|
|
}else{
|
|
tm = time.localtime(t);
|
|
}
|
|
|
|
if (!t)
|
|
return 1;
|
|
|
|
var out = time.strftime(format,tm);
|
|
if (!out)
|
|
return 1;
|
|
|
|
stdio.printf('%s\n',out);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('head',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
var lines = 10;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
head - copy the first part of files
|
|
Usage: head [OPTION] <FILE>
|
|
|
|
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<lines && (l = stdio.readLine(fd)) != null; i++) {
|
|
stdio.printf('%s\n',l);
|
|
}
|
|
|
|
stdio.close(fd);
|
|
io.exit(0);
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
var lnext = false;
|
|
var short = null;
|
|
var file = null;
|
|
for (var i=1; i<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'n':
|
|
lnext = true;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (lnext) {
|
|
lines = parseInt(argv[i]);
|
|
if (lines < 1) {
|
|
stdio.fprintf(io.stderr,'invalid lines count "%d"\n',lines);
|
|
return 1;
|
|
}
|
|
lnext = false;
|
|
}else if (file == null) {
|
|
short = argv[i];
|
|
file = clite.resolvePath(argv[i]);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
if (!stdio.isatty(io.stdin)) {
|
|
writeFile(io.stdin);
|
|
return null;
|
|
}
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
var fd = stdio.open(file,stdio.flags.O_RDONLY,writeFile);
|
|
if (!fd) {
|
|
stdio.fprintf(io.stderr,'could not open file: %s\n',short);
|
|
return 1;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('tail',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
var lines = 10;
|
|
var chars = 0;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
tail - copy the last part of a file
|
|
Usage: tail [OPTION] <FILE>
|
|
|
|
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'c':
|
|
cnext = true;
|
|
break;
|
|
case 'n':
|
|
lnext = true;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (lnext) {
|
|
lines = parseInt(argv[i]);
|
|
if (lines < 1) {
|
|
stdio.fprintf(io.stderr,'invalid lines count "%d"\n',lines);
|
|
return 1;
|
|
}
|
|
lnext = false;
|
|
}else if (cnext) {
|
|
chars = parseInt(argv[i]);
|
|
if (chars < 1) {
|
|
stdio.fprintf(io.stderr,'invalid characters count "%d"\n',chars);
|
|
return 1;
|
|
}
|
|
cnext = false;
|
|
}else if (file == null) {
|
|
short = argv[i];
|
|
file = clite.resolvePath(argv[i]);
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
if (!stdio.isatty(io.stdin)) {
|
|
writeFile(io.stdin);
|
|
return null;
|
|
}
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
var fd = stdio.open(file,stdio.flags.O_RDONLY,writeFile);
|
|
if (!fd) {
|
|
stdio.fprintf(io.stderr,'could not open file: %s\n',short);
|
|
return 1;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('strip',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
strip - remove unnecessary data from strippable files
|
|
Usage: strip [OPTION] <FILE> [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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
stdio.fprintf(io.stderr,'unknown argument: %s\n',argv[i]);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('sleep',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var stdlib = io.include('stdlib');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
sleep - suspend execution for a time
|
|
Usage: sleep [OPTION] <SECONDS>
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
function scb(r) {
|
|
io.exit(0);
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
var seconds = 0;
|
|
for (var i=1; i<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
seconds = parseInt(argv[i]);
|
|
}
|
|
}
|
|
if (seconds < 1)
|
|
return 0;
|
|
|
|
if (!stdlib.sleep(seconds,scb))
|
|
return 1;
|
|
return null;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('test',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
test - evalutate expression
|
|
Usage: test [OPTION] [EXPRESSION]
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
function main(argc,argv) {
|
|
var negate = false;
|
|
if (argc == 1)
|
|
return 1;
|
|
if (argc == 2) {
|
|
if (argv[1] == '-?') {
|
|
help();
|
|
return 0;
|
|
}
|
|
if (argv[1].length > 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] <FILE>
|
|
|
|
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
short = argv[i];
|
|
file = clite.resolvePath(short);
|
|
}
|
|
}
|
|
|
|
if (!file) {
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
var fd = stdio.open('/dev/local',stdio.flags.O_RDWR|stdio.flags.O_SYNC);
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'could not open local device for reading\n');
|
|
return 1;
|
|
}
|
|
|
|
if (!stdio.read(fd,fcb)) {
|
|
stdio.close(fd);
|
|
stdio.write(io.stderr,'could not read from local device\n');
|
|
return 1;
|
|
}
|
|
|
|
stdio.close(fd);
|
|
|
|
return null;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
clite.commands.load('chown',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
var clite = io.include('clite');
|
|
|
|
let user = null;
|
|
let group = null;
|
|
|
|
let uid = -1;
|
|
let gid = -1;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
chown - change the owner of files
|
|
Usage: chown [OPTION] <USER>[:GROUP] <FILE>
|
|
|
|
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<argc; i++) {
|
|
if (argv[i][0] == '-') {
|
|
for (var j=1; j<argv[i].length; j++) {
|
|
switch (argv[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'R':
|
|
recurse = true;
|
|
break;
|
|
default:
|
|
stdio.fprintf(io.stderr,'unknown argument: -%c\n',argv[i][j]);
|
|
}
|
|
}
|
|
}else if (user == null) {
|
|
user = argv[i];
|
|
}else{
|
|
files.push(argv[i]);
|
|
}
|
|
}
|
|
|
|
if (files.length < 1) {
|
|
stdio.write(io.stderr,'no file specified\n');
|
|
return 1;
|
|
}
|
|
|
|
if (!user) {
|
|
stdio.write(io.stderr,'no user specified\n');
|
|
return 1;
|
|
}
|
|
|
|
let ug = user.split(':');
|
|
if (ug.length > 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<files.length; i++) {
|
|
let p = clite.resolvePath(files[i]);
|
|
let r = stdio.chown(p,uid,gid);
|
|
if (!r) {
|
|
stdio.fprintf(io.stderr,'could not change ownership of file: %s\n',p);
|
|
continue;
|
|
}
|
|
if (!recurse)
|
|
continue;
|
|
let st = stdio.stat(p);
|
|
if (st && st.type == stdio.types.FT_DIR)
|
|
recurseDir(p);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return main(args.length,args);
|
|
});
|
|
|
|
if (window.location.protocol == 'file:')
|
|
clite.commands.load('exp',`
|
|
var stdio = io.include('stdio');
|
|
|
|
function main(argc,argv) {
|
|
stdio.printf('hello world\\n');
|
|
return 0;
|
|
}
|
|
`);
|
|
|
|
// insert commands above this line
|
|
}
|