~ubuntu-branches/ubuntu/feisty/irssi/feisty-backports

« back to all changes in this revision

Viewing changes to src/fe-common/core/fe-log.c

  • Committer: Bazaar Package Importer
  • Author(s): David Pashley
  • Date: 2005-12-10 21:25:51 UTC
  • Revision ID: james.westby@ubuntu.com-20051210212551-5qwm108g7inyu2f2
Tags: upstream-0.8.10
ImportĀ upstreamĀ versionĀ 0.8.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 fe-log.c : irssi
 
3
 
 
4
    Copyright (C) 1999-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
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
*/
 
20
 
 
21
#include "module.h"
 
22
#include "module-formats.h"
 
23
#include "signals.h"
 
24
#include "commands.h"
 
25
#include "chat-protocols.h"
 
26
#include "servers.h"
 
27
#include "levels.h"
 
28
#include "misc.h"
 
29
#include "log.h"
 
30
#include "special-vars.h"
 
31
#include "settings.h"
 
32
#include "lib-config/iconfig.h"
 
33
 
 
34
#include "fe-windows.h"
 
35
#include "window-items.h"
 
36
#include "formats.h"
 
37
#include "themes.h"
 
38
#include "printtext.h"
 
39
 
 
40
/* close autologs after 5 minutes of inactivity */
 
41
#define AUTOLOG_INACTIVITY_CLOSE (60*5)
 
42
 
 
43
static int autolog_level;
 
44
static int autoremove_tag;
 
45
static const char *autolog_path;
 
46
 
 
47
static THEME_REC *log_theme;
 
48
static int skip_next_printtext;
 
49
static const char *log_theme_name;
 
50
 
 
51
static int log_dir_create_mode;
 
52
 
 
53
static char *log_colorizer_strip(const char *str)
 
54
{
 
55
        return strip_codes(str);
 
56
}
 
57
 
 
58
static void log_add_targets(LOG_REC *log, const char *targets, const char *tag)
 
59
{
 
60
        char **tmp, **items;
 
61
 
 
62
        g_return_if_fail(log != NULL);
 
63
        g_return_if_fail(targets != NULL);
 
64
 
 
65
        items = g_strsplit(targets, " ", -1);
 
66
 
 
67
        for (tmp = items; *tmp != NULL; tmp++)
 
68
                log_item_add(log, LOG_ITEM_TARGET, *tmp, tag);
 
69
 
 
70
        g_strfreev(items);
 
71
}
 
72
 
 
73
/* SYNTAX: LOG OPEN [-noopen] [-autoopen] [-window] [-<server tag>]
 
74
                    [-targets <targets>] [-colors]
 
75
                    <fname> [<levels>] */
 
76
static void cmd_log_open(const char *data)
 
77
{
 
78
        SERVER_REC *server;
 
79
        GHashTable *optlist;
 
80
        char *targetarg, *fname, *levels, *servertag;
 
81
        void *free_arg;
 
82
        char window[MAX_INT_STRLEN];
 
83
        LOG_REC *log;
 
84
        int level;
 
85
 
 
86
        if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
 
87
                            PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_OPTIONS,
 
88
                            "log open", &optlist, &fname, &levels))
 
89
                return;
 
90
        if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
 
91
 
 
92
        level = level2bits(levels);
 
93
        log = log_create_rec(fname, level != 0 ? level : MSGLEVEL_ALL);
 
94
 
 
95
        /* -<server tag> */
 
96
        server = cmd_options_get_server("log open", optlist, NULL);
 
97
        servertag = server == NULL ? NULL : server->tag;
 
98
 
 
99
        if (g_hash_table_lookup(optlist, "window")) {
 
100
                /* log by window ref# */
 
101
                targetarg = g_hash_table_lookup(optlist, "targets");
 
102
                if (targetarg == NULL || !is_numeric(targetarg, '\0')) {
 
103
                        ltoa(window, active_win->refnum);
 
104
                        targetarg = window;
 
105
                }
 
106
                log_item_add(log, LOG_ITEM_WINDOW_REFNUM, targetarg,
 
107
                             servertag);
 
108
        } else {
 
109
                targetarg = g_hash_table_lookup(optlist, "targets");
 
110
                if (targetarg != NULL && *targetarg != '\0')
 
111
                        log_add_targets(log, targetarg, servertag);
 
112
                else if (servertag != NULL)
 
113
                        log_add_targets(log, "*", servertag);
 
114
        }
 
115
 
 
116
        if (g_hash_table_lookup(optlist, "autoopen"))
 
117
                log->autoopen = TRUE;
 
118
 
 
119
        if (g_hash_table_lookup(optlist, "colors") == NULL)
 
120
                log->colorizer = log_colorizer_strip;
 
121
 
 
122
        log_update(log);
 
123
 
 
124
        if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) {
 
125
                /* start logging */
 
126
                if (log_start_logging(log)) {
 
127
                        printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
 
128
                                    TXT_LOG_OPENED, fname);
 
129
                } else {
 
130
                        log_close(log);
 
131
                }
 
132
        }
 
133
 
 
134
        cmd_params_free(free_arg);
 
135
}
 
136
 
 
137
static LOG_REC *log_find_from_data(const char *data)
 
138
{
 
139
        GSList *tmp;
 
140
 
 
141
        if (!is_numeric(data, ' '))
 
142
                return log_find(data);
 
143
 
 
144
        /* with index number */
 
145
        tmp = g_slist_nth(logs, atoi(data)-1);
 
146
        return tmp == NULL ? NULL : tmp->data;
 
147
}
 
148
 
 
149
/* SYNTAX: LOG CLOSE <id>|<file> */
 
150
static void cmd_log_close(const char *data)
 
151
{
 
152
        LOG_REC *log;
 
153
 
 
154
        log = log_find_from_data(data);
 
155
        if (log == NULL)
 
156
                printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_LOG_NOT_OPEN, data);
 
157
        else {
 
158
                log_close(log);
 
159
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_CLOSED, data);
 
160
        }
 
161
}
 
162
 
 
163
/* SYNTAX: LOG START <id>|<file> */
 
164
static void cmd_log_start(const char *data)
 
165
{
 
166
        LOG_REC *log;
 
167
 
 
168
        log = log_find_from_data(data);
 
169
        if (log != NULL) {
 
170
                log_start_logging(log);
 
171
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_OPENED, data);
 
172
        }
 
173
}
 
174
 
 
175
/* SYNTAX: LOG STOP <id>|<file> */
 
176
static void cmd_log_stop(const char *data)
 
177
{
 
178
        LOG_REC *log;
 
179
 
 
180
        log = log_find_from_data(data);
 
181
        if (log == NULL || log->handle == -1)
 
182
                printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_LOG_NOT_OPEN, data);
 
183
        else {
 
184
                log_stop_logging(log);
 
185
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_CLOSED, data);
 
186
        }
 
187
}
 
188
 
 
189
static char *log_items_get_list(LOG_REC *log)
 
190
{
 
191
        GSList *tmp;
 
192
        GString *str;
 
193
        char *ret;
 
194
        LOG_ITEM_REC *rec = NULL;
 
195
 
 
196
        g_return_val_if_fail(log != NULL, NULL);
 
197
        g_return_val_if_fail(log->items != NULL, NULL);
 
198
 
 
199
        str = g_string_new(NULL);
 
200
        for (tmp = log->items; tmp != NULL; tmp = tmp->next) {
 
201
                rec = tmp->data;
 
202
 
 
203
                g_string_sprintfa(str, "%s, ", rec->name);
 
204
        }
 
205
        g_string_truncate(str, str->len-2);
 
206
        if(rec->servertag != NULL)
 
207
                g_string_sprintfa(str, " (%s)", rec->servertag);
 
208
 
 
209
        ret = str->str;
 
210
        g_string_free(str, FALSE);
 
211
        return ret;
 
212
}
 
213
 
 
214
static void cmd_log_list(void)
 
215
{
 
216
        GSList *tmp;
 
217
        char *levelstr, *items;
 
218
        int index;
 
219
 
 
220
        printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_LOG_LIST_HEADER);
 
221
        for (tmp = logs, index = 1; tmp != NULL; tmp = tmp->next, index++) {
 
222
                LOG_REC *rec = tmp->data;
 
223
 
 
224
                levelstr = bits2level(rec->level);
 
225
                items = rec->items == NULL ? NULL :
 
226
                        log_items_get_list(rec);
 
227
 
 
228
                printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_LOG_LIST,
 
229
                            index, rec->fname, items != NULL ? items : "",
 
230
                            levelstr, rec->autoopen ? " -autoopen" : "");
 
231
 
 
232
                g_free_not_null(items);
 
233
                g_free(levelstr);
 
234
        }
 
235
        printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_LOG_LIST_FOOTER);
 
236
}
 
237
 
 
238
static void cmd_log(const char *data, SERVER_REC *server, void *item)
 
239
{
 
240
        if (*data == '\0')
 
241
                cmd_log_list();
 
242
        else
 
243
                command_runsub("log", data, server, item);
 
244
}
 
245
 
 
246
static LOG_REC *logs_find_item(int type, const char *item,
 
247
                               const char *servertag, LOG_ITEM_REC **ret_item)
 
248
{
 
249
        LOG_ITEM_REC *logitem;
 
250
        GSList *tmp;
 
251
 
 
252
        for (tmp = logs; tmp != NULL; tmp = tmp->next) {
 
253
                LOG_REC *log = tmp->data;
 
254
 
 
255
                logitem = log_item_find(log, type, item, servertag);
 
256
                if (logitem != NULL) {
 
257
                        if (ret_item != NULL) *ret_item = logitem;
 
258
                        return log;
 
259
                }
 
260
        }
 
261
 
 
262
        return NULL;
 
263
}
 
264
 
 
265
/* SYNTAX: WINDOW LOG on|off|toggle [<filename>] */
 
266
static void cmd_window_log(const char *data)
 
267
{
 
268
        LOG_REC *log;
 
269
        char *set, *fname, window[MAX_INT_STRLEN];
 
270
        void *free_arg;
 
271
        int open_log, close_log;
 
272
 
 
273
        if (!cmd_get_params(data, &free_arg, 2, &set, &fname))
 
274
                return;
 
275
 
 
276
        ltoa(window, active_win->refnum);
 
277
        log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL);
 
278
 
 
279
        open_log = close_log = FALSE;
 
280
        if (g_strcasecmp(set, "ON") == 0)
 
281
                open_log = TRUE;
 
282
        else if (g_strcasecmp(set, "OFF") == 0) {
 
283
                close_log = TRUE;
 
284
        } else if (g_strcasecmp(set, "TOGGLE") == 0) {
 
285
                open_log = log == NULL;
 
286
                close_log = log != NULL;
 
287
        } else {
 
288
                printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_NOT_TOGGLE);
 
289
                cmd_params_free(free_arg);
 
290
                return;
 
291
        }
 
292
 
 
293
        if (open_log && log == NULL) {
 
294
                /* irc.log.<windowname> or irc.log.Window<ref#> */
 
295
                fname = *fname != '\0' ? g_strdup(fname) :
 
296
                        g_strdup_printf("~/irc.log.%s%s",
 
297
                                        active_win->name != NULL ? active_win->name : "Window",
 
298
                                        active_win->name != NULL ? "" : window);
 
299
                log = log_create_rec(fname, MSGLEVEL_ALL);
 
300
                log->colorizer = log_colorizer_strip;
 
301
                log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL);
 
302
                log_update(log);
 
303
                g_free(fname);
 
304
        }
 
305
 
 
306
        if (open_log && log != NULL) {
 
307
                log_start_logging(log);
 
308
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_OPENED, log->fname);
 
309
        } else if (close_log && log != NULL && log->handle != -1) {
 
310
                log_stop_logging(log);
 
311
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_CLOSED, log->fname);
 
312
        }
 
313
 
 
314
        cmd_params_free(free_arg);
 
315
}
 
316
 
 
317
/* Create log file entry to window, but don't start logging */
 
318
/* SYNTAX: WINDOW LOGFILE <file> */
 
319
static void cmd_window_logfile(const char *data)
 
320
{
 
321
        LOG_REC *log;
 
322
        char window[MAX_INT_STRLEN];
 
323
 
 
324
        ltoa(window, active_win->refnum);
 
325
        log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL);
 
326
 
 
327
        if (log != NULL) {
 
328
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_WINDOWLOG_FILE_LOGGING);
 
329
                return;
 
330
        }
 
331
 
 
332
        log = log_create_rec(data, MSGLEVEL_ALL);
 
333
        log->colorizer = log_colorizer_strip;
 
334
        log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL);
 
335
        log_update(log);
 
336
 
 
337
        printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_WINDOWLOG_FILE, data);
 
338
}
 
339
 
 
340
/* window's refnum changed - update the logs to log the new window refnum */
 
341
static void sig_window_refnum_changed(WINDOW_REC *window, gpointer old_refnum)
 
342
{
 
343
        char winnum[MAX_INT_STRLEN];
 
344
        LOG_REC *log;
 
345
        LOG_ITEM_REC *item;
 
346
 
 
347
        ltoa(winnum, GPOINTER_TO_INT(old_refnum));
 
348
        log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, winnum, NULL, &item);
 
349
 
 
350
        if (log != NULL) {
 
351
                ltoa(winnum, window->refnum);
 
352
 
 
353
                g_free(item->name);
 
354
                item->name = g_strdup(winnum);
 
355
        }
 
356
}
 
357
 
 
358
static void sig_server_disconnected(SERVER_REC *server)
 
359
{
 
360
        LOG_ITEM_REC *logitem;
 
361
        GSList *tmp, *next;
 
362
 
 
363
        for (tmp = logs; tmp != NULL; tmp = next) {
 
364
                LOG_REC *log = tmp->data;
 
365
                next = tmp->next;
 
366
 
 
367
                if (!log->temp || log->items == NULL)
 
368
                        continue;
 
369
 
 
370
                logitem = log->items->data;
 
371
                if (logitem->type == LOG_ITEM_TARGET &&
 
372
                    logitem->servertag != NULL &&
 
373
                    g_strcasecmp(logitem->servertag, server->tag) == 0 &&
 
374
                    server_ischannel(server, logitem->name)) /* kludge again.. so we won't close dcc chats */
 
375
                        log_close(log);
 
376
        }
 
377
}
 
378
 
 
379
static void autologs_close_all(void)
 
380
{
 
381
        GSList *tmp, *next;
 
382
 
 
383
        for (tmp = logs; tmp != NULL; tmp = next) {
 
384
                LOG_REC *rec = tmp->data;
 
385
 
 
386
                next = tmp->next;
 
387
                if (rec->temp) log_close(rec);
 
388
        }
 
389
}
 
390
 
 
391
/* '%' -> '%%', '/' -> '_' */
 
392
static char *escape_target(const char *target)
 
393
{
 
394
        char *str, *p;
 
395
 
 
396
        p = str = g_malloc(strlen(target)*2+1);
 
397
        while (*target != '\0') {
 
398
                if (*target == '/')
 
399
                        *p++ = '_';
 
400
                else {
 
401
                        if (*target == '%')
 
402
                                *p++ = '%';
 
403
                        *p++ = *target;
 
404
                }
 
405
 
 
406
                target++;
 
407
        }
 
408
        *p = '\0';
 
409
 
 
410
        return str;
 
411
}
 
412
 
 
413
static void autolog_open(SERVER_REC *server, const char *server_tag,
 
414
                         const char *target)
 
415
{
 
416
        LOG_REC *log;
 
417
        char *fname, *dir, *fixed_target, *params;
 
418
 
 
419
        log = logs_find_item(LOG_ITEM_TARGET, target, server_tag, NULL);
 
420
        if (log != NULL && !log->failed) {
 
421
                log_start_logging(log);
 
422
                return;
 
423
        }
 
424
 
 
425
        /* '/' -> '_' - don't even accidentally try to log to
 
426
           #../../../file if you happen to join to such channel..
 
427
 
 
428
           '%' -> '%%' - so strftime() won't mess with them */
 
429
        fixed_target = escape_target(target);
 
430
        if (CHAT_PROTOCOL(server)->case_insensitive)
 
431
                g_strdown(fixed_target);
 
432
 
 
433
        /* $0 = target, $1 = server tag */
 
434
        params = g_strconcat(fixed_target, " ", server_tag, NULL);
 
435
        g_free(fixed_target);
 
436
 
 
437
        fname = parse_special_string(autolog_path, server, NULL,
 
438
                                     params, NULL, 0);
 
439
        g_free(params);
 
440
 
 
441
        if (log_find(fname) == NULL) {
 
442
                log = log_create_rec(fname, autolog_level);
 
443
                if (!settings_get_bool("autolog_colors"))
 
444
                        log->colorizer = log_colorizer_strip;
 
445
                log_item_add(log, LOG_ITEM_TARGET, target, server_tag);
 
446
 
 
447
                dir = g_dirname(log->real_fname);
 
448
                mkpath(dir, log_dir_create_mode);
 
449
                g_free(dir);
 
450
 
 
451
                log->temp = TRUE;
 
452
                log_update(log);
 
453
                log_start_logging(log);
 
454
        }
 
455
        g_free(fname);
 
456
}
 
457
 
 
458
static void autolog_open_check(SERVER_REC *server, const char *server_tag,
 
459
                               const char *target, int level)
 
460
{
 
461
        char **targets, **tmp;
 
462
 
 
463
        /* FIXME: kind of a kludge, but we don't want to reopen logs when
 
464
           we're parting the channel with /WINDOW CLOSE.. Maybe a small
 
465
           timeout would be nice instead of immediately closing the log file
 
466
           after "window item destroyed" */
 
467
        if (level == MSGLEVEL_PARTS ||
 
468
            (autolog_level & level) == 0 || target == NULL || *target == '\0')
 
469
                return;
 
470
 
 
471
        /* there can be multiple targets separated with comma */
 
472
        targets = g_strsplit(target, ",", -1);
 
473
        for (tmp = targets; *tmp != NULL; tmp++)
 
474
                autolog_open(server, server_tag, *tmp);
 
475
        g_strfreev(targets);
 
476
}
 
477
 
 
478
static void log_single_line(WINDOW_REC *window, const char *server_tag,
 
479
                            const char *target, int level, const char *text)
 
480
{
 
481
        char windownum[MAX_INT_STRLEN];
 
482
        char **targets, **tmp;
 
483
        LOG_REC *log;
 
484
 
 
485
        if (window != NULL) {
 
486
                /* save to log created with /WINDOW LOG */
 
487
                ltoa(windownum, window->refnum);
 
488
                log = logs_find_item(LOG_ITEM_WINDOW_REFNUM,
 
489
                                     windownum, NULL, NULL);
 
490
                if (log != NULL)
 
491
                        log_write_rec(log, text, level);
 
492
        }
 
493
 
 
494
        if (target == NULL)
 
495
                log_file_write(server_tag, NULL, level, text, FALSE);
 
496
        else {
 
497
                /* there can be multiple items separated with comma */
 
498
                targets = g_strsplit(target, ",", -1);
 
499
                for (tmp = targets; *tmp != NULL; tmp++)
 
500
                        log_file_write(server_tag, *tmp, level, text, FALSE);
 
501
                g_strfreev(targets);
 
502
        }
 
503
}
 
504
 
 
505
static void log_line(TEXT_DEST_REC *dest, const char *text)
 
506
{
 
507
        char **lines, **tmp;
 
508
 
 
509
        if (dest->level == MSGLEVEL_NEVER)
 
510
                return;
 
511
 
 
512
        /* let autolog open the log records */
 
513
        autolog_open_check(dest->server, dest->server_tag,
 
514
                           dest->target, dest->level);
 
515
 
 
516
        if (logs == NULL)
 
517
                return;
 
518
 
 
519
        /* text may contain one or more lines, log wants to eat them one
 
520
           line at a time */
 
521
        lines = g_strsplit(text, "\n", -1);
 
522
        for (tmp = lines; *tmp != NULL; tmp++)
 
523
                log_single_line(dest->window, dest->server_tag,
 
524
                                dest->target, dest->level, *tmp);
 
525
        g_strfreev(lines);
 
526
}
 
527
 
 
528
static void sig_printtext(TEXT_DEST_REC *dest, const char *text,
 
529
                          const char *stripped)
 
530
{
 
531
        if (skip_next_printtext) {
 
532
                skip_next_printtext = FALSE;
 
533
                return;
 
534
        }
 
535
 
 
536
        log_line(dest, text);
 
537
}
 
538
 
 
539
static void sig_print_format(THEME_REC *theme, const char *module,
 
540
                             TEXT_DEST_REC *dest, void *formatnum, char **args)
 
541
{
 
542
        char *str, *linestart, *tmp;
 
543
 
 
544
        if (log_theme == NULL) {
 
545
                /* theme isn't loaded for some reason (/reload destroys it),
 
546
                   reload it. */
 
547
                log_theme = theme_load(log_theme_name);
 
548
                if (log_theme == NULL) return;
 
549
        }
 
550
 
 
551
        if (theme == log_theme)
 
552
                return;
 
553
 
 
554
        str = format_get_text_theme_charargs(log_theme, module, dest,
 
555
                                             GPOINTER_TO_INT(formatnum), args);
 
556
        skip_next_printtext = TRUE;
 
557
 
 
558
        if (*str != '\0') {
 
559
                /* add the line start format */
 
560
                linestart = format_get_level_tag(log_theme, dest);
 
561
                tmp = str;
 
562
                str = format_add_linestart(tmp, linestart);
 
563
                g_free_not_null(linestart);
 
564
                g_free(tmp);
 
565
 
 
566
                /* strip colors from text, log it. */
 
567
                log_line(dest, str);
 
568
        }
 
569
        g_free(str);
 
570
 
 
571
}
 
572
 
 
573
static int sig_autoremove(void)
 
574
{
 
575
        SERVER_REC *server;
 
576
        LOG_ITEM_REC *logitem;
 
577
        GSList *tmp, *next;
 
578
        time_t removetime;
 
579
 
 
580
        removetime = time(NULL)-AUTOLOG_INACTIVITY_CLOSE;
 
581
        for (tmp = logs; tmp != NULL; tmp = next) {
 
582
                LOG_REC *log = tmp->data;
 
583
 
 
584
                next = tmp->next;
 
585
 
 
586
                if (!log->temp || log->last > removetime || log->items == NULL)
 
587
                        continue;
 
588
 
 
589
                /* Close only logs with private messages */
 
590
                logitem = log->items->data;
 
591
                if (logitem->servertag == NULL)
 
592
                        continue;
 
593
 
 
594
                server = server_find_tag(logitem->servertag);
 
595
                if (logitem->type == LOG_ITEM_TARGET &&
 
596
                    server != NULL && !server_ischannel(server, logitem->name))
 
597
                        log_close(log);
 
598
        }
 
599
        return 1;
 
600
}
 
601
 
 
602
static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item)
 
603
{
 
604
        LOG_REC *log;
 
605
 
 
606
        log = logs_find_item(LOG_ITEM_TARGET, item->visible_name,
 
607
                             item->server == NULL ? NULL :
 
608
                             item->server->tag, NULL);
 
609
        if (log != NULL && log->temp)
 
610
                log_close(log);
 
611
}
 
612
 
 
613
static void sig_log_locked(LOG_REC *log)
 
614
{
 
615
        printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
 
616
                    TXT_LOG_LOCKED, log->fname);
 
617
}
 
618
 
 
619
static void sig_log_create_failed(LOG_REC *log)
 
620
{
 
621
        printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
 
622
                    TXT_LOG_CREATE_FAILED,
 
623
                    log->real_fname, g_strerror(errno));
 
624
}
 
625
 
 
626
static void sig_log_new(LOG_REC *log)
 
627
{
 
628
        if (!settings_get_bool("awaylog_colors") &&
 
629
            strcmp(log->fname, settings_get_str("awaylog_file")) == 0)
 
630
                log->colorizer = log_colorizer_strip;
 
631
}
 
632
 
 
633
static void sig_log_config_read(LOG_REC *log, CONFIG_NODE *node)
 
634
{
 
635
        if (!config_node_get_bool(node, "colors", FALSE))
 
636
                log->colorizer = log_colorizer_strip;
 
637
}
 
638
 
 
639
static void sig_log_config_save(LOG_REC *log, CONFIG_NODE *node)
 
640
{
 
641
        if (log->colorizer == NULL)
 
642
                iconfig_node_set_bool(node, "colors", TRUE);
 
643
        else
 
644
                iconfig_node_set_str(node, "colors", NULL);
 
645
}
 
646
 
 
647
static void sig_awaylog_show(LOG_REC *log, gpointer pmsgs, gpointer pfilepos)
 
648
{
 
649
        char *str;
 
650
        int msgs, filepos;
 
651
 
 
652
        msgs = GPOINTER_TO_INT(pmsgs);
 
653
        filepos = GPOINTER_TO_INT(pfilepos);
 
654
 
 
655
        if (msgs == 0)
 
656
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_NO_AWAY_MSGS, log->fname);
 
657
        else {
 
658
                printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->fname, msgs);
 
659
 
 
660
                str = g_strdup_printf("\"%s\" %d", log->fname, filepos);
 
661
                signal_emit("command cat", 1, str);
 
662
                g_free(str);
 
663
        }
 
664
}
 
665
 
 
666
static void sig_theme_destroyed(THEME_REC *theme)
 
667
{
 
668
        if (theme == log_theme)
 
669
                log_theme = NULL;
 
670
}
 
671
 
 
672
static void read_settings(void)
 
673
{
 
674
        int old_autolog = autolog_level;
 
675
        int log_file_create_mode;
 
676
 
 
677
        autolog_path = settings_get_str("autolog_path");
 
678
        autolog_level = !settings_get_bool("autolog") ? 0 :
 
679
                settings_get_level("autolog_level");
 
680
 
 
681
        if (old_autolog && !autolog_level)
 
682
                autologs_close_all();
 
683
 
 
684
        /* write to log files with different theme? */
 
685
        if (log_theme_name != NULL)
 
686
                signal_remove("print format", (SIGNAL_FUNC) sig_print_format);
 
687
        log_theme_name = settings_get_str("log_theme");
 
688
        if (*log_theme_name == '\0')
 
689
                log_theme_name = NULL;
 
690
        else
 
691
                signal_add("print format", (SIGNAL_FUNC) sig_print_format);
 
692
 
 
693
        log_theme = log_theme_name == NULL ? NULL :
 
694
                theme_load(log_theme_name);
 
695
 
 
696
        log_file_create_mode = octal2dec(settings_get_int("log_create_mode"));
 
697
        log_dir_create_mode = log_file_create_mode;
 
698
        if (log_file_create_mode & 0400) log_dir_create_mode |= 0100;
 
699
        if (log_file_create_mode & 0040) log_dir_create_mode |= 0010;
 
700
        if (log_file_create_mode & 0004) log_dir_create_mode |= 0001;
 
701
}
 
702
 
 
703
void fe_log_init(void)
 
704
{
 
705
        autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL);
 
706
        skip_next_printtext = FALSE;
 
707
 
 
708
        settings_add_bool("log", "awaylog_colors", TRUE);
 
709
        settings_add_bool("log", "autolog", FALSE);
 
710
        settings_add_bool("log", "autolog_colors", FALSE);
 
711
        settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log");
 
712
        settings_add_level("log", "autolog_level", "all -crap -clientcrap -ctcps");
 
713
        settings_add_str("log", "log_theme", "");
 
714
 
 
715
        autolog_level = 0;
 
716
        log_theme_name = NULL;
 
717
        read_settings();
 
718
 
 
719
        command_bind("log", NULL, (SIGNAL_FUNC) cmd_log);
 
720
        command_bind("log open", NULL, (SIGNAL_FUNC) cmd_log_open);
 
721
        command_bind("log close", NULL, (SIGNAL_FUNC) cmd_log_close);
 
722
        command_bind("log start", NULL, (SIGNAL_FUNC) cmd_log_start);
 
723
        command_bind("log stop", NULL, (SIGNAL_FUNC) cmd_log_stop);
 
724
        command_bind("window log", NULL, (SIGNAL_FUNC) cmd_window_log);
 
725
        command_bind("window logfile", NULL, (SIGNAL_FUNC) cmd_window_logfile);
 
726
        signal_add_first("print text", (SIGNAL_FUNC) sig_printtext);
 
727
        signal_add("window item remove", (SIGNAL_FUNC) sig_window_item_remove);
 
728
        signal_add("window refnum changed", (SIGNAL_FUNC) sig_window_refnum_changed);
 
729
        signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
 
730
        signal_add("log locked", (SIGNAL_FUNC) sig_log_locked);
 
731
        signal_add("log create failed", (SIGNAL_FUNC) sig_log_create_failed);
 
732
        signal_add("log new", (SIGNAL_FUNC) sig_log_new);
 
733
        signal_add("log config read", (SIGNAL_FUNC) sig_log_config_read);
 
734
        signal_add("log config save", (SIGNAL_FUNC) sig_log_config_save);
 
735
        signal_add("awaylog show", (SIGNAL_FUNC) sig_awaylog_show);
 
736
        signal_add("theme destroyed", (SIGNAL_FUNC) sig_theme_destroyed);
 
737
        signal_add("setup changed", (SIGNAL_FUNC) read_settings);
 
738
 
 
739
        command_set_options("log open", "noopen autoopen -targets window colors");
 
740
}
 
741
 
 
742
void fe_log_deinit(void)
 
743
{
 
744
        g_source_remove(autoremove_tag);
 
745
        if (log_theme_name != NULL)
 
746
                signal_remove("print format", (SIGNAL_FUNC) sig_print_format);
 
747
 
 
748
        command_unbind("log", (SIGNAL_FUNC) cmd_log);
 
749
        command_unbind("log open", (SIGNAL_FUNC) cmd_log_open);
 
750
        command_unbind("log close", (SIGNAL_FUNC) cmd_log_close);
 
751
        command_unbind("log start", (SIGNAL_FUNC) cmd_log_start);
 
752
        command_unbind("log stop", (SIGNAL_FUNC) cmd_log_stop);
 
753
        command_unbind("window log", (SIGNAL_FUNC) cmd_window_log);
 
754
        command_unbind("window logfile", (SIGNAL_FUNC) cmd_window_logfile);
 
755
        signal_remove("print text", (SIGNAL_FUNC) sig_printtext);
 
756
        signal_remove("window item remove", (SIGNAL_FUNC) sig_window_item_remove);
 
757
        signal_remove("window refnum changed", (SIGNAL_FUNC) sig_window_refnum_changed);
 
758
        signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
 
759
        signal_remove("log locked", (SIGNAL_FUNC) sig_log_locked);
 
760
        signal_remove("log create failed", (SIGNAL_FUNC) sig_log_create_failed);
 
761
        signal_remove("log new", (SIGNAL_FUNC) sig_log_new);
 
762
        signal_remove("log config read", (SIGNAL_FUNC) sig_log_config_read);
 
763
        signal_remove("log config save", (SIGNAL_FUNC) sig_log_config_save);
 
764
        signal_remove("awaylog show", (SIGNAL_FUNC) sig_awaylog_show);
 
765
        signal_remove("theme destroyed", (SIGNAL_FUNC) sig_theme_destroyed);
 
766
        signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
 
767
}