ii-1.8-usernames.diff (6438B)
1 diff --git a/ii.c b/ii.c 2 index 6583792..f5ed614 100644 3 --- a/ii.c 4 +++ b/ii.c 5 @@ -33,15 +33,23 @@ size_t strlcpy(char *, const char *, size_t); 6 7 enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST }; 8 9 +typedef struct Nick Nick; 10 +struct Nick { 11 + char name[32]; 12 + Nick *next; 13 +}; 14 + 15 typedef struct Channel Channel; 16 struct Channel { 17 int fdin; 18 char name[IRC_CHANNEL_MAX]; /* channel name (normalized) */ 19 char inpath[PATH_MAX]; /* input path */ 20 char outpath[PATH_MAX]; /* output path */ 21 + Nick *nicks; 22 Channel *next; 23 }; 24 25 +static void add_name(Channel *, const char *); 26 static Channel * channel_add(const char *); 27 static Channel * channel_find(const char *); 28 static Channel * channel_join(const char *); 29 @@ -61,10 +69,14 @@ static void handle_server_output(int); 30 static int isnumeric(const char *); 31 static void loginkey(int, const char *); 32 static void loginuser(int, const char *, const char *); 33 +static void nick_name(const char *, const char *); 34 static void proc_channels_input(int, Channel *, char *); 35 static void proc_channels_privmsg(int, Channel *, char *); 36 +static void proc_names(Channel *, char *); 37 static void proc_server_cmd(int, char *); 38 +static void quit_name(const char *, const char *, const char *); 39 static int read_line(int, char *, size_t); 40 +static int rm_name(Channel *, const char *); 41 static void run(int, const char *); 42 static void setup(void); 43 static void sighandler(int); 44 @@ -236,6 +248,7 @@ channel_new(const char *name) 45 c->next = NULL; 46 strlcpy(c->name, name, sizeof(c->name)); 47 channel_normalize_name(c->name); 48 + c->nicks = NULL; 49 50 create_filepath(c->inpath, sizeof(c->inpath), ircpath, 51 channelpath, "in"); 52 @@ -294,6 +307,7 @@ static void 53 channel_rm(Channel *c) 54 { 55 Channel *p; 56 + Nick *n, *nn; 57 58 if (channels == c) { 59 channels = channels->next; 60 @@ -303,6 +317,10 @@ channel_rm(Channel *c) 61 if (p && p->next == c) 62 p->next = c->next; 63 } 64 + for (n = c->nicks; n; n = nn) { 65 + nn = n->next; 66 + free(n); 67 + } 68 free(c); 69 } 70 71 @@ -318,6 +336,70 @@ channel_leave(Channel *c) 72 channel_rm(c); 73 } 74 75 +static void 76 +add_name(Channel *c, const char *name) { 77 + Nick *n; 78 + for (n = c->nicks; n; n = n->next) 79 + if (!strcmp(name, n->name)) return; 80 + if (!(n = calloc(1, sizeof(Nick)))) { 81 + fprintf(stderr, "%s: calloc: %s\n", argv0, strerror(errno)); 82 + exit(1); 83 + } 84 + strlcpy(n->name, name, sizeof(n->name)); 85 + n->next = c->nicks; 86 + c->nicks = n; 87 +} 88 + 89 +static int 90 +rm_name(Channel *c, const char *name) { 91 + Nick *n, *pn = NULL; 92 + for (n = c->nicks; n; pn = n, n = n->next) { 93 + if (!strcmp(name, n->name)) { 94 + if (pn) 95 + pn->next = n->next; 96 + else 97 + c->nicks = n->next; 98 + free(n); 99 + return 1; 100 + } 101 + } 102 + return 0; 103 +} 104 + 105 +static void 106 +proc_names(Channel *c, char *names) { 107 + char *p; 108 + if (!(p = strtok(names," "))) return; 109 + do { 110 + if (*p == '@' || *p == '+') 111 + p++; 112 + add_name(c,p); 113 + } while ((p = strtok(NULL," "))); 114 +} 115 + 116 +static void 117 +quit_name(const char *name, const char *user, const char *text) { 118 + Channel *c; 119 + for (c = channels; c; c = c->next) { 120 + if (rm_name(c, name)) { 121 + snprintf(msg, PIPE_BUF, "-!- %s(%s) has quit \"%s\"", name, user, text ? text : ""); 122 + channel_print(c, msg); 123 + } 124 + } 125 +} 126 + 127 +static void 128 +nick_name(const char *old, const char *new) { 129 + Channel *c; 130 + for (c = channels; c; c = c->next) { 131 + if (rm_name(c, old)) { 132 + add_name(c, new); 133 + snprintf(msg, PIPE_BUF, "-!- %s changed nick to \"%s\"", old, new); 134 + channel_print(c, msg); 135 + } 136 + } 137 +} 138 + 139 static void 140 loginkey(int ircfd, const char *key) 141 { 142 @@ -590,6 +672,15 @@ proc_server_cmd(int fd, char *buf) 143 snprintf(msg, sizeof(msg), "PONG %s\r\n", argv[TOK_TEXT]); 144 ewritestr(fd, msg); 145 return; 146 + } else if (!strcmp("353", argv[TOK_CMD])) { 147 + p = strtok(argv[TOK_ARG]," "); 148 + if (!(p = strtok(NULL," "))) 149 + return; 150 + snprintf(msg, PIPE_BUF, "%s%s", argv[TOK_ARG] ? argv[TOK_ARG] : "", argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); 151 + channel_print(channelmaster, msg); 152 + if ((c = channel_find(p))) 153 + proc_names(c, argv[TOK_TEXT]); 154 + return; 155 } else if (!argv[TOK_NICKSRV] || !argv[TOK_USER]) { 156 /* server command */ 157 snprintf(msg, sizeof(msg), "%s%s", 158 @@ -605,9 +696,13 @@ proc_server_cmd(int fd, char *buf) 159 argv[TOK_CHAN] = argv[TOK_TEXT]; 160 snprintf(msg, sizeof(msg), "-!- %s(%s) has joined %s", 161 argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]); 162 + if ((c = channel_find(argv[TOK_CHAN]))) 163 + add_name(c, argv[TOK_NICKSRV]); 164 } else if (!strcmp("PART", argv[TOK_CMD]) && argv[TOK_CHAN]) { 165 snprintf(msg, sizeof(msg), "-!- %s(%s) has left %s", 166 argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]); 167 + if ((c = channel_find(argv[TOK_CHAN]))) 168 + rm_name(c, argv[TOK_NICKSRV]); 169 /* if user itself leaves, don't write to channel (don't reopen channel). */ 170 if (!strcmp(argv[TOK_NICKSRV], nick)) 171 return; 172 @@ -618,17 +713,18 @@ proc_server_cmd(int fd, char *buf) 173 argv[TOK_ARG] ? argv[TOK_ARG] : "", 174 argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); 175 } else if (!strcmp("QUIT", argv[TOK_CMD])) { 176 - snprintf(msg, sizeof(msg), "-!- %s(%s) has quit \"%s\"", 177 - argv[TOK_NICKSRV], argv[TOK_USER], 178 - argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); 179 + quit_name(argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_TEXT]); 180 + return; 181 } else if (!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT] && 182 !strcmp(_nick, argv[TOK_TEXT])) { 183 strlcpy(nick, _nick, sizeof(nick)); 184 snprintf(msg, sizeof(msg), "-!- changed nick to \"%s\"", nick); 185 channel_print(channelmaster, msg); 186 + nick_name(argv[TOK_NICKSRV], argv[TOK_TEXT]); 187 + return; 188 } else if (!strcmp("NICK", argv[TOK_CMD]) && argv[TOK_TEXT]) { 189 - snprintf(msg, sizeof(msg), "-!- %s changed nick to %s", 190 - argv[TOK_NICKSRV], argv[TOK_TEXT]); 191 + nick_name(argv[TOK_NICKSRV], argv[TOK_TEXT]); 192 + return; 193 } else if (!strcmp("TOPIC", argv[TOK_CMD])) { 194 snprintf(msg, sizeof(msg), "-!- %s changed topic to \"%s\"", 195 argv[TOK_NICKSRV], 196 @@ -637,6 +733,8 @@ proc_server_cmd(int fd, char *buf) 197 snprintf(msg, sizeof(msg), "-!- %s kicked %s (\"%s\")", 198 argv[TOK_NICKSRV], argv[TOK_ARG], 199 argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); 200 + if ((c = channel_find(argv[TOK_CHAN]))) 201 + rm_name(c, argv[TOK_ARG]); 202 } else if (!strcmp("NOTICE", argv[TOK_CMD])) { 203 snprintf(msg, sizeof(msg), "-!- \"%s\")", 204 argv[TOK_TEXT] ? argv[TOK_TEXT] : "");