ref: 6f2fd5526607692e2e800d0a1efa72ee92a6b138
dir: /main.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <acme.h> char *srv = "tcp!9p.zone!9990"; char *mtpt = "/n/wired"; char *chan = "chat"; char *sep = "•"; char *nick; void connectsrv(void) { int fd; fd = dial(srv, nil, nil, nil); if(fd < 0) sysfatal("dial: %r"); if(mount(fd, -1, mtpt, MREPL, "") < 0) sysfatal("mount: %r"); } AWin * makewin(char *name, Channel *c) { AWin *win; win = awincreate(); win->aux = c; fprint(win->ctlfd, "name /wired/%s/%s\n", chan, name); fprint(win->ctlfd, "scratch\nnomenu\n"); return win; } void readproc(void *aux) { AWin *win; char *file; char buf[8192]; int fd; long n; threadsetname("read"); win = aux; file = smprint("%s/%s", mtpt, chan); if(!file) { awincloseall(); sysfatal("smprint failed"); } fd = open(file, OREAD); if(fd < 0) { awincloseall(); sysfatal("channel not found"); } while((n = read(fd, buf, sizeof(buf))) > 0) write(win->bodyfd, buf, n); awincloseall(); sysfatal("failed to read channel"); } void eventproc(void *aux) { AWin *win; Channel *events; AEvent ev; threadsetname("event"); win = aux; events = win->aux; win->eventfd = awinfsopen(win, "event", ORDWR); while(aeventnext(win, &ev)) { switch(ev.type) { case 'L': case 'l': aeventsend(win, &ev); break; default: send(events, &ev); } } threadexits(nil); } void filter(char *s) { int len; int i, j; /* strip eot */ j = 0; len = strlen(s); for(i = 0; i < len; i++) { if(s[i] != '') { s[j] = s[i]; j++; } } s[j] = 0; /* strip trailing nl */ len = strlen(s); for(i = len-1; i > 0; i--) if(s[i] == '\n') s[i] = 0; else break; } void writemessage(char *prefix, AWin *win) { int fd; char *file; char buf[4096]; long n; file = smprint("%s/%s", mtpt, chan); if(!file) { awincloseall(); sysfatal("smprint failed"); } fd = open(file, OWRITE); if(fd < 0) { awincloseall(); sysfatal("couldn't write channel"); } /* read the input window in 4096 byte chunks. * if the message is too large it will be split awkwardly :( * hopefully nobody needs a message that large */ fprint(win->addrfd, ","); while((n = read(win->datafd, buf, sizeof(buf)-1)) > 0) { /* null terminate and filter */ buf[n] = '\0'; filter(buf); /* no blank messages */ if(buf[0] == 0) return; fprint(fd, "%s %s\n", prefix, buf); }; close(fd); /* clear: use of buf here means nothing, the write is 0 bytes. * it is only there to prevent a crash due to a bad syscall. */ fprint(win->addrfd, ","); write(win->datafd, buf, 0); } void sendmessage(AWin *win) { char *prefix; prefix = smprint("%s %s", nick, sep); if(!prefix) { awincloseall(); sysfatal("smprint failed"); } writemessage(prefix, win); free(prefix); } void sendaction(AWin *win) { char *prefix; prefix = smprint("* %s", nick); if(!prefix) { awincloseall(); sysfatal("smprint failed"); } writemessage(prefix, win); free(prefix); } void usage(void) { fprint(2, "usage: %s [-s srv] [-n nick] [channel...]", argv0); threadexitsall(nil); } void threadmain(int argc, char *argv[]) { AWin *log, *input; Channel *events; AEvent ev; nick = getuser(); ARGBEGIN { case 'u': nick = EARGF(usage()); break; case 's': srv = EARGF(usage()); break; case 'c': chan = EARGF(usage()); break; } ARGEND connectsrv(); events = chancreate(sizeof(AEvent), 0); log = makewin("log", events); input = makewin("input", events); awinsettag(input, " Send Act "); proccreate(readproc, log, 16*1024); proccreate(eventproc, log, 8*1024); proccreate(eventproc, input, 8*1024); while(recv(events, &ev)) { switch(ev.type) { case 'x': case 'X': if(strcmp(ev.text, "Del") == 0) goto quit; if(strcmp(ev.text, "Send") == 0) sendmessage(input); if(strcmp(ev.text, "Act") == 0) sendaction(input); break; case 'I': /* there is an EOT char here, it allows ctrl+d to send */ if(strchr(ev.text, '')) sendmessage(input); } } quit: unmount(nil, mtpt); awincloseall(); threadexitsall(nil); }