This is a port of some Plan 9 libraries and programs to Unix. * Obtaining the source Tarballs will be posted nightly (but only when there are updates!) at http://swtch.com/plan9port /usr/local/plan9 is the suggested location to keep the software. All the paths in the tarball begin with plan9/, so it's okay to unpack it directly in /usr/local. You can use CVS to obtain the very latest version and stay up-to-date. See below. * Building First, you need to extract the tarball or check out the CVS tree (see below for CVS). You should be able to install the tree anywhere -- tools check the environment variable $PLAN9 for the root of the tree. Most of them assume /usr/local/plan9 if $PLAN9 is not set. To build and install, cd into the plan9/ directory and run "./INSTALL". This will first build "mk" and then use mk to build the rest of the system, installing libraries in plan9/lib/ and binaries in plan9/bin/. There are a few shell scripts already included in bin -- B, E, and samsave. Arguably these directories should be broken up by architecture so that During the initial build of mk, you will likely see a message like Assembler messages: Error: can't open getcallerpc-386.s for reading getcallerpc-386.s: No error This is not a problem. The script tries to build getcallerpc from assembly and then C. As long as one of them succeeds, great. There are various directories that are not built by default. They are listed in the BUGGERED definitions in src/mkfile and src/cmd/mkfile. These aren't built because they're not quite ready for prime time. Either they don't actually build or they haven't been very well tested. As of this writing, factotum is buggered because it's not done yet, and Venti and vac are buggered because they've hardly been tested and are in a state of flux (they were both quite rewritten for the port). * Writing programs The bin/ directory contains shell scripts 9a, 9c, 9l, and 9ar that mimic the Plan 9 tools pretty well, except in the object names: "9c x.c" produces x.o not x.9, and "9l x.o" produces "a.out" not "9.out" or "o.out". Mkfiles look substantially the same as in Plan 9, with slightly different names for the included rules. The most significant difference is that, since there is no autolinker, the Plan 9 libraries needed must be named explicitly. The variable SHORTLIBS can be used to list them without giving paths, e.g.: SHORTLIBS=thread bio 9 The default is "SHORTLIBS=9". (Libc is known as lib9; libregexp is known as libregexp9; the rest of the libraries retain their usual names.) Various function names (like open, accept, dup, malloc) are #defined in order to provide routines that mimic the Plan 9 interface better (for example, open handles the OCEXEC flag). Lib9.h contains these definitions. Function "foo" is #defined to "p9foo". These definitions can cause problems in the rare case that other Unix headers are needed as well. To avoid this, #define NOPLAN9DEFINES before including lib9.h, and then add the p9 prefix yourself for the renamed functions you wish to use. * 9P servers and "name spaces" A few Plan 9 programs, notably the plumber and acme, are heavily dependent on the use of 9P to interact with other programs. Rather than rewrite them, they have been left alone. Via the helper program 9pserve, they post a Unix domain socket with a well-known name (for example, "acme" or "plumb") in the directory /tmp/ns.$USER.$DISPLAY. Clients connect to that socket and interact via 9P. 9pserve takes care of muxing the various clients of that socket onto a single 9P conversation with the actual server, just like the kernel does on Plan 9. The choice of "namespace" directory is meant to provide a different name space for each X11 session a user has. The environment variable $NAMESPACE overrides this. The command "namespace" prints the current name space directory. In order to run normal Unix commands with their input or output connected to a 9P server, there is a new 9P request "openfd" whose response contains a real Unix file descriptor. 9pserve handles this request by sending a normal open to the real 9P server and sending back one side of a pipe. Then 9pserver forks a thread to ferry bytes back and forth between its end of the pipe and the 9P conversation. This works reasonably well, but has the drawback that reads are no longer "demand-driven" (the ferry thread issues the reads and fills the pipe regardless of whether the other end of the pipe is being read) and writes cannot return errors (writes to the pipe by the application will always succeed even though the write in the ferry thread might actually draw an interesting error). This doesn't cause too many problems in practice, but is worth keeping in mind. The command "9p" interacts with a given server to read or write a particular file. Run "9p" for a usage message. * Plumbing There is a plumber. It expects to find a plumbing rule file in $HOME/lib/plumbing. $PLAN9/plumb/initial.plumbing is a good start. Sam and acme interact with the plumber as they do on Plan 9. (If there is no plumber, sam falls back to a named pipe as it always has on Unix.) Unlike on Plan 9, there is a "web" command whose purpose is to load files or URLs in a running web browser. Right now, only Mozilla Firebird and Opera are supported, but it should be easy to add others to the script. The plumbing rules in $PLAN9/plumb/basic know to run "web" to handle URLs. Because sam and acme read from the plumber using file descriptors (and therefore the openfd hack described above), if the editor exits, this fact is not noted until the ferry thread tries to write the next plumbing message to the pipe. At this point the ferry thread closes the corresponding plumber fid, but the plumber thinks the message has been sent -- the message is lost. The message did serve a purpose -- now the plumber knows there are no readers of the "edit" channel, so when it gets the next message it will start a new editor. This situation doesn't happen often, but it is worth keeping in mind. Both acme and sam try to raise themselves when they get plumbing messages. * Acme Acme works. Programs executed with the middle button interact with acme by the "openfd" trick described above. In a plain execution (as opposed to >prog or |prog), because of the delay introduced by the pipes, there is no guarantee that the command output will finish being displayed before the exit status notice is displayed. This can be annoying. There is a "win" shell. Of course, since we're on Unix, win can't tell when programs are reading from the tty, so proper input point management is right out the window. * Rio, 9term There is a 9wm-derived window manager called rio. Along with the terminal 9term, the emulation feels quite like Plan 9. * Window Placement All the graphical Plan 9 programs accept a new -W option that can be used to specify window size. The syntax is acme -W spec where spec can be WIDTHxHEIGHT, WIDTHxHEIGHT@XMIN,YMIN 'XMIN YMIN XMAX YMAX' or XMIN,YMIN,XMAX,YMAX. * Mouse scrolling The libraries pass along buttons 4 and 5, so if you have a scroll mouse and have X configured to send the up/down events as buttons 4 and 5, acme and 9term will scroll in response. You will likely need to change your X config to enable this. In my XF86Config-4 I have Section "InputDevice" Identifier "Mouse0" Driver "mouse" Option "Buttons" "5" Option "Emulate3Buttons" "off" Option "Protocol" "ImPS/2" Option "ZAxisMapping" "4 5" Option "Device" "/dev/psaux" EndSection You'll want to find your mouse section (which may have a different Identifier -- just leave it alone) and edit that. The "Buttons", "Protocol", "ZAxisMapping", and "Emulate3Buttons" lines are all important. * Helping out If you'd like to help out, great! The TODO file contains a small list. If you port this code to other architectures, please share your changes so others can benefit. See PORTING for some notes. Please use diff -u or CVS (see below) to prepare patches. * CVS You can use CVS to keep your local copy up-to-date as we make changes and fix bugs. The idioms explained here are pretty much all you need to know about CVS. To check out from the anonymous CVS repository, use cd /usr/local >$HOME/.cvspass cvs -d :pserver:anoncvs@cvs.pdos.lcs.mit.edu:/cvs login cvs -d :pserver:anoncvs@cvs.pdos.lcs.mit.edu:/cvs checkout plan9 When prompted for a password, just hit enter. If there is already a /usr/local/plan9 directory (from a previous unpacking), remove it or move it out of the way. You need write access to /usr/local in order to run the checkout, but after that you'll only need write access to the plan9 subtree. I typically run the initial checkout as root and then chown -R rsc plan9 so that I can do things as rsc afterward. From then on, when you want to update, you can do cd /usr/local/plan9 cvs update -dAP If there are conflicts between changes you have made locally and changes on the server, cvs will warn about them and leave them clearly marked in the updated files. If you change something and want to submit the change (please do!), you can run cd /usr/local/plan9 cvs diff -u to generate the diff in a format that will be easy to apply. (You can also use this to see what you've changed.) cvs diff -D20040101 -u shows you differences txixt your tree and the repository as of January 1, 2004. Running the cvs commands in /usr/local/plan9 makes them apply to the whole tree. Running them in a subdirectory applies only to the code rooted there in the code. There's not much magical about /usr/local/plan9. If you check out the tree in some other directory, it should work just as well. Thanks. Russ Cox