File: | core/expandos.c |
Location: | line 74, column 2 |
Description: | Dereference of null pointer. |
1 | /* |
2 | expandos.c : irssi |
3 | |
4 | Copyright (C) 2000 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 "core.h" |
22 | #include "module.h" |
23 | #include "modules.h" |
24 | #include "signals.h" |
25 | #include "expandos.h" |
26 | #include "settings.h" |
27 | #include "commands.h" |
28 | #include "misc.h" |
29 | #include "irssi-version.h" |
30 | |
31 | #include "servers.h" |
32 | #include "channels.h" |
33 | #include "queries.h" |
34 | #include "window-item-def.h" |
35 | |
36 | #ifdef HAVE_SYS_UTSNAME_H1 |
37 | # include <sys/utsname.h> |
38 | #endif |
39 | |
40 | #define MAX_EXPANDO_SIGNALS10 10 |
41 | |
42 | typedef struct { |
43 | EXPANDO_FUNC func; |
44 | |
45 | int signals; |
46 | int signal_ids[MAX_EXPANDO_SIGNALS10]; |
47 | int signal_args[MAX_EXPANDO_SIGNALS10]; |
48 | } EXPANDO_REC; |
49 | |
50 | const char *current_expando = NULL((void *)0); |
51 | |
52 | static int timer_tag; |
53 | |
54 | static EXPANDO_REC *char_expandos[255]; |
55 | static GHashTable *expandos; |
56 | static char *last_sent_msg, *last_sent_msg_body; |
57 | static char *last_privmsg_from, *last_public_from; |
58 | static char *sysname, *sysrelease, *sysarch; |
59 | |
60 | static const char *timestamp_format; |
61 | static int timestamp_seconds; |
62 | static time_t last_timestamp; |
63 | |
64 | #define CHAR_EXPANDO(chr)(char_expandos[(int) (unsigned char) chr]) \ |
65 | (char_expandos[(int) (unsigned char) chr]) |
66 | |
67 | /* Create expando - overrides any existing ones. */ |
68 | void expando_create(const char *key, EXPANDO_FUNC func, ...) |
69 | { |
70 | EXPANDO_REC *rec; |
71 | const char *signal; |
72 | va_list va; |
73 | |
74 | g_return_if_fail(key != NULL || *key == '\0')do{ if (key != ((void *)0) || *key == '\0') { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "key != NULL || *key == '\\0'" ); return; }; }while (0); |
Dereference of null pointer | |
75 | g_return_if_fail(func != NULL)do{ if (func != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "func != NULL"); return; }; }while (0); |
76 | |
77 | if (key[1] != '\0') |
78 | rec = g_hash_table_lookup(expandos, key); |
79 | else { |
80 | /* single character expando */ |
81 | rec = CHAR_EXPANDO(*key)(char_expandos[(int) (unsigned char) *key]); |
82 | } |
83 | |
84 | if (rec != NULL((void *)0)) |
85 | rec->signals = 0; |
86 | else { |
87 | rec = g_new0(EXPANDO_REC, 1)((EXPANDO_REC *) g_malloc0 (((gsize) sizeof (EXPANDO_REC)) * ( (gsize) (1)))); |
88 | if (key[1] != '\0') |
89 | g_hash_table_insert(expandos, g_strdup(key), rec); |
90 | else |
91 | char_expandos[(int) (unsigned char) *key] = rec; |
92 | } |
93 | |
94 | rec->func = func; |
95 | |
96 | va_start(va, func)__builtin_va_start((va), (func)); |
97 | while ((signal = (const char *) va_arg(va, const char *)__builtin_va_arg((va), const char *)) != NULL((void *)0)) |
98 | expando_add_signal(key, signal, (int) va_arg(va, int)__builtin_va_arg((va), int)); |
99 | va_end(va)__builtin_va_end(va); |
100 | } |
101 | |
102 | static EXPANDO_REC *expando_find(const char *key) |
103 | { |
104 | if (key[1] != '\0') |
105 | return g_hash_table_lookup(expandos, key); |
106 | else |
107 | return CHAR_EXPANDO(*key)(char_expandos[(int) (unsigned char) *key]); |
108 | } |
109 | |
110 | /* Add new signal to expando */ |
111 | void expando_add_signal(const char *key, const char *signal, ExpandoArg arg) |
112 | { |
113 | EXPANDO_REC *rec; |
114 | |
115 | g_return_if_fail(key != NULL)do{ if (key != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "key != NULL"); return; } ; }while (0); |
116 | g_return_if_fail(signal != NULL)do{ if (signal != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "signal != NULL"); return ; }; }while (0); |
117 | |
118 | rec = expando_find(key); |
119 | 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); |
120 | |
121 | if (arg == EXPANDO_NEVER) { |
122 | /* expando changes never */ |
123 | rec->signals = -1; |
124 | } else if (rec->signals < MAX_EXPANDO_SIGNALS10) { |
125 | g_return_if_fail(rec->signals != -1)do{ if (rec->signals != -1) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "rec->signals != -1") ; return; }; }while (0); |
126 | |
127 | rec->signal_ids[rec->signals] = signal_get_uniq_id(signal)module_get_uniq_id_str("signals", signal); |
128 | rec->signal_args[rec->signals] = arg; |
129 | rec->signals++; |
130 | } |
131 | } |
132 | |
133 | /* Destroy expando */ |
134 | void expando_destroy(const char *key, EXPANDO_FUNC func) |
135 | { |
136 | gpointer origkey, value; |
137 | EXPANDO_REC *rec; |
138 | |
139 | g_return_if_fail(key != NULL || *key == '\0')do{ if (key != ((void *)0) || *key == '\0') { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "key != NULL || *key == '\\0'" ); return; }; }while (0); |
140 | g_return_if_fail(func != NULL)do{ if (func != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "func != NULL"); return; }; }while (0); |
141 | |
142 | if (key[1] == '\0') { |
143 | /* single character expando */ |
144 | rec = CHAR_EXPANDO(*key)(char_expandos[(int) (unsigned char) *key]); |
145 | if (rec != NULL((void *)0) && rec->func == func) { |
146 | char_expandos[(int) (unsigned char) *key] = NULL((void *)0); |
147 | g_free(rec); |
148 | } |
149 | } else if (g_hash_table_lookup_extended(expandos, key, |
150 | &origkey, &value)) { |
151 | rec = value; |
152 | if (rec->func == func) { |
153 | g_hash_table_remove(expandos, key); |
154 | g_free(origkey); |
155 | g_free(rec); |
156 | } |
157 | } |
158 | } |
159 | |
160 | void expando_bind(const char *key, int funccount, SIGNAL_FUNC *funcs) |
161 | { |
162 | SIGNAL_FUNC func; |
163 | EXPANDO_REC *rec; |
164 | int n, arg; |
165 | |
166 | g_return_if_fail(key != NULL)do{ if (key != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "key != NULL"); return; } ; }while (0); |
167 | g_return_if_fail(funccount >= 1)do{ if (funccount >= 1) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "funccount >= 1"); return ; }; }while (0); |
168 | g_return_if_fail(funcs != NULL)do{ if (funcs != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "funcs != NULL"); return ; }; }while (0); |
169 | g_return_if_fail(funcs[0] != NULL)do{ if (funcs[0] != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "funcs[0] != NULL"); return ; }; }while (0); |
170 | |
171 | rec = expando_find(key); |
172 | 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); |
173 | |
174 | if (rec->signals == 0) { |
175 | /* it's unknown when this expando changes.. |
176 | check it once in a second */ |
177 | signal_add("expando timer", funcs[EXPANDO_ARG_NONE])signal_add_full("core", 0, ("expando timer"), (SIGNAL_FUNC) ( funcs[EXPANDO_ARG_NONE]), ((void *)0)); |
178 | } |
179 | |
180 | for (n = 0; n < rec->signals; n++) { |
181 | arg = rec->signal_args[n]; |
182 | func = arg < funccount ? funcs[arg] : NULL((void *)0); |
183 | if (func == NULL((void *)0)) func = funcs[EXPANDO_ARG_NONE]; |
184 | |
185 | signal_add_full_id(MODULE_NAME"core", SIGNAL_PRIORITY_DEFAULT0, |
186 | rec->signal_ids[n], func, NULL((void *)0)); |
187 | } |
188 | } |
189 | |
190 | void expando_unbind(const char *key, int funccount, SIGNAL_FUNC *funcs) |
191 | { |
192 | SIGNAL_FUNC func; |
193 | EXPANDO_REC *rec; |
194 | int n, arg; |
195 | |
196 | g_return_if_fail(key != NULL)do{ if (key != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "key != NULL"); return; } ; }while (0); |
197 | g_return_if_fail(funccount >= 1)do{ if (funccount >= 1) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "funccount >= 1"); return ; }; }while (0); |
198 | g_return_if_fail(funcs != NULL)do{ if (funcs != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "funcs != NULL"); return ; }; }while (0); |
199 | g_return_if_fail(funcs[0] != NULL)do{ if (funcs[0] != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "funcs[0] != NULL"); return ; }; }while (0); |
200 | |
201 | rec = expando_find(key); |
202 | 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); |
203 | |
204 | if (rec->signals == 0) { |
205 | /* it's unknown when this expando changes.. |
206 | check it once in a second */ |
207 | signal_remove("expando timer", funcs[EXPANDO_ARG_NONE])signal_remove_full(("expando timer"), (SIGNAL_FUNC) (funcs[EXPANDO_ARG_NONE ]), ((void *)0)); |
208 | } |
209 | |
210 | for (n = 0; n < rec->signals; n++) { |
211 | arg = rec->signal_args[n]; |
212 | func = arg < funccount ? funcs[arg] : NULL((void *)0); |
213 | if (func == NULL((void *)0)) func = funcs[EXPANDO_ARG_NONE]; |
214 | |
215 | signal_remove_id(rec->signal_ids[n], func, NULL((void *)0)); |
216 | } |
217 | } |
218 | |
219 | /* Returns [<signal id>, EXPANDO_ARG_xxx, <signal id>, ..., -1] */ |
220 | int *expando_get_signals(const char *key) |
221 | { |
222 | EXPANDO_REC *rec; |
223 | int *signals; |
224 | int n; |
225 | |
226 | g_return_val_if_fail(key != NULL, NULL)do{ if (key != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "key != NULL"); return ( ((void *)0)); }; }while (0); |
227 | |
228 | rec = expando_find(key); |
229 | if (rec == NULL((void *)0) || rec->signals < 0) |
230 | return NULL((void *)0); |
231 | |
232 | if (rec->signals == 0) { |
233 | /* it's unknown when this expando changes.. |
234 | check it once in a second */ |
235 | signals = g_new(int, 3)((int *) g_malloc (((gsize) sizeof (int)) * ((gsize) (3)))); |
236 | signals[0] = signal_get_uniq_id("expando timer")module_get_uniq_id_str("signals", "expando timer"); |
237 | signals[1] = EXPANDO_ARG_NONE; |
238 | signals[2] = -1; |
239 | return signals; |
240 | } |
241 | |
242 | signals = g_new(int, rec->signals*2+1)((int *) g_malloc (((gsize) sizeof (int)) * ((gsize) (rec-> signals*2 +1)))); |
243 | for (n = 0; n < rec->signals; n++) { |
244 | signals[n*2] = rec->signal_ids[n]; |
245 | signals[n*2+1] = rec->signal_args[n]; |
246 | } |
247 | signals[rec->signals*2] = -1; |
248 | return signals; |
249 | } |
250 | |
251 | EXPANDO_FUNC expando_find_char(char chr) |
252 | { |
253 | return CHAR_EXPANDO(chr)(char_expandos[(int) (unsigned char) chr]) == NULL((void *)0) ? NULL((void *)0) : |
254 | CHAR_EXPANDO(chr)(char_expandos[(int) (unsigned char) chr])->func; |
255 | } |
256 | |
257 | EXPANDO_FUNC expando_find_long(const char *key) |
258 | { |
259 | EXPANDO_REC *rec = g_hash_table_lookup(expandos, key); |
260 | return rec == NULL((void *)0) ? NULL((void *)0) : rec->func; |
261 | } |
262 | |
263 | static gboolean free_expando(gpointer key, gpointer value, gpointer user_data) |
264 | { |
265 | g_free(key); |
266 | g_free(value); |
267 | return TRUE(!(0)); |
268 | } |
269 | |
270 | /* last person who sent you a MSG */ |
271 | static char *expando_lastmsg(SERVER_REC *server, void *item, int *free_ret) |
272 | { |
273 | return last_privmsg_from; |
274 | } |
275 | |
276 | /* last person to whom you sent a MSG */ |
277 | static char *expando_lastmymsg(SERVER_REC *server, void *item, int *free_ret) |
278 | { |
279 | return last_sent_msg; |
280 | } |
281 | |
282 | /* last person to send a public message to a channel you are on */ |
283 | static char *expando_lastpublic(SERVER_REC *server, void *item, int *free_ret) |
284 | { |
285 | return last_public_from; |
286 | } |
287 | |
288 | /* text of your AWAY message, if any */ |
289 | static char *expando_awaymsg(SERVER_REC *server, void *item, int *free_ret) |
290 | { |
291 | return server == NULL((void *)0) ? "" : server->away_reason; |
292 | } |
293 | |
294 | /* body of last MSG you sent */ |
295 | static char *expando_lastmymsg_body(SERVER_REC *server, void *item, int *free_ret) |
296 | { |
297 | return last_sent_msg_body; |
298 | } |
299 | |
300 | /* current channel */ |
301 | static char *expando_channel(SERVER_REC *server, void *item, int *free_ret) |
302 | { |
303 | return !IS_CHANNEL(item)(((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL")) ? (!(0)) : (0)) ? NULL((void *)0) : CHANNEL(item)((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL"))->name; |
304 | } |
305 | |
306 | /* time client was started, $time() format */ |
307 | static char *expando_clientstarted(SERVER_REC *server, void *item, int *free_ret) |
308 | { |
309 | *free_ret = TRUE(!(0)); |
310 | return g_strdup_printf("%ld", (long) client_start_time); |
311 | } |
312 | |
313 | /* channel you were last INVITEd to */ |
314 | static char *expando_last_invite(SERVER_REC *server, void *item, int *free_ret) |
315 | { |
316 | return server == NULL((void *)0) ? "" : server->last_invite; |
317 | } |
318 | |
319 | /* client version text string */ |
320 | static char *expando_version(SERVER_REC *server, void *item, int *free_ret) |
321 | { |
322 | return PACKAGE_VERSION"0.8.13-svn"; |
323 | } |
324 | |
325 | /* current value of CMDCHARS */ |
326 | static char *expando_cmdchars(SERVER_REC *server, void *item, int *free_ret) |
327 | { |
328 | return (char *) settings_get_str("cmdchars"); |
329 | } |
330 | |
331 | /* first CMDCHAR */ |
332 | static char *expando_cmdchar(SERVER_REC *server, void *item, int *free_ret) |
333 | { |
334 | char str[2] = { 0, 0 }; |
335 | |
336 | str[0] = *settings_get_str("cmdchars"); |
337 | |
338 | *free_ret = TRUE(!(0)); |
339 | return g_strdup(str); |
340 | } |
341 | |
342 | /* modes of current channel, if any */ |
343 | static char *expando_chanmode(SERVER_REC *server, void *item, int *free_ret) |
344 | { |
345 | char *cmode; |
346 | char *args; |
347 | |
348 | *free_ret = FALSE(0); |
349 | |
350 | if (!IS_CHANNEL(item)(((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL")) ? (!(0)) : (0))) |
351 | return NULL((void *)0); |
352 | |
353 | if (!settings_get_bool("chanmode_expando_strip")) |
354 | return CHANNEL(item)((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL"))->mode; |
355 | |
356 | *free_ret = TRUE(!(0)); |
357 | cmode = g_strdup(CHANNEL(item)((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL"))->mode); |
358 | args = strchr(cmode, ' '); |
359 | if (args != NULL((void *)0)) |
360 | *args = 0; |
361 | |
362 | return cmode; |
363 | } |
364 | |
365 | /* current nickname */ |
366 | static char *expando_nick(SERVER_REC *server, void *item, int *free_ret) |
367 | { |
368 | return server == NULL((void *)0) ? "" : server->nick; |
369 | } |
370 | |
371 | /* value of STATUS_OPER if you are an irc operator */ |
372 | static char *expando_statusoper(SERVER_REC *server, void *item, int *free_ret) |
373 | { |
374 | return server == NULL((void *)0) || !server->server_operator ? "" : |
375 | (char *) settings_get_str("STATUS_OPER"); |
376 | } |
377 | |
378 | /* if you are a channel operator in $C, expands to a '@' */ |
379 | static char *expando_chanop(SERVER_REC *server, void *item, int *free_ret) |
380 | { |
381 | return IS_CHANNEL(item)(((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL")) ? (!(0)) : (0)) && CHANNEL(item)((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL"))->chanop ? "@" : ""; |
382 | } |
383 | |
384 | /* nickname of whomever you are QUERYing */ |
385 | static char *expando_query(SERVER_REC *server, void *item, int *free_ret) |
386 | { |
387 | return !IS_QUERY(item)(((QUERY_REC *) module_check_cast_module(item, __builtin_offsetof (QUERY_REC, type), "WINDOW ITEM TYPE", "QUERY")) ? (!(0)) : ( 0)) ? "" : QUERY(item)((QUERY_REC *) module_check_cast_module(item, __builtin_offsetof (QUERY_REC, type), "WINDOW ITEM TYPE", "QUERY"))->name; |
388 | } |
389 | |
390 | /* version of current server */ |
391 | static char *expando_serverversion(SERVER_REC *server, void *item, int *free_ret) |
392 | { |
393 | return server == NULL((void *)0) ? "" : server->version; |
394 | } |
395 | |
396 | /* target of current input (channel or QUERY nickname) */ |
397 | static char *expando_target(SERVER_REC *server, void *item, int *free_ret) |
398 | { |
399 | return item == NULL((void *)0) ? "" : |
400 | (char *) window_item_get_target((WI_ITEM_REC *) item)(((WI_ITEM_REC *) item)->get_target((WI_ITEM_REC *) item)); |
401 | } |
402 | |
403 | /* client release date (in YYYYMMDD format) */ |
404 | static char *expando_releasedate(SERVER_REC *server, void *item, int *free_ret) |
405 | { |
406 | *free_ret = TRUE(!(0)); |
407 | return g_strdup_printf("%d", IRSSI_VERSION_DATE20090227); |
408 | } |
409 | |
410 | /* client release time (in HHMM format) */ |
411 | static char *expando_releasetime(SERVER_REC *server, void *item, int *free_ret) |
412 | { |
413 | *free_ret = TRUE(!(0)); |
414 | return g_strdup_printf("%04d", IRSSI_VERSION_TIME1532); |
415 | } |
416 | |
417 | /* current working directory */ |
418 | static char *expando_workdir(SERVER_REC *server, void *item, int *free_ret) |
419 | { |
420 | *free_ret = TRUE(!(0)); |
421 | return g_get_current_dir(); |
422 | } |
423 | |
424 | /* value of REALNAME */ |
425 | static char *expando_realname(SERVER_REC *server, void *item, int *free_ret) |
426 | { |
427 | return server == NULL((void *)0) ? "" : server->connrec->realname; |
428 | } |
429 | |
430 | /* time of day (hh:mm) */ |
431 | static char *expando_time(SERVER_REC *server, void *item, int *free_ret) |
432 | { |
433 | time_t now; |
434 | struct tm *tm; |
435 | char str[256]; |
436 | |
437 | now = time(NULL((void *)0)); |
438 | tm = localtime(&now); |
439 | |
440 | if (strftime(str, sizeof(str), timestamp_format, tm) == 0) |
441 | return ""; |
442 | |
443 | *free_ret = TRUE(!(0)); |
444 | return g_strdup(str); |
445 | } |
446 | |
447 | /* a literal '$' */ |
448 | static char *expando_dollar(SERVER_REC *server, void *item, int *free_ret) |
449 | { |
450 | return "$"; |
451 | } |
452 | |
453 | /* system name */ |
454 | static char *expando_sysname(SERVER_REC *server, void *item, int *free_ret) |
455 | { |
456 | return sysname; |
457 | } |
458 | |
459 | /* system release */ |
460 | static char *expando_sysrelease(SERVER_REC *server, void *item, int *free_ret) |
461 | { |
462 | return sysrelease; |
463 | } |
464 | |
465 | /* system architecture */ |
466 | static char *expando_sysarch(SERVER_REC *server, void *item, int *free_ret) |
467 | { |
468 | return sysarch; |
469 | } |
470 | |
471 | /* Topic of active channel (or address of queried nick) */ |
472 | static char *expando_topic(SERVER_REC *server, void *item, int *free_ret) |
473 | { |
474 | if (IS_CHANNEL(item)(((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL")) ? (!(0)) : (0))) |
475 | return CHANNEL(item)((CHANNEL_REC *) module_check_cast_module(item, __builtin_offsetof (CHANNEL_REC, type), "WINDOW ITEM TYPE", "CHANNEL"))->topic; |
476 | if (IS_QUERY(item)(((QUERY_REC *) module_check_cast_module(item, __builtin_offsetof (QUERY_REC, type), "WINDOW ITEM TYPE", "QUERY")) ? (!(0)) : ( 0))) { |
477 | QUERY_REC *query = QUERY(item)((QUERY_REC *) module_check_cast_module(item, __builtin_offsetof (QUERY_REC, type), "WINDOW ITEM TYPE", "QUERY")); |
478 | |
479 | if (query->server_tag == NULL((void *)0)) |
480 | return ""; |
481 | |
482 | *free_ret = TRUE(!(0)); |
483 | return query->address == NULL((void *)0) ? |
484 | g_strdup_printf("(%s)", query->server_tag) : |
485 | g_strdup_printf("%s (%s)", query->address, |
486 | query->server_tag); |
487 | } |
488 | return ""; |
489 | } |
490 | |
491 | /* Server tag */ |
492 | static char *expando_servertag(SERVER_REC *server, void *item, int *free_ret) |
493 | { |
494 | return server == NULL((void *)0) ? "" : server->tag; |
495 | } |
496 | |
497 | /* Server chatnet */ |
498 | static char *expando_chatnet(SERVER_REC *server, void *item, int *free_ret) |
499 | { |
500 | return server == NULL((void *)0) ? "" : server->connrec->chatnet; |
501 | } |
502 | |
503 | /* visible_name of current window item */ |
504 | static char *expando_itemname(SERVER_REC *server, void *item, int *free_ret) |
505 | { |
506 | return item == NULL((void *)0) ? "" : ((WI_ITEM_REC *) item)->visible_name; |
507 | } |
508 | |
509 | static void sig_message_public(SERVER_REC *server, const char *msg, |
510 | const char *nick, const char *address, |
511 | const char *target) |
512 | { |
513 | g_free_not_null(last_public_from)g_free(last_public_from); |
514 | last_public_from = g_strdup(nick); |
515 | } |
516 | |
517 | static void sig_message_private(SERVER_REC *server, const char *msg, |
518 | const char *nick, const char *address) |
519 | { |
520 | g_free_not_null(last_privmsg_from)g_free(last_privmsg_from); |
521 | last_privmsg_from = g_strdup(nick); |
522 | } |
523 | |
524 | static void sig_message_own_private(SERVER_REC *server, const char *msg, |
525 | const char *target, const char *origtarget) |
526 | { |
527 | 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); |
528 | g_return_if_fail(msg != NULL)do{ if (msg != ((void *)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "msg != NULL"); return; } ; }while (0); |
529 | |
530 | if (target != NULL((void *)0)) { |
531 | if (target != last_sent_msg) { |
532 | g_free_not_null(last_sent_msg)g_free(last_sent_msg); |
533 | last_sent_msg = g_strdup(target); |
534 | } |
535 | g_free_not_null(last_sent_msg_body)g_free(last_sent_msg_body); |
536 | last_sent_msg_body = g_strdup(msg); |
537 | } |
538 | } |
539 | |
540 | static int sig_timer(void) |
541 | { |
542 | time_t now; |
543 | struct tm *tm; |
544 | int last_min; |
545 | |
546 | signal_emit("expando timer", 0); |
547 | |
548 | /* check if $Z has changed */ |
549 | now = time(NULL((void *)0)); |
550 | if (last_timestamp != now) { |
551 | if (!timestamp_seconds && last_timestamp != 0) { |
552 | /* assume it changes every minute */ |
553 | tm = localtime(&last_timestamp); |
554 | last_min = tm->tm_min; |
555 | |
556 | tm = localtime(&now); |
557 | if (tm->tm_min == last_min) |
558 | return 1; |
559 | } |
560 | |
561 | signal_emit("time changed", 0); |
562 | last_timestamp = now; |
563 | } |
564 | |
565 | return 1; |
566 | } |
567 | |
568 | static void read_settings(void) |
569 | { |
570 | timestamp_format = settings_get_str("timestamp_format"); |
571 | timestamp_seconds = |
572 | strstr(timestamp_format, "%r") != NULL((void *)0) || |
573 | strstr(timestamp_format, "%s") != NULL((void *)0) || |
574 | strstr(timestamp_format, "%S") != NULL((void *)0) || |
575 | strstr(timestamp_format, "%X") != NULL((void *)0) || |
576 | strstr(timestamp_format, "%T") != NULL((void *)0); |
577 | |
578 | } |
579 | |
580 | void expandos_init(void) |
581 | { |
582 | #ifdef HAVE_SYS_UTSNAME_H1 |
583 | struct utsname un; |
584 | #endif |
585 | settings_add_str("misc", "STATUS_OPER", "*")settings_add_str_module("core", "misc", "STATUS_OPER", "*"); |
586 | settings_add_str("lookandfeel", "timestamp_format", "%H:%M")settings_add_str_module("core", "lookandfeel", "timestamp_format" , "%H:%M"); |
587 | settings_add_bool("lookandfeel", "chanmode_expando_strip", FALSE)settings_add_bool_module("core", "lookandfeel", "chanmode_expando_strip" , (0)); |
588 | |
589 | last_sent_msg = NULL((void *)0); last_sent_msg_body = NULL((void *)0); |
590 | last_privmsg_from = NULL((void *)0); last_public_from = NULL((void *)0); |
591 | last_timestamp = 0; |
592 | |
593 | sysname = sysrelease = sysarch = NULL((void *)0); |
594 | #ifdef HAVE_SYS_UTSNAME_H1 |
595 | if (uname(&un) >= 0) { |
596 | sysname = g_strdup(un.sysname); |
597 | sysrelease = g_strdup(un.release); |
598 | sysarch = g_strdup(un.machine); |
599 | } |
600 | #endif |
601 | |
602 | memset(char_expandos, 0, sizeof(char_expandos)); |
603 | expandos = g_hash_table_new((GHashFunc) g_str_hash, |
604 | (GCompareFunc) g_str_equal); |
605 | |
606 | expando_create(",", expando_lastmsg, |
607 | "message private", EXPANDO_ARG_SERVER, NULL((void *)0)); |
608 | expando_create(".", expando_lastmymsg, |
609 | "command msg", EXPANDO_ARG_NONE, NULL((void *)0)); |
610 | expando_create(";", expando_lastpublic, |
611 | "message public", EXPANDO_ARG_SERVER, NULL((void *)0)); |
612 | expando_create("A", expando_awaymsg, |
613 | "away mode changed", EXPANDO_ARG_NONE, NULL((void *)0)); |
614 | expando_create("B", expando_lastmymsg_body, |
615 | "command msg", EXPANDO_ARG_NONE, NULL((void *)0)); |
616 | expando_create("C", expando_channel, |
617 | "window changed", EXPANDO_ARG_NONE, |
618 | "window item changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
619 | expando_create("F", expando_clientstarted, |
620 | "", EXPANDO_NEVER, NULL((void *)0)); |
621 | expando_create("I", expando_last_invite, NULL((void *)0)); |
622 | expando_create("J", expando_version, |
623 | "", EXPANDO_NEVER, NULL((void *)0)); |
624 | expando_create("K", expando_cmdchars, |
625 | "setup changed", EXPANDO_ARG_NONE, NULL((void *)0)); |
626 | expando_create("k", expando_cmdchar, |
627 | "setup changed", EXPANDO_ARG_NONE, NULL((void *)0)); |
628 | expando_create("M", expando_chanmode, |
629 | "window changed", EXPANDO_ARG_NONE, |
630 | "window item changed", EXPANDO_ARG_WINDOW, |
631 | "channel mode changed", EXPANDO_ARG_WINDOW_ITEM, NULL((void *)0)); |
632 | expando_create("N", expando_nick, |
633 | "window changed", EXPANDO_ARG_NONE, |
634 | "window connect changed", EXPANDO_ARG_WINDOW, |
635 | "window server changed", EXPANDO_ARG_WINDOW, |
636 | "server nick changed", EXPANDO_ARG_SERVER, NULL((void *)0)); |
637 | expando_create("O", expando_statusoper, |
638 | "setup changed", EXPANDO_ARG_NONE, |
639 | "window changed", EXPANDO_ARG_NONE, |
640 | "window server changed", EXPANDO_ARG_WINDOW, |
641 | "user mode changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
642 | expando_create("P", expando_chanop, |
643 | "window changed", EXPANDO_ARG_NONE, |
644 | "window item changed", EXPANDO_ARG_WINDOW, |
645 | "nick mode changed", EXPANDO_ARG_WINDOW_ITEM, NULL((void *)0)); |
646 | expando_create("Q", expando_query, |
647 | "window changed", EXPANDO_ARG_NONE, |
648 | "window item changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
649 | expando_create("R", expando_serverversion, |
650 | "window changed", EXPANDO_ARG_NONE, |
651 | "window server changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
652 | expando_create("T", expando_target, |
653 | "window changed", EXPANDO_ARG_NONE, |
654 | "window item changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
655 | expando_create("V", expando_releasedate, |
656 | "", EXPANDO_NEVER, NULL((void *)0)); |
657 | expando_create("versiontime", expando_releasetime, |
658 | "", EXPANDO_NEVER, NULL((void *)0)); |
659 | expando_create("W", expando_workdir, NULL((void *)0)); |
660 | expando_create("Y", expando_realname, |
661 | "window changed", EXPANDO_ARG_NONE, |
662 | "window connect changed", EXPANDO_ARG_WINDOW, |
663 | "window server changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
664 | expando_create("Z", expando_time, |
665 | "time changed", EXPANDO_ARG_NONE, NULL((void *)0)); |
666 | expando_create("$", expando_dollar, |
667 | "", EXPANDO_NEVER, NULL((void *)0)); |
668 | |
669 | expando_create("sysname", expando_sysname, |
670 | "", EXPANDO_NEVER, NULL((void *)0)); |
671 | expando_create("sysrelease", expando_sysrelease, |
672 | "", EXPANDO_NEVER, NULL((void *)0)); |
673 | expando_create("sysarch", expando_sysarch, |
674 | "", EXPANDO_NEVER, NULL((void *)0)); |
675 | expando_create("topic", expando_topic, |
676 | "window changed", EXPANDO_ARG_NONE, |
677 | "window item changed", EXPANDO_ARG_WINDOW, |
678 | "channel topic changed", EXPANDO_ARG_WINDOW_ITEM, |
679 | "query address changed", EXPANDO_ARG_WINDOW_ITEM, NULL((void *)0)); |
680 | expando_create("tag", expando_servertag, |
681 | "window changed", EXPANDO_ARG_NONE, |
682 | "window connect changed", EXPANDO_ARG_WINDOW, |
683 | "window server changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
684 | expando_create("chatnet", expando_chatnet, |
685 | "window changed", EXPANDO_ARG_NONE, |
686 | "window connect changed", EXPANDO_ARG_WINDOW, |
687 | "window server changed", EXPANDO_ARG_WINDOW, NULL((void *)0)); |
688 | expando_create("itemname", expando_itemname, |
689 | "window changed", EXPANDO_ARG_NONE, |
690 | "window item changed", EXPANDO_ARG_WINDOW, |
691 | "window item name changed", EXPANDO_ARG_WINDOW_ITEM, |
692 | NULL((void *)0)); |
693 | |
694 | read_settings(); |
695 | |
696 | timer_tag = g_timeout_add(5000, (GSourceFunc) sig_timer, NULL((void *)0)); |
697 | signal_add("message public", (SIGNAL_FUNC) sig_message_public)signal_add_full("core", 0, ("message public"), (SIGNAL_FUNC) ( (SIGNAL_FUNC) sig_message_public), ((void *)0)); |
698 | signal_add("message private", (SIGNAL_FUNC) sig_message_private)signal_add_full("core", 0, ("message private"), (SIGNAL_FUNC) ((SIGNAL_FUNC) sig_message_private), ((void *)0)); |
699 | signal_add("message own_private", (SIGNAL_FUNC) sig_message_own_private)signal_add_full("core", 0, ("message own_private"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) sig_message_own_private), ((void *)0)); |
700 | signal_add_first("setup changed", (SIGNAL_FUNC) read_settings)signal_add_full("core", -100, ("setup changed"), (SIGNAL_FUNC ) ((SIGNAL_FUNC) read_settings), ((void *)0)); |
701 | } |
702 | |
703 | void expandos_deinit(void) |
704 | { |
705 | int n; |
706 | |
707 | for (n = 0; n < sizeof(char_expandos)/sizeof(char_expandos[0]); n++) |
708 | g_free_not_null(char_expandos[n])g_free(char_expandos[n]); |
709 | |
710 | g_hash_table_foreach_remove(expandos, free_expando, NULL((void *)0)); |
711 | g_hash_table_destroy(expandos); |
712 | |
713 | g_free_not_null(last_sent_msg)g_free(last_sent_msg); g_free_not_null(last_sent_msg_body)g_free(last_sent_msg_body); |
714 | g_free_not_null(last_privmsg_from)g_free(last_privmsg_from); g_free_not_null(last_public_from)g_free(last_public_from); |
715 | g_free_not_null(sysname)g_free(sysname); g_free_not_null(sysrelease)g_free(sysrelease); |
716 | g_free_not_null(sysarch)g_free(sysarch); |
717 | |
718 | g_source_remove(timer_tag); |
719 | signal_remove("message public", (SIGNAL_FUNC) sig_message_public)signal_remove_full(("message public"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_message_public), ((void *)0)); |
720 | signal_remove("message private", (SIGNAL_FUNC) sig_message_private)signal_remove_full(("message private"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_message_private), ((void *)0)); |
721 | signal_remove("message own_private", (SIGNAL_FUNC) sig_message_own_private)signal_remove_full(("message own_private"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) sig_message_own_private), ((void *)0)); |
722 | signal_remove("setup changed", (SIGNAL_FUNC) read_settings)signal_remove_full(("setup changed"), (SIGNAL_FUNC) ((SIGNAL_FUNC ) read_settings), ((void *)0)); |
723 | } |