diff --git a/clite/core.js b/clite/core.js index 5e77254..2da0da1 100644 --- a/clite/core.js +++ b/clite/core.js @@ -1,6 +1,6 @@ var clite = { state:{ - version:'0.2-2', + version:'0.2-3', isinit:false }, core:{ @@ -1318,6 +1318,7 @@ clite.vfs = { vfsdata.api.mkDir('/usr/clite/web'); vfsdata.api.mkDir('/usr/home'); vfsdata.api.mkDir('/usr/share'); + vfsdata.api.mkDir('/usr/share/docs'); vfsdata.api.mkDir('/usr/share/site'); vfsdata.api.mkDir('/usr/src'); vfsdata.api.mkDir('/usr/src/libs'); diff --git a/data/filesys.txt b/data/filesys.txt index e0fe6ef..2736475 100644 --- a/data/filesys.txt +++ b/data/filesys.txt @@ -14,4 +14,7 @@ clite/core.css:/usr/clite/web/core.css:0:0:-rw-r----- data/intro.txt:/usr/share/introduction:0:0:-rw-rw-r-- data/about.txt:/usr/share/site/about:0:0:-rw-rw-r-- data/lipsum.txt:/usr/share/site/lipsum:0:0:-rw-rw-r-- -readme.txt:/usr/clite/readme.txt:0:0:-rw-r--r-- +readme.txt:/usr/share/docs/readme.txt:0:0:-rw-r--r-- +readme-libs.txt:/usr/share/docs/readme-libs.txt:0:0:-rw-r--r-- +readme-programs.txt:/usr/share/docs/readme-programs.txt:0:0:-rw-r--r-- +readme-internals.txt:/usr/share/docs/readme-internals.txt:0:0:-rw-r--r-- diff --git a/readme-internals.txt b/readme-internals.txt new file mode 100644 index 0000000..8dcdec4 --- /dev/null +++ b/readme-internals.txt @@ -0,0 +1,103 @@ +CLIte Internals: + +CLite's aim is not just to create a functional unix-like terminal in a + web page, but also to have that built on top of a unix-like operating + system written in javascript and which runs in a web page. + +CLIte follows the common programming methodology of creating in three + steps: + + First, make it work. + Second, make it work right. + Third, make it work well. + +This means that some areas are still very much a work in progress, but + are gradually being improved. + +At its core, CLIte is made up of the follow parts: + +The Core: + Effectively CLIte's 'kernel', this consists of functions needed to do + basic tasks, such as loading files, loading scripts, safely running + code, downloading files, rebooting the system, and system initialisation. + Most of this is either abstracted away to higher level functions, or + otherwise need never be used by user-level programs. + +The Terminal: + The terminal handles user input, and displays program output. Most of + which is abstracted away to standard io calls on /dev/tty, and even + further abstracted to standard io calls on the standard input, output, + and error filedescriptors that every program has. Additionally the + term library offers some advanced functionality which is subject to + change. + +The VFS: (Virtual File Sytem) + CLIte's virtual file system bares no relation to the file system of the + server it is run on (thus /etc/passwd is not the server's /etc/passwd + file!). + During system initialisation, the root filesystem is mounted by creating + the VFS, with physical server-side files then mapped into the VFS using + a plain-text config file which is stored in /dev/wfs (web file system, + for lack of a better name). The content of files are then loaded in as + needed when the VFS file is accessed. + However other files in the VFS are created dynamically as needed during + system initialisation. For instance, commands are loaded in directly + from javascript functions, which creates both the executable file in + /bin/ as well as the source file in /usr/src/.js. Thus two + VFS files are created from each command, with many commands being held + in a single server-side file. Libraries are loaded in similarly, to + both /lib/.so and /usr/src/libs/.js + Additionally, configuration files in /etc, and various default devices + in /dev are also created programatically. As is the system log file + in /var/logs. + Most VFS functions are abstracted away to stdio functions. + +The Process Manager: + CLIte's process manager keeps track of running programs as processes and + process groups, in a typical unix-like manner. It also wraps each + process in its own try/catch block to ensure errors are handled + correctly, and that failed processes aren't left 'hanging'. + It also manages callbacks for functions such as wait() so that processes + can monitor and act upon each other as needed. + +The User Manager: + The user manager controls the user logins, and dynamically generates a + guest session as needed. + +The Logger: + The Logger manages the system logs, printing them to the terminal during + system initialisation and shutdown, as well as writing them to the + system log at /var/logs + +The Lifecycle of a Process: + + 1. fork() is called with the environment and io data passed to it. + This adds a new process to the process manager, which assigns it + a process id (pid) and also creates a file in /proc/ for + storing data about the process. + Both the environment and io data are then cloned, and the new + process is called asynchronously, forking it from the current + process. + The process id of the new process is returned to the parent. + 2. exec() is called, again the environment and io data is passed to it, + along with the file path and arguments for a new program. + This checks the file both exists and is executable by the current + user. + Then updated details of the program are sent to the process manager. + The current program is then overwritten with a call to the new + program. + 3. The program then runs as intended, and exits normally, or fails and + is caught by a try/catch which exits the program. + 4. exit() is called with an integer 'exit state': + zero for no error. + less than zero for internal error + greater than zero for the program's own use + This ends the program, and notifies the process manager that the + process has exit. + The process manager will then remove the process from the process + list, delete the process' data file in /proc/, then handle + any wait() calls that have been queued for the process exit. + + Typically, this is when the shell's waitpid() on the process causes the + shell to once again show a prompt, awaiting the user's next command + input. diff --git a/readme-libs.txt b/readme-libs.txt new file mode 100644 index 0000000..b43ffa4 --- /dev/null +++ b/readme-libs.txt @@ -0,0 +1,323 @@ +CLIte libraries: + +System libraries may be loaded into a program for use of their API using the + io.include() function: + +var stdio = io.include('stdio'); + + This returns a reference to the library which can be stored in a variable as + seen above. Calls to library functions can then be made using that reference: + +stdio.open('/path/to/file'); + + There is no need to name the variable the same as the library name, however + this is considered good practice. + A library's 'header' name, as used in include() is not the same as its + file name /lib/lib*.so. For instance for the standard io library, you + would include 'stdio' but the filename is libio.so + +The libraries, and their API functions are listed below: + +stdlib (libstd.so): io.include('stdlib') + Provides a growing standard unix-like library. + + basename('path') + returns the base name of a file path: + '/usr/home/guest/file.txt' -> 'file.txt' + + dirname('path') + returns the directory name of a file path: + '/usr/home/guest/file.txt' -> '/usr/home/guest' + + uname() + returns an object containing system information: + { + sysname:'CLIte', // system name, always 'CLIte' + nodename:'localhost', // network hostname + release:'0.1...', // contains the current CLIte version as stored in clite.state.version + version:'0.1...', // same as release + machine:navigator.userAgent // contains the browser user agent string + } + + nodename is either the website domain, or 'localhost' if loaded + without a webserver. This allows programs to test if the system + is running locally or not (example is `cat -l' which does not + print unloaded files if running without a webserver). + + fork(env,io,call) + Creates a new process, with environment and io data passed to it. + Returns the pid of the new process, or 0 on failure. + call should be a function that accepts the env and io as + arguments, this is where the new process begins. + + function newProc(env,io) { + io.write('this is a new process!'); + io.exit(0); + } + var pid = fork(env,io,newProc); + + exec(path,args,env,io) + Executes a new program, replacing the current one. + Returns 0 on success, non-zero on failure. + Unlike typical unix exec(), this always returns. On success the + original program should do nothing more, including not exiting. + + path is the fully resolved file path of the program to be + executed, such as '/bin/ls'. + args is the argument array created by passing a command line to + strToArgs, see above. + env and io, are the current environment and io data. + + var command = "ls -l"; + var args = stdlib.strToArgs(command); + var path = stdlib.resolvePath(args[0],'/bin'); + var r = stdlib.exec(path,args,env,io); + if (r == 0) + return; + + wait(cb) + Calls cb(pid) once any child of the current process has exited. + Calls immediately if the are no child processes. + Returns false on error. + + waitpid(pid,cb) + Calls cb(pid) when the process with id pid has exited. Calls + immediately if the process does not exist. + If pid is less than 0, functions like wait(cb) + Returns false on error. + + waitall(cb) + Calls cb(pid) once all child processes of the current process + group have exited. Calls immediately if the are no child processes. + Returns false on error. + + getuid() + Returns the numeric user id of the current user. + + getgid() + Returns teh numeric group id of the current user. + +clite (libclite.so): io.include('clite') + Provides provides special functions used in CLIte. + + resolvePath('path','base') + Resolves a relative path to a full path, using the present + working directory or 'base': + + clite.resolvePath('file.txt') -> '/usr/home/guest/file.txt' + clite.resolvePath('file.txt','/etc') -> '/etc/file.txt' + clite.resolvePath('~/../file.txt') -> '/usr/home/file.txt' + + strToArgs('string') + Splits a string into an array of arguments for passing to + exec(), supports quotes and so on: + + clite.strToArgs('ls -l /var') -> ['ls','-l','var'] + + +stdio (libio.so): io.include('stdio') + Provides access to io functions and types for file access + + stdio.types: + object for mapping values of stat.type: + FT_UNKOWN: 0 Unknown file type + FT_TEXT: 1 Plain text file + FT_BINARY: 2 Binary file, likely a javascript function + FT_DIR: 3 Directory + FT_LINK: 4 Symbolic link + FT_DEV: 5 Device + FT_REMOTE: 6 Unloaded remote data (will change after loading) + FT_SCRIPT: 7 Plain text file beginning with #! + FT_IMAGE: 8 Image file, specifically a javascript Image object + + creat('path','-') + creates a new file at path + returns true on success + + open('path',callback,open_link) + Open the file at path, returns a file descriptor. + On error returns null, and calls callback(null) if set. + If callback is set, will call the function at callback with the + file descriptor, this allows remote data to be loaded for the + file before beginning read or write operations. + If callback is false, open will return directly, without loading + remote data. + If open_link is set and true, and 'path' is a symbolic link, the + returned file descriptor is for the link, not the file pointed to. + + var fd = stdio.open('path',false); // opens the file without loading data + var fd = stdio.open('path',callback); // calls callback(fd) when data is loaded + var fd = stdio.open('path',callback,true); // as above, but will not follow a link + var fd = stdio.open('path'); // as a general rule, don't do this + + close(fd) + Closes a file opened with open() + + stdio.close(fd); + + read(fd,callback) + Reads a single character or keystroke from a file. + callback is an optional callback function, used soley for + asynchronously reading from a tty. + Returns null if there is no data to read. + + When reading from a regular file, will return a single character. + When reading from a tty: + Returns true on success or false on failure. + Calls callback() and passes as an argument either: + A full line of text as entered by the user. + \1 (start of header) followed by a special key + name (such as ArrowUp). + null if the tty cannot be read from. + + var c = stdio.read(fd); + + readLine(fd,callback) + Reads a line from a file, up to the next newline, or end of file. + Returns null if there is no data to read. + + When reading from a tty, functions the same as read(). + + var line = stdio.readLine(fd); + + readAll(fd) + Returns the entire content of a file. + Returns null if there is no data to read. + Works only on regular files (and some non-tty devices). + + var data = stdio.readAll(fd); + + write(fd,data) + Write data to a file. + Returns true on success. + + if (stdio.write(fd,'string')) { + // it worked + }else{ + // it failed + } + + ftruncate(fd,length) + truncate('path',length) + Truncates a file's size to no more than length. + Does not increase a file's size to length. + Returns true on success. + + var result = stdio.ftruncate(fd,10); + var result = stdio.truncate('/usr/home/guest/file.txt',10); + + seek(fd,pos) + Moves the read/write position of an open file to pos. + If pos is less than 0, then returns the current position without + changing, otherwise returns the new position. + pos is always relative to the start of the file. When a file is + first opened, pos will be set to the start of the file. + To set the position to the end of a file, first get the file size + using stat() or fstat(). + + var p = stdio.seek(fd,10); + + remove('path') + Deletes a file or directory. + Returns true on success. + To delete a directory, the directory must be empty. + + if (stdio.remove('/usr/home/guest/file.txt')) + // success! + + link('path','target') + Creates a new symbolic link at 'path' which points to 'target'. + 'target' must exist. + If 'path' exists, and is already a link, will update the link. + Returns true on success. + + if (stdio.link('/usr/home/guest/logfile','/vr/logs')) + // success! + + stat('path') + fstat(fd) + Returns a stat object with infomation about a file. + Returns null on error. + Editing the returned object does not change anything for the + actual file, it just means your stat object is now wrong. + + var st = stdio.stat('/usr/home/guest/file.txt'); + var st = stdio.fstat(fd); + + Stat object contents: + st.name: string containing the file name + st.type: file type identifier, see stdio.types above for more info + st.uid: numeric id of the file owner + st.gid: numeric id of the file group + st.size: file size, or 0 for non text files + st.perms: the permissions string for the file, see chmod below. + + chmod('path','mode') + fchmod(fd,'mode') + Change a file's mode (permissions). + Returns true on success. + + The mode string is a 9 or 10 character string describing the + file permissions. The optional first character describes the + file type, and cannot be changed. Attempting to change the first + character will not cause the function to fail, but only the + permissions will be changed. + + 10 character string: -rwxrwxrwx + 9 character string: rwxrwxrwx + + After the option first character, the mode string is comprised of + 3 sets of permissions for Read, Write, and eXecute, one each for + the user, group, and others. + + rwx permissions for the file's owner + rwx permissions for users in the file's group + rwx permissions for other users + + Replacing any of the permissions with a dash '-' will remove that + permission from that set: + + rwxr-xr-- + The user has all permissions, the group has read and execute + permissions, others have only read permissions. + + isattty(fd) + returns true if fd refers to a tty. + + fprintf(fd,format,args) + Print formatted text to the file at fd. + Actually formatting is a work in progress, ignore the args. + Returns true on success. + + printf(fmt,args) + Equivalent to fprintf(io.stdout,fmt,args); + +term (libterm.so): io.include('term') + Provides access to raw terminal and tty functions. + + clear() + Clears the current terminal, equivalent to running `clear' from + the shell. + + opentty() + Creates a new blank terminal (tty) with raw key events, for + custom displays and interactions. (The less command uses this). + Returns a reference object for interacting with the new tty. + Returns null on error. + + var tty = term.opentty(); + + closetty(tty) + Closes a tty created with opentty(). + + ttyctrl(func,v) + Special function for setting and accessing CLIte-specific tty + data. Specifically for interacting directly with the form used + for user data input. + func is a string containing the intended function. + v is the value to set. + Returns either the requested data, or false on error. + + term.ttyctrl('iset',string); // sets the current input value + var txt = term.ttyctrl('iget'); // gets the current input value + term.ttyctrl('prompt',string); // sets the current prompt text diff --git a/readme-programs.txt b/readme-programs.txt new file mode 100644 index 0000000..6c8b91b --- /dev/null +++ b/readme-programs.txt @@ -0,0 +1,123 @@ +CLIte command details and API: + +Commands are mostly contained in clite/commands.js and are loaded in + at runtime. Each command looks something like: + +clite.commands.load('name',function(args,env,io) { + io.write("Hello World!"); + return 0; +} + +The load function is only available during boot time, and will: + 1. load the program into the vfs at /bin/name + 2. load the source of the program into the vfs at /usr/src/name.js + +The function in the second argument is roughly equivalent to main() in C. + This function takes 3 arguments: + 'args' is equivalent to argv in C, being an array of strings containing + the command line arguments, args[0] is the command itself, args.length + is equivalent to argc in C. + 'env' contains the current environment variables: env.PWD contains the + present working directory, and so on. + 'io' contains file descriptors for accessing standard input, output, + and error, as well as a method for loading in libraries: + + io.stdout + file descriptor for standard output + + io.stderr + file descriptor for standard error + + io.stdin + file descriptor for standard input + + Note that writing to stdout or stderr, when it is a tty, will + currently always print that output as a line, with a newline + appended. This may change in the future. + + io.exit(value) exits the program, equivalent to the C exit() function. + A program can also be exited by returning a non-null value from the 'main' + function. + + io.include('name') loads a library into the current scope for use. See + the libs readme file for more details. + + +Example Programs: + Due to the nature of javascript, it is not possible to simply stop half + way through a function to wait for user input or for some remote data + to load. Instead we have to use a callback function, which complicates + things a little, and means there are two kinds of programs: Synchronous, + and Asynchronous. + +Synchronous Program: + A Synchronous program runs and then exits, with no waiting for callbacks. + As such, it looks much like a regular unix program might, and simply + returns with an exit code. + Here's a "Hello World" as an example: + +clite.commands.load('hello',function(args,env,io) { + io.write("Hello World!"); + return 0; +} + +Asynchronous Program: + An Asynchronous program typically uses io calls to interact with data + that may not be immediately available; such as remotely loading file + data or reading input from a user. As such callbacks are needed to + handle that data once it is available. + Therefore a return null is used, which lets the system know it is an + asyncronous program that will exit later using the io.exit() function. + Here's a simple program that reads in a file, and prints it to stdout: + +clite.commands.load('show',function(args,env,io) { + var stdlib = io.include('stdlib'); + var stdio = io.include('stdio'); + + // check there's a file to read from + if (args.length != 2) { + io.error('Specify a file to read'); + return 1; // not asyncronous yet, so just return + } + + // take the argument, and get it's full path + var file = stdlib.resolvePath(args[1]); + + // file callback function that will receive the file descriptor + // once the file has data in it + function fcb(fd) { + if (!fd) { + // print an error, exit the program, then end + io.error('could not open file'); + io.exit(1); + return; + } + + // read in the whole file in one go + var data = stdio.readAll(fd); + // close the file + stdio.close(fd); + + // check there's something there + if (!data) { + // print an error, exit the program, then end + io.error('could not read file'); + io.exit(1); + return; + } + + // write to stdout + io.write(data); + + // and exit successfully + io.exit(0); + } + + // open the file, and set the callback + var fd = stdio.open(file,fcb); + + // we don't want to exit the program yet, + // so return null to let the system know that the + // program is asyncronous (reads user data, or loads remote data) + return null; +} diff --git a/readme.txt b/readme.txt index f5fed74..6b974aa 100644 --- a/readme.txt +++ b/readme.txt @@ -71,445 +71,6 @@ export - without arguments: will print all environment variables and their - with argument: allows an environment variable to be changed or created. `export FOO=bar' - -Command details and API: - -Commands are currently all contained in clite/commands.js and are loaded in - at runtime. Each command looks something like: - - -clite.commands.load('name',function(args,env,io) { - io.write("Hello World!"); - return 0; -} - -The load function is only available during boot time, and will: - 1. load the program into the vfs at /bin/name - 2. load the source of the program into the vfs at /usr/src/name.js - -The function in the second argument is roughly equivalent to main() in C. - This function takes 3 arguments: - 'args' is equivalent to argv in C, being an array of strings containing - the command line arguments, args[0] is the command itself, args.length - is equivalent to argc in C. - 'env' contains the current environment variables: env.PWD contains the - present working directory, and so on. - 'io' contains file descriptors for accessing standard input, output, - and error, as well as a method for loading in libraries: - - io.stdout - file descriptor for standard output - - io.stderr - file descriptor for standard error - - io.stdin - file descriptor for standard input - - Note that writting to stdout or stderr, when it is a tty, will - currently always print that output as a line, with a newline - appended. This may change in the future. - - io.exit(value) exits the program, equivalent to the C exit() function. - A program can also be exited by returning a non-null value from the 'main' - function. - - io.include('name') loads a library into the current scope for use. See - below for more details. - - -Libraries: - -System libraries may be loaded into a program for use of their API using the - io.include() function: - -var stdio = io.include('stdio'); - - This returns a reference to the library which can be stored in a variable as - seen above. Calls to library functions can then be made using that reference: - -stdio.open('/path/to/file'); - - There is no need to name the variable the same as the library name, however - this is considered good practice. - -The libraries, and their API functions are listed below: - -stdlib: io.include('stdlib') - Provides a growing standard unix-like library. - - basename('path') - returns the base name of a file path: - '/usr/home/guest/file.txt' -> 'file.txt' - - dirname('path') - returns the directory name of a file path: - '/usr/home/guest/file.txt' -> '/usr/home/guest' - - resolvePath('path','base') - special function that resolves a relative path to a full path, - using the present working directory or 'base': - resolvePath('file.txt') -> '/usr/home/guest/file.txt' - resolvePath('file.txt','/etc') -> '/etc/file.txt' - resolvePath('~/../file.txt') -> '/usr/home/file.txt' - - strToArgs('string') - special function that splits a string into an array of arguments - for passing to exec(), supports quotes and so on: - 'ls -l /var' -> ['ls','-l','var'] - - uname() - returns an object containing system information: - { - sysname:'CLIte', // system name, always 'CLIte' - nodename:'localhost', // network hostname - release:'0.1...', // contains the current CLIte version as stored in clite.state.version - version:'0.1...', // same as release - machine:navigator.userAgent // contains the browser user agent string - } - - nodename is either the website domain, or 'localhost' if loaded - without a webserver. This allows programs to test if the system - is running locally or not (example is `cat -l' which does not - print unloaded files if running without a webserver). - - fork(env,io,call) - Creates a new process, with environment and io data passed to it. - Returns the pid of the new process, or 0 on failure. - call should be a function that accepts the env and io as - arguments, this is where the new process begins. - - function newProc(env,io) { - io.write('this is a new process!'); - io.exit(0); - } - var pid = fork(env,io,newProc); - - exec(path,args,env,io) - Executes a new program, replacing the current one. - Returns 0 on success, non-zero on failure. - Unlike typical unix exec(), this always returns. On success the - original program should do nothing more, including not exiting. - - path is the fully resolved file path of the program to be - executed, such as '/bin/ls'. - args is the argument array created by passing a command line to - strToArgs, see above. - env and io, are the current environment and io data. - - var command = "ls -l"; - var args = stdlib.strToArgs(command); - var path = stdlib.resolvePath(args[0],'/bin'); - var r = stdlib.exec(path,args,env,io); - if (r == 0) - return; - - wait(cb) - Calls cb(pid) once any child of the current process has exited. - Calls immediately if the are no child processes. - Returns false on error. - - waitpid(pid,cb) - Calls cb(pid) when the process with id pid has exited. Calls - immediately if the process does not exist. - If pid is less than 0, functions like wait(cb) - Returns false on error. - - waitall(cb) - Calls cb(pid) once all child processes of the current process - group have exited. Calls immediately if the are no child processes. - Returns false on error. - - getuid() - Returns the numeric user id of the current user. - - getgid() - Returns teh numeric group id of the current user. - - -stdio: io.include('stdio') - Provides access to io functions and types for file access - - stdio.types: - object for mapping values of stat.type: - FT_UNKOWN: 0 Unknown file type - FT_TEXT: 1 Plain text file - FT_BINARY: 2 Binary file, likely a javascript function - FT_DIR: 3 Directory - FT_LINK: 4 Symbolic link - FT_DEV: 5 Device - FT_REMOTE: 6 Unloaded remote data (will change after loading) - FT_SCRIPT: 7 Plain text file beginning with #! - FT_IMAGE: 8 Image file, specifically a javascript Image object - - creat('path','-') - creates a new file at path - returns true on success - - open('path',callback,open_link) - Open the file at path, returns a file descriptor. - On error returns null, and calls callback(null) if set. - If callback is set, will call the function at callback with the - file descriptor, this allows remote data to be loaded for the - file before beginning read or write operations. - If callback is false, open will return directly, without loading - remote data. - If open_link is set and true, and 'path' is a symbolic link, the - returned file descriptor is for the link, not the file pointed to. - - var fd = stdio.open('path',false); // opens the file without loading data - var fd = stdio.open('path',callback); // calls callback(fd) when data is loaded - var fd = stdio.open('path',callback,true); // as above, but will not follow a link - var fd = stdio.open('path'); // as a general rule, don't do this - - close(fd) - Closes a file opened with open() - - stdio.close(fd); - - read(fd,callback) - Reads a single character or keystroke from a file. - callback is an optional callback function, used soley for - asynchronously reading from a tty. - Returns null if there is no data to read. - - When reading from a regular file, will return a single character. - When reading from a tty: - Returns true on success or false on failure. - Calls callback() and passes as an argument either: - A full line of text as entered by the user. - \1 (start of header) followed by a special key - name (such as ArrowUp). - null if the tty cannot be read from. - - var c = stdio.read(fd); - - readLine(fd,callback) - Reads a line from a file, up to the next newline, or end of file. - Returns null if there is no data to read. - - When reading from a tty, functions the same as read(). - - var line = stdio.readLine(fd); - - readAll(fd) - Returns the entire content of a file. - Returns null if there is no data to read. - Works only on regular files (and some non-tty devices). - - var data = stdio.readAll(fd); - - write(fd,data) - Write data to a file. - Returns true on success. - - if (stdio.write(fd,'string')) { - // it worked - }else{ - // it failed - } - - ftruncate(fd,length) - truncate('path',length) - Truncates a file's size to no more than length. - Does not increase a file's size to length. - Returns true on success. - - var result = stdio.ftruncate(fd,10); - var result = stdio.truncate('/usr/home/guest/file.txt',10); - - seek(fd,pos) - Moves the read/write position of an open file to pos. - If pos is less than 0, then returns the current position without - changing, otherwise returns the new position. - pos is always relative to the start of the file. When a file is - first opened, pos will be set to the start of the file. - To set the position to the end of a file, first get the file size - using stat() or fstat(). - - var p = stdio.seek(fd,10); - - remove('path') - Deletes a file or directory. - Returns true on success. - To delete a directory, the directory must be empty. - - if (stdio.remove('/usr/home/guest/file.txt')) - // success! - - link('path','target') - Creates a new symbolic link at 'path' which points to 'target'. - 'target' must exist. - If 'path' exists, and is already a link, will update the link. - Returns true on success. - - if (stdio.link('/usr/home/guest/logfile','/vr/logs')) - // success! - - stat('path') - fstat(fd) - Returns a stat object with infomation about a file. - Returns null on error. - Editing the returned object does not change anything for the - actual file, it just means your stat object is now wrong. - - var st = stdio.stat('/usr/home/guest/file.txt'); - var st = stdio.fstat(fd); - - Stat object contents: - st.name: string containing the file name - st.type: file type identifier, see stdio.types above for more info - st.uid: numeric id of the file owner - st.gid: numeric id of the file group - st.size: file size, or 0 for non text files - st.perms: the permissions string for the file, see chmod below. - - chmod('path','mode') - fchmod(fd,'mode') - Change a file's mode (permissions). - Returns true on success. - - The mode string is a 9 or 10 character string describing the - file permissions. The optional first character describes the - file type, and cannot be changed. Attempting to change the first - character will not cause the function to fail, but only the - permissions will be changed. - - 10 character string: -rwxrwxrwx - 9 character string: rwxrwxrwx - - After the option first character, the mode string is comprised of - 3 sets of permissions for Read, Write, and eXecute, one each for - the user, group, and others. - - rwx permissions for the file's owner - rwx permissions for users in the file's group - rwx permissions for other users - - Replacing any of the permissions with a dash '-' will remove that - permission from that set: - - rwxr-xr-- - The user has all permissions, the group has read and execute - permissions, others have only read permissions. - - isattty(fd) - returns true if fd refers to a tty. - - fprintf(fd,format,args) - Print formatted text to the file at fd. - Actually formatting is a work in progress, ignore the args. - Returns true on success. - - printf(fmt,args) - Equivalent to fprintf(io.stdout,fmt,args); - -term: io.include('term') - Provides access to raw terminal and tty functions. - - clear() - Clears the current terminal, equivalent to running `clear' from - the shell. - - opentty() - Creates a new blank terminal (tty) with raw key events, for - custom displays and interactions. (The less command uses this). - Returns a reference object for interacting with the new tty. - Returns null on error. - - var tty = term.opentty(); - - closetty(tty) - Closes a tty created with opentty(). - - ttyctrl(func,v) - Special function for setting and accessing CLIte-specific tty - data. Specifically for interacting directly with the form used - for user data input. - func is a string containing the intended function. - v is the value to set. - Returns either the requested data, or false on error. - - term.ttyctrl('iset',string); // sets the current input value - var txt = term.ttyctrl('iget'); // gets the current input value - term.ttyctrl('prompt',string); // sets the current prompt text - - -Example Programs: - Due to the nature of javascript, it is not possible to simply stop half - way through a function to wait for user input or for some remote data - to load. Instead we have to use a callback function, which complicates - things a little, and means there are two kinds of programs: Syncronous, - and Asyncronous. - -Syncronous Program: - A Syncronous program runs and then exits, with no waiting for callbacks. - As such, it looks much like a regular unix program might, and simply - returns with an exit code. - Here's a "Hello World" as an example: - -clite.commands.load('hello',function(args,env,io) { - io.write("Hello World!"); - return 0; -} - -Asyncronous Program: - An Asycronous program typically uses io calls to interact with data - that may not be immediately available; such as remotely loading file - data or reading input from a user. As such callbacks are needed to - handle that data once it is available. - Therefore a return null is used, which lets the system know it is an - asyncronous program that will exit later using the io.exit() function. - Here's a simple program that reads in a file, and prints it to stdout: - -clite.commands.load('show',function(args,env,io) { - var stdlib = io.include('stdlib'); - var stdio = io.include('stdio'); - - // check there's a file to read from - if (args.length != 2) { - io.error('Specify a file to read'); - return 1; // not asyncronous yet, so just return - } - - // take the argument, and get it's full path - var file = stdlib.resolvePath(args[1]); - - // file callback function that will receive the file descriptor - // once the file has data in it - function fcb(fd) { - if (!fd) { - // print an error, exit the program, then end - io.error('could not open file'); - io.exit(1); - return; - } - - // read in the whole file in one go - var data = stdio.readAll(fd); - // close the file - stdio.close(fd); - - // check there's something there - if (!data) { - // print an error, exit the program, then end - io.error('could not read file'); - io.exit(1); - return; - } - - // write to stdout - io.write(data); - - // and exit successfully - io.exit(0); - } - - // open the file, and set the callback - var fd = stdio.open(file,fcb); - - // we don't want to exit the program yet, - // so return null to let the system know that the - // program is asyncronous (reads user data, or loads remote data) - return null; -} +For more information, check the other readme files for info on CLIte internals. +Also, consider buying the developer a coffee: +https://ko-fi.com/ticklishhoneybee