ref: b59c7180abdd10cf3abe7fd1b58b17683b7436d8
author: james palmer <foura@biobuf.link>
date: Mon Jun 7 16:10:04 EDT 2021
init
--- /dev/null
+++ b/LICENSE
@@ -1,0 +1,19 @@
+Copyright © 2021 James Palmer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+++ b/main.c
@@ -1,0 +1,196 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <thread.h>
+#include <acme.h>
+
+typedef struct Session Session;
+struct Session {
+ AWin *cwin;
+ AWin *iwin;
+
+ char *mtpt;
+ char *chan;
+ char *usr;
+
+ Channel *ctl;
+
+ int fd;
+};
+
+enum { Stack = 4*1024, };
+
+void
+chatcatproc(void *aux)
+{
+ Session *s;
+ AWin *w;
+
+ w = aux;
+ s = w->aux;
+
+ awincat(w, s->fd);
+}
+
+void
+wineventproc(void *aux)
+{
+ AWin *w;
+ AEvent ev;
+ Session *s;
+ Channel *ctl;
+ Channel *eventc;
+
+ w = aux;
+ s = w->aux;
+ ctl = s->ctl;
+ eventc = aeventlisten(w);
+
+ while(recv(eventc, &ev)) {
+ switch(ev.type) {
+ case 'x':
+ if(strcmp(ev.text, "Del") == 0)
+ sendp(ctl, "quit");
+ if(strcmp(ev.text, "Send") == 0)
+ sendp(ctl, "send");
+ if(strcmp(ev.text, "Action") == 0)
+ sendp(ctl, "act");
+
+ break;
+ }
+ }
+}
+
+char *
+readbody(AWin *w)
+{
+ Biobuf *fd;
+ char *buf;
+
+ fd = awinfsbopen(w, "body", OREAD);
+ buf = Brdstr(fd, '\0', 0);
+ Bterm(fd);
+
+ awinclear(w);
+
+ return buf;
+}
+
+void
+domessage(Session *s, char *msg)
+{
+ char *buf;
+
+ if(msg[0] == '\0')
+ return;
+
+ buf = smprint("%s • %s\n", s->usr, msg);
+ write(s->fd, buf, strlen(buf));
+
+ free(buf);
+ free(msg);
+}
+
+void
+doaction(Session *s, char *msg)
+{
+ char *buf;
+
+ if(msg[0] == '\0')
+ return;
+
+ buf = smprint("* %s %s", s->usr, msg);
+ write(s->fd, buf, strlen(buf));
+
+ free(buf);
+ free(msg);
+}
+
+void
+dochat(char *mtpt, char *chan, char *usr)
+{
+ Session *s;
+ char buf[128];
+ char *ctl;
+
+ s = mallocz(sizeof(Session), 1);
+
+ s->mtpt = strdup(mtpt);
+ s->chan = strdup(chan);
+ s->usr = strdup(usr);
+
+ snprint(buf, sizeof(buf), "%s/%s", s->mtpt, s->chan);
+ s->fd = open(buf, ORDWR);
+ if(s->fd < 0) {
+ free(s->mtpt);
+ free(s->chan);
+ free(s->usr);
+ free(s);
+
+ sysfatal("chat server not mounted");
+ };
+
+ s->cwin = awincreate();
+ awinctl(s->cwin, "name /wired/chat\n");
+ awinctl(s->cwin, "scratch\n");
+ awinctl(s->cwin, "nomenu\n");
+ s->cwin->aux = s;
+
+ s->iwin = awincreate();
+ awinctl(s->iwin, "name /wired/input\n");
+ awinctl(s->iwin, "scratch\n");
+ awinctl(s->iwin, "nomenu\n");
+ awinsettag(s->iwin, " Send Action ");
+ s->iwin->aux = s;
+
+ s->ctl = chancreate(sizeof(char*), 0);
+
+ proccreate(chatcatproc, s->cwin, Stack);
+ proccreate(wineventproc, s->cwin, Stack);
+ proccreate(wineventproc, s->iwin, Stack);
+
+ while(ctl = recvp(s->ctl)) {
+ if(strcmp(ctl, "send") == 0)
+ domessage(s, readbody(s->iwin));
+ if(strcmp(ctl, "act") == 0)
+ doaction(s, readbody(s->iwin));
+ if(strcmp(ctl, "quit") == 0)
+ break;
+ }
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-s srv] [-c chan] [-u user]\n", argv0);
+ exits(nil);
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ char *srv, *user, *chan;
+
+ srv = "/n/chat";
+ chan = "chat";
+ user = getuser();
+
+ ARGBEGIN {
+ case 's':
+ srv = EARGF(usage());
+ break;
+ case 'c':
+ chan = EARGF(usage());
+ break;
+ case 'u':
+ user = EARGF(usage());
+ break;
+ default:
+ usage();
+ } ARGEND
+
+ dochat(srv, chan, user);
+
+ awincloseall();
+ threadexitsall(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+BIN=/acme/bin/$objtype
+TARG=Wired
+OFILES=main.$O
+
+</sys/src/cmd/mkone