/src/irssi/src/core/rawlog.c
Line | Count | Source |
1 | | /* |
2 | | rawlog.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 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 <irssi/src/core/rawlog.h> |
23 | | #include <irssi/src/core/log.h> |
24 | | #include <irssi/src/core/modules.h> |
25 | | #include <irssi/src/core/signals.h> |
26 | | #include <irssi/src/core/commands.h> |
27 | | #include <irssi/src/core/misc.h> |
28 | | #include <irssi/src/core/write-buffer.h> |
29 | | #include <irssi/src/core/settings.h> |
30 | | #ifdef HAVE_CAPSICUM |
31 | | #include <irssi/src/core/capsicum.h> |
32 | | #endif |
33 | | |
34 | | #include <irssi/src/core/servers.h> |
35 | | |
36 | | static int rawlog_lines; |
37 | | static int signal_rawlog; |
38 | | |
39 | | RAWLOG_REC *rawlog_create(void) |
40 | 36.6k | { |
41 | 36.6k | RAWLOG_REC *rec; |
42 | | |
43 | 36.6k | rec = g_new0(RAWLOG_REC, 1); |
44 | 36.6k | rec->lines = g_queue_new(); |
45 | 36.6k | return rec; |
46 | 36.6k | } |
47 | | |
48 | | void rawlog_destroy(RAWLOG_REC *rawlog) |
49 | 36.6k | { |
50 | 36.6k | g_return_if_fail(rawlog != NULL); |
51 | | |
52 | 36.6k | g_queue_foreach(rawlog->lines, (GFunc) g_free, NULL); |
53 | 36.6k | g_queue_free(rawlog->lines); |
54 | | |
55 | 36.6k | if (rawlog->logging) { |
56 | 0 | write_buffer_flush(); |
57 | 0 | close(rawlog->handle); |
58 | 0 | } |
59 | 36.6k | g_free(rawlog); |
60 | 36.6k | } |
61 | | |
62 | | /* NOTE! str must be dynamically allocated and must not be freed after! */ |
63 | | static void rawlog_add(RAWLOG_REC *rawlog, char *str) |
64 | 68.6k | { |
65 | 126k | while (rawlog->lines->length >= rawlog_lines && rawlog_lines > 0) { |
66 | 57.8k | void *tmp = g_queue_pop_head(rawlog->lines); |
67 | 57.8k | g_free(tmp); |
68 | 57.8k | } |
69 | | |
70 | 68.6k | if (rawlog->logging) { |
71 | 0 | write_buffer(rawlog->handle, str, strlen(str)); |
72 | 0 | write_buffer(rawlog->handle, "\n", 1); |
73 | 0 | } |
74 | | |
75 | 68.6k | g_queue_push_tail(rawlog->lines, str); |
76 | 68.6k | signal_emit_id(signal_rawlog, 2, rawlog, str); |
77 | 68.6k | } |
78 | | |
79 | | void rawlog_input(RAWLOG_REC *rawlog, const char *str) |
80 | 0 | { |
81 | 0 | g_return_if_fail(rawlog != NULL); |
82 | 0 | g_return_if_fail(str != NULL); |
83 | | |
84 | 0 | rawlog_add(rawlog, g_strdup_printf(">> %s", str)); |
85 | 0 | } |
86 | | |
87 | | void rawlog_output(RAWLOG_REC *rawlog, const char *str) |
88 | 63.8k | { |
89 | 63.8k | g_return_if_fail(rawlog != NULL); |
90 | 63.8k | g_return_if_fail(str != NULL); |
91 | | |
92 | 63.8k | rawlog_add(rawlog, g_strdup_printf("<< %s", str)); |
93 | 63.8k | } |
94 | | |
95 | | void rawlog_redirect(RAWLOG_REC *rawlog, const char *str) |
96 | 4.75k | { |
97 | 4.75k | g_return_if_fail(rawlog != NULL); |
98 | 4.75k | g_return_if_fail(str != NULL); |
99 | | |
100 | 4.75k | rawlog_add(rawlog, g_strdup_printf("--> %s", str)); |
101 | 4.75k | } |
102 | | |
103 | | static void rawlog_dump(RAWLOG_REC *rawlog, int f) |
104 | 0 | { |
105 | 0 | GList *tmp; |
106 | 0 | ssize_t ret = 0; |
107 | |
|
108 | 0 | for (tmp = rawlog->lines->head; ret != -1 && tmp != NULL; tmp = tmp->next) { |
109 | 0 | ret = write(f, tmp->data, strlen((char *) tmp->data)); |
110 | 0 | if (ret != -1) |
111 | 0 | ret = write(f, "\n", 1); |
112 | 0 | } |
113 | |
|
114 | 0 | if (ret == -1) { |
115 | 0 | g_warning("rawlog write() failed: %s", strerror(errno)); |
116 | 0 | } |
117 | 0 | } |
118 | | |
119 | | void rawlog_open(RAWLOG_REC *rawlog, const char *fname) |
120 | 0 | { |
121 | 0 | char *path; |
122 | |
|
123 | 0 | g_return_if_fail(rawlog != NULL); |
124 | 0 | g_return_if_fail(fname != NULL); |
125 | | |
126 | 0 | if (rawlog->logging) |
127 | 0 | return; |
128 | | |
129 | 0 | path = convert_home(fname); |
130 | | #ifdef HAVE_CAPSICUM |
131 | | rawlog->handle = capsicum_open_wrapper(path, |
132 | | O_WRONLY | O_APPEND | O_CREAT, |
133 | | log_file_create_mode); |
134 | | #else |
135 | 0 | rawlog->handle = open(path, O_WRONLY | O_APPEND | O_CREAT, |
136 | 0 | log_file_create_mode); |
137 | 0 | #endif |
138 | |
|
139 | 0 | g_free(path); |
140 | |
|
141 | 0 | if (rawlog->handle == -1) { |
142 | 0 | g_warning("rawlog open() failed: %s", strerror(errno)); |
143 | 0 | return; |
144 | 0 | } |
145 | | |
146 | 0 | rawlog_dump(rawlog, rawlog->handle); |
147 | 0 | rawlog->logging = TRUE; |
148 | 0 | } |
149 | | |
150 | | void rawlog_close(RAWLOG_REC *rawlog) |
151 | 0 | { |
152 | 0 | if (rawlog->logging) { |
153 | 0 | write_buffer_flush(); |
154 | 0 | close(rawlog->handle); |
155 | 0 | rawlog->logging = FALSE; |
156 | 0 | } |
157 | 0 | } |
158 | | |
159 | | void rawlog_save(RAWLOG_REC *rawlog, const char *fname) |
160 | 0 | { |
161 | 0 | char *path, *dir; |
162 | 0 | int f; |
163 | |
|
164 | 0 | dir = g_path_get_dirname(fname); |
165 | | #ifdef HAVE_CAPSICUM |
166 | | capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); |
167 | | #else |
168 | 0 | g_mkdir_with_parents(dir, log_dir_create_mode); |
169 | 0 | #endif |
170 | 0 | g_free(dir); |
171 | |
|
172 | 0 | path = convert_home(fname); |
173 | | #ifdef HAVE_CAPSICUM |
174 | | f = capsicum_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, |
175 | | log_file_create_mode); |
176 | | #else |
177 | 0 | f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); |
178 | 0 | #endif |
179 | 0 | g_free(path); |
180 | |
|
181 | 0 | if (f < 0) { |
182 | 0 | g_warning("rawlog open() failed: %s", strerror(errno)); |
183 | 0 | return; |
184 | 0 | } |
185 | | |
186 | 0 | rawlog_dump(rawlog, f); |
187 | 0 | close(f); |
188 | 0 | } |
189 | | |
190 | | void rawlog_set_size(int lines) |
191 | 10 | { |
192 | 10 | rawlog_lines = lines; |
193 | 10 | } |
194 | | |
195 | | static void read_settings(void) |
196 | 8 | { |
197 | 8 | rawlog_set_size(settings_get_int("rawlog_lines")); |
198 | 8 | } |
199 | | |
200 | | static void cmd_rawlog(const char *data, SERVER_REC *server, void *item) |
201 | 0 | { |
202 | 0 | command_runsub("rawlog", data, server, item); |
203 | 0 | } |
204 | | |
205 | | /* SYNTAX: RAWLOG SAVE <file> */ |
206 | | static void cmd_rawlog_save(const char *data, SERVER_REC *server) |
207 | 0 | { |
208 | 0 | g_return_if_fail(data != NULL); |
209 | 0 | if (server == NULL || server->rawlog == NULL) |
210 | 0 | cmd_return_error(CMDERR_NOT_CONNECTED); |
211 | | |
212 | 0 | if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); |
213 | 0 | rawlog_save(server->rawlog, data); |
214 | 0 | } |
215 | | |
216 | | /* SYNTAX: RAWLOG OPEN <file> */ |
217 | | static void cmd_rawlog_open(const char *data, SERVER_REC *server) |
218 | 0 | { |
219 | 0 | g_return_if_fail(data != NULL); |
220 | 0 | if (server == NULL || server->rawlog == NULL) |
221 | 0 | cmd_return_error(CMDERR_NOT_CONNECTED); |
222 | | |
223 | 0 | if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); |
224 | 0 | rawlog_open(server->rawlog, data); |
225 | 0 | } |
226 | | |
227 | | /* SYNTAX: RAWLOG CLOSE */ |
228 | | static void cmd_rawlog_close(const char *data, SERVER_REC *server) |
229 | 0 | { |
230 | 0 | g_return_if_fail(data != NULL); |
231 | 0 | if (server == NULL || server->rawlog == NULL) |
232 | 0 | cmd_return_error(CMDERR_NOT_CONNECTED); |
233 | | |
234 | 0 | rawlog_close(server->rawlog); |
235 | 0 | } |
236 | | |
237 | | void rawlog_init(void) |
238 | 8 | { |
239 | 8 | signal_rawlog = signal_get_uniq_id("rawlog"); |
240 | | |
241 | 8 | settings_add_int("history", "rawlog_lines", 200); |
242 | 8 | read_settings(); |
243 | | |
244 | 8 | signal_add("setup changed", (SIGNAL_FUNC) read_settings); |
245 | | |
246 | 8 | command_bind("rawlog", NULL, (SIGNAL_FUNC) cmd_rawlog); |
247 | 8 | command_bind("rawlog save", NULL, (SIGNAL_FUNC) cmd_rawlog_save); |
248 | 8 | command_bind("rawlog open", NULL, (SIGNAL_FUNC) cmd_rawlog_open); |
249 | 8 | command_bind("rawlog close", NULL, (SIGNAL_FUNC) cmd_rawlog_close); |
250 | 8 | } |
251 | | |
252 | | void rawlog_deinit(void) |
253 | 0 | { |
254 | 0 | signal_remove("setup changed", (SIGNAL_FUNC) read_settings); |
255 | |
|
256 | 0 | command_unbind("rawlog", (SIGNAL_FUNC) cmd_rawlog); |
257 | 0 | command_unbind("rawlog save", (SIGNAL_FUNC) cmd_rawlog_save); |
258 | 0 | command_unbind("rawlog open", (SIGNAL_FUNC) cmd_rawlog_open); |
259 | | command_unbind("rawlog close", (SIGNAL_FUNC) cmd_rawlog_close); |
260 | 0 | } |