Introduction
Introduction Statistics Contact Development Disclaimer Help
Track user names to properly show joins and parts - irc - A minimalistic IRC cl…
git clone git://vernunftzentrum.de/irc.git
Log
Files
Refs
README
---
commit e5ae717f4ac681933c42f9bb82ffd01386545522
parent a68ac08f9543bbb869b49f1329fdf9281d412127
Author: Christian Kellermann <[email protected]>
Date: Fri, 6 Apr 2018 23:03:04 +0200
Track user names to properly show joins and parts
Diffstat:
irc.c | 145 +++++++++++++++++++++++++++++--
1 file changed, 136 insertions(+), 9 deletions(-)
---
diff --git a/irc.c b/irc.c
@@ -36,7 +36,8 @@
enum {
ChanLen = 64,
LineLen = 512,
- MaxChans = 16,
+ MaxChans = 32,
+ MaxKnownUsers = 2048,
BufSz = 2048,
LogSz = 4096,
MaxRecons = 10, /* -1 for infinitely many */
@@ -62,6 +63,12 @@ static struct Chan {
char join; /* Channel was 'j'-oined. */
} chl[MaxChans];
+static struct User {
+ char nick[64];
+ uint32_t channels; /* Needs to match MaxChans */
+ char inuse;
+} usrs[MaxKnownUsers];
+
static int ssl;
static struct {
int fd;
@@ -84,6 +91,8 @@ static void tdrawbar(void);
static void tredraw(void);
static void treset(void);
+static void usrchandrop(int);
+
static void
panic(const char *m)
{
@@ -326,6 +335,7 @@ chdel(char *name)
if (!(n = chfind(name)))
return 0;
+ usrchandrop(n);
nch--;
free(chl[n].buf);
memmove(&chl[n], &chl[n + 1], (nch - n) * sizeof(struct Chan));
@@ -334,6 +344,81 @@ chdel(char *name)
return 1;
}
+static void
+usrchandrop(int chan)
+{
+ for (size_t i = 0; i < MaxKnownUsers; i++)
+ if (usrs[i].channels == (1 << chan)) {
+ usrs[i].channels = 0;
+ usrs[i].inuse = 0;
+ bzero(usrs[i].nick, 64);
+ }
+}
+
+static size_t
+usrfind(char *nick)
+{
+ size_t i = 0;
+ for (i = MaxKnownUsers - 1; i > 0; i--){
+ if (usrs[i].inuse && !strcmp(nick, usrs[i].nick))
+ break;
+ }
+ return i;
+}
+
+static void
+usradd(char* nick, int chan)
+{
+ size_t i;
+ i = usrfind(nick);
+ if (!i) {
+ for (i = MaxKnownUsers - 1; i > 0; i--)
+ if (!usrs[i].inuse)
+ break;
+ }
+ if (!i)
+ panic("Too many users!");
+ strlcpy(usrs[i].nick, nick, 64);
+ usrs[i].channels |= 1 << chan;
+ usrs[i].inuse = 1;
+}
+
+static void
+usrdel(char* nick, int chan)
+{
+ size_t h;
+
+ h = usrfind(nick);
+ if (!h)
+ return;
+ if (!chan)
+ usrs[h].channels = 0;
+
+ usrs[h].channels &= ~(1 << chan);
+
+ if (!usrs[h].channels) {
+ usrs[h].inuse = 0;
+ bzero(usrs[h].nick, 64);
+ }
+}
+
+static void
+usrchange(char* old, char* new)
+{
+ size_t h;
+
+ h = usrfind(old);
+ if(!h)
+ panic("Missed a user!");
+ strlcpy(usrs[h].nick, new, 64);
+}
+
+static uint32_t
+usrchans(char* nick)
+{
+ return usrs[usrfind(nick)].channels;
+}
+
static char *
pushl(char *p, char *e)
{
@@ -461,7 +546,7 @@ scmd(char *usr, char *cmd, char *par, char *data)
tdrawbar();
}
} else if (!strcmp(cmd, "NICK")) {
- if (!data || !pm)
+ if (!data)
return;
if (!strcmp(usr, nick)){
for (int c=0; c < nch; c++){
@@ -469,21 +554,33 @@ scmd(char *usr, char *cmd, char *par, char *data)
}
strlcpy(nick, data, sizeof(nick));
} else {
- pushf(chfind(pm), "%s - is now known as %s", usr, data…
+ pushf(chfind(data), "%s - is now known as %s", usr, da…
+ usrchange(usr, data);
}
tredraw();
return;
} else if (!strcmp(cmd, "PING")) {
sndf("PONG :%s", data ? data : "(null)");
} else if (!strcmp(cmd, "PART")) {
+ int ch = 0;
if (!pm)
return;
- pushf(chfind(pm), "-!- %s has left %s", usr, pm);
+ ch = chfind(pm);
+ pushf(ch, "-!- %s has left %s", usr, pm);
+ usrdel(usr, ch);
} else if (!strcmp(cmd, "JOIN")) { /* some servers pass the channel as…
- if (pm)
- pushf(chfind(pm), "-!- %s has joined %s", usr, pm);
- else if (data)
- pushf(chfind(data), "-!- %s has joined %s", usr, data);
+ int ch;
+ char *chan;
+ if (pm) {
+ ch = chfind(pm);
+ chan = pm;
+ } else if (data) {
+ ch = chfind(data);
+ chan = data;
+ }
+
+ pushf(ch, "-!- %s has joined %s", usr, chan);
+ usradd(usr, ch);
return;
} else if (!strcmp(cmd, "470")) { /* Channel forwarding. */
char *ch = strtok(0, " "), *fch = strtok(0, " ");
@@ -500,6 +597,23 @@ scmd(char *usr, char *cmd, char *par, char *data)
return;
pushf(chfind(chan), "Topic for %s: %s", chan, data);
tredraw();
+ } else if (!strcmp(cmd, "353")) { /* RPL_NAMREPLY */
+ pushf(0, "Names %s", data ? data : "");
+ if ((pm = strtok(0, " ")) && (!strcmp(pm, "=") || !strcmp(pm, …
+ char *n;
+ char *chan = strtok(0, " ");
+ int c = chfind(chan);
+ if (!chan || !data || !c)
+ return;
+ n = strtok(data, " ");
+ if (!n)
+ return;
+ do {
+ if (n[0] == '@' || n[0] == '+')
+ n+=1;
+ usradd(n, c);
+ } while ((n = strtok(0, " ")));
+ }
} else if (!strcmp(cmd, "471") || !strcmp(cmd, "473")
|| !strcmp(cmd, "474") || !strcmp(cmd, "475")) { /* Join er…
if ((pm = strtok(0, " "))) {
@@ -513,7 +627,19 @@ scmd(char *usr, char *cmd, char *par, char *data)
return;
pushf(0, "-!- Cannot change to nick %s: %s", pm, data);
tredraw();
- } else if (!strcmp(cmd, "QUIT")) { /* Commands we don't care about. */
+ } else if (!strcmp(cmd, "QUIT")) {
+ char *msg = "";
+ if (!usr)
+ return;
+ uint64_t chans = usrchans(usr);
+ usrdel(usr, 0);
+ if (data)
+ msg = data;
+ for (int c = 0; c < MaxChans; c++) {
+ if (1<<c & chans)
+ pushf(c, "-!- %s has left ('%s').", usr, msg);
+ }
+ tredraw();
return;
} else if (!strcmp(cmd, "NOTICE") || !strcmp(cmd, "375")
|| !strcmp(cmd, "372") || !strcmp(cmd, "376")) {
@@ -894,6 +1020,7 @@ main(int argc, char *argv[])
strcpy(nick, user);
if (!nick[0])
goto usage;
+ bzero(usrs, MaxKnownUsers * sizeof(*usrs));
tinit();
err = dial(server, port);
if (err)
You are viewing proxied material from vernunftzentrum.de. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.