#include <u.h>#include <libc.h>#include <bio.h>#include <draw.h> char help[] ="cmd explanation/example\n""--------------------------------------------\n""/m privmsg #chan/nick message\n""/M mode #chan +nt\n""/j join #chan\n""/p part #chan\n""/q send parameters raw to the server\n""/l list #chan\n""/n nick newnick\n""/N notice #chan/nick message\n""/t set victim\n""/T topic #chan newtopic\n""/W whois nick\n""/w who nick (a shorter whois)\n"; #define NPAR 14 enum state { Cmd, Prefix, Middle, Trail, Ok }; typedef struct handler Handler; struct handler { char *cmd; int (*fun)(int fd, char *pre, char *cmd, char *par[]);}; QLock lck;int server_in;int server_out;int scr;char *victim;char *nick;char *unick;int inacme; /* running in acme? */int linewidth; /* terminal width in # of characters */ int replay; /* just print the log ma'am */ void setwintitle(char *chan); int rtcs(int fd, char *cset);int wtcs(int fd, char *cset);int follow(int fd);void getwidth(void); /* establish the width of the terminal, from mc.c */ int pmsg(int fd, char *pre, char *cmd, char *par[]);int ntc(int fd, char *pre, char *cmd, char *par[]);int generic(int fd, char *pre, char *cmd, char *par[]);int misc(int fd, char *pre, char *cmd, char *par[]);int numeric(int fd, char *pre, char *cmd, char *par[]); Handler handlers[] = { {"PRIVMSG", pmsg}, {"NOTICE", ntc}, {"JOIN", misc}, {"PART", misc}, {"MODE", misc}, {"QUIT", misc}, {"TOPIC", misc}, {"332", numeric}, {"333", numeric}, {"352", numeric}, {"315", numeric}, {"311", numeric}, {"319", numeric}, {"312", numeric}, {"320", numeric}, {"317", numeric}, {"318", numeric}, {nil, nil}}; int srvparse(char *line, char **pre, char **cmd, char *par[], int npar);int usrparse(char *ln, char *cmd, char *par[], int npar); voidusage(void){ char usage[] = "usage: irc [-S] [-c charset] [-t victim] [-b lines] [-n nick] [-r file] [/srv/irc] [/tmp/irc]\n"; write(1, usage, sizeof(usage)-1); exits("usage");} voidsetwintitle(char *chan){ int fd; // if /dev/acme doesn't exist you're probably in a normal window // otherwise you can't set the title in a windowless window if ((fd = open("/dev/acme/ctl", OWRITE)) >= 0) { fprint(fd, "name -IRC/%s/guide\n", chan); close(fd); inacme = 1; } else if ((fd = open("/dev/label", OWRITE)) >= 0) { fprint(fd, "%s", chan); close(fd); }} /* try to find out whether we're running in acme's win -e */inttestacme(void){ return access("/dev/acme", OREAD) >= 0 ? 1 : 0;} voidusrin(void){ char *line, *p; char *par[2]; char cmd; int n, i; Biobuf kbd; Binit(&kbd, 0, OREAD); while ((line = Brdstr(&kbd, '\n', 0)) != nil) { n = utflen(line); if(!inacme) { p = malloc(n); for (i = 0; i < n; ++i) p[i] = '\b'; write(scr, p, i); free(p); } qlock(&lck); if (!usrparse(line, &cmd, par, 2)) { switch(cmd) { case 'q': /* quote, just send the params ... */ if(par[0]) { fprint(server_out, "%s %s\r\n", par[0], par[1] ? par[1] : ""); } else { fprint(scr, "/q %s %s: not enough arguments\n", par[0], par[1]); } break; case 'M': if(par[0] && par[1]) { fprint(server_out, "MODE %s %s\r\n", par[0], par[1]); } else { fprint(scr, "/M %s %s: not enough arguments\n", par[0], par[1]); } break; case 'm': if(par[0] && par[1]) { fprint(server_out, "PRIVMSG %s :%s\r\n", par[0], par[1]); } else { fprint(scr, "/m %s %s: not enough arguments\n", par[0], par[1]); } break; case 't': if(par[0] != nil) { free(victim); victim = strdup(par[0]); setwintitle(par[0]); } fprint(scr, "*** default victim set to '%s'\n", par[0]); break; case 'T': if(par[0] == nil) fprint(server_out, "TOPIC %s\r\n", victim); else if(par[1] == nil) fprint(server_out, "TOPIC %s\r\n", par[0]); else fprint(server_out, "TOPIC %s :%s\r\n", par[0], par[1]); break; case 'j': fprint(server_out, "JOIN %s\r\n", par[0] == nil ? victim : par[0]); break; case 'p': fprint(server_out, "PART %s\r\n", par[0] == nil ? victim : par[0]); break; case 'n': if(par[0] != nil) { fprint(server_out, "NICK %s\r\n", par[0]); free(nick); nick = strdup(par[0]); unick = strdup(par[0]); } else { fprint(scr, "%s", help); } break; case 'N': if(par[1] != nil) fprint(server_out, "NOTICE %s :%s\r\n", par[0] == nil ? victim : par[0], par[1]); break; case 'W': fprint(server_out, "WHOIS %s %s\r\n", par[0] == nil ? victim : par[0], par[0]); case 'w': fprint(server_out, "WHO %s\r\n", par[0] == nil ? victim : par[0]); break; case 'l': fprint(server_out, "LIST %s\r\n", par[0] == nil ? victim : par[0]); break; case 'L': fprint(server_out, "NAMES %s\r\n", par[0] == nil ? victim : par[0]); break; case 'f': break; case 'h': case 'H': fprint(scr, "%s", help); break; } } else { fprint(scr, "%s", help); } qunlock(&lck); free(line); } exits(0);} voidsrvin(void){ char *line; char *pre, *cmd, *par[NPAR]; Biobuf srv; Binit(&srv, server_in, OREAD); while ((line = Brdstr(&srv, '\n', 0)) != nil) { if (!srvparse(line, &pre, &cmd, par, NPAR)) { Handler *hp = handlers; qlock(&lck); while (hp->cmd != nil) { if (!strcmp(hp->cmd, cmd)) { hp->fun(server_out, pre, cmd, par); break; } ++hp; } if (hp->cmd == nil) generic(server_out, pre, cmd, par); qunlock(&lck); } free(line); }} voidreplayfile(void){ char *line; char *pre, *cmd, *par[NPAR]; Biobuf srv; Binit(&srv, server_in, OREAD); while ((line = Brdstr(&srv, '\n', 0)) != nil) { if (!srvparse(line, &pre, &cmd, par, NPAR)) { Handler *hp = handlers; qlock(&lck); while (hp->cmd != nil) { if (!strcmp(hp->cmd, cmd)) { hp->fun(server_out, pre, cmd, par); break; } ++hp; } if (hp->cmd == nil) generic(server_out, pre, cmd, par); qunlock(&lck); } free(line); }} /* * display the last N lines from the conversation * if we have a default target only the conversation with * that target will be shown */voidseekback(int fd, int lines){ Biobuf srv; int found = 0, off; char c, *line; if(lines < 0) return; Binit(&srv, fd, OREAD); Bseek(&srv, -2, 2); while(((off = Boffset(&srv)) > 0) && found < lines) { c = Bgetc(&srv); Bungetc(&srv); if(c == '\n') { Bseek(&srv, 1, 1); line = Brdstr(&srv, '\n', '\0'); if(victim) { if(cistrstr(line, victim)) found++; } else { found++; } free(line); } Bseek(&srv, off-1, 0); } Bterm(&srv);} voidmain(int argc, char *argv[]){ char *charset = nil; char buf[32], buf2[32], *out = nil, *in = nil; char *user; int olduser = 0; char *arg; int sb = 10; /* how many lines are we displaying initially */ int uipid; int scroll = 1; int wctlfd; unick = nil; user = getuser(); ARGBEGIN { case 't': victim = strdup(EARGF(usage())); break; case 'b': arg = ARGF(); if(arg != nil && arg[0] != '-') sb = atoi(arg); else sb = 0; /* show all text */ break; case 'c': charset = EARGF(usage()); break; case 'r': replay = 1; sb = 0; break; case 'o': olduser = 1; break; case 'n': unick = strdup(EARGF(usage())); break; case 'S': scroll = 0; break; default: usage(); } ARGEND; switch(argc) { case 0: break; case 1: if(replay) in = argv[0]; else out = argv[0]; break; case 2: out = argv[0]; in = argv[1]; break; default: usage(); } if(out == nil && in == nil){ if(olduser == 1 && strlen(user) > 4) user[4] = '\0'; snprint(buf, sizeof buf, "/srv/%sirc", user); snprint(buf2, sizeof buf, "/tmp/%sirc", user); out = strdup(buf); in = strdup(buf2); } if(unick == nil) unick = strdup(user); if(scroll == 1){ if((wctlfd = open("/dev/wctl", OWRITE)) < 0) print("irc: could not open /dev/wctl: %r\n"); else { fprint(wctlfd, "scroll\n"); close(wctlfd); } } if(!replay && (server_out = open(out, OWRITE)) < 0) sysfatal("open write: %s %r", out); if ((server_in = open(in, OREAD)) < 0) sysfatal("open read: %s %r", in); inacme = testacme(); getwidth(); if(sb) seekback(server_in, sb); while(read(server_in, buf, 1) > 0) if(*buf == '\n') break; if(victim && cistrncmp(victim, "MSGS", 4)){ setwintitle(victim); fprint(server_out, "JOIN %s\r\n", victim); } scr = 1; server_in = follow(server_in); if (charset != nil && strcmp(charset, "utf")) { server_out = wtcs(server_out, charset); server_in = rtcs(server_in, charset); } if(replay) { replayfile(); } else { if ((uipid = rfork(RFPROC|RFFDG|RFMEM)) == 0) srvin(); usrin(); postnote(PNPROC, uipid, "kill"); while (waitpid() != uipid); } exits(0);} intwtcs(int fd, char *cset){ int totcs[2]; int pid; pipe(totcs); pid = fork(); if (pid == 0) { dup(totcs[0], 0); dup(fd, 1); close(totcs[1]); execl("/bin/tcs", "tcs", "-f", "utf", "-t", cset, nil); exits("execfailure"); } close(totcs[0]); return totcs[1];} intrtcs(int fd, char *cset){ int fromtcs[2]; int pid; pipe(fromtcs); pid = fork(); if (pid == 0){ dup(fromtcs[1], 1); dup(fd, 0); close(fromtcs[0]); execl("/bin/tcs", "tcs", "-f", cset, "-t", "utf", nil); exits("execfailure"); } close(fromtcs[1]); return fromtcs[0];} intfollow(int fd){ int p[2], pid; long n; char buf[1024]; Dir *dp; pipe(p); pid = fork(); if (pid == 0){ dup(p[1], 1); dup(fd, 0); close(p[0]); for(;;){ while((n = read(0, buf, sizeof(buf))) > 0) write(1, buf, n); sleep(1000);Lines 1–500 of 838. Load more
#include <u.h> #include <libc.h> #include <bio.h> #include <draw.h> char help[] = "cmd explanation/example\n" "--------------------------------------------\n" "/m privmsg #chan/nick message\n" "/M mode #chan +nt\n" "/j join #chan\n" "/p part #chan\n" "/q send parameters raw to the server\n" "/l list #chan\n" "/n nick newnick\n" "/N notice #chan/nick message\n" "/t set victim\n" "/T topic #chan newtopic\n" "/W whois nick\n" "/w who nick (a shorter whois)\n"; #define NPAR 14 enum state { Cmd, Prefix, Middle, Trail, Ok }; typedef struct handler Handler; struct handler { char *cmd; int (*fun)(int fd, char *pre, char *cmd, char *par[]); }; QLock lck; int server_in; int server_out; int scr; char *victim; char *nick; char *unick; int inacme; /* running in acme? */ int linewidth; /* terminal width in # of characters */ int replay; /* just print the log ma'am */ void setwintitle(char *chan); int rtcs(int fd, char *cset); int wtcs(int fd, char *cset); int follow(int fd); void getwidth(void); /* establish the width of the terminal, from mc.c */ int pmsg(int fd, char *pre, char *cmd, char *par[]); int ntc(int fd, char *pre, char *cmd, char *par[]); int generic(int fd, char *pre, char *cmd, char *par[]); int misc(int fd, char *pre, char *cmd, char *par[]); int numeric(int fd, char *pre, char *cmd, char *par[]); Handler handlers[] = { {"PRIVMSG", pmsg}, {"NOTICE", ntc}, {"JOIN", misc}, {"PART", misc}, {"MODE", misc}, {"QUIT", misc}, {"TOPIC", misc}, {"332", numeric}, {"333", numeric}, {"352", numeric}, {"315", numeric}, {"311", numeric}, {"319", numeric}, {"312", numeric}, {"320", numeric}, {"317", numeric}, {"318", numeric}, {nil, nil} }; int srvparse(char *line, char **pre, char **cmd, char *par[], int npar); int usrparse(char *ln, char *cmd, char *par[], int npar); void usage(void) { char usage[] = "usage: irc [-S] [-c charset] [-t victim] [-b lines] [-n nick] [-r file] [/srv/irc] [/tmp/irc]\n"; write(1, usage, sizeof(usage)-1); exits("usage"); } void setwintitle(char *chan) { int fd; // if /dev/acme doesn't exist you're probably in a normal window // otherwise you can't set the title in a windowless window if ((fd = open("/dev/acme/ctl", OWRITE)) >= 0) { fprint(fd, "name -IRC/%s/guide\n", chan); close(fd); inacme = 1; } else if ((fd = open("/dev/label", OWRITE)) >= 0) { fprint(fd, "%s", chan); close(fd); } } /* try to find out whether we're running in acme's win -e */ int testacme(void) { return access("/dev/acme", OREAD) >= 0 ? 1 : 0; } void usrin(void) { char *line, *p; char *par[2]; char cmd; int n, i; Biobuf kbd; Binit(&kbd, 0, OREAD); while ((line = Brdstr(&kbd, '\n', 0)) != nil) { n = utflen(line); if(!inacme) { p = malloc(n); for (i = 0; i < n; ++i) p[i] = '\b'; write(scr, p, i); free(p); } qlock(&lck); if (!usrparse(line, &cmd, par, 2)) { switch(cmd) { case 'q': /* quote, just send the params ... */ if(par[0]) { fprint(server_out, "%s %s\r\n", par[0], par[1] ? par[1] : ""); } else { fprint(scr, "/q %s %s: not enough arguments\n", par[0], par[1]); } break; case 'M': if(par[0] && par[1]) { fprint(server_out, "MODE %s %s\r\n", par[0], par[1]); } else { fprint(scr, "/M %s %s: not enough arguments\n", par[0], par[1]); } break; case 'm': if(par[0] && par[1]) { fprint(server_out, "PRIVMSG %s :%s\r\n", par[0], par[1]); } else { fprint(scr, "/m %s %s: not enough arguments\n", par[0], par[1]); } break; case 't': if(par[0] != nil) { free(victim); victim = strdup(par[0]); setwintitle(par[0]); } fprint(scr, "*** default victim set to '%s'\n", par[0]); break; case 'T': if(par[0] == nil) fprint(server_out, "TOPIC %s\r\n", victim); else if(par[1] == nil) fprint(server_out, "TOPIC %s\r\n", par[0]); else fprint(server_out, "TOPIC %s :%s\r\n", par[0], par[1]); break; case 'j': fprint(server_out, "JOIN %s\r\n", par[0] == nil ? victim : par[0]); break; case 'p': fprint(server_out, "PART %s\r\n", par[0] == nil ? victim : par[0]); break; case 'n': if(par[0] != nil) { fprint(server_out, "NICK %s\r\n", par[0]); free(nick); nick = strdup(par[0]); unick = strdup(par[0]); } else { fprint(scr, "%s", help); } break; case 'N': if(par[1] != nil) fprint(server_out, "NOTICE %s :%s\r\n", par[0] == nil ? victim : par[0], par[1]); break; case 'W': fprint(server_out, "WHOIS %s %s\r\n", par[0] == nil ? victim : par[0], par[0]); case 'w': fprint(server_out, "WHO %s\r\n", par[0] == nil ? victim : par[0]); break; case 'l': fprint(server_out, "LIST %s\r\n", par[0] == nil ? victim : par[0]); break; case 'L': fprint(server_out, "NAMES %s\r\n", par[0] == nil ? victim : par[0]); break; case 'f': break; case 'h': case 'H': fprint(scr, "%s", help); break; } } else { fprint(scr, "%s", help); } qunlock(&lck); free(line); } exits(0); } void srvin(void) { char *line; char *pre, *cmd, *par[NPAR]; Biobuf srv; Binit(&srv, server_in, OREAD); while ((line = Brdstr(&srv, '\n', 0)) != nil) { if (!srvparse(line, &pre, &cmd, par, NPAR)) { Handler *hp = handlers; qlock(&lck); while (hp->cmd != nil) { if (!strcmp(hp->cmd, cmd)) { hp->fun(server_out, pre, cmd, par); break; } ++hp; } if (hp->cmd == nil) generic(server_out, pre, cmd, par); qunlock(&lck); } free(line); } } void replayfile(void) { char *line; char *pre, *cmd, *par[NPAR]; Biobuf srv; Binit(&srv, server_in, OREAD); while ((line = Brdstr(&srv, '\n', 0)) != nil) { if (!srvparse(line, &pre, &cmd, par, NPAR)) { Handler *hp = handlers; qlock(&lck); while (hp->cmd != nil) { if (!strcmp(hp->cmd, cmd)) { hp->fun(server_out, pre, cmd, par); break; } ++hp; } if (hp->cmd == nil) generic(server_out, pre, cmd, par); qunlock(&lck); } free(line); } } /* * display the last N lines from the conversation * if we have a default target only the conversation with * that target will be shown */ void seekback(int fd, int lines) { Biobuf srv; int found = 0, off; char c, *line; if(lines < 0) return; Binit(&srv, fd, OREAD); Bseek(&srv, -2, 2); while(((off = Boffset(&srv)) > 0) && found < lines) { c = Bgetc(&srv); Bungetc(&srv); if(c == '\n') { Bseek(&srv, 1, 1); line = Brdstr(&srv, '\n', '\0'); if(victim) { if(cistrstr(line, victim)) found++; } else { found++; } free(line); } Bseek(&srv, off-1, 0); } Bterm(&srv); } void main(int argc, char *argv[]) { char *charset = nil; char buf[32], buf2[32], *out = nil, *in = nil; char *user; int olduser = 0; char *arg; int sb = 10; /* how many lines are we displaying initially */ int uipid; int scroll = 1; int wctlfd; unick = nil; user = getuser(); ARGBEGIN { case 't': victim = strdup(EARGF(usage())); break; case 'b': arg = ARGF(); if(arg != nil && arg[0] != '-') sb = atoi(arg); else sb = 0; /* show all text */ break; case 'c': charset = EARGF(usage()); break; case 'r': replay = 1; sb = 0; break; case 'o': olduser = 1; break; case 'n': unick = strdup(EARGF(usage())); break; case 'S': scroll = 0; break; default: usage(); } ARGEND; switch(argc) { case 0: break; case 1: if(replay) in = argv[0]; else out = argv[0]; break; case 2: out = argv[0]; in = argv[1]; break; default: usage(); } if(out == nil && in == nil){ if(olduser == 1 && strlen(user) > 4) user[4] = '\0'; snprint(buf, sizeof buf, "/srv/%sirc", user); snprint(buf2, sizeof buf, "/tmp/%sirc", user); out = strdup(buf); in = strdup(buf2); } if(unick == nil) unick = strdup(user); if(scroll == 1){ if((wctlfd = open("/dev/wctl", OWRITE)) < 0) print("irc: could not open /dev/wctl: %r\n"); else { fprint(wctlfd, "scroll\n"); close(wctlfd); } } if(!replay && (server_out = open(out, OWRITE)) < 0) sysfatal("open write: %s %r", out); if ((server_in = open(in, OREAD)) < 0) sysfatal("open read: %s %r", in); inacme = testacme(); getwidth(); if(sb) seekback(server_in, sb); while(read(server_in, buf, 1) > 0) if(*buf == '\n') break; if(victim && cistrncmp(victim, "MSGS", 4)){ setwintitle(victim); fprint(server_out, "JOIN %s\r\n", victim); } scr = 1; server_in = follow(server_in); if (charset != nil && strcmp(charset, "utf")) { server_out = wtcs(server_out, charset); server_in = rtcs(server_in, charset); } if(replay) { replayfile(); } else { if ((uipid = rfork(RFPROC|RFFDG|RFMEM)) == 0) srvin(); usrin(); postnote(PNPROC, uipid, "kill"); while (waitpid() != uipid); } exits(0); } int wtcs(int fd, char *cset) { int totcs[2]; int pid; pipe(totcs); pid = fork(); if (pid == 0) { dup(totcs[0], 0); dup(fd, 1); close(totcs[1]); execl("/bin/tcs", "tcs", "-f", "utf", "-t", cset, nil); exits("execfailure"); } close(totcs[0]); return totcs[1]; } int rtcs(int fd, char *cset) { int fromtcs[2]; int pid; pipe(fromtcs); pid = fork(); if (pid == 0){ dup(fromtcs[1], 1); dup(fd, 0); close(fromtcs[0]); execl("/bin/tcs", "tcs", "-f", cset, "-t", "utf", nil); exits("execfailure"); } close(fromtcs[1]); return fromtcs[0]; } int follow(int fd) { int p[2], pid; long n; char buf[1024]; Dir *dp; pipe(p); pid = fork(); if (pid == 0){ dup(p[1], 1); dup(fd, 0); close(p[0]); for(;;){ while((n = read(0, buf, sizeof(buf))) > 0) write(1, buf, n); sleep(1000);