From af78a4cd2b73800af86db8d999d80b1ef0e9bd75 Mon Sep 17 00:00:00 2001 From: rsc Date: Tue, 2 Mar 2004 23:11:58 +0000 Subject: Little tweaks and documentation. --- NOTES | 123 ++++++++++++++++++++++++++++++++++++++++++++---- TODO | 18 ------- bin/web | 35 ++++++++++++++ plumb/basic | 11 +++-- src/cmd/9term/9term.c | 4 +- src/cmd/acme/look.c | 2 + src/cmd/samterm/mesg.c | 6 +-- src/cmd/samterm/mkfile | 2 +- src/cmd/samterm/plan9.c | 34 +++++-------- src/libdraw/x11-init.c | 2 + src/libdraw/x11-wsys.c | 5 +- 11 files changed, 178 insertions(+), 64 deletions(-) create mode 100755 bin/web diff --git a/NOTES b/NOTES index 7b1f7309..7c695506 100644 --- a/NOTES +++ b/NOTES @@ -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 @@ -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. diff --git a/TODO b/TODO index e09311a6..7ca8745f 100644 --- a/TODO +++ b/TODO @@ -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". diff --git a/bin/web b/bin/web new file mode 100755 index 00000000..39615200 --- /dev/null +++ b/bin/web @@ -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 + diff --git a/plumb/basic b/plumb/basic index 918cc51b..23fd7adc 100644 --- a/plumb/basic +++ b/plumb/basic @@ -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 + diff --git a/src/cmd/9term/9term.c b/src/cmd/9term/9term.c index cfee0013..41a0a2f7 100644 --- a/src/cmd/9term/9term.c +++ b/src/cmd/9term/9term.c @@ -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"); @@ -163,7 +163,7 @@ void hoststart(void) { hostc = chancreate(sizeof(int), 0); - proccreate(hostproc, hostc, 32*1024); + threadcreate(hostproc, hostc, 32*1024); } void diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c index ca7eba42..6b259288 100644 --- a/src/cmd/acme/look.c +++ b/src/cmd/acme/look.c @@ -196,6 +196,7 @@ plumblook(Plumbmsg *m) openfile(nil, &e); free(e.name); free(e.u.at); + drawtopwindow(); } void @@ -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 diff --git a/src/cmd/samterm/mesg.c b/src/cmd/samterm/mesg.c index 0bffad3d..20528431 100644 --- a/src/cmd/samterm/mesg.c +++ b/src/cmd/samterm/mesg.c @@ -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**); @@ -296,11 +296,9 @@ inmesg(Hmesg type, int count) threadexitsall(nil); break; -/* case Hplumb: hplumb(m); break; -*/ } } @@ -668,7 +666,6 @@ hsetsnarf(int nc) setcursor(mousectl, cursor); } -/* void hplumb(int nc) { @@ -687,7 +684,6 @@ hplumb(int nc) } free(s); } -*/ void hgrow(int m, long a, long new, int req) diff --git a/src/cmd/samterm/mkfile b/src/cmd/samterm/mkfile index 67997f39..facc78d2 100644 --- a/src/cmd/samterm/mkfile +++ b/src/cmd/samterm/mkfile @@ -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 diff --git a/src/cmd/samterm/plan9.c b/src/cmd/samterm/plan9.c index 60ef5c0e..7c4ed39b 100644 --- a/src/cmd/samterm/plan9.c +++ b/src/cmd/samterm/plan9.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "flayer.h" #include "samterm.h" @@ -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; } @@ -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]; @@ -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 */ } } } @@ -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) diff --git a/src/libdraw/x11-init.c b/src/libdraw/x11-init.c index fb6a9144..1283f430 100644 --- a/src/libdraw/x11-init.c +++ b/src/libdraw/x11-init.c @@ -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); diff --git a/src/libdraw/x11-wsys.c b/src/libdraw/x11-wsys.c index ac4aa40c..e27202f5 100644 --- a/src/libdraw/x11-wsys.c +++ b/src/libdraw/x11-wsys.c @@ -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); } -- cgit v1.2.3