Mercurial > pidgin
annotate src/log.c @ 7431:643cbc9a6035
[gaim-migrate @ 8036]
This is good enough for CVS. This is new logging. It centers around the
highly modular "GaimLogLogger," which controls how to write the log. Currently
I only have the plain text logger. I wrote the beginning of an XML logger, but
decided I didn't think it was that great an idea. Plugins can implement loggers
themselves, so you can have, like, an SQL logger or something.
The default logger writes to a file unique to the conversation, and they're saved
on disk in a heirarchical fashion: ~/.gaim/logs/aim/seanegn/robflynn-date.log would
be a conversation I had with Rob on date.
What doesn't work:
System logging
The search button in the log viewer.
Oh, chats probably don't log either, I didn't test.
You can only log in plain text right now.
Obviously, it's not done yet. But you can play around with it, and give it
some love. I'll get back to it tomorrow after school, maybe.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Wed, 05 Nov 2003 06:15:49 +0000 |
parents | ab828b8c3f22 |
children | 7cdbd2eb7546 |
rev | line source |
---|---|
7431 | 1 /** |
2 * @file log.c Logging API | |
3 * @ingroup core | |
4 * | |
5 * gaim | |
6 * | |
7 * Copyright (C) 2003 Buzz Lightyear | |
8 * | |
9 * This program is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU General Public License | |
20 * along with this program; if not, write to the Free Software | |
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
4184 | 22 */ |
4195 | 23 |
7431 | 24 #include "account.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
25 #include "debug.h" |
7431 | 26 #include "internal.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
27 #include "log.h" |
5548 | 28 #include "prefs.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
29 #include "util.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
30 |
7431 | 31 static GaimLogLogger txt_logger; |
32 static GaimLogLogger old_logger; | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
33 |
7431 | 34 /************************************************************************** |
35 * PUBLIC LOGGING FUNCTIONS *********************************************** | |
36 **************************************************************************/ | |
4184 | 37 |
7431 | 38 GaimLog *gaim_log_new(GaimLogType type, const char *name, GaimAccount *account, time_t time) |
39 { | |
40 GaimLog *log = g_new0(GaimLog, 1); | |
41 log->name = g_strdup(name); | |
42 log->account = account; | |
43 log->time = time; | |
44 log->logger = gaim_log_logger_get(); | |
45 if (log->logger && log->logger->new) | |
46 log->logger->new(log); | |
47 return log; | |
4184 | 48 } |
49 | |
7431 | 50 void gaim_log_free(GaimLog *log) |
4184 | 51 { |
7431 | 52 g_return_if_fail(log); |
53 if (log->logger && log->logger->finalize) | |
54 log->logger->finalize(log); | |
55 g_free(log->name); | |
56 g_free(log); | |
57 } | |
58 | |
4184 | 59 |
7431 | 60 void gaim_log_write(GaimLog *log, GaimMessageFlags type, |
61 const char *from, time_t time, const char *message) | |
62 { | |
63 g_return_if_fail(log); | |
64 g_return_if_fail(log->logger); | |
65 g_return_if_fail(log->logger->write); | |
66 | |
67 log->logger->write(log, type, from, time, message); | |
4184 | 68 } |
69 | |
7431 | 70 char *gaim_log_read(GaimLog *log, GaimLogReadFlags *flags) |
4184 | 71 { |
7431 | 72 g_return_val_if_fail(log && log->logger, NULL); |
73 if (log->logger->read) | |
74 return log->logger->read(log, flags); | |
75 return (_("<b><font color\"=red\">The logger has no read function</font></b>")); | |
4184 | 76 } |
77 | |
7431 | 78 /**************************************************************************** |
79 * LOGGER FUNCTIONS ********************************************************* | |
80 ****************************************************************************/ | |
4184 | 81 |
7431 | 82 static GaimLogLogger *current_logger = NULL; |
83 static GSList *loggers = NULL; | |
84 | |
85 static void logger_pref_cb(const char *name, GaimPrefType type, | |
86 gpointer value, gpointer data) | |
87 { | |
88 GaimLogLogger *logger; | |
89 GSList *l = loggers; | |
90 while (l) { | |
91 logger = l->data; | |
92 if (!strcmp(logger->id, value)) { | |
93 gaim_log_logger_set(logger); | |
94 return; | |
4184 | 95 } |
7431 | 96 l = l->next; |
97 } | |
98 gaim_log_logger_set(&txt_logger); | |
99 } | |
4184 | 100 |
101 | |
7431 | 102 GaimLogLogger *gaim_log_logger_new(void(*new)(GaimLog *), |
103 void(*write)(GaimLog *, GaimMessageFlags, const char *, | |
104 time_t, const char *), | |
105 void(*finalize)(GaimLog *), GList*(*list)(const char*, GaimAccount*), | |
106 char*(*read)(GaimLog*, GaimLogReadFlags*)) | |
107 { | |
108 GaimLogLogger *logger = g_new0(GaimLogLogger, 1); | |
109 logger->new = new; | |
110 logger->write = write; | |
111 logger->finalize = finalize; | |
112 logger->list = list; | |
113 logger->read = read; | |
114 return logger; | |
4184 | 115 } |
116 | |
7431 | 117 void gaim_log_logger_free(GaimLogLogger *logger) |
4184 | 118 { |
7431 | 119 g_free(logger); |
120 } | |
4184 | 121 |
7431 | 122 void gaim_log_logger_add (GaimLogLogger *logger) |
123 { | |
124 g_return_if_fail(logger); | |
125 if (g_slist_find(loggers, logger)) | |
126 return; | |
127 loggers = g_slist_append(loggers, logger); | |
128 } | |
129 | |
130 void gaim_log_logger_remove (GaimLogLogger *logger) | |
131 { | |
132 g_return_if_fail(logger); | |
133 g_slist_remove(loggers, logger); | |
4184 | 134 } |
135 | |
7431 | 136 void gaim_log_logger_set (GaimLogLogger *logger) |
4184 | 137 { |
7431 | 138 g_return_if_fail(logger); |
139 current_logger = logger; | |
140 } | |
4184 | 141 |
7431 | 142 GaimLogLogger *gaim_log_logger_get() |
143 { | |
144 return current_logger; | |
145 } | |
4184 | 146 |
7431 | 147 GList *gaim_log_logger_get_options(void) |
148 { | |
149 GSList *n; | |
150 GList *list = NULL; | |
151 GaimLogLogger *data; | |
4184 | 152 |
7431 | 153 for (n = loggers; n; n = n->next) { |
154 data = n->data; | |
155 if (!data->write) | |
156 continue; | |
157 list = g_list_append(list, data->name); | |
158 list = g_list_append(list, data->id); | |
4184 | 159 } |
160 | |
7431 | 161 return list; |
162 } | |
163 | |
164 static gint log_compare(GaimLog *a, GaimLog *b) | |
165 { | |
166 return b->time - a->time; | |
167 } | |
168 | |
169 GList *gaim_log_get_logs(const char *name, GaimAccount *account) | |
170 { | |
171 GList *logs = NULL; | |
172 GSList *n; | |
173 for (n = loggers; n; n = n->next) { | |
174 GaimLogLogger *logger = n->data; | |
175 if (!logger->list) | |
176 continue; | |
177 logs = g_list_concat(logs, logger->list(name, account)); | |
178 } | |
179 | |
180 return g_list_sort(logs, log_compare); | |
181 } | |
182 | |
183 void gaim_log_init(void) | |
184 { | |
185 gaim_prefs_add_none("/core/logging"); | |
186 gaim_prefs_add_string("/core/logging/format", "txt"); | |
187 gaim_log_logger_add(&txt_logger); | |
188 gaim_log_logger_add(&old_logger); | |
189 gaim_prefs_connect_callback("/core/logging/format", | |
190 logger_pref_cb, NULL); | |
191 gaim_prefs_trigger_callback("/core/logging/format"); | |
192 } | |
193 | |
194 /**************************************************************************** | |
195 * LOGGERS ****************************************************************** | |
196 ****************************************************************************/ | |
197 | |
198 static GList *log_lister_common(const char *screenname, GaimAccount *account, const char *ext, GaimLogLogger *logger) | |
199 { | |
200 GDir *dir; | |
201 GList *list = NULL; | |
202 const char *filename; | |
203 char *me = g_strdup(gaim_normalize(account, gaim_account_get_username(account))); | |
4184 | 204 |
7431 | 205 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
206 (gaim_find_prpl(gaim_account_get_protocol(account)))->list_icon(account, NULL); | |
207 char *path = g_build_filename(gaim_user_dir(), "logs", prpl, me, gaim_normalize(account, screenname), NULL); | |
208 | |
209 if (!(dir = g_dir_open(path, 0, NULL))) { | |
210 g_free(path); | |
211 g_free(me); | |
212 return NULL; | |
213 } | |
214 while ((filename = g_dir_read_name(dir))) { | |
215 if (g_str_has_suffix(filename, ext)) { | |
216 const char *l = filename; | |
217 struct tm time; | |
218 GaimLog *log; | |
219 char d[5]; | |
220 | |
221 strncpy(d, l, 4); | |
222 d[4] = '\0'; | |
223 time.tm_year = atoi(d) - 1900; | |
224 l = l + 5; | |
225 | |
226 strncpy(d, l, 2); | |
227 d[2] = '\0'; | |
228 time.tm_mon = atoi(d) - 1; | |
229 l = l + 3; | |
230 | |
231 strncpy(d, l, 2); | |
232 time.tm_mday = atoi(d); | |
233 l = l + 3; | |
234 | |
235 strncpy(d, l, 2); | |
236 time.tm_hour = atoi(d); | |
237 l = l + 2; | |
238 | |
239 strncpy(d, l, 2); | |
240 time.tm_min = atoi(d); | |
241 l = l + 2; | |
242 | |
243 strncpy(d, l, 2); | |
244 time.tm_sec = atoi(d); | |
245 l = l + 2; | |
246 log = gaim_log_new(GAIM_LOG_IM, screenname, account, mktime(&time)); | |
247 log->logger = logger; | |
248 log->logger_data = g_build_filename(path, filename, NULL); | |
249 list = g_list_append(list, log); | |
4184 | 250 } |
251 } | |
7431 | 252 g_dir_close(dir); |
253 return list; | |
254 } | |
4184 | 255 |
7431 | 256 #if 0 /* Maybe some other time. */ |
257 /**************** | |
258 ** XML LOGGER ** | |
259 ****************/ | |
260 | |
261 static const char *str_from_msg_type (GaimMessageFlags type) | |
262 { | |
263 | |
264 return ""; | |
265 | |
266 } | |
267 | |
268 static void xml_logger_write(GaimLog *log, | |
269 GaimMessageFlags type, | |
270 const char *from, time_t time, const char *message) | |
271 { | |
272 char date[64]; | |
273 char *xhtml = NULL; | |
274 if (!log->logger_data) { | |
275 /* This log is new. We could use the loggers 'new' function, but | |
276 * creating a new file there would result in empty files in the case | |
277 * that you open a convo with someone, but don't say anything. | |
278 */ | |
279 char *ud = gaim_user_dir(); | |
280 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
281 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO | |
282 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
283 char *dir; | |
284 FILE *file; | |
285 | |
286 strftime(date, sizeof(date), "%F.%H%M%S.xml", localtime(&log->time)); | |
287 | |
288 dir = g_build_filename(ud, "logs", NULL); | |
289 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
290 g_free(dir); | |
291 dir = g_build_filename(ud, "logs", | |
292 prpl, NULL); | |
293 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
294 g_free(dir); | |
295 dir = g_build_filename(ud, "logs", | |
296 prpl, guy, NULL); | |
297 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
298 g_free(dir); | |
299 dir = g_build_filename(ud, "logs", | |
300 prpl, guy, gaim_normalize(log->account, log->name), NULL); | |
301 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
302 | |
303 char *filename = g_build_filename(dir, date, NULL); | |
304 g_free(dir); | |
305 | |
306 file = fopen(dir, "r"); | |
307 if(!file) | |
308 mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
309 else | |
310 fclose(file); | |
311 | |
312 log->logger_data = fopen(filename, "a"); | |
313 if (!log->logger_data) { | |
314 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
315 return; | |
316 } | |
317 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" | |
318 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | |
319 | |
320 strftime(date, sizeof(date), "%F %T", localtime(&log->time)); | |
321 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", | |
322 date, log->name, prpl); | |
323 } | |
324 | |
325 strftime(date, sizeof(date), "%T", localtime(&time)); | |
326 gaim_markup_html_to_xhtml(message, &xhtml, NULL); | |
327 if (from) | |
328 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", | |
329 str_from_msg_type(type), | |
330 type & GAIM_MESSAGE_SEND ? "direction='sent'" : | |
331 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
332 from, date, xhtml); | |
333 else | |
334 fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", | |
335 str_from_msg_type(type), | |
336 type & GAIM_MESSAGE_SEND ? "direction='sent'" : | |
337 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
338 date, xhtml); | |
339 fflush(log->logger_data); | |
340 g_free(xhtml); | |
341 } | |
342 | |
343 static void xml_logger_finalize(GaimLog *log) | |
344 { | |
345 if (log->logger_data) { | |
346 fprintf(log->logger_data, "</conversation>\n"); | |
347 fclose(log->logger_data); | |
348 log->logger_data = NULL; | |
349 } | |
350 } | |
351 | |
352 static GList *xml_logger_list(const char *sn, GaimAccount *account) | |
353 { | |
354 return log_lister_common(sn, account, ".xml", &xml_logger); | |
4184 | 355 } |
356 | |
7431 | 357 static GaimLogLogger xml_logger = { |
358 N_("XML"), "xml", | |
359 NULL, | |
360 xml_logger_write, | |
361 xml_logger_finalize, | |
362 xml_logger_list, | |
363 NULL | |
364 }; | |
365 #endif | |
5563
9eb5b13fd412
[gaim-migrate @ 5965]
Christian Hammond <chipx86@chipx86.com>
parents:
5560
diff
changeset
|
366 |
7431 | 367 /**************************** |
368 ** PLAIN TEXT LOGGER ******* | |
369 ****************************/ | |
4184 | 370 |
7431 | 371 static void txt_logger_write(GaimLog *log, |
372 GaimMessageFlags type, | |
373 const char *from, time_t time, const char *message) | |
374 { | |
375 char date[64]; | |
376 char *stripped = NULL; | |
377 if (!log->logger_data) { | |
378 /* This log is new. We could use the loggers 'new' function, but | |
379 * creating a new file there would result in empty files in the case | |
380 * that you open a convo with someone, but don't say anything. | |
381 */ | |
382 char *ud = gaim_user_dir(); | |
383 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
384 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO | |
385 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
386 char *dir; | |
387 FILE *file; | |
388 | |
389 strftime(date, sizeof(date), "%F.%H%M%S.txt", localtime(&log->time)); | |
390 | |
391 dir = g_build_filename(ud, "logs", NULL); | |
392 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
393 g_free(dir); | |
394 dir = g_build_filename(ud, "logs", | |
395 prpl, NULL); | |
396 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
397 g_free(dir); | |
398 dir = g_build_filename(ud, "logs", | |
399 prpl, guy, NULL); | |
400 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
401 g_free(dir); | |
402 dir = g_build_filename(ud, "logs", | |
403 prpl, guy, gaim_normalize(log->account, log->name), NULL); | |
404 mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
405 | |
406 char *filename = g_build_filename(dir, date, NULL); | |
407 g_free(dir); | |
408 | |
409 file = fopen(dir, "r"); | |
410 if(!file) | |
411 mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
412 else | |
413 fclose(file); | |
414 | |
415 log->logger_data = fopen(filename, "a"); | |
416 if (!log->logger_data) { | |
417 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
418 return; | |
4184 | 419 } |
7431 | 420 strftime(date, sizeof(date), "%F %T", localtime(&log->time)); |
421 fprintf(log->logger_data, "Conversation with %s at %s on %s (%s)\n", | |
422 log->name, date, gaim_account_get_username(log->account), prpl); | |
423 } | |
424 | |
425 strftime(date, sizeof(date), "%T", localtime(&time)); | |
426 stripped = gaim_markup_strip_html(message); | |
427 fprintf(log->logger_data, "(%s) %s%s %s\n", date, from ? from : "", from ? ":" : "", stripped); | |
428 fflush(log->logger_data); | |
429 g_free(stripped); | |
430 } | |
431 | |
432 static void txt_logger_finalize(GaimLog *log) | |
433 { | |
434 if (log->logger_data) | |
435 fclose(log->logger_data); | |
436 } | |
437 | |
438 static GList *txt_logger_list(const char *sn, GaimAccount *account) | |
439 { | |
440 return log_lister_common(sn, account, ".txt", &txt_logger); | |
441 } | |
442 | |
443 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
444 { | |
445 char *read, *minus_header; | |
446 if (!log->logger_data) | |
447 return g_strdup("<font color='red'><b>log->logger_data was NULL!</b></font>"); | |
448 if (g_file_get_contents((char *)log->logger_data, &read, NULL, NULL)) { | |
449 minus_header = strchr(read, '\n'); | |
450 if (!minus_header) | |
451 minus_header = g_strdup(read); | |
452 else | |
453 minus_header = g_strdup(minus_header + 1); | |
454 g_free(read); | |
455 return minus_header; | |
456 } | |
457 return g_strdup(_("<font color='red'><b>Could not read file: %s</b></font>")); | |
458 } | |
459 | |
460 static GaimLogLogger txt_logger = { | |
461 N_("Plain text"), "txt", | |
462 NULL, | |
463 txt_logger_write, | |
464 txt_logger_finalize, | |
465 txt_logger_list, | |
466 txt_logger_read | |
467 }; | |
468 | |
469 /**************** | |
470 * OLD LOGGER *** | |
471 ****************/ | |
472 | |
473 /* The old logger doesn't write logs, only reads them. This is to include | |
474 * old logs in the log viewer transparently. | |
475 */ | |
476 | |
477 struct old_logger_data { | |
478 char *path; | |
479 int offset; | |
480 int length; | |
481 }; | |
482 | |
483 static GList *old_logger_list(const char *sn, GaimAccount *account) | |
484 { | |
485 FILE *file; | |
486 char buf[BUF_LONG]; | |
487 struct tm tm; | |
488 struct old_logger_data *data = NULL; | |
489 char day[4], month[4], year[5]; | |
490 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); | |
491 char *date; | |
492 char *path = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); | |
493 char *newlog; | |
494 | |
495 GaimLog *log = NULL; | |
496 GList *list = NULL; | |
497 | |
498 if (!(file = fopen(path, "r"))) | |
499 return NULL; | |
500 | |
501 while (fgets(buf, BUF_LONG, file)) { | |
502 if ((newlog = strstr(buf, "---- New C"))) { | |
503 int length; | |
504 int offset; | |
505 GDate gdate; | |
506 char convostart[32]; | |
507 char *temp = strchr(buf, '@'); | |
508 | |
509 if (temp == NULL || strlen(temp) < 2) | |
510 continue; | |
511 | |
512 temp++; | |
513 length = strcspn(temp, "-"); | |
514 if (length > 31) length = 31; | |
515 | |
516 offset = ftell(file); | |
517 | |
518 if (data) { | |
519 data->length = offset - data->offset - length - | |
520 strlen("<HR><BR><H3 Align=Center> ---- New Conversation @ ") - | |
521 strlen("----</H3><BR>"); | |
522 if (data->length != 0) | |
523 list = g_list_append(list, log); | |
524 else | |
525 gaim_log_free(log); | |
526 } | |
527 | |
528 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
529 log->logger = &old_logger; | |
530 | |
531 data = g_malloc(sizeof(struct old_logger_data)); | |
532 data->offset = offset; | |
533 data->path = path; | |
534 log->logger_data = data; | |
535 | |
536 | |
537 g_snprintf(convostart, length, "%s", temp); | |
538 sscanf(convostart, "%*s %s %s %d:%d:%d %s", | |
539 month, day, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, year); | |
540 date = g_strdup_printf("%s %s %s", month, day, year); | |
541 g_date_set_parse(&gdate, date); | |
542 tm.tm_mday = g_date_get_day(&gdate); | |
543 tm.tm_mon = g_date_get_month(&gdate) - 1; | |
544 tm.tm_year = g_date_get_year(&gdate) - 1900; | |
545 log->time = mktime(&tm); | |
546 | |
4184 | 547 } |
548 } | |
7431 | 549 fclose(file); |
550 return list; | |
4184 | 551 } |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
552 |
7431 | 553 char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
554 { |
7431 | 555 *flags = GAIM_LOG_READ_NO_NEWLINE; |
556 struct old_logger_data *data = log->logger_data; | |
557 FILE *file = fopen(data->path, "r"); | |
558 char *read = g_malloc(data->length + 1); | |
559 fseek(file, data->offset, SEEK_SET); | |
560 fread(read, data->length, 1, file); | |
561 read[data->length] = '\0'; | |
562 return read; | |
563 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
564 |
7431 | 565 static GaimLogLogger old_logger = { |
566 "old logger", "old", | |
567 NULL, NULL, NULL, | |
568 old_logger_list, | |
569 old_logger_read | |
570 }; |