File: | irc/core/irc.c |
Location: | line 385, column 2 |
Description: | Branch condition evaluates to an uninitialized value. |
1 | /* |
2 | irc.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 "modules.h" |
23 | #include "network.h" |
24 | #include "net-sendbuffer.h" |
25 | #include "rawlog.h" |
26 | #include "misc.h" |
27 | |
28 | #include "irc-servers.h" |
29 | #include "irc-channels.h" |
30 | #include "servers-redirect.h" |
31 | |
32 | char *current_server_event; |
33 | static int signal_default_event; |
34 | static int signal_server_event; |
35 | static int signal_server_incoming; |
36 | |
37 | #ifdef BLOCKING_SOCKETS |
38 | # define MAX_SOCKET_READS5 1 |
39 | #else |
40 | # define MAX_SOCKET_READS5 5 |
41 | #endif |
42 | |
43 | /* The core of the irc_send_cmd* functions. If `raw' is TRUE, the `cmd' |
44 | won't be checked at all if it's 512 bytes or not, or if it contains |
45 | line feeds or not. Use with extreme caution! */ |
46 | void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, |
47 | int send_now, int immediate, int raw) |
48 | { |
49 | char str[513]; |
50 | int len; |
51 | |
52 | 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); |
53 | g_return_if_fail(cmd != NULL)do{ if (cmd != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "cmd != NULL"); return; } ; }while (0); |
54 | |
55 | if (server->connection_lost) |
56 | return; |
57 | |
58 | len = strlen(cmd); |
59 | if (server->cmdcount == 0) |
60 | irc_servers_start_cmd_timeout(); |
61 | server->cmdcount++; |
62 | |
63 | if (!raw) { |
64 | /* check that we don't send any longer commands |
65 | than 510 bytes (2 bytes for CR+LF) */ |
66 | strncpy(str, cmd, 510); |
67 | if (len > 510) len = 510; |
68 | str[len] = '\0'; |
69 | cmd = str; |
70 | } |
71 | |
72 | if (send_now) { |
73 | rawlog_output(server->rawlog, cmd); |
74 | server_redirect_command(server, cmd, server->redirect_next); |
75 | server->redirect_next = NULL((void *)0); |
76 | } |
77 | |
78 | if (!raw) { |
79 | /* Add CR+LF to command */ |
80 | str[len++] = 13; |
81 | str[len++] = 10; |
82 | str[len] = '\0'; |
83 | } |
84 | |
85 | if (send_now) { |
86 | irc_server_send_data(server, cmd, len); |
87 | } else { |
88 | |
89 | /* add to queue */ |
90 | if (immediate) { |
91 | server->cmdqueue = g_slist_prepend(server->cmdqueue, |
92 | server->redirect_next); |
93 | server->cmdqueue = g_slist_prepend(server->cmdqueue, |
94 | g_strdup(cmd)); |
95 | } else { |
96 | server->cmdqueue = g_slist_append(server->cmdqueue, |
97 | g_strdup(cmd)); |
98 | server->cmdqueue = g_slist_append(server->cmdqueue, |
99 | server->redirect_next); |
100 | } |
101 | } |
102 | server->redirect_next = NULL((void *)0); |
103 | } |
104 | |
105 | /* Send command to IRC server */ |
106 | void irc_send_cmd(IRC_SERVER_REC *server, const char *cmd) |
107 | { |
108 | GTimeVal now; |
109 | int send_now; |
110 | |
111 | g_get_current_time(&now); |
112 | send_now = g_timeval_cmp(&now, &server->wait_cmd) >= 0 && |
113 | (server->cmdcount < server->max_cmds_at_once || |
114 | server->cmd_queue_speed <= 0); |
115 | |
116 | irc_send_cmd_full(server, cmd, send_now, FALSE(0), FALSE(0)); |
117 | } |
118 | |
119 | /* Send command to IRC server */ |
120 | void irc_send_cmdv(IRC_SERVER_REC *server, const char *cmd, ...) |
121 | { |
122 | va_list args; |
123 | char *str; |
124 | |
125 | va_start(args, cmd)__builtin_va_start((args), (cmd)); |
126 | |
127 | str = g_strdup_vprintf(cmd, args); |
128 | irc_send_cmd(server, str); |
129 | g_free(str); |
130 | |
131 | va_end(args)__builtin_va_end(args); |
132 | } |
133 | |
134 | /* Send command to server immediately bypassing all flood protections |
135 | and queues. */ |
136 | void irc_send_cmd_now(IRC_SERVER_REC *server, const char *cmd) |
137 | { |
138 | g_return_if_fail(cmd != NULL)do{ if (cmd != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "cmd != NULL"); return; } ; }while (0); |
139 | |
140 | irc_send_cmd_full(server, cmd, TRUE(!(0)), TRUE(!(0)), FALSE(0)); |
141 | } |
142 | |
143 | /* Send command to server putting it at the beginning of the queue of |
144 | commands to send -- it will go out as soon as possible in accordance |
145 | to the flood protection settings. */ |
146 | void irc_send_cmd_first(IRC_SERVER_REC *server, const char *cmd) |
147 | { |
148 | g_return_if_fail(cmd != NULL)do{ if (cmd != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "cmd != NULL"); return; } ; }while (0); |
149 | |
150 | irc_send_cmd_full(server, cmd, FALSE(0), TRUE(!(0)), FALSE(0)); |
151 | } |
152 | |
153 | static char *split_nicks(const char *cmd, char **pre, char **nicks, char **post, int arg) |
154 | { |
155 | char *p; |
156 | |
157 | *pre = g_strdup(cmd); |
158 | *post = *nicks = NULL((void *)0); |
159 | for (p = *pre; *p != '\0'; p++) { |
160 | if (*p != ' ') |
161 | continue; |
162 | |
163 | if (arg == 1) { |
164 | /* text after nicks */ |
165 | *p++ = '\0'; |
166 | while (*p == ' ') p++; |
167 | *post = p; |
168 | break; |
169 | } |
170 | |
171 | /* find nicks */ |
172 | while (p[1] == ' ') p++; |
173 | if (--arg == 1) { |
174 | *p = '\0'; |
175 | *nicks = p+1; |
176 | } |
177 | } |
178 | |
179 | return *pre; |
180 | } |
181 | |
182 | void irc_send_cmd_split(IRC_SERVER_REC *server, const char *cmd, |
183 | int nickarg, int max_nicks) |
184 | { |
185 | char *str, *pre, *post, *nicks; |
186 | char **nicklist, **tmp; |
187 | GString *nickstr; |
188 | int count; |
189 | |
190 | 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); |
191 | g_return_if_fail(cmd != NULL)do{ if (cmd != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "cmd != NULL"); return; } ; }while (0); |
192 | |
193 | str = split_nicks(cmd, &pre, &nicks, &post, nickarg); |
194 | if (nicks == NULL((void *)0)) { |
195 | /* no nicks given? */ |
196 | g_free(str); |
197 | return; |
198 | } |
199 | |
200 | /* split the nicks */ |
201 | nickstr = g_string_new(NULL((void *)0)); |
202 | nicklist = g_strsplit(nicks, ",", -1); count = 0; |
203 | |
204 | tmp = nicklist; |
205 | for (;; tmp++) { |
206 | if (*tmp != NULL((void *)0)) { |
207 | g_string_append_printf(nickstr, "%s,", *tmp); |
208 | if (++count < max_nicks) |
209 | continue; |
210 | } |
211 | |
212 | count = 0; |
213 | if (nickstr->len > 0) |
214 | g_string_truncate(nickstr, nickstr->len-1); |
215 | irc_send_cmdv(server, post == NULL((void *)0) ? "%s %s" : "%s %s %s", |
216 | pre, nickstr->str, post); |
217 | g_string_truncate(nickstr, 0); |
218 | |
219 | if (*tmp == NULL((void *)0) || tmp[1] == NULL((void *)0)) |
220 | break; |
221 | } |
222 | g_strfreev(nicklist); |
223 | g_string_free(nickstr, TRUE(!(0))); |
224 | |
225 | g_free(str); |
226 | } |
227 | |
228 | /* Get next parameter */ |
229 | char *event_get_param(char **data) |
230 | { |
231 | char *pos; |
232 | |
233 | g_return_val_if_fail(data != NULL, NULL)do{ if (data != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "data != NULL"); return ( ((void *)0)); }; }while (0); |
234 | g_return_val_if_fail(*data != NULL, NULL)do{ if (*data != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "*data != NULL"); return (((void *)0)); }; }while (0); |
235 | |
236 | if (**data == ':') { |
237 | /* last parameter */ |
238 | pos = *data; |
239 | *data += strlen(*data); |
240 | return pos+1; |
241 | } |
242 | |
243 | pos = *data; |
244 | while (**data != '\0' && **data != ' ') (*data)++; |
245 | if (**data == ' ') *(*data)++ = '\0'; |
246 | |
247 | return pos; |
248 | } |
249 | |
250 | /* Get count parameters from data */ |
251 | char *event_get_params(const char *data, int count, ...) |
252 | { |
253 | char **str, *tmp, *duprec, *datad; |
254 | gboolean rest; |
255 | va_list args; |
256 | |
257 | g_return_val_if_fail(data != NULL, NULL)do{ if (data != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "data != NULL"); return ( ((void *)0)); }; }while (0); |
258 | |
259 | va_start(args, count)__builtin_va_start((args), (count)); |
260 | duprec = datad = g_strdup(data); |
261 | |
262 | rest = count & PARAM_FLAG_GETREST0x00002000; |
263 | count = PARAM_WITHOUT_FLAGS(count)((count) & 0x00000fff); |
264 | |
265 | while (count-- > 0) { |
266 | str = (char **) va_arg(args, char **)__builtin_va_arg((args), char **); |
267 | if (count == 0 && rest) { |
268 | /* put the rest to last parameter */ |
269 | tmp = *datad == ':' ? datad+1 : datad; |
270 | } else { |
271 | tmp = event_get_param(&datad); |
272 | } |
273 | if (str != NULL((void *)0)) *str = tmp; |
274 | } |
275 | va_end(args)__builtin_va_end(args); |
276 | |
277 | return duprec; |
278 | } |
279 | |
280 | static void irc_server_event(IRC_SERVER_REC *server, const char *line, |
281 | const char *nick, const char *address) |
282 | { |
283 | const char *signal; |
284 | char *event, *args; |
285 | |
286 | g_return_if_fail(line != NULL)do{ if (line != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "line != NULL"); return; }; }while (0); |
287 | |
288 | /* split event / args */ |
289 | event = g_strconcat("event ", line, NULL((void *)0)); |
290 | args = strchr(event+6, ' '); |
291 | if (args != NULL((void *)0)) *args++ = '\0'; else args = ""; |
292 | while (*args == ' ') args++; |
293 | g_strdown(event); |
294 | |
295 | /* check if event needs to be redirected */ |
296 | signal = server_redirect_get_signal(server, nick, event, args); |
297 | if (signal == NULL((void *)0)) |
298 | signal = event; |
299 | else |
300 | rawlog_redirect(server->rawlog, signal); |
301 | |
302 | /* emit it */ |
303 | current_server_event = event+6; |
304 | if (!signal_emit(signal, 4, server, args, nick, address)) |
305 | signal_emit_id(signal_default_event, 4, server, line, nick, address); |
306 | current_server_event = NULL((void *)0); |
307 | |
308 | g_free(event); |
309 | } |
310 | |
311 | static char *irc_parse_prefix(char *line, char **nick, char **address) |
312 | { |
313 | char *p; |
314 | |
315 | *nick = *address = NULL((void *)0); |
316 | |
317 | /* :<nick> [["!" <user>] "@" <host>] SPACE */ |
318 | |
319 | if (*line != ':') |
320 | return line; |
321 | |
322 | *nick = ++line; p = NULL((void *)0); |
323 | while (*line != '\0' && *line != ' ') { |
324 | if (*line == '!' || *line == '@') { |
325 | p = line; |
326 | if (*line == '!') |
327 | break; |
328 | } |
329 | line++; |
330 | } |
331 | |
332 | if (p != NULL((void *)0)) { |
333 | line = p; |
334 | *line++ = '\0'; |
335 | *address = line; |
336 | while (*line != '\0' && *line != ' ') |
337 | line++; |
338 | } |
339 | |
340 | if (*line == ' ') { |
341 | *line++ = '\0'; |
342 | while (*line == ' ') line++; |
343 | } |
344 | |
345 | return line; |
346 | } |
347 | |
348 | /* Parse command line sent by server */ |
349 | static void irc_parse_incoming_line(IRC_SERVER_REC *server, char *line) |
350 | { |
351 | char *nick, *address; |
352 | |
353 | 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); |
354 | g_return_if_fail(line != NULL)do{ if (line != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "line != NULL"); return; }; }while (0); |
355 | |
356 | line = irc_parse_prefix(line, &nick, &address); |
357 | if (*line != '\0') |
358 | signal_emit_id(signal_server_event, 4, server, line, nick, address); |
359 | } |
360 | |
361 | /* input function: handle incoming server messages */ |
362 | static void irc_parse_incoming(SERVER_REC *server) |
363 | { |
364 | char *str; |
365 | int count; |
366 | int ret; |
367 | |
368 | 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); |
[1] Taking true branch | |
[2] Loop condition is false. Exiting loop | |
369 | |
370 | /* Some commands can send huge replies and irssi might handle them |
371 | too slowly, so read only a few times from the socket before |
372 | letting other tasks to run. */ |
373 | count = 0; |
374 | server_ref(server); |
375 | while (!server->disconnected && |
[3] Loop condition is false. Execution continues on line 385 | |
376 | (ret = net_sendbuffer_receive_line(server->handle, &str, count < MAX_SOCKET_READS5)) > 0) { |
377 | rawlog_input(server->rawlog, str); |
378 | signal_emit_id(signal_server_incoming, 2, server, str); |
379 | |
380 | if (server->connection_lost) |
381 | server_disconnect(server); |
382 | |
383 | count++; |
384 | } |
385 | if (ret == -1) { |
[4] Branch condition evaluates to an uninitialized value | |
386 | /* connection lost */ |
387 | server->connection_lost = TRUE(!(0)); |
388 | server_disconnect(server); |
389 | } |
390 | server_unref(server); |
391 | } |
392 | |
393 | static void irc_init_server(IRC_SERVER_REC *server) |
394 | { |
395 | 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); |
396 | |
397 | 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))) |
398 | return; |
399 | |
400 | server->readtag = |
401 | g_input_add(net_sendbuffer_handle(server->handle), |
402 | G_INPUT_READ(1 << 0), |
403 | (GInputFunction) irc_parse_incoming, server); |
404 | } |
405 | |
406 | void irc_irc_init(void) |
407 | { |
408 | signal_add("server event", (SIGNAL_FUNC) irc_server_event)signal_add_full("irc/core", 0, ("server event"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) irc_server_event), ((void *)0)); |
409 | signal_add("server connected", (SIGNAL_FUNC) irc_init_server)signal_add_full("irc/core", 0, ("server connected"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) irc_init_server), ((void *)0)); |
410 | signal_add("server incoming", (SIGNAL_FUNC) irc_parse_incoming_line)signal_add_full("irc/core", 0, ("server incoming"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) irc_parse_incoming_line), ((void *)0)); |
411 | |
412 | current_server_event = NULL((void *)0); |
413 | signal_default_event = signal_get_uniq_id("default event")module_get_uniq_id_str("signals", "default event"); |
414 | signal_server_event = signal_get_uniq_id("server event")module_get_uniq_id_str("signals", "server event"); |
415 | signal_server_incoming = signal_get_uniq_id("server incoming")module_get_uniq_id_str("signals", "server incoming"); |
416 | } |
417 | |
418 | void irc_irc_deinit(void) |
419 | { |
420 | signal_remove("server event", (SIGNAL_FUNC) irc_server_event)signal_remove_full(("server event"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) irc_server_event), ((void *)0)); |
421 | signal_remove("server connected", (SIGNAL_FUNC) irc_init_server)signal_remove_full(("server connected"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) irc_init_server), ((void *)0)); |
422 | signal_remove("server incoming", (SIGNAL_FUNC) irc_parse_incoming_line)signal_remove_full(("server incoming"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) irc_parse_incoming_line), ((void *)0)); |
423 | } |