ref: c0172717d6d97c793847defd61d0fa8bf78f2fa3
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; case 'I': if(strcmp(ev.text, "") == 0) sendp(ctl, "send"); break; } } } char * readbody(AWin *w) { Biobuf *fd; char *buf; int i; fd = awinfsbopen(w, "body", OREAD); buf = Brdstr(fd, '\0', 0); Bterm(fd); for(i = strlen(buf)-1; i > 0; i--) { if(buf[i] == '' || buf[i] == '\n') buf[i] = '\0'; else break; } 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\n", 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("couldn't read channel: %r"); }; 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 dialchat(char *srv, char *mtpt) { int fd; if((fd = dial(srv, nil, nil, nil)) < 0) sysfatal("couldn't dial chat server: %r"); if(mount(fd, -1, mtpt, MREPL, "") == -1) sysfatal("couldn't mount chat server: %r"); } 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, *mtpt, *user, *chan; srv = "tcp!chat.9p.zone!9990"; mtpt = "/n/chat"; chan = "chat"; user = getuser(); ARGBEGIN { case 's': srv = EARGF(usage()); break; case 'm': mtpt = EARGF(usage()); break; case 'c': chan = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; default: usage(); } ARGEND dialchat(srv, mtpt); dochat(mtpt, chan, user); awincloseall(); threadexitsall(nil); }