Contents

Plan 9 Setup

Introduction

This page gives some notes about my own Plan 9 setup, and some of the shell scripts I use.

In summary, I use (all running on one machine) :-

The following sections describe how to reproduce my setup.

Bridged Networking

Using bridged networking on the VM host is essential, since it allows guests to behave just as though they were separate machines connected to the local network. They can ping the host, and vice versa, get their IP addresses via the local DHCP service, and so on.

Since I have a very simple setup on my host machine (static IP, no Ubuntu NetworkManager running), setting up bridged networking was very easy. I simply edited /etc/network/interfaces and restarted the network service. I can’t comment on other potential setups of course. For what it’s worth, here is my interfaces file :-

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
      bridge_ports enp0s31f6
      bridge_stp off
      bridge_maxwait 0
      bridge_fd 0
      address 10.3.7.14
      netmask 255.0.0.0
      network 10.0.0.0
      broadcast 10.255.255.255
      gateway 10.3.7.12
      dns-nameservers 10.3.7.14
      dns-search poges

# The primary network interface
#auto enp0s31f6
#iface enp0s31f6 inet dhcp

To restart networking, use :-

sudo service networking restart

I also run dnsmasq on the same machine, to provide both DNS and DHCP services.

u9fs

This is a program which I run on the host. It provides a 9P file server for the files on the host. This means I can mount a directory on the host and use it as my home directory on the Plan 9 VM. This enables easy editing and transfer of files, use of subversion, and so on.

To set this up, firstly download and compile the source, which can be obtained from https://github.com/unofficial-mirror/u9fs. See also the manpage for u9fs :- http://man.cat-v.org/plan_9/4/u9fs.

After compilation, save the resulting executable under /usr/local as follows :-

sudo cp u9fs /usr/local/sbin

Next, it is necessary to set up a systemd service. Download and save the following two files :-

Download u9fs@.service

[Unit]
Description=u9fs daemon

[Service]
ExecStart=-/usr/local/sbin/u9fs -m 65560 -a none
User=root
Group=root
StandardInput=socket

Download u9fs.socket

[Unit]
Description=u9fs daemon activation socket

[Socket]
ListenStream=564
KeepAlive=yes
Accept=yes

[Install]
WantedBy=sockets.target

and then copy them as follows :-

sudo cp u9fs\@.service /lib/systemd/system/
sudo cp u9fs.socket /lib/systemd/system/

Now to enable and start :-

sudo systemctl enable u9fs.socket
sudo systemctl start u9fs.socket

To see the status :-

systemctl status u9fs.socket

To disable :-

sudo systemctl stop u9fs.socket
sudo systemctl disable u9fs.socket

Now create a new directory to use as your home directory on Plan 9. Then, in that directory, extract this tar file. This includes the following :-

VirtualBox

Download the following iso https://9p.io/plan9/download/plan9.iso.bz2, and extract with :-

bunzip2 plan9.iso.bz2

Now set up a new VM in VirtualBox :-

Now start the VM and proceed with the installation. For the most part, just select the defaults. Some brief observations :-

Before restarting, remove the plan9.iso from the CD (“Settings/Storage” again). Then restart. When asked “root is from”, just press return; when prompted for a user, enter “glenda”.

Add a new user

The first step is to add a new user. After restarting, middle-click in the foremost window and select the “Scroll” option. the “term %” prompt should appear. Now enter the following commands, substituting two things :-

% con -l /srv/fscons
prompt: uname USER USER
prompt: uname sys +USER
prompt: uname adm +USER
prompt: fsys main create active/g sys sys d555
prompt: fsys main create active/mnt/gcon sys sys d555
prompt: fsys main create active/mnt/HOST sys sys d555
prompt: fsys all sync

Then type control-\ then q. Note however that at this point “\” may be the “#” key, because the keymap isn’t set up correctly. At least it is on my UK keyboard.

Finally, back at the “term %” prompt type “fshalt”. The disk should be synced. Now restart the VM and login as the new user. Note that an easy way to restart is to press control-t twice, followed by “r”. After restarting, ignore the error messages, and at the “%” prompt type “rio” to start the graphical interface. Open a new terminal window by right clicking and selecting “New”, and dragging out a new window.

Enter the commands :-

% ramfs
% acme /bin/termrc

The editor should appear. Note that the cursor up key doesn’t do what you would expect! So move the cursor using the mouse. Remove the L option from TIMESYNCARGS on the third line, so it reads

TIMESYNCARGS=(-ra100000000)

and uncomment the following two lines about DHCP (at about line 45) :-

if(! test -e /net/ipifc/0/ctl)
    ip/ipconfig

Save the file by middle-clicking on “Put” in the menu. Then middle-click “Exit”. Now enter “fshalt” and restart again. As before, enter “rio” to start the graphical interface.

Now networking should be functional. Check this with :-

# To see the routing table
% cat /net/iproute
# To ping HOST
% ip/ping HOST.DOMAIN

“.DOMAIN” is just the local domain. If that is not available, try using a numerical IP address instead.

Now run the following commands :-

% ramfs
% mkdir lib
% acme lib/profile

and type the following in before saving (“Put” and “Exit”) :-

srv -m HOST.DOMAIN HOST.DOMAIN /mnt/HOST
bind -c /mnt/HOST/home/USER/plan9 $home
hypervisor=vbox
cd
. lib/profile

Naturally you must change :-

Now type “fshalt” and restart again. At this point, the windowing system (now “riox” rather than “rio”) should start automatically, and provide a single terminal window. Now the following bindings should be in place :-

Check that these directories are correct with “ls”. The home directory should include sub-directories bin, lib and tmp, and /tmp should include a couple of C source files and an .ini file.

If this is working, then it means you can edit files in your home directory (and /tmp) either within Plan 9 or on your u9fs host.

Kernel compilation

Unfortunately at this point it is necessary to compile the kernel to fix a buffer size problem in the Intel network driver. At the same time we can optionally fix an input problem which will become annoying if your Linux desktop uses an “Alt-Tab” style window switcher. (The problem is that the pressing of the “Alt” key interacts with Plan 9 in such a way that it is misinterpreted as the multi-key compose key, resulting in missing or incorrect characters appear after the next keyboard input). If you don’t use “Alt-Tab”, or intend to just use drawterm, this second fix isn’t needed (but it’s harmless anyway of course).

As mentioned above, I have placed the two replacement files in the “tmp” directory of the home directory tar file, and so they can be found in the bound /tmp directory.

To proceed, firstly cd to the kernel source directory and copy the two files as follows :-

cd /sys/src/9/pc
# Mandatory - the Intel driver
cp /tmp/etherigbe.c .
# Optional - the Alt-Tab fix
cp /tmp/kbd.c .

Now recompile and save the resulting modified kernel :-

mk 'CONF=pcf'
9fat:
cp 9pcf /n/9fat
unmount /n/9fat

Now restart with “halt -r”.

Timezone

To set the timezone, select from those in the directory /adm/timezone, and copy it to the file local, also in that directory. In my case :-

cd /adm/timezone
cp GB-Eire local

Then restart for this to take effect.

Drawterm

Drawterm can now be used to provide a better graphics interface than VirtualBox’s PC graphics emulation. I use my own modified version, documented here. Most importantly, this provides a scaled display that works with modern HiDPI monitors.

The IP address of the Plan 9 VM is written (by lib/profile) to a file, “IP” in the home directory. A password, “admin”, is also set up in lib/profile. So now drawterm can be started with :-

# cd to your Plan 9 home directory
$ cd ~/plan9
# Get the IP address of the VM
$ IP=$( cat IP )
# Edit the username to your own
$ drawterm -c $IP -a $IP -u USER -p admin -R 1600x1000 

Boot menu

It is rather annoying to have to enter your username at every boot. A boot menu can avoid this, and also provide a higher resolution of the VM’s graphics emulation. The file configuring this is called “plan9.ini”, and a replacement is found in the “tmp” directory of the home directory tar file.

Since this must of course contain your username, the file must be edited. Replace the string “USER” with your own username. Then copy it to the boot directory as follows :-

9fat:
cp /n/9fat/plan9.ini /tmp/plan9.ini.orig
cp /tmp/plan9.ini /n/9fat
unmount /n/9fat

Now restart with “halt -r”.

Object Icon

I have added a few hooks to make it very easy to install Object Icon in this setup. If you wish to do so, run the following command (on Linux) in your Plan 9 home directory :-

svn co svn://svn.code.sf.net/p/objecticon/code/branches/plan9 objecticon

Then run (on Plan 9) :-

mkoi

Ignore any error messages like “stringwith: bad character set…”.

After successful completion :-

halt -r

On restart, oit, oix etc should be available.

To update the Object Icon directory, just run “svn up” from within it, and run “mkoi” again. There is no need to restart, that only applies to the initial build.

Riox

As mentioned above, two binaries, riox and l, are included in the “home tar” file. I periodically update these with bug fixes and improvements, and the latest sources can be downloaded from this page, and compiled.

Shell scripts

There are several scripts in the bin/rc directory, and a few simple rc functions defined in lib/rcextra, as follows :-

File utilities

System utilities

Namespace utilities

Miscellany

More on namespace utilities

As listed above, there are a few shell scripts which help work with namespaces, and a couple of these deserve further explanation.

The first one is twin. One notable feature of riox (and rio) is that opening a new shell window (via the “New” menu option) creates a new namespace for the shell to operate in. Therefore any mount in one shell will not be usable from any other shell window. This can be rather frustrating, especially when trying to work on a new file server. twin creates a new riox window (by using mount) and then attaches a new shell’s I/O to that window. All the while, the original namespace is retained (although the environment variables are copied). Thus mounts in the twin window are visible in the original window and vice versa. The prompt and label of the twin window are related to the original window, for easy identification. Thus if the original window were labelled “rc 20”, then the twin might be “twin 20.31”. 20 is the window ID ($wdir/winid) of the original, 31 the ID of the twin.

The second script, gcon, is a little more involved. At startup, lib/profile uses srvfs and mount to relay the contents of /n to /g. This mount will be copied into all derived namespaces. At the same time, the plumber is started. This includes a rule which runs a shell command when a particular string (“Local”) is sent to the plumber. Such a command will run in the same namespace which is having its /n relayed to /g. gcon starts a shell window which shares this namespace (it does this by sending a “Local”plumbing message).

All this is rather complicated, so an example will make it clear. Firstly, run gcon. A new shell window appears, with prompt and label set appropriately. Now mount something in /n, say by running “9fs sources” :-

G.32 % 9fs sources
post...
G.32 % l /n
9     a:    c   dist    kfs      paq   sources      tapefs  vac
9fat  b     c:  fossil  kremvax  sid   sourcesdump  temp
a     boot  d:  ftp     newwin   snap  sourcessnap  usb
G.32 % l /n/sources
9grid     adm      dist   lsr  patch  wiki
_sources  contrib  extra  nix  plan9  xen
G.32 %

Now go back to the original “normal” shell window. Here, /n/sources is of course empty, but /g is mounted, and provides a window into the other namespace’s /n, as follows :-

1 % l /n
9     a:    c   dist    kfs      paq   sources      tapefs  vac
9fat  b     c:  fossil  kremvax  sid   sourcesdump  temp
a     boot  d:  ftp     newwin   snap  sourcessnap  usb
1 % l /n/sources
1 % ns | grep /g
mount -c '#s/plumbspace' /g
1 % l /g/sources
9grid     adm      dist   lsr  patch  wiki
_sources  contrib  extra  nix  plan9  xen
1 % 

A command can be sent directly via the plumber, rather than starting a gcon window, as follows :-

1 % local 9fs sources

local is just a shell function that calls the plumb command. The disadvantage here is that the output of the command cannot easily be seen. It actually appears on the original /dev/cons, which can be captured by opening the file /dev/kprint. riostart runs a simple shell script, kprint, which does this and outputs the result to a window with the label “kprint”, which is initially hidden. So if we run :-

1 % local echo hello

then “hello” should appear in this “kprint” window. Personally, I much prefer to use gcon to get a normal shell interaction.

Contents