ref: c6b15096dd0493dbe7a91cdfd3330dc2218b90d3
dir: /main.c/
#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); }