diff options
Diffstat (limited to 'files')
-rw-r--r-- | files/djv.tar | bin | 0 -> 1822720 bytes | |||
-rw-r--r-- | files/djvmono.tar | bin | 0 -> 993280 bytes | |||
-rw-r--r-- | files/faces.patch | 105 | ||||
-rw-r--r-- | files/ndb.diff | 70 | ||||
-rw-r--r-- | files/websocket-webfs.patch | 565 |
5 files changed, 740 insertions, 0 deletions
diff --git a/files/djv.tar b/files/djv.tar Binary files differnew file mode 100644 index 0000000..5d60262 --- /dev/null +++ b/files/djv.tar diff --git a/files/djvmono.tar b/files/djvmono.tar Binary files differnew file mode 100644 index 0000000..1fb0c7d --- /dev/null +++ b/files/djvmono.tar diff --git a/files/faces.patch b/files/faces.patch new file mode 100644 index 0000000..3309c1b --- /dev/null +++ b/files/faces.patch @@ -0,0 +1,105 @@ +From 5595dbb332eae353832dbc2ad11ef92aeb8fcab0 +From: Peter Mikkelsen <peter@pmikkelsen.com> +Date: Mon, 28 Jun 2021 21:45:53 +0000 +Subject: [PATCH] Add -u flag to faces, making it only show unread messages. + +--- +diff 658757abed7be283e06bae3b1722fc2703334d74 5595dbb332eae353832dbc2ad11ef92aeb8fcab0 +--- a/sys/man/1/faces Sun Jun 27 02:13:58 2021 ++++ b/sys/man/1/faces Mon Jun 28 23:45:53 2021 +@@ -4,7 +4,7 @@ + .SH SYNOPSIS + .B faces + [ +-.B -ihc ++.B -ihcu + ] [ + .B -m + .I maildir +@@ -99,6 +99,15 @@ + rather than the current state of the mail box. + In particular, faces are not removed from the screen when messages are deleted. + Also, in this mode clicking button 1 in the display will clear the window. ++.PP ++The ++.B -u ++flag causes ++.I faces ++to read in the mailbox like with the ++.B -i ++flag, but it only shows the unread ones. ++When right-clicking on a message icon in this mode, the message is both plumbed and removed from the view. + .PP + .I Seemail + is an +--- a/sys/src/cmd/faces/main.c Sun Jun 27 02:13:58 2021 ++++ b/sys/src/cmd/faces/main.c Mon Jun 28 23:45:53 2021 +@@ -10,6 +10,7 @@ + int history = 0; /* use old interface, showing history of mailbox rather than current state */ + int initload = 0; /* initialize program with contents of mail box */ + int clickrm = 0; /* allows removing mail faces by left clicking */ ++int onlyunread = 0; /* initialize program with unread messages, remove when clicked */ + + enum + { +@@ -358,6 +359,28 @@ + unlockdisplay(display); + } + ++int ++isunread(char *dir, char *num) ++{ ++ char buf[1024], flags[8]; ++ int n, fd, unread; ++ ++ snprint(buf, sizeof(buf), "%s/%s/flags", dir, num); ++ fd = open(buf, OREAD); ++ if(fd < 0) ++ return 0; ++ n = readn(fd, flags, 7); ++ close(fd); ++ if(n != 7) ++ return 0; ++ flags[n] = '\0'; ++ if(strchr(flags, 's') != nil) ++ unread = 0; ++ else ++ unread = 1; ++ return unread; ++} ++ + void + loadmboxfaces(char *maildir) + { +@@ -370,7 +393,8 @@ + chdir(maildir); + while((n = dirread(dirfd, &d)) > 0){ + for(i=0; i<n; i++) +- addface(dirface(maildir, d[i].name)); ++ if(onlyunread && isunread(maildir, d[i].name)) ++ addface(dirface(maildir, d[i].name)); + free(d); + } + close(dirfd); +@@ -616,6 +640,10 @@ + for(i=first; i<last; i++) + if(ptinrect(p, facerect(i-first))){ + showmail(faces[i]); ++ if(onlyunread){ ++ delface(i); ++ flushimage(display, 1); ++ } + break; + } + unlockdisplay(display); +@@ -698,6 +726,10 @@ + break; + case 'c': + clickrm++; ++ break; ++ case 'u': ++ initload++; ++ onlyunread++; + break; + default: + usage(); diff --git a/files/ndb.diff b/files/ndb.diff new file mode 100644 index 0000000..b752cd4 --- /dev/null +++ b/files/ndb.diff @@ -0,0 +1,70 @@ +diff -r 4adb989bc93e sys/src/cmd/ndb/dblookup.c +--- a/sys/src/cmd/ndb/dblookup.c Tue Nov 03 20:47:14 2020 +0100 ++++ b/sys/src/cmd/ndb/dblookup.c Sun Nov 29 16:42:47 2020 +0100 +@@ -40,7 +40,7 @@ + static RR* srvrr(Ndbtuple*, Ndbtuple*); + static RR* txtrr(Ndbtuple*, Ndbtuple*); + +-static int implemented[Tall] = ++static int implemented[Tcaa] = + { + [Ta] 1, + [Taaaa] 1, +@@ -118,7 +118,7 @@ + rp = nil; + + if(type == Tall){ +- for (type = Ta; type < Tall; type++) ++ for (type = Ta; type < Tcaa; type++) + if(implemented[type]) + rrcat(&rp, dblookup(name, class, type, auth, ttl)); + +diff -r 4adb989bc93e sys/src/cmd/ndb/dn.c +--- a/sys/src/cmd/ndb/dn.c Tue Nov 03 20:47:14 2020 +0100 ++++ b/sys/src/cmd/ndb/dn.c Sun Nov 29 16:42:47 2020 +0100 +@@ -97,6 +97,7 @@ + [Tmailb] "mailb", + [Tmaila] "maila", + [Tall] "all", ++[Tcaa] "caa", + 0, + }; + +@@ -1042,7 +1043,7 @@ + { + int i; + +- for(i = 0; i <= Tall; i++) ++ for(i = 0; i <= Tcaa; i++) + if(rrtname[i] && strcmp(rrtname[i], atype) == 0) + return i; + +@@ -1061,7 +1062,7 @@ + int + rrsupported(int type) + { +- if(type < 0 || type >Tall) ++ if(type < 0 || type >Tcaa) + return 0; + return rrtname[type] != nil; + } +@@ -1891,7 +1892,7 @@ + char *t; + + t = nil; +- if(type >= 0 && type <= Tall) ++ if(type >= 0 && type <= Tcaa) + t = rrtname[type]; + if(t==nil){ + snprint(buf, len, "%d", type); +diff -r 4adb989bc93e sys/src/cmd/ndb/dns.h +--- a/sys/src/cmd/ndb/dns.h Tue Nov 03 20:47:14 2020 +0100 ++++ b/sys/src/cmd/ndb/dns.h Sun Nov 29 16:42:47 2020 +0100 +@@ -71,6 +71,7 @@ + Tmailb= 253, /* { Tmb, Tmg, Tmr } */ + Tmaila= 254, /* obsolete */ + Tall= 255, /* all records */ ++ Tcaa= 257, /* Certification authority restriction */ + + /* classes */ + Csym= 0, /* internal symbols */ diff --git a/files/websocket-webfs.patch b/files/websocket-webfs.patch new file mode 100644 index 0000000..77c44b0 --- /dev/null +++ b/files/websocket-webfs.patch @@ -0,0 +1,565 @@ +From 424bcc25db6c3de73678fe43d44e4b408cd0434d +From: Peter Mikkelsen <petermikkelsen10@gmail.com> +Date: Wed, 23 Jun 2021 15:44:24 +0000 +Subject: [PATCH] Initial buggy version of adding websocket support to webfs + + +It can create connections but doesn't handle errors very well yet. +--- +diff ce73821f3575921e24f839b21c7be60520a9dc42 424bcc25db6c3de73678fe43d44e4b408cd0434d +--- a/sys/src/cmd/webfs/fns.h Mon Jun 21 17:38:11 2021 ++++ b/sys/src/cmd/webfs/fns.h Wed Jun 23 17:44:24 2021 +@@ -41,3 +41,6 @@ + int authenticate(Url *u, Url *ru, char *method, char *s); + void flushauth(Url *u, char *t); + void http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost); ++ ++/* websocket */ ++void websocket(int fd, Buq *qbody, Buq *qpost); +--- a/sys/src/cmd/webfs/fs.c Mon Jun 21 17:38:11 2021 ++++ b/sys/src/cmd/webfs/fs.c Wed Jun 23 17:44:24 2021 +@@ -4,6 +4,7 @@ + #include <fcall.h> + #include <thread.h> + #include <9p.h> ++#include <libsec.h> + + #include "dat.h" + #include "fns.h" +@@ -19,10 +20,12 @@ + Url *baseurl; + Url *url; + Key *hdr; ++ int wantwebsocket; + + int obody; /* body opend */ + int cbody; /* body closed */ + Buq *qbody; ++ Buq *websocketin; /* websocket input */ + }; + + struct Webfid +@@ -121,6 +124,8 @@ + + buclose(cl->qbody, 0); + bufree(cl->qbody); ++ buclose(cl->websocketin, 0); ++ bufree(cl->websocketin); + + while(k = cl->hdr){ + cl->hdr = k->next; +@@ -384,6 +389,25 @@ + if(cl->qbody == nil){ + char *m; + ++ if(f->level == Qbody && (!strcmp(cl->url->scheme, "ws") || !strcmp(cl->url->scheme, "wss"))){ ++ cl->wantwebsocket = 1; ++ cl->websocketin = bualloc(64*1024); ++ if(!lookkey(cl->hdr, "Upgrade")) ++ cl->hdr = addkey(cl->hdr, "Upgrade", "websocket"); ++ if(!lookkey(cl->hdr, "Connection")) ++ cl->hdr = addkey(cl->hdr, "Connection", "upgrade"); ++ if(!lookkey(cl->hdr, "Sec-WebSocket-Version")) ++ cl->hdr = addkey(cl->hdr, "Sec-WebSocket-Version", "13"); ++ if(!lookkey(cl->hdr, "Sec-WebSocket-Key")){ ++ uchar nonce[16]; ++ char *b64nonce; ++ genrandom(nonce, 16); ++ b64nonce = smprint("%.*[", 16, nonce); ++ cl->hdr = addkey(cl->hdr, "Sec-WebSocket-Key", b64nonce); ++ free(b64nonce); ++ } ++ } ++ + if(cl->url == nil){ + respond(r, "no url set"); + return; +@@ -413,7 +437,7 @@ + if(agent && !lookkey(cl->hdr, "User-Agent")) + cl->hdr = addkey(cl->hdr, "User-Agent", agent); + +- http(m, cl->url, cl->hdr, cl->qbody, f->buq); ++ http(m, cl->url, cl->hdr, cl->qbody, cl->wantwebsocket ? cl->websocketin : f->buq); + cl->request[0] = 0; + cl->url = nil; + cl->hdr = nil; +@@ -683,6 +707,11 @@ + case Qpost: + bureq(f->buq, r); + return; ++ case Qbody: ++ if(f->client->wantwebsocket){ ++ bureq(f->client->websocketin, r); ++ return; ++ } + } + respond(r, "not implemented"); + } +--- a/sys/src/cmd/webfs/http.c Mon Jun 21 17:38:11 2021 ++++ b/sys/src/cmd/webfs/http.c Wed Jun 23 17:44:24 2021 +@@ -131,7 +131,7 @@ + if(strcmp(proxy->scheme, "https") == 0) + fd = tlswrap(fd, proxy->host); + } else { +- if(strcmp(u->scheme, "https") == 0) ++ if(strcmp(u->scheme, "https") == 0 || strcmp(u->scheme, "wss") == 0) + fd = tlswrap(fd, u->host); + } + if(fd < 0){ +@@ -520,7 +520,7 @@ + void + http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost) + { +- int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody, badauth; ++ int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody, badauth, wantwebsocket; + char *s, *x, buf[8192+2], status[256], method[16], *host; + vlong length, offset; + Url ru, tu, *nu; +@@ -549,8 +549,13 @@ + break; + } + ++ if(!strcmp(u->scheme, "ws") || !strcmp(u->scheme, "wss")) ++ wantwebsocket = 1; ++ else ++ wantwebsocket = 0; ++ + notify(catch); +- if(qpost){ ++ if(qpost && !wantwebsocket){ + /* file for spooling the postbody if we need to restart the request */ + snprint(buf, sizeof(buf), "/tmp/http.%d.%d.post", getppid(), getpid()); + fd = create(buf, OEXCL|ORDWR|ORCLOSE, 0600); +@@ -565,7 +570,7 @@ + badauth = 0; + for(try = 0; try < 12; try++){ + strcpy(status, "0 No status"); +- if(u == nil || (strcmp(u->scheme, "http") && strcmp(u->scheme, "https"))){ ++ if(u == nil || (strcmp(u->scheme, "http") && strcmp(u->scheme, "https") && strcmp(u->scheme, "ws") && strcmp(u->scheme, "wss"))){ + werrstr("bad url scheme"); + break; + } +@@ -591,7 +596,7 @@ + + length = 0; + chunked = 0; +- if(qpost){ ++ if(qpost && !wantwebsocket){ + /* have to read it to temp file to figure out the length */ + if(fd >= 0 && needlength && lookkey(shdr, "Content-Length") == nil){ + seek(fd, 0, 2); +@@ -700,7 +705,7 @@ + goto Retry; + } + +- if(qpost && !h->tunnel){ ++ if(qpost && !h->tunnel && !wantwebsocket){ + h->cancel = 0; + if((pid = rfork(RFMEM|RFPROC)) <= 0){ + int ifd; +@@ -802,8 +807,42 @@ + goto Status; + } + goto Error; +- case 100: /* Continue */ + case 101: /* Switching Protocols */ ++ if(wantwebsocket){ ++ int ok = 1; ++ char *wskey = lookkey(shdr, "Sec-WebSocket-Key"); ++ ++ k = getkey(rhdr, "Upgrade"); ++ if(k == nil || cistrcmp(k->val, "websocket") != 0) ++ ok = 0; ++ ++ k = getkey(rhdr, "Connection"); ++ if(k == nil && cistrcmp(k->val, "upgrade") != 0) ++ ok = 0; ++ ++ k = getkey(rhdr, "Sec-WebSocket-Accept"); ++ if(k == nil || wskey == nil) ++ ok = 0; ++ else{ ++ uchar digest[SHA1dlen]; ++ char *str = smprint("%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", wskey); ++ ++ sha1((uchar*)str, strlen(str), digest, nil); ++ char *val = smprint("%.*[", SHA1dlen, digest); ++ if(strcmp(val, k->val) != 0) ++ ok = 0; ++ free(str); ++ free(val); ++ } ++ ++ if(ok){ ++ qbody->url = u; u = nil; ++ qbody->hdr = rhdr; rhdr = nil; ++ websocket(h->fd, qbody, qpost); ++ } ++ goto Error; ++ } ++ case 100: /* Continue */ + case 102: /* Processing */ + case 103: /* Early Hints */ + while(k = rhdr){ +--- a/sys/src/cmd/webfs/mkfile Mon Jun 21 17:38:11 2021 ++++ b/sys/src/cmd/webfs/mkfile Wed Jun 23 17:44:24 2021 +@@ -3,6 +3,6 @@ + TARG=webfs + + HFILES=fns.h dat.h +-OFILES=sub.$O url.$O buq.$O http.$O fs.$O ++OFILES=sub.$O url.$O buq.$O http.$O websocket.$O fs.$O + + </sys/src/cmd/mkone +--- /dev/null Mon Jun 21 23:24:08 2021 ++++ b/sys/src/cmd/webfs/websocket.c Wed Jun 23 17:44:24 2021 +@@ -0,0 +1,349 @@ ++#include <u.h> ++#include <libc.h> ++#include <fcall.h> ++#include <thread.h> ++#include <9p.h> ++#include <libsec.h> ++ ++#include "dat.h" ++#include "fns.h" ++ ++typedef struct Frame Frame; ++typedef struct Message Message; ++ ++struct Frame ++{ ++ int final; ++ int opcode; ++ int masked; ++ uchar maskkey[4]; ++ uvlong length; ++ uchar *data; ++ ++ Frame *next; /* Chain frames in a message together */ ++}; ++ ++struct Message ++{ ++ int type; ++ uvlong length; ++ uchar *data; ++}; ++ ++enum { ++ ContinueFrame = 0x0, ++ TextFrame = 0x1, ++ BinaryFrame = 0x2, ++ CloseFrame = 0x8, ++ PingFrame = 0x9, ++ PongFrame = 0xA, ++}; ++ ++void writemessage(int, Message *); ++ ++void ++maskframe(Frame *f) ++{ ++ uvlong i; ++ for(i = 0; i < f->length; i++) ++ f->data[i] = f->data[i] ^ f->maskkey[i%4]; ++} ++ ++Frame * ++readframe(int fd) ++{ ++ Frame *f = malloc(sizeof(Frame)); ++ long n; ++ int offset; ++ uchar len; ++ ++ uchar buf[4096]; ++ ++Again: ++ offset = 0; ++ n = read(fd, buf, 2); ++ if(n != 2) ++ goto Error; ++ ++ f->final = (buf[offset] >> 7) & 0x1; ++ /* ignore rsv1, rsv2, rsv3 */ ++ f->opcode = buf[offset] & 0x0F; ++ offset++; ++ ++ f->masked = (buf[offset] >> 7) & 0x1; ++ len = buf[offset] & 0x7F; ++ offset++; ++ ++ if(len <= 125) ++ f->length = len; ++ else if(len == 126){ ++ n = read(fd, buf+offset, 2); ++ if(n != 2) ++ goto Error; ++ ++ f->length = buf[offset++] << 8; ++ f->length |= buf[offset++]; ++ }else if(len == 127){ ++ n = read(fd, buf+offset, 8); ++ if(n != 8) ++ goto Error; ++ f->length = (uvlong)buf[offset++] << 56; ++ f->length |= (uvlong)buf[offset++] << 48; ++ f->length |= (uvlong)buf[offset++] << 40; ++ f->length |= (uvlong)buf[offset++] << 32; ++ f->length |= buf[offset++] << 24; ++ f->length |= buf[offset++] << 16; ++ f->length |= buf[offset++] << 8; ++ f->length |= buf[offset++]; ++ } ++ ++ if(f->masked){ ++ n = read(fd, buf+offset, 4); ++ if(n != 4) ++ goto Error; ++ ++ f->maskkey[0] = buf[offset++]; ++ f->maskkey[1] = buf[offset++]; ++ f->maskkey[2] = buf[offset++]; ++ f->maskkey[3] = buf[offset]; ++ } ++ ++ f->data = malloc(f->length); ++ readn(fd, f->data, f->length); ++ if(f->masked) ++ maskframe(f); ++ ++ if(f->opcode == PingFrame){ ++ Message *m = malloc(sizeof(Message)); ++ m->type = PongFrame; ++ m->length = f->length; ++ m->data = f->data; ++ writemessage(fd, m); /* SHOULD LOCK */ ++ free(m); ++ free(f->data); ++ goto Again; ++ } ++ ++ return f; ++Error: ++ exits("Readframe failed"); ++ return nil; ++} ++ ++Message * ++framestomessage(Frame *frames) ++{ ++ Message *m = malloc(sizeof(Message)); ++ uvlong length = 0; ++ uvlong offset = 0; ++ ++ Frame *f; ++ for(f = frames; f != nil; f = f->next) ++ length += f->length; ++ ++ m->type = frames->opcode; ++ m->length = length; ++ m->data = malloc(length); ++ for(f = frames; f != nil; f = f->next){ ++ memcpy(m->data + offset, f->data, f->length); ++ offset += f->length; ++ } ++ ++ return m; ++} ++ ++Message * ++readmsg(int fd) ++{ ++ Frame *frames = readframe(fd); ++ Frame *last = frames; ++ Message *m; ++ ++ while(!last->final){ ++ last->next = readframe(fd); ++ last = last->next; ++ } ++ last->next = nil; ++ ++ m = framestomessage(frames); ++ while(frames){ ++ Frame *f = frames->next; ++ free(frames->data); ++ free(frames); ++ frames = f; ++ } ++ return m; ++} ++ ++void ++writeframe(int fd, Frame *f) ++{ ++ uchar *buf; ++ uvlong totsize = 0; ++ uvlong offset = 0; ++ int lenbytes = 0; ++ ++ totsize += 2; /* Always there */ ++ if(f->length == 126) ++ lenbytes = 2; ++ else if(f->length == 127) ++ lenbytes = 8; ++ totsize += lenbytes; ++ ++ if(f->masked) ++ totsize += 4; ++ ++ totsize += f->length; ++ ++ buf = malloc(totsize); ++ ++ buf[offset] = f->final << 7; ++ buf[offset++] |= f->opcode; ++ buf[offset] = f->masked << 7; ++ ++ if(lenbytes == 0) ++ buf[offset++] |= f->length; ++ else if(lenbytes == 2) ++ buf[offset++] |= 126; ++ else if(lenbytes == 8) ++ buf[offset++] |= 127; ++ ++ if(lenbytes == 2){ ++ buf[offset++] = 0xFF & (f->length >> 8); ++ buf[offset++] = 0xFF & f->length; ++ }else if(lenbytes == 8){ ++ buf[offset++] = 0xFF & (f->length >> 56); ++ buf[offset++] = 0xFF & (f->length >> 48); ++ buf[offset++] = 0xFF & (f->length >> 40); ++ buf[offset++] = 0xFF & (f->length >> 32); ++ buf[offset++] = 0xFF & (f->length >> 24); ++ buf[offset++] = 0xFF & (f->length >> 16); ++ buf[offset++] = 0xFF & (f->length >> 8); ++ buf[offset++] = 0xFF & f->length; ++ } ++ ++ if(f->masked){ ++ buf[offset++] = f->maskkey[0]; ++ buf[offset++] = f->maskkey[1]; ++ buf[offset++] = f->maskkey[2]; ++ buf[offset++] = f->maskkey[3]; ++ } ++ ++ memcpy(buf + offset, f->data, f->length); ++ write(fd, buf, totsize); ++} ++ ++void ++writemessage(int fd, Message *m) ++{ ++ /* Could split up the message into frames but not right now. */ ++ ++ Frame *f = malloc(sizeof(Frame)); ++ f->final = 1; ++ f->opcode = m->type; ++ f->masked = 1; ++ genrandom(f->maskkey, 4); ++ f->length = m->length; ++ f->data = malloc(f->length); ++ memcpy(f->data, m->data, f->length); ++ maskframe(f); ++ f->next = nil; ++ ++ writeframe(fd, f); ++ free(f->data); ++ free(f); ++} ++ ++void ++websocketrecv(int fd, Buq *qbody) ++{ ++ /* ++ * Plan: Read frames and when we have a whole message do: ++ * 1) If control, act on it ++ * 2) If data, format as text and buwrite it ++ */ ++ while(1){ ++ Message *m = readmsg(fd); ++ //print("Received message type=%d length=%ulld\n", m->type, m->length); ++ ++ if(m->type == TextFrame || m->type == BinaryFrame){ ++ char *header; ++ if(m->type == TextFrame) ++ header = smprint("t %0.20ulld", m->length); ++ else ++ header = smprint("b %0.20ulld", m->length); ++ buwrite(qbody, header, 22); ++ buwrite(qbody, m->data, m->length); ++ } ++ free(m->data); ++ free(m); ++ } ++} ++ ++void ++websocketsend(int fd, Buq *qpost) ++{ ++ /* buread messages and pack them up in frames and send them */ ++ char buf[64]; ++ long n; ++ Message *m; ++ while(1){ ++ n = buread(qpost, buf, 22); ++ if(n != 22){ ++ buclose(qpost, "Header short"); ++ return; ++ } ++ buf[n] = 0; ++ ++ m = malloc(sizeof(Message)); ++ if(buf[0] == 't') ++ m->type = TextFrame; ++ else if(buf[0] == 'b') ++ m->type = BinaryFrame; ++ ++ char *ret; ++ m->length = strtoull(buf+2, &ret, 10); ++ if(ret != buf+22){ ++ buclose(qpost, "Header format wrong"); ++ return; ++ } ++ ++ m->data = malloc(m->length); ++ n = 0; ++ while(n < m->length){ ++ uvlong missing = m->length - n; ++ n += buread(qpost, m->data + n, (missing < 8192) ? missing : 8192); ++ } ++ ++ writemessage(fd, m); ++ free(m->data); ++ free(m); ++ } ++} ++ ++void ++websocket(int fd, Buq *qbody, Buq *qpost) ++{ ++ buwrite(qbody, "websocket ready\n", 16); ++ switch(rfork(RFPROC|RFMEM)){ ++ default: ++ websocketrecv(fd, qbody); ++ break; ++ case 0: ++ websocketsend(fd, qpost); ++ goto End; ++ case -1: ++ buclose(qbody, "can't fork"); ++ bufree(qbody); ++ buclose(qpost, "can't fork"); ++ bufree(qpost); ++ break; ++ } ++End: ++ close(fd); ++ buclose(qbody, nil); ++ bufree(qbody); ++ buclose(qpost, nil); ++ bufree(qpost); ++ exits(nil); ++} |