tLittle tweaks and documentation. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit af78a4cd2b73800af86db8d999d80b1ef0e9bd75
 (DIR) parent efc2b0c99e1a4f9d2be9e72785d566df903c66fb
 (HTM) Author: rsc <devnull@localhost>
       Date:   Tue,  2 Mar 2004 23:11:58 +0000
       
       Little tweaks and documentation.
       
       Diffstat:
         M NOTES                               |     123 ++++++++++++++++++++++++++++---
         M TODO                                |      18 ------------------
         A bin/web                             |      35 +++++++++++++++++++++++++++++++
         M plumb/basic                         |      11 +++++++----
         M src/cmd/9term/9term.c               |       4 ++--
         M src/cmd/acme/look.c                 |       2 ++
         M src/cmd/samterm/mesg.c              |       6 +-----
         M src/cmd/samterm/mkfile              |       2 +-
         M src/cmd/samterm/plan9.c             |      34 ++++++++++---------------------
         M src/libdraw/x11-init.c              |       2 ++
         M src/libdraw/x11-wsys.c              |       5 ++++-
       
       11 files changed, 178 insertions(+), 64 deletions(-)
       ---
 (DIR) diff --git a/NOTES b/NOTES
       t@@ -1,9 +1,5 @@
        This is a port of some Plan 9 libraries and programs to Unix.
        
       -Some parts expect that the tree is installed in /usr/local/plan9.
       -Most are position independent.  The few hard-coded references
       -(there's one in sam) should really be fixed.
       -
        * Obtaining the source
        
        Tarballs will be posted nightly (but only when there are updates!) at
       t@@ -19,18 +15,125 @@ See below.
        
        * Building
        
       -To build, cd into src and run make; mk install.  This will place binaries
       -in "bin".  At time of writing, the commands are sam, samterm, rc, and mk.
       -There are a few shell scripts already included in bin -- B, Bwait,
       -and samsave.
       +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.
        
       -The "make" builds mk.  Mk builds the rest.
       +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, Bwait,
       +and samsave.  Arguably these directories should be broken up by
       +architecture so that
       +
       +* 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.
        
        * Helping out
        
        If you'd like to help out, great!
        
       -The TODO file contains our (somewhat long) to do list.
       +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.
 (DIR) diff --git a/TODO b/TODO
       t@@ -2,24 +2,6 @@
                - bug with discovery of initial window size in certain cases
                  (reported by Sean Dorward)
        
       -* Plumber
       -        - have named-pipe-based plumber from Caerwyn Jones
       -        - 9term right-click plumbs
       -        - plumb rules file runs B
       -        - easy to hook up web browser:
       -
       -# urls to web browser
       -type is text
       -data matches '(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero)://[a-zA-Z0-9_@\-]+([.:][a-zA-Z0-9_@\-]+)*/?[a-zA-Z0-9_?,%#~&/\-+=]+([:.][a-zA-Z0-9_?,%#~&/\-+=]+)*'
       -plumb to web
       -plumb start /usr/rsc/bin/web $0
       -
       -        - want to change back to 9P-based plumber, need to build
       -          infrastructure first
       -
       -* Acme
       -        - with 9P infrastructure, should "just work".
       -
        * upas/fs+Mail
                - with 9P infrastructure, should "just work".
        
 (DIR) diff --git a/bin/web b/bin/web
       t@@ -0,0 +1,35 @@
       +#!/bin/sh
       +
       +plumb1()
       +{
       +        case $BROWSER in
       +        # Other browsers here
       +        # ...
       +        *opera*)
       +                $BROWSER -remote 'openURL('$i', new-page)'
       +                ;;
       +        *firebird*)
       +                $BROWSER -remote 'openURL('$i', new-window)'
       +                ;;
       +        esac
       +}
       +
       +if [ $# = 0 ]
       +then
       +        plumb1 about:blank
       +else
       +        for i
       +        do
       +                if [ -f "$i" ]
       +                then
       +                        i=file://`pwd`/$i
       +                fi
       +                plumb1 $i
       +        done
       +fi
       +
       +case $BROWSER in
       +*opera*)
       +        $BROWSER -remote 'raise()'
       +esac
       +
 (DIR) diff --git a/plumb/basic b/plumb/basic
       t@@ -119,7 +119,10 @@ dst is postscript
        arg isfile $data
        plumb start gv $data
        
       -type        is        text
       -data        matches        'Local (.*)'
       -plumb        to        none
       -plumb        start        rc -c $1
       +# urls to internet explorer on another machine
       +type is text
       +data matches '(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero)://[a-zA-Z0-9_@\-]+([.:][a-zA-Z0-9_@\-]+)*/?[a-zA-Z0-9_?,%#~&/\-+=@]+([:.][@a-zA-Z0-9_?,%#~&/\-+=]+)*'
       +plumb to web
       +plumb start /usr/rsc/bin/web $0
       +# plumb start winstart iexplore -new $0
       +
 (DIR) diff --git a/src/cmd/9term/9term.c b/src/cmd/9term/9term.c
       t@@ -147,7 +147,7 @@ hostproc(void *arg)
                i = 0;
                for(;;){
                        i = 1-i;        /* toggle */
       -                n = read(rcfd[0], rcbuf[i].data, sizeof rcbuf[i].data);
       +                n = threadread(rcfd[0], rcbuf[i].data, sizeof rcbuf[i].data);
                        if(n <= 0){
                                if(n < 0)
                                        fprint(2, "9term: host read error: %r\n");
       t@@ -163,7 +163,7 @@ void
        hoststart(void)
        {
                hostc = chancreate(sizeof(int), 0);
       -        proccreate(hostproc, hostc, 32*1024);
       +        threadcreate(hostproc, hostc, 32*1024);
        }
        
        void
 (DIR) diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c
       t@@ -196,6 +196,7 @@ plumblook(Plumbmsg *m)
                openfile(nil, &e);
                free(e.name);
                free(e.u.at);
       +        drawtopwindow();
        }
        
        void
       t@@ -234,6 +235,7 @@ plumbshow(Plumbmsg *m)
                winsettag(w);
                textscrdraw(&w->body);
                textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc);
       +        drawtopwindow();
        }
        
        int
 (DIR) diff --git a/src/cmd/samterm/mesg.c b/src/cmd/samterm/mesg.c
       t@@ -25,7 +25,7 @@ long        invlong(int);
        void        hsetdot(int, long, long);
        void        hmoveto(int, long);
        void        hsetsnarf(int);
       -/* void        hplumb(int); */
       +void        hplumb(int);
        void        clrlock(void);
        int        snarfswap(char*, int, char**);
        
       t@@ -296,11 +296,9 @@ inmesg(Hmesg type, int count)
                        threadexitsall(nil);
                        break;
        
       -/*
                case Hplumb:
                        hplumb(m);
                        break;
       -*/
                }
        }
        
       t@@ -668,7 +666,6 @@ hsetsnarf(int nc)
                setcursor(mousectl, cursor);
        }
        
       -/*
        void
        hplumb(int nc)
        {
       t@@ -687,7 +684,6 @@ hplumb(int nc)
                }
                free(s);
        }
       -*/
        
        void
        hgrow(int m, long a, long new, int req)
 (DIR) diff --git a/src/cmd/samterm/mkfile b/src/cmd/samterm/mkfile
       t@@ -23,6 +23,6 @@ HFILES=\
        
        CFLAGS=$CFLAGS -I../sam
        LDFLAGS=$LDFLAGS -L$X11/lib -lX11 -lm
       -SHORTLIB=frame draw thread regexp9 bio 9
       +SHORTLIB=frame draw plumb fs mux thread regexp9 bio 9
        
        <$PLAN9/src/mkone
 (DIR) diff --git a/src/cmd/samterm/plan9.c b/src/cmd/samterm/plan9.c
       t@@ -10,6 +10,7 @@
        #include <cursor.h>
        #include <keyboard.h>
        #include <frame.h>
       +#include <plumb.h>
        #include "flayer.h"
        #include "samterm.h"
        
       t@@ -170,20 +171,15 @@ extstart(void)
                atexit(removeextern);
        }
        
       -#if 0
        int
       -plumbformat(int i)
       +plumbformat(Plumbmsg *m, int i)
        {
       -        Plumbmsg *m;
                char *addr, *data, *act;
                int n;
        
                data = (char*)plumbbuf[i].data;
       -        m = plumbunpack(data, plumbbuf[i].n);
       -        if(m == nil)
       -                return 0;
                n = m->ndata;
       -        if(n == 0){
       +        if(n == 0 || 2+n+2 >= READBUFSIZE){
                        plumbfree(m);
                        return 0;
                }
       t@@ -219,8 +215,9 @@ void
        plumbproc(void *argv)
        {
                Channel *c;
       -        int i, n, which, *fdp;
       +        int i, *fdp;
                void **arg;
       +        Plumbmsg *m;
        
                arg = argv;
                c = arg[0];
       t@@ -229,16 +226,14 @@ plumbproc(void *argv)
                i = 0;
                threadfdnoblock(*fdp);
                for(;;){
       -                i = 1-i;        /* toggle */
       -                n = threadread(*fdp, plumbbuf[i].data, READBUFSIZE);
       -                if(n <= 0){
       +                m = threadplumbrecv(*fdp);
       +                if(m == nil){
                                fprint(2, "samterm: plumb read error: %r\n");
                                threadexits("plumb");        /* not a fatal error */
                        }
       -                plumbbuf[i].n = n;
       -                if(plumbformat(i)){
       -                        which = i;
       -                        send(c, &which);
       +                if(plumbformat(m, i)){
       +                        send(c, &i);
       +                        i = 1-i;        /* toggle */
                        }
                }
        }
       t@@ -258,18 +253,11 @@ plumbstart(void)
                        close(fd);
                        return -1;
                }
       -        arg[0] =plumbc;
       +        arg[0] = plumbc;
                arg[1] = &fd;
                threadcreate(plumbproc, arg, STACK);
                return 1;
        }
       -#endif
       -
       -int
       -plumbstart(void)
       -{
       -        return -1;
       -}
        
        void
        hostproc(void *arg)
 (DIR) diff --git a/src/libdraw/x11-init.c b/src/libdraw/x11-init.c
       t@@ -124,6 +124,8 @@ xerror(XDisplay *d, XErrorEvent *e)
        {
                char buf[200];
        
       +        if(e->request_code == 42) /* XSetInputFocus */
       +                return 0;
                print("X error: error_code=%d, request_code=%d, minor=%d disp=%p\n",
                        e->error_code, e->request_code, e->minor_code, d);
                XGetErrorText(d, e->error_code, buf, sizeof buf);
 (DIR) diff --git a/src/libdraw/x11-wsys.c b/src/libdraw/x11-wsys.c
       t@@ -8,7 +8,10 @@
        void
        drawtopwindow(void)
        {
       -        XRaiseWindow(_x.display, _x.drawable);
       +        XMapRaised(_x.display, _x.drawable);
       +        XFlush(_x.display);
       +        XSetInputFocus(_x.display, _x.drawable, RevertToPointerRoot,
       +                CurrentTime);
                XFlush(_x.display);
        }