summaryrefslogtreecommitdiff
path: root/sys/src/cmd/samterm/plan9.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/samterm/plan9.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/samterm/plan9.c')
-rwxr-xr-xsys/src/cmd/samterm/plan9.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/sys/src/cmd/samterm/plan9.c b/sys/src/cmd/samterm/plan9.c
new file mode 100755
index 000000000..a7e3d5b70
--- /dev/null
+++ b/sys/src/cmd/samterm/plan9.c
@@ -0,0 +1,299 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <frame.h>
+#include <plumb.h>
+#include "flayer.h"
+#include "samterm.h"
+
+static char exname[64];
+
+void
+usage(void)
+{
+ fprint(2, "usage: samterm [-a]\n");
+ threadexitsall("usage");
+}
+
+void
+getscreen(int argc, char **argv)
+{
+ char *t;
+
+ ARGBEGIN{
+ case 'a':
+ autoindent = 1;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(initdraw(panic1, nil, "sam") < 0){
+ fprint(2, "samterm: initdraw: %r\n");
+ threadexitsall("init");
+ }
+ t = getenv("tabstop");
+ if(t != nil)
+ maxtab = strtoul(t, nil, 0);
+ draw(screen, screen->clipr, display->white, nil, ZP);
+}
+
+int
+screensize(int *w, int *h)
+{
+ int fd, n;
+ char buf[5*12+1];
+
+ fd = open("/dev/screen", OREAD);
+ if(fd < 0)
+ return 0;
+ n = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ if (n != sizeof(buf)-1)
+ return 0;
+ buf[n] = 0;
+ if (h) {
+ *h = atoi(buf+4*12)-atoi(buf+2*12);
+ if (*h < 0)
+ return 0;
+ }
+ if (w) {
+ *w = atoi(buf+3*12)-atoi(buf+1*12);
+ if (*w < 0)
+ return 0;
+ }
+ return 1;
+}
+
+int
+snarfswap(char *fromsam, int nc, char **tosam)
+{
+ char *s1;
+ int f, n, ss;
+
+ f = open("/dev/snarf", 0);
+ if(f < 0)
+ return -1;
+ ss = SNARFSIZE;
+ if(hversion < 2)
+ ss = 4096;
+ *tosam = s1 = alloc(ss);
+ n = read(f, s1, ss-1);
+ close(f);
+ if(n < 0)
+ n = 0;
+ if (n == 0) {
+ *tosam = 0;
+ free(s1);
+ } else
+ s1[n] = 0;
+ f = create("/dev/snarf", 1, 0666);
+ if(f >= 0){
+ write(f, fromsam, nc);
+ close(f);
+ }
+ return n;
+}
+
+void
+dumperrmsg(int count, int type, int count0, int c)
+{
+ fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n",
+ count, type, count0, c, rcvstring());
+}
+
+void
+removeextern(void)
+{
+ remove(exname);
+}
+
+Readbuf hostbuf[2];
+Readbuf plumbbuf[2];
+
+void
+extproc(void *argv)
+{
+ Channel *c;
+ int i, n, which, *fdp;
+ void **arg;
+
+ arg = argv;
+ c = arg[0];
+ fdp = arg[1];
+
+ i = 0;
+ for(;;){
+ i = 1-i; /* toggle */
+ n = read(*fdp, plumbbuf[i].data, sizeof plumbbuf[i].data);
+ if(n <= 0){
+ fprint(2, "samterm: extern read error: %r\n");
+ threadexits("extern"); /* not a fatal error */
+ }
+ plumbbuf[i].n = n;
+ which = i;
+ send(c, &which);
+ }
+}
+
+void
+extstart(void)
+{
+ char buf[32];
+ int fd;
+ static int p[2];
+ static void *arg[2];
+
+ if(pipe(p) < 0)
+ return;
+ sprint(exname, "/srv/sam.%s", getuser());
+ fd = create(exname, 1, 0600);
+ if(fd < 0){ /* assume existing guy is more important */
+ Err:
+ close(p[0]);
+ close(p[1]);
+ return;
+ }
+ sprint(buf, "%d", p[0]);
+ if(write(fd, buf, strlen(buf)) <= 0)
+ goto Err;
+ close(fd);
+ /*
+ * leave p[0] open so if the file is removed the event
+ * library won't get an error
+ */
+ plumbc = chancreate(sizeof(int), 0);
+ arg[0] = plumbc;
+ arg[1] = &p[1];
+ proccreate(extproc, arg, 1024);
+ atexit(removeextern);
+}
+
+int
+plumbformat(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){
+ plumbfree(m);
+ return 0;
+ }
+ act = plumblookup(m->attr, "action");
+ if(act!=nil && strcmp(act, "showfile")!=0){
+ /* can't handle other cases yet */
+ plumbfree(m);
+ return 0;
+ }
+ addr = plumblookup(m->attr, "addr");
+ if(addr){
+ if(addr[0] == '\0')
+ addr = nil;
+ else
+ addr = strdup(addr); /* copy to safe storage; we'll overwrite data */
+ }
+ memmove(data, "B ", 2); /* we know there's enough room for this */
+ memmove(data+2, m->data, n);
+ n += 2;
+ if(data[n-1] != '\n')
+ data[n++] = '\n';
+ if(addr != nil){
+ if(n+strlen(addr)+1+1 <= READBUFSIZE)
+ n += sprint(data+n, "%s\n", addr);
+ free(addr);
+ }
+ plumbbuf[i].n = n;
+ plumbfree(m);
+ return 1;
+}
+
+void
+plumbproc(void *argv)
+{
+ Channel *c;
+ int i, n, which, *fdp;
+ void **arg;
+
+ arg = argv;
+ c = arg[0];
+ fdp = arg[1];
+
+ i = 0;
+ for(;;){
+ i = 1-i; /* toggle */
+ n = read(*fdp, plumbbuf[i].data, READBUFSIZE);
+ if(n <= 0){
+ 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);
+ }
+ }
+}
+
+int
+plumbstart(void)
+{
+ static int fd;
+ static void *arg[2];
+
+ plumbfd = plumbopen("send", OWRITE|OCEXEC); /* not open is ok */
+ fd = plumbopen("edit", OREAD|OCEXEC);
+ if(fd < 0)
+ return -1;
+ plumbc = chancreate(sizeof(int), 0);
+ if(plumbc == nil){
+ close(fd);
+ return -1;
+ }
+ arg[0] =plumbc;
+ arg[1] = &fd;
+ proccreate(plumbproc, arg, 4096);
+ return 1;
+}
+
+void
+hostproc(void *arg)
+{
+ Channel *c;
+ int i, n, which;
+
+ c = arg;
+
+ i = 0;
+ for(;;){
+ i = 1-i; /* toggle */
+ n = read(0, hostbuf[i].data, sizeof hostbuf[i].data);
+ if(n <= 0){
+ if(n==0){
+ if(exiting)
+ threadexits(nil);
+ werrstr("unexpected eof");
+ }
+ fprint(2, "samterm: host read error: %r\n");
+ threadexitsall("host");
+ }
+ hostbuf[i].n = n;
+ which = i;
+ send(c, &which);
+ }
+}
+
+void
+hoststart(void)
+{
+ hostc = chancreate(sizeof(int), 0);
+ proccreate(hostproc, hostc, 1024);
+}