diff --git a/readme.txt b/readme.txt index 77aec83..4f64947 100644 --- a/readme.txt +++ b/readme.txt @@ -53,6 +53,7 @@ The shell supports argument in "quotes" and 'single quotes', as well as Shell paths support tilde (~) for the user's home directory, as well as dot (.) and dot dot (..) for current and parent directories. The asterisk (*) wildcard is not currently supported + The shell maintains a command history, use up and down arrows to access. The following shell builtin commands or macros are available: clear - clears the terminal window @@ -75,16 +76,13 @@ Commands are currently all contained in clite/commands.js and are loaded in clite.commands.load('name',function(args,env,io) { - // executable code io.write("Hello World!"); - return 0; // exits the program, return null if the program is - // asyncronous (reads user data, or loads remote data) - // see io.exit() below for how to exit in such a case + 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 /usr/src/name + 2. load the source of the program into the vfs at /usr/src/name The function in the second argument is roughly equivalent to main() in C. This function takes 3 arguments: @@ -195,8 +193,8 @@ stdio: io.include('stdio') 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 if provided, this allows remote data to be - loaded for the file before beginning read or write operations. + 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 @@ -291,23 +289,23 @@ stdio: io.include('stdio') 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 - uid: numeric id of the file owner - gid: numeric id of the file group - size: file size, or 0 for non text files - perms: the permissions string for the file, see chmod below. + 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 + 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 still succeed, but only the permissions will be - changed. + character will not cause the function to fail, but only the + permissions will be changed. 10 character string: -rwxrwxrwx 9 character string: rwxrwxrwx @@ -344,3 +342,83 @@ term: io.include('term') closeTTY(tty) Closes a tty opened with createTTY(). + + +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; +}