The Lua OS Manual (v. 0.13)
Written by Stefan Reich, Nov 12 2011.
Version covered: Lua OS 0.13
Lua OS homepage: LuaOS.net
Online version: LuaOS.net/docs/manual.php
Author contact: webmaster@LuaOS.net
Table of contents
Lua OS is an operating system for IBM PC-compatible
computers.
Lua OS consists of two parts:
- Next-gen: A newly designed environment for secure mobile script code written in
a variant of Lua ("Safe Lua").
- Legacy: A full-featured Linux that should allow you to run all standard software available
today.
Lua OS's legacy area is based on Debian Linux (Knoppix 6.4, to be precise).
Thanks go to Klaus Knopper for creating Knoppix. However, Klaus: You should
replace your forum moderator (on knoppix.net) who makes your forum
almost unusable.
- Any standard PC of less than infinite age should be able to run Lua OS.
- 384 MB of main memory are known to suffice, but more is always better.
- For installing on disk, 4 GB of disk space are required. (For installing
additional applications and having some space for your data, we find 12 GB to
be a comfortable size.)
- Lua OS is a graphical operating system. As
far as we know, any standard graphics adapter will work.
The Lua OS Live-CD is supposed to run in a single-user mode. Technically,
two users are known to the system: "knoppix", the main user; and "root", the
super user. The system logs in to user "knoppix" automatically. For
administrative purposes, you can switch to "root" by typing "su" in a terminal,
or by using "sudo". Many tasks switch to root automatically if necessary. No
password is required to become "root".
Lua OS can be installed to disk in two modes: single-user or multi-user.
You will ask for the mode you want when running the installer.
In single-user mode, the installed Lua OS operates exactly like the Lua OS Live-CD.
During installation in multi-user mode, you will be asked for details about
the main user you'd like to create. In this mode, Lua OS will not log you in
automatically after booting, but present a log in prompt. Also, you will be
in text mode after logging in.
In multi-user mode, type startx to switch to the graphical environment.
Currently, there is a single switch to change both keyboard layout and
the language of system messages etc.
Lua OS may start in German or English mode by default, depending on where
it is shipped. We'll hand out a heap of German Live-CDs on local campuses.
Lua OS images on the web are usually English.
Whatever version you got: You can choose your language when booting Lua OS. The
Live-CD will offer you a menu: type "en" for English or "de" for German.
When Lua OS is already installed, switching the language is a little more difficult.
You can edit the command line when booting. Or edit menu.lst and rewrite grub.
We'll quite certainly offer a tool for this in the future.
It follows: A loose collection of keywords, applications and so on.
All Debian packages should be installable in Lua OS over the usual means
(apt-get).
If, for any software, there is a choice of a KDE or GNOME version: Choose
GNOME - because GNOME is already installed in Lua OS.
The Flash plugin is already installed in the Lua OS default web browser
(Iceweasel), so you can access YouTube right away. And xhamster.com. And
everything else you love.
To install VirtualBox, open a terminal and type:
sudo apt-get install virtualbox-ose
Yeah, that's all. You'll find VirtualBox in the start menu afterwards.
It appears that the version of VirtualBox you will receive is not the
latest one, but a bit older. (They'll update the Debian package in a while
I assume.) That version of VirtualBox works fine for me anyway - I use it to
master Lua OS CDs.
Lua OS comes with VLC preinstalled. As far as we know, VLC plays everything.
If, in a future version, VLC is not there, just type:
sudo apt-get install vlc
(in a terminal).
There are many audio players for Linux. We recommend Exaile which is said
to be similar to Amarok which is a popular player for KDE. To install Exaile,
type:
sudo apt-get install exaile
...is called Iceweasel in Lua OS (in case you looked for a "Firefox" in vain).
Why? Ask Klaus Knopper, he came up with that. :]
Transmission works really well for all your BitTorrent needs:
sudo apt-get install transmission
Just a little hint: You should be a little careful with the mouse button
in Lua OS - if you're coming from the Windows world. Often, things require just
a single click. Icons in the file manager are an example. One click and they
launch. Double-clicking can make them launch twice. Yeah, it's a little stupid.
Computers are like that. We could and probably should improve that in the future.
Oh, and sometimes, my touch pad doesn't respond to double-tapping. I have to
use the actual button. Don't know if that is specific to my notebook or a
general thing.
If you run Windows in parallel to Lua OS: Don't use "Suspend to disk" and
then start Lua OS. It tends to fucks up your partitions. Unfortunately it's
something that cannot easily be fixed either (every Linux has this problem).
"Suspend to disk" in Lua OS could theoretically be enabled; the function is
still considered experimental in Linux though. And frankly, I haven't gotten it
to work yet around here. Drop me a note if you have some ideas on how to do this.
I don't know if there is an easier way, but what I did for this is copy the .ttf file to
/usr/share/fonts/truetype (on the terminal, as root). After that, the font was usable
in GIMP.
Unfortunately, "apt-get install libreoffice" didn't work for me (with an older version
of Lua OS anyway, should test this with 0.13).
However, manual
installation worked. I downloaded the version for Debian systems from libreoffice.org and
followed the instructions. (Unpacking the archive and running dpkg twice.)
Also, downloading the Debian package from openoffice.org and installing all
the files with "dpkg -i *.deb */*.deb" worked too.
To keep the Lua OS CD small, I removed printing support from it. But it can be added again.
To do this, run "sudo apt-get install cups" (CUPS is the Unix printing system).
Then, go to start menu, Preferences, Printer settings. The CUPS page will open in Iceweasel.
Click "Add printer". Log in as root. To do this, root needs a password. I had to set that manually
(su, then passwd). Yeah, we'll improve this in the next release. Now I could select my printer
(Brother HL-2030). One last hurdle: There was a choice of different implementations.
The first one (CUPS) did not work. The second one (Foomatic) worked. Linux is funny like that sometimes.
But now I have the printed page in my hands. Printed from Lua OS!
This is a nice and useful GUI library for Lua. I installed it in Lua OS like
this:
- Download iup-3.5_Linux26_lib.tar.gz
- Unpack in a temp directory
- Go to that directory in the terminal
- sudo ./install
- sudo ./config_lua_module
- sudo apt-get install libmotif4
- sudo ln -s /usr/lib/libXm.so.4 /usr/lib/libXm.so.3
That was all. It seems to work, although iup.Message produces a mysteriously
unclosable dialog box. iup.Alarm works fine though. Some further testing might be
appropriate.
sudo apt-get install audacity
Seems to work great. OGG export works fine.
MP3 export does not work yet, on my box anyway. It asks for libmp3lame.so.0 but apt-get
does not seem to want to install libmp3lame0 for some reason.
To be written.
Safe Lua, the language used to program for
Lua OS, is a variant of Lua.
This document describes Lua OS / Safe Lua 0.13.
Lua OS nests programs in two levels. The outermost structure is called a cage. Currently,
only one cage exists in a system. Support for multiple cages is planned for later releases.
(This will then also enable physical multitasking.)
Within every cage, there are a number of sandboxes. Each sandbox
- runs exactly one Safe Lua script
- has a number of special powers (or no such powers) granted to it
- maintains a message queue and can send and receive messages
- runs as a Lua coroutine and thus shares CPU time with the other sandboxes in the cage
cooperatively
- can be marked as a 'system sandbox' or 'user sandbox' (relevant when persisting a cage)
- can have a timeout (maximum number of instructions that can be executed before
sandbox is automatically shutdown)
- can have a "soft timeout" (maximum number of instructions per incoming message
/ between yields)
A cage is defined by a fragment of Lua code (basically just a table). In order to parse
the definition, the code is run in a sandbox with no powers, yielding a table. (The result
of this is called a cage definition in 'table form'.)
A cage definition looks like this:
Cage {
Sandbox {
code = [[
print "Endless loops are not scary!"
while true do end
]]
},
Sandbox {
script = "myscript.slua",
pdata = "somedata",
softtimeout = 100000
},
Sandbox {
script = "mycagemanager.slua",
magic = {"socket", "cageManagement"},
system = true
}
timeout = 1000000 -- cage-wide time limit for all sandboxes
}
(The keywords Cage and Sandbox are just syntactic sugar.)
Here's what the various fields mean:
- code: Inline (Safe) Lua code
- script: Filename of a script to load (from current directory).
(If both code and script are given, the code is taken
from the code attribute and as script name in the task manager,
the script attribute is used. Thus the script name display may
not necessarily say anything about the code being run. There might be
a special visual notice in these case in the future to avoid confusion.)
- pdata: Persisted data from an earlier script run (optional)
- timeout: Hard timeout for script execution (optional)
- softtimeout: Soft timeout for computation steps between yields (optional)
- magic: List of superpowers allowed for a sandbox (optional)
- system: System sandbox? (boolean, optional, default is false)
timeout and softtimeout may appear both on the sandbox and on the cage level
(sandbox level takes precedence, although we might change that).
Safe Lua's syntax is identical to Lua's syntax.
Some parts of the standard Lua API are also present in Safe Lua.
Additionally, there is a new set of functions and objects.
The term 'persistable data' refers to types of data that can be
persisted to disk.
Persistable data is:
- nil
- Numbers
- Strings
- Booleans
- Non-recursive tables where all values are persistable data
'Exchangeable data' is data that can be passed as arguments and return values
in cross-sandbox method/function calls.
Exchangeable data is:
- Any persistable data
- Functions
- Objects
- Cross-sandbox references to functions and objects
- Non-recursive tables where all values are exchangeable data
An object is distinguished from a table by the presence of a metatable. When crossing
a sandbox barrier, tables are copied and objects are transformed into a reference to the
object. (The object itself remains in the original sandbox.)
To create an object, the function object() is provided which creates an
empty table with an empty metatable.
The following global Lua variables are currently accessible in Safe Lua:
print
error
string
tostring
table
ipairs
pairs
type
tonumber
rawget
pcall (reimplemented to uphold Lua OS security requirements)
require (this is experimental and only works with the parameter 'lib_util')
We expect to have a proper security audit at some point and then make a qualified
decision about which parts of the Lua library we deem safe.
For the following, keep in mind that Safe Lua code always runs in a sandbox. By
default, a sandbox has limited power, but they can be extended by explicitly
asking for additional powers.
- tostr(data)
- Converts data to a string and returns the string. Prints tables nicely.
Can be used to convert exchangeable data to executable Lua code.
- dump(data)
- Converts data to a string (using tostr) and prints it.
- include(script)
- Includes another script (relative to the current dir, which is a very foggy
notion at this point). This will have to be defined more properly in a future
version.
- object()
- Returns a new object (an empty table with an empty metatable). Preferrable to
{} because the resulting structure will be recognized as an object by
safecomm. (A Lua table without a metatable will not be regarded an object by safecomm.)
- breathe()
- Yields control to allow other sandboxes to do things,
but returns to execution of this sandbox as soon as possible
(call this every now and then when you do long-running calculations
to keep cooperative multitasking smooth & afloat)
- elems(list)
- Iterator on all items in a list. Use like this: for elem in elems(list) do...
- use(powers)
- A shorthand for safelua.requestExtension(). powers is a string with the names of all
powers you'd like to request, e.g. "socket json io". Each power object will be assigned to
a global variable of the same name. If one of the powers is not available, an error is
produced and the script is halted. So the call
use("socket json io")
is equivalent to:
socket = safelua.requestExtension("socket")
json = safelua.requestExtension("json")
io = safelua.requestExtension("io")
- _pdata
- Contains the contents of the field pdata (persistence data) given in the sandbox definition
- or nil if no persistence data is available.
This globally accessible object provides the following functions.
- safelua.requestExtension(name)
- Requests a 'magic power' from the OS. The power is identified by name (a string).
If the wish is granted, an object is returned providing the desired abilities.
If it is denied, an error is thrown. (Currently, errors can not be caught in
Safe Lua, but we will change that in a future release.)
Currently defined superpowers are: "socket" and "cageManagement".
- safelua.onShutdown(f)
- Registers a shutdown handler for this sandbox (a function with no arguments).
The shutdown handler is called prior to shutting down the sandbox. Usually,
this is only necessary for sandboxes with extended powers (those that hold
references to sockets or other system resources).
Most sandboxes don't need that as they will stay in the 'safe' (unextended) realm.
- safelua.exit()
- Exit from the current sandbox (stop the script)
- safelua.yield()
- Pause execution of this script for a moment and allow other scripts to do some work.
If you are doing long-running computations, this method should be called at strategic
points. If your script is event-based, you usually won't need it though.
The semantics of safelua.yield() are still a bit under discussion. The question is when script
execution is resumed. A script may want to perform more computation as soon as possible;
or only resume when there is any event (from the message system or an external resource).
Currently, safelua.yield() assumes that you have more work to do and are just taking a
breath to avoid blocking the system or hitting a soft timeout (a timeout on the length of
computations between yields).
- safelua.setPersistenceHandler(handler)
- Enables persistence for this sandbox.
A persistence handler is a zero-argument function returning some exchangeable data.
(Returning nil is OK too.) A sandbox is considered persistable if and only if a
persistence handler is defined, so if you want persistence, it is crucial to define
a persistence handler even if you have no data to be persisted.
When recreating the sandbox later (on the same machine or another one), the persisted
data is returned to the script in the global variable _pdata.
If persisting is currently not possible for any reason, the persistence handler may
throw an error.
- safelua.sandboxId()
- Returns the id (a string) of the current sandbox.
- safelua.exitSoon()
- Exits the sandbox. As the qualifier "soon" indicates, handling of events currently
in flight is completed and then the sandbox is actually shutdown. This is typically a better
and cleaner way to shutdown a sandbox than actually interrupting execution in the middle
of everything. (Although there will probably also be a function for that in a future
release.)
- safelua.osVersion()
- Returns the version of Lua OS the script is running in (a string), for example:
"Lua OS 0.10".
This globally accessible object provides services for communication between sandboxes.
- safecomm.send{recipient, cmd [, data]}
- (Note the curly brackets.) Send a message to another sandbox. recipient (a string) is either a
sandbox id or a channel. cmd is the command to send (an arbitrary string).
data is a list of named or unnamed items to be added to the message.
Multiple items can be put in directly, without extra curly braces.
(All items must be exchangeable data.)
send places the message in the recipient's (or the recipients') event queues and then
returns immediately. If you want to wait for an answer, use safecomm.invoke.
- safecomm.invoke{recipient, cmd [,data]}
- (Note the curly brackets.)
Like safecomm.send, but blocks (sleeps) until an answer is received which is then
returned to you.
- safecomm.handler(handler)
- Register a message handler. A sandbox can have multiple message handlers.
Whenever a message is received, all the message handlers are run on it.
A message handler is a function taking three arguments: sender (sandbox id), command
(string) and data (a table with exchangeable data). It does not return any value.
- safecomm.removeHandler(handler)
- Remove a message handler from the list.
- safecomm.listenOn(channel)
- Registers this sandbox as a listener on a given channel. A channel is identified by
a string. When a message is sent to a channel by any sandbox, all listeners for that
channel in the same cage receive this message.
- safecomm.yield(result, exitAfterEvents)
- An extended yield function. You will usually only need this if you work with sockets.
result is: nil (=I still have stuff to do anyway), true
(=sleep and only wake up for incoming messages) or a list of sockets that you are waiting
on.
- safecomm.daemon()
- Keeps this sandbox alive, waiting for messages. Same as: safecomm.yield(true)
- safecomm.answer(sender, data, answer)
- Send an answer. sender and data are the parameters from the original message. (The
data field will contain an id identifying the original mesage.)
answer is some exchangeable data that constitutes the answer you'd like to send.
- safecomm.registerService(name, object)
- Registers a (local) object as a service implementation. Services are announced
cage-wide and are identified by name. If two sandboxes register an implementation for
the same service, currently the latter implementation replaces the former. This might
be handled more flexibly in the future.
- safecomm.connectToService(name)
- Connect to a service. Returns the implementation object if one is found, ready to
use (with transparent sandbox tunnelling on method calls). If no implementation is
found, connectToService returns nil.
Access to cage management (if permitted for the current sandbox) is enabled by calling:
cageManagement = safelua.requestExtension("cageManagement")
The object then provides the following functions:
- cageManagement:sandboxIds()
- Returns a list containing the ids of all sandboxes in the cage.
- cageManagement:getInfo(id)
- Returns an array with information about a sandbox. (TODO: Describe what
information that is...)
- cageManagement:startSandbox(def)
- Create a new sandbox, add it to the cage and run it. def is the
sandbox definition in table form.
- cageManagement:deleteSandbox(id)
- Delete the sandbox with the given id. The shutdown handler is called for cleanup
if one was defined.
- cageManagement:sandboxCode(id)
- Return the text of the script running in a sandbox.
- cageManagement:sandboxOutput(id)
- Return all text that was printed by the sandbox.
(All output is captured and stored automatically.)