Bug Summary

File:irc/core/netsplit.c
Location:line 244, column 2
Description:Value stored to 'host1' is never read

Annotated Source Code

1/*
2 netsplit.c : irssi
3
4 Copyright (C) 1999 Timo Sirainen
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "module.h"
22#include "signals.h"
23#include "commands.h"
24#include "misc.h"
25
26#include "irc-servers.h"
27#include "irc-channels.h"
28#include "netsplit.h"
29
30/* How long to keep netsplits in memory (seconds) */
31#define NETSPLIT_MAX_REMEMBER(60*60) (60*60)
32
33static int split_tag;
34
35static NETSPLIT_SERVER_REC *netsplit_server_find(IRC_SERVER_REC *server,
36 const char *servername,
37 const char *destserver)
38{
39 GSList *tmp;
40
41 g_return_val_if_fail(IS_IRC_SERVER(server), NULL)do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return (((void *)0)); }; }while (0)
;
42
43 for (tmp = server->split_servers; tmp != NULL((void *)0); tmp = tmp->next) {
44 NETSPLIT_SERVER_REC *rec = tmp->data;
45
46 if (g_strcasecmp(rec->server, servername) == 0 &&
47 g_strcasecmp(rec->destserver, destserver) == 0)
48 return rec;
49 }
50
51 return NULL((void *)0);
52}
53
54static NETSPLIT_SERVER_REC *netsplit_server_create(IRC_SERVER_REC *server,
55 const char *servername,
56 const char *destserver)
57{
58 NETSPLIT_SERVER_REC *rec;
59
60 g_return_val_if_fail(IS_IRC_SERVER(server), NULL)do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return (((void *)0)); }; }while (0)
;
61
62 rec = netsplit_server_find(server, servername, destserver);
63 if (rec != NULL((void *)0)) {
64 rec->last = time(NULL((void *)0));
65 return rec;
66 }
67
68 rec = g_new0(NETSPLIT_SERVER_REC, 1)((NETSPLIT_SERVER_REC *) g_malloc0 (((gsize) sizeof (NETSPLIT_SERVER_REC
)) * ((gsize) (1))))
;
69 rec->last = time(NULL((void *)0));
70 rec->server = g_strdup(servername);
71 rec->destserver = g_strdup(destserver);
72
73 server->split_servers = g_slist_append(server->split_servers, rec);
74 signal_emit("netsplit server new", 2, server, rec);
75
76 return rec;
77}
78
79static void netsplit_server_destroy(IRC_SERVER_REC *server,
80 NETSPLIT_SERVER_REC *rec)
81{
82 g_return_if_fail(IS_IRC_SERVER(server))do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return; }; }while (0)
;
83
84 server->split_servers = g_slist_remove(server->split_servers, rec);
85
86 signal_emit("netsplit server remove", 2, server, rec);
87
88 g_free(rec->server);
89 g_free(rec->destserver);
90 g_free(rec);
91}
92
93static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick,
94 const char *address, const char *servers)
95{
96 NETSPLIT_REC *rec;
97 NETSPLIT_CHAN_REC *splitchan;
98 NICK_REC *nickrec;
99 GSList *tmp;
100 char *p, *dupservers;
101
102 g_return_val_if_fail(IS_IRC_SERVER(server), NULL)do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return (((void *)0)); }; }while (0)
;
103 g_return_val_if_fail(nick != NULL, NULL)do{ if (nick != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "nick != NULL"); return (
((void *)0)); }; }while (0)
;
104 g_return_val_if_fail(address != NULL, NULL)do{ if (address != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "address != NULL"); return
(((void *)0)); }; }while (0)
;
105
106 /* get splitted servers */
107 dupservers = g_strdup(servers);
108 p = strchr(dupservers, ' ');
109 if (p == NULL((void *)0)) {
110 g_free(dupservers);
111 g_warning("netsplit_add() : only one server found")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "netsplit_add() : only one server found"
)
;
112 return NULL((void *)0);
113 }
114 *p++ = '\0';
115
116 rec = g_new0(NETSPLIT_REC, 1)((NETSPLIT_REC *) g_malloc0 (((gsize) sizeof (NETSPLIT_REC)) *
((gsize) (1))))
;
117 rec->nick = g_strdup(nick);
118 rec->address = g_strdup(address);
119 rec->destroy = time(NULL((void *)0))+NETSPLIT_MAX_REMEMBER(60*60);
120
121 rec->server = netsplit_server_create(server, dupservers, p);
122 rec->server->count++;
123 g_free(dupservers);
124
125 /* copy the channel nick records.. */
126 for (tmp = server->channels; tmp != NULL((void *)0); tmp = tmp->next) {
127 CHANNEL_REC *channel = tmp->data;
128
129 nickrec = nicklist_find(channel, nick);
130 if (nickrec == NULL((void *)0))
131 continue;
132
133 splitchan = g_new0(NETSPLIT_CHAN_REC, 1)((NETSPLIT_CHAN_REC *) g_malloc0 (((gsize) sizeof (NETSPLIT_CHAN_REC
)) * ((gsize) (1))))
;
134 splitchan->name = g_strdup(channel->visible_name);
135 splitchan->op = nickrec->op;
136 splitchan->halfop = nickrec->halfop;
137 splitchan->voice = nickrec->voice;
138 memcpy(splitchan->prefixes, nickrec->prefixes, sizeof(splitchan->prefixes));
139
140 rec->channels = g_slist_append(rec->channels, splitchan);
141 }
142
143 if (rec->channels == NULL((void *)0))
144 g_warning("netsplit_add(): nick '%s' not in any channels", nick)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "netsplit_add(): nick '%s' not in any channels"
, nick)
;
145
146 g_hash_table_insert(server->splits, rec->nick, rec);
147
148 signal_emit("netsplit new", 1, rec);
149 return rec;
150}
151
152static void netsplit_destroy(IRC_SERVER_REC *server, NETSPLIT_REC *rec)
153{
154 GSList *tmp;
155
156 g_return_if_fail(IS_IRC_SERVER(server))do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return; }; }while (0)
;
157 g_return_if_fail(rec != NULL)do{ if (rec != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "rec != NULL"); return; }
; }while (0)
;
158
159 signal_emit("netsplit remove", 1, rec);
160 for (tmp = rec->channels; tmp != NULL((void *)0); tmp = tmp->next) {
161 NETSPLIT_CHAN_REC *rec = tmp->data;
162
163 g_free(rec->name);
164 g_free(rec);
165 }
166 g_slist_free(rec->channels);
167
168 if (--rec->server->count == 0)
169 netsplit_server_destroy(server, rec->server);
170
171 g_free(rec->nick);
172 g_free(rec->address);
173 g_free(rec);
174}
175
176static void netsplit_destroy_hash(void *key, NETSPLIT_REC *rec,
177 IRC_SERVER_REC *server)
178{
179 netsplit_destroy(server, rec);
180}
181
182NETSPLIT_REC *netsplit_find(IRC_SERVER_REC *server, const char *nick,
183 const char *address)
184{
185 NETSPLIT_REC *rec;
186
187 g_return_val_if_fail(IS_IRC_SERVER(server), NULL)do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return (((void *)0)); }; }while (0)
;
188 g_return_val_if_fail(nick != NULL, NULL)do{ if (nick != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "nick != NULL"); return (
((void *)0)); }; }while (0)
;
189
190 rec = g_hash_table_lookup(server->splits, nick);
191 if (rec == NULL((void *)0)) return NULL((void *)0);
192
193 return (address == NULL((void *)0) ||
194 g_strcasecmp(rec->address, address) == 0) ? rec : NULL((void *)0);
195}
196
197NETSPLIT_CHAN_REC *netsplit_find_channel(IRC_SERVER_REC *server,
198 const char *nick, const char *address,
199 const char *channel)
200{
201 NETSPLIT_REC *rec;
202 GSList *tmp;
203
204 g_return_val_if_fail(IS_IRC_SERVER(server), NULL)do{ if ((((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC
*) module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "IS_IRC_SERVER(server)")
; return (((void *)0)); }; }while (0)
;
205 g_return_val_if_fail(nick != NULL, NULL)do{ if (nick != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "nick != NULL"); return (
((void *)0)); }; }while (0)
;
206 g_return_val_if_fail(channel != NULL, NULL)do{ if (channel != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "channel != NULL"); return
(((void *)0)); }; }while (0)
;
207
208 rec = netsplit_find(server, nick, address);
209 if (rec == NULL((void *)0)) return NULL((void *)0);
210
211 for (tmp = rec->channels; tmp != NULL((void *)0); tmp = tmp->next) {
212 NETSPLIT_CHAN_REC *rec = tmp->data;
213
214 if (g_strcasecmp(rec->name, channel) == 0)
215 return rec;
216 }
217
218 return NULL((void *)0);
219}
220
221/* check if quit message is a netsplit message */
222int quitmsg_is_split(const char *msg)
223{
224 const char *host1, *host2, *p;
225 int prev, len, host1_dot, host2_dot;
226
227 g_return_val_if_fail(msg != NULL, FALSE)do{ if (msg != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "msg != NULL"); return (
(0)); }; }while (0)
;
228
229 /* NOTE: there used to be some paranoia checks (some older IRC
230 clients have even more), but they're pretty useless nowadays,
231 since IRC server prefixes the quit message with a space if it
232 looks like a netsplit message.
233
234 So, the check is currently just:
235 - host1.domain1 host2.domain2
236 - top-level domains have to be 2+ characters long,
237 containing only alphabets
238 - only 1 space
239 - no double-dots (".." - probably useless check)
240 - hosts/domains can't start or end with a dot
241 - the two hosts can't be identical (probably useless check)
242 - can't contain ':' or '/' chars (some servers allow URLs)
243 */
244 host1 = msg; host2 = NULL((void *)0);
Value stored to 'host1' is never read
245 prev = '\0'; len = 0; host1_dot = host2_dot = 0;
246 while (*msg != '\0') {
247 if (*msg == ' ') {
248 if (prev == '.' || prev == '\0') {
249 /* domains can't end with '.', space can't
250 be the first character in msg. */
251 return FALSE(0);
252 }
253 if (host2 != NULL((void *)0))
254 return FALSE(0); /* only one space allowed */
255 if (!host1_dot)
256 return FALSE(0); /* host1 didn't have domain */
257 host2 = msg+1; len = -1;
258 } else if (*msg == '.') {
259 if (prev == '\0' || prev == ' ' || prev == '.') {
260 /* domains can't start with '.'
261 and can't have ".." */
262 return FALSE(0);
263 }
264
265 if (host2 != NULL((void *)0))
266 host2_dot = TRUE(!(0));
267 else
268 host1_dot = TRUE(!(0));
269 } else if (*msg == ':' || *msg == '/')
270 return FALSE(0);
271
272 prev = *msg;
273 msg++; len++;
274 }
275
276 if (!host2_dot || prev == '.')
277 return FALSE(0);
278
279 /* top-domain1 must be 2+ chars long and contain only alphabets */
280 p = host2-1;
281 while (p[-1] != '.') {
282 if (!i_isalpha(p[-1])__sbistype(((int) (unsigned char) (p[-1])), 0x00000100L))
283 return FALSE(0);
284 p--;
285 }
286 if (host2-p-1 < 2) return FALSE(0);
287
288 /* top-domain2 must be 2+ chars long and contain only alphabets */
289 p = host2+strlen(host2);
290 while (p[-1] != '.') {
291 if (!i_isalpha(p[-1])__sbistype(((int) (unsigned char) (p[-1])), 0x00000100L))
292 return FALSE(0);
293 p--;
294 }
295 if (strlen(p) < 2) return FALSE(0);
296
297 return TRUE(!(0));
298}
299
300static void split_set_timeout(void *key, NETSPLIT_REC *rec, NETSPLIT_REC *orig)
301{
302 /* same servers -> split over -> destroy old records sooner.. */
303 if (rec->server == orig->server)
304 rec->destroy = time(NULL((void *)0))+60;
305}
306
307static void event_join(IRC_SERVER_REC *server, const char *data,
308 const char *nick, const char *address)
309{
310 NETSPLIT_REC *rec;
311
312 if (nick == NULL((void *)0))
313 return;
314
315 /* check if split is over */
316 rec = g_hash_table_lookup(server->splits, nick);
317
318 if (rec != NULL((void *)0) && g_strcasecmp(rec->address, address) == 0) {
319 /* yep, looks like it is. for same people that had the same
320 splitted servers set the timeout to one minute.
321
322 .. if the user just changed server, she can't use the
323 same nick (unless the server is broken) so don't bother
324 checking that the nick's server matches the split. */
325 g_hash_table_foreach(server->splits,
326 (GHFunc) split_set_timeout, rec);
327 }
328}
329
330/* remove the nick from netsplit, but do it last so that other "event join"
331 signal handlers can check if the join was a netjoin */
332static void event_join_last(IRC_SERVER_REC *server, const char *data,
333 const char *nick, const char *address)
334{
335 NETSPLIT_REC *rec;
336
337 if (nick == NULL((void *)0))
338 return;
339
340 rec = g_hash_table_lookup(server->splits, nick);
341 if (rec != NULL((void *)0)) {
342 g_hash_table_remove(server->splits, rec->nick);
343 netsplit_destroy(server, rec);
344 }
345}
346
347static void event_quit(IRC_SERVER_REC *server, const char *data,
348 const char *nick, const char *address)
349{
350 g_return_if_fail(data != NULL)do{ if (data != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "data != NULL"); return;
}; }while (0)
;
351
352 if (*data == ':') data++;
353 if (g_strcasecmp(nick, server->nick) != 0 && quitmsg_is_split(data)) {
354 /* netsplit! */
355 netsplit_add(server, nick, address, data);
356 }
357}
358
359static void event_nick(IRC_SERVER_REC *server, const char *data)
360{
361 NETSPLIT_REC *rec;
362 char *params, *nick;
363
364 params = event_get_params(data, 1, &nick);
365
366 /* remove nick from split list when somebody changed
367 nick to this one during split */
368 rec = g_hash_table_lookup(server->splits, nick);
369 if (rec != NULL((void *)0)) {
370 g_hash_table_remove(server->splits, rec->nick);
371 netsplit_destroy(server, rec);
372 }
373
374 g_free(params);
375}
376
377static void sig_disconnected(IRC_SERVER_REC *server)
378{
379 g_return_if_fail(server != NULL)do{ if (server != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "server != NULL"); return
; }; }while (0)
;
380
381 if (!IS_IRC_SERVER(server)(((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC *)
module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))
)
382 return;
383
384 g_hash_table_foreach(server->splits,
385 (GHFunc) netsplit_destroy_hash, server);
386 g_hash_table_destroy(server->splits);
387 server->splits = NULL((void *)0);
388}
389
390static int split_server_check(void *key, NETSPLIT_REC *rec,
391 IRC_SERVER_REC *server)
392{
393 /* Check if this split record is too old.. */
394 if (rec->destroy > time(NULL((void *)0)))
395 return FALSE(0);
396
397 netsplit_destroy(server, rec);
398 return TRUE(!(0));
399}
400
401static int split_check_old(void)
402{
403 GSList *tmp;
404
405 for (tmp = servers; tmp != NULL((void *)0); tmp = tmp->next) {
406 IRC_SERVER_REC *server = tmp->data;
407
408 if (!IS_IRC_SERVER(server)(((IRC_SERVER_REC *) chat_protocol_check_cast(((SERVER_REC *)
module_check_cast(server, __builtin_offsetof(SERVER_REC, type
), "SERVER")), __builtin_offsetof(IRC_SERVER_REC, chat_type),
"IRC")) ? (!(0)) : (0))
)
409 continue;
410
411 g_hash_table_foreach_remove(server->splits,
412 (GHRFunc) split_server_check,
413 server);
414 }
415
416 return 1;
417}
418
419void netsplit_init(void)
420{
421 split_tag = g_timeout_add(1000, (GSourceFunc) split_check_old, NULL((void *)0));
422 signal_add_first("event join", (SIGNAL_FUNC) event_join)signal_add_full("irc/core", -100, ("event join"), (SIGNAL_FUNC
) ((SIGNAL_FUNC) event_join), ((void *)0))
;
423 signal_add_last("event join", (SIGNAL_FUNC) event_join_last)signal_add_full("irc/core", 100, ("event join"), (SIGNAL_FUNC
) ((SIGNAL_FUNC) event_join_last), ((void *)0))
;
424 signal_add_first("event quit", (SIGNAL_FUNC) event_quit)signal_add_full("irc/core", -100, ("event quit"), (SIGNAL_FUNC
) ((SIGNAL_FUNC) event_quit), ((void *)0))
;
425 signal_add("event nick", (SIGNAL_FUNC) event_nick)signal_add_full("irc/core", 0, ("event nick"), (SIGNAL_FUNC) (
(SIGNAL_FUNC) event_nick), ((void *)0))
;
426 signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected)signal_add_full("irc/core", 0, ("server disconnected"), (SIGNAL_FUNC
) ((SIGNAL_FUNC) sig_disconnected), ((void *)0))
;
427}
428
429void netsplit_deinit(void)
430{
431 g_source_remove(split_tag);
432 signal_remove("event join", (SIGNAL_FUNC) event_join)signal_remove_full(("event join"), (SIGNAL_FUNC) ((SIGNAL_FUNC
) event_join), ((void *)0))
;
433 signal_remove("event join", (SIGNAL_FUNC) event_join_last)signal_remove_full(("event join"), (SIGNAL_FUNC) ((SIGNAL_FUNC
) event_join_last), ((void *)0))
;
434 signal_remove("event quit", (SIGNAL_FUNC) event_quit)signal_remove_full(("event quit"), (SIGNAL_FUNC) ((SIGNAL_FUNC
) event_quit), ((void *)0))
;
435 signal_remove("event nick", (SIGNAL_FUNC) event_nick)signal_remove_full(("event nick"), (SIGNAL_FUNC) ((SIGNAL_FUNC
) event_nick), ((void *)0))
;
436 signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected)signal_remove_full(("server disconnected"), (SIGNAL_FUNC) ((SIGNAL_FUNC
) sig_disconnected), ((void *)0))
;
437}