Inferno FAQ for the 4th Edition

Last modified: Wed Oct 7 21:11:48 CEST 2009







[Names, roots]






What is the licence for Inferno and how much does it cost?

Currently there are 2 ways to use Inferno. One is free the other is not. You get the same software, the difference is only in the way you are allowed to use it. It's your decision which licence you choose. Have a look at .

How can I run Inferno on my OS?

Inferno can be run in an emulation environment. This is the preferred way to do development. Inferno runs as a separate program on top of most major operating systems. The following host operating systems are supported: Windows NT/2000/XP, Irix, Linux, MacOS X, FreeBSD, Solaris, Plan 9.

If you have Internet Explorer on Windows, you can run it as a plug-in.

Can I run Inferno directly on my PC?

Inferno can be run on bare hardware, though for most PC parts there is a limited set of device drivers.

What hardware architectures are supported?

Is there a mailing list?

Currently Vita Nuova is maintaining a mailing list. Look at . There is a mailing list archive at .

Where is the current faq?

Comments to me

What is in there?

Inferno is a complete OS and development environment.

How can I program it?

Limbo is a programming language designed specifically for writing applications under Inferno, and takes maximum advantage of the facilities that Inferno provides. Also Inferno has a very powerful shell. There is a C to limbo translator as well.

How are Inferno binaries run?

Inferno binaries are the same across all platforms. It doesn't matter if a program was compiled on a different architecture. A binary is run by the virtual machine Dis. By convention all Dis binaries have .dis extension.

What is the "size" of Inferno?

Inferno programs can run in as little as 1MB of RAM. All Inferno applications have similarly small memory requirements. The emulation environment can be set to use all of the hosts memory if needed. The compressed downloadable full source and compiled binaries for all architectures is 50MB.

Is Unicode supported?

Inferno uses Unicode. Strings are encoded in Utf-8.

What is the intended end-user environment?

Inferno is a complete solution to a very rich set of problems. These problems have at least two things is common:

It provides complete grid, embedded and distributed solutions. Although it is not intended as a desktop replacement, it has all of the functionality an inferno developer needs.

Inferno is an Operating System for the construction of distributed applications on everything from resource constrained devices to high-end servers.

What are the design principles?

Have a look at

How can I install Inferno?

The installation instructions are available at in section 3.

What's new in 4th edition Inferno?

After installing Inferno have a look at changes.pdf.

Where can I find documentation?

Have a look at . You should read intro(1) and all other intro pages (type intro in wm/man).

After you install Inferno in the inferno root, there is a lot of documentation in /doc.

Currently there is no printed documentation for 4th edition Inferno, though you can get high quality printed documentation on 3rd edition from Vita Nuova. Phillip Stanley-Marbell had written a book on 3rd edition Inferno.

What kind of security is provided by Inferno?

Probably the most important Inferno feature is end to end security at the highest communication level.

From security-intro(2):

"Inferno provides several levels of security:

Inferno makes it easy to enforce any one or all of these levels of security."

The following algorithms and protocols are implemented: IDEA, 56 bit DES, 40, 128 and 256 bit RC4 encryption algorithms, MD4, MD5 and SHA secure hash algorithms.

Where are my usual applications in Inferno?

When you run the windowing environment most of these are available by clicking on the Vita Nuova logo in the bottom left corner.

What are those directories in the inferno root?

For a detailed description read namespace(4).

Why does 'ls' show some directories twice?

If you read the faq, you probably don't want to know at the moment.

It is a result of a sys->bind. Read sys-intro(2) and all other intro pages as advised above.

Where is PATH?

There is no PATH variable in Inferno. The shell runs binaries by convention from /dis. Some programs are grouped by separate directories in /dis.

How can I compile and run my Limbo programs?

At the inferno shell type:

% limbo myprog.b
% ./myprog
Assuming myprog.b contains your Limbo source code.

What about the names?

Quite a few names were borrowed from Inferno by Dante Alighieri. Have a look at .

What is the history of Inferno?

From , after 'History':

"Developed, circa 1995, by the Computing Science Research Center at Bell Labs by Sean Dorward, Rob Pike, David Presotto, Dennis Ritchie, Howard Trickey, Phil Winterbottom. Drew upon lessons learned building Plan 9 research OS. Developed as a decidedly commercial product. Developed by Bell Labs research, transferred to the Inferno Business Unit a semi-autonomous spinoff, housed within Lucent (Murray Hill, NJ). ... No significant improvement of Inferno (as delivered by research group) is performed before attempting to sell it. Circa 1999, Inferno Business Unit folds.

2000: Rights to Inferno sold to Vita Nuova Holdings, York England." ...

How do I implement the "Hello, World" program?

Here is the Limbo code, without any comments:

implement Hello;

include "sys.m";
   sys: Sys;
include "draw.m";
Hello: module
	init:   fn(ctxt: ref Draw->Context, argv: list of string);

init(ctxt: ref Draw->Context, argv: list of string)
	sys = load Sys Sys->PATH;
	sys->print("hello, world\n");

And here's the same Limbo code, with extensive comments:

# this file implements the Hello module (declared below)
# Implementation files often implement modules that are
# declared in separate files, but in this case, the module
# is included in this file

implement Hello;	

# include module interfaces for modules that will be referenced
# in this program.  Note that include is a Limbo statement: there
# is no preprocessor.

include "sys.m";	# include the Sys module declaration in the file "sys.m"
   sys: Sys;		# sys is declared as type Sys (OK once sys.m is included)
include "draw.m";	# include the draw module declaration in "draw.m" 
# Here is the Hello module declaration.
# The init() function is a convention that must be observed for
# commands to be executed from the shell (sh.b) command line.
# sh calls the init function of commands executed from its command line.
# Note that the module declaration (a statement) ends with a semicolon.

Hello: module		
	init:   fn(ctxt: ref Draw->Context, argv: list of string);
# Here is the init function definition.
# The arguments are dictated by the form of init that shell
# is expecting. ctxt is the graphical context for the program, 
# argv is a list of arguments. Note that we don't actually use
# either of these arguments in this simple function.

init(ctxt: ref Draw->Context, argv: list of string)
# give sys a value by loading an instance of the Sys module from
# the location specified in Sys->PATH. Sys is a special case because
# its implementation is part of the kernel.
	sys = load Sys Sys->PATH;
# do it -- call the print function of Sys
	sys->print("hello, world\n");

To compile this program, type:

% limbo hello.b

The Limbo compiler creates a binary file of Dis bytecode and saves it in hello.dis. There are many options to the limbo command (see the Inferno Reference Manual). You can run the program by typing:

% hello

(You do not need to type the .dis extension.)

What is a module?

A module is a declaration of the public interface of a program. It includes constants, data, functions, and abstract data types that are visible to other modules.

A module is often placed in a separate .m file, while the implementation (the code for the functions declared in the module, in addition to other functions) is conventionally placed in a .b file. The .b file can also include a module declaration as part of the implementation.

For example, the shell function cat begins:

implement Cat;

include "sys.m";
include "draw.m";

Cat: module
	init:	fn(ctxt: ref Draw->Context, argv: list of string);

sys: Sys;
stderr, stdout: ref Sys->FD;

init(nil: ref Draw->Context, argl: list of string)
	sys = load Sys Sys->PATH;

	stdout = sys->fildes(1);
	stderr = sys->fildes(2);

As another example, the string module declares various functions that you can call for string manipulation. The code to implement these functions appears in the implementation file string.b. Here is an excerpt from the module file string.m:

String: module
	PATH:		con	"/dis/lib/string.dis";


	splitl:		fn(s, cl: string): (string, string);
	splitr:		fn(s, cl: string): (string, string);
	drop:		fn(s, cl: string): string;
	take:		fn(s, cl: string): string;
	in:		fn(c: int, cl: string): int;


I am having problems creating synthetic files with file2chan.

I tried to create a synthetic file with file2chan, but when I try to receive on the channel, my program dies with an "OSFault "sys: trap: general protection violation pc=0xdeaddead"

You should check to see if file2chan returned a non-nil value, and if it returned nil, find out what the last system error was (by using the %r print format. The most likely reason for the error was that you had not bound the serve device to the directory that you wanted to serve the file from For example:

init(ctxt : ref Draw->Context, args : list of string)
	c : ref FileIO;

	sys = load Sys Sys->PATH;

	# bind serve device 
	sys->bind("#s", "/chan", sys->MREPL);

	# create synthetic file, then check
	c = sys->file2chan("/chan", "chanfile");
	if (c == nil)
		sys->print("Could not create chan file : %r\n");


Can you directly compare structured types (e.g., tuples, lists)?

I have a program with two tuples like:

a:= (0,0);
b:= (1,1);

and when I try to compare them I get an error like

x.b:123 : cannot compare '(1,1)'  if type (int, int) 
to '(0,0)' of type (int, int)

You cannot compare structured types in Limbo.

I am getting compiler errors accessing members of an array.

I have a program in which I define an array of strings in the global declarations like:

s : array [10] of string;
s[4] = "Some String"

I get a compiler error. Similar thing happens if I do:

i : array [10] of int;
i[4] = 10;

In Limbo, declarations are of the form:

	identifier-list	: type;

In both statements, array [10] of string and array [10] of int are not data types, but rather allocated instances (both of size 10), and are expressions and not types. The correct way to perform the declaration is
identifier-list := expression;
Thus the corrected statements are
s := array [10] of string;
i := array [10] of int;

Can I "unload" a module to free memory it is occupying ?

I have a program that is consuming a lot of memory. I load twelve different modules at startup, but I do not need them halfway into the program. Is there some way to "unload" these modules after they are no longer needed, thereby reducing the memory footprint of my application ?

You can "unload" a module at any time by setting it's module handle to nil.


	my_module_handle : Module;
	my_module_handle = load Module Module->PATH;


	my_module_handle = nil;


Copyright (c) 2000 Ed Bacher, Phillip Stanley-Marbell, Gergely Fodemesi. All rights reserved.

All code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be nice (but not required).