X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fjournal.c;h=84d0cd922266c0dbe1d745af84a8005fc6b7de42;hb=c924d7187269c30657e0ad2d5a989b30aeb85c3f;hp=67657f6247cc8ec731cf8154c4f45aa48d369003;hpb=deb4fd96c0c171fc8eb64f7f1e7f5c2af4931416;p=pspp diff --git a/src/output/journal.c b/src/output/journal.c index 67657f6247..84d0cd9222 100644 --- a/src/output/journal.c +++ b/src/output/journal.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2010, 2012, 2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,91 +16,194 @@ #include -#include +#include "output/journal.h" #include #include #include +#include -#include -#include +#include "data/file-name.h" +#include "libpspp/cast.h" +#include "libpspp/message.h" +#include "libpspp/str.h" +#include "output/driver-provider.h" +#include "output/message-item.h" +#include "output/text-item.h" -#include "fwriteerror.h" -#include "error.h" -#include "xalloc.h" +#include "gl/fwriteerror.h" +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) -/* Journaling enabled? */ -static bool journal_enabled = false; +struct journal_driver + { + struct output_driver driver; + FILE *file; + char *command_name; -/* Name of the journal file. */ -static char *journal_file_name = NULL; + /* Name of journal file. */ + char *file_name; + bool destroyed; + }; -/* Journal file. */ -static FILE *journal_file = NULL; +static const struct output_driver_class journal_class; + +/* Journal driver, if journaling is enabled. */ +static struct journal_driver journal; + + +static struct journal_driver * +journal_driver_cast (struct output_driver *driver) +{ + assert (driver->class == &journal_class); + return UP_CAST (driver, struct journal_driver, driver); +} + +static void +journal_close (void) +{ + if (journal.file != NULL) + { + if (fwriteerror (journal.file)) + msg_error (errno, _("error writing output file `%s'"), + journal.file_name); + + } + journal.file = NULL; +} + +static void +journal_destroy (struct output_driver *driver) +{ + struct journal_driver *j = journal_driver_cast (driver); + + if ( !j->destroyed) + { + journal_close (); + free (j->command_name); + } + + j->destroyed = true; +} + +static void +journal_output (struct journal_driver *j, const char *s) +{ + if ( j->file == NULL) + return; + + fprintf (j->file, "%s\n", s); + + /* Flush the journal in case the syntax we're about to write + causes a crash. Having the syntax already written to disk + makes postmortem analysis of the problem possible. */ + fflush (j->file); +} + +static void +journal_submit (struct output_driver *driver, const struct output_item *item) +{ + struct journal_driver *j = journal_driver_cast (driver); + + output_driver_track_current_command (item, &j->command_name); + + if (is_text_item (item)) + { + const struct text_item *text_item = to_text_item (item); + enum text_item_type type = text_item_get_type (text_item); + + if (type == TEXT_ITEM_SYNTAX) + journal_output (j, text_item_get_text (text_item)); + } + else if (is_message_item (item)) + { + const struct message_item *message_item = to_message_item (item); + const struct msg *msg = message_item_get_msg (message_item); + char *s = msg_to_string (msg, j->command_name); + journal_output (j, s); + free (s); + } +} + +static const struct output_driver_class journal_class = + { + "journal", + journal_destroy, + journal_submit, + NULL /* flush */ + }; + + /* Enables journaling. */ void -journal_enable (void) +journal_init (void) { - journal_enabled = true; + /* Create journal driver. */ + output_driver_init (&journal.driver, &journal_class, "journal", + SETTINGS_DEVICE_UNFILTERED); + journal.file = NULL; + journal.command_name = NULL; + + /* Register journal driver. */ + output_driver_register (&journal.driver); + + journal_enable (); + journal.destroyed = false; } /* Disables journaling. */ void journal_disable (void) { - journal_enabled = false; - if (journal_file != NULL) - fflush (journal_file); + journal_close (); } -/* Sets the name of the journal file to FILE_NAME. */ + +/* Enable journaling. */ void -journal_set_file_name (const char *file_name) +journal_enable (void) { - assert (file_name != NULL); - - if (journal_file != NULL) + if (journal.file == NULL) { - if (fwriteerror (journal_file)) - error (0, errno, _("error writing \"%s\""), journal_file_name); + journal.file = fopen (journal_get_file_name (), "a"); + if (journal.file == NULL) + { + msg_error (errno, _("error opening output file `%s'"), + journal_get_file_name ()); + journal_close (); + } } +} + - free (journal_file_name); - journal_file_name = xstrdup (file_name); +/* Returns true if journaling is enabled, false otherwise. */ +bool +journal_is_enabled (void) +{ + return journal.file != NULL ; } -/* Writes LINE to the journal file (if journaling is enabled). - If PREFIX is non-null, the line will be prefixed by "> ". */ +/* Sets the name of the journal file to FILE_NAME. */ void -journal_write (bool prefix, const char *line) +journal_set_file_name (const char *file_name) { - if (!journal_enabled) - return; + journal_close (); + free (journal.file_name); + journal.file_name = xstrdup (file_name); +} - if (journal_file == NULL) +/* Returns the name of the journal file. The caller must not modify or free + the returned string. */ +const char * +journal_get_file_name (void) +{ + if (journal.file_name == NULL) { - if (journal_file_name == NULL) - { - const char *output_path = default_output_path (); - journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl"); - } - journal_file = fopen (journal_file_name, "w"); - if (journal_file == NULL) - { - error (0, errno, _("error creating \"%s\""), journal_file_name); - journal_enabled = false; - return; - } + const char *output_path = default_output_path (); + journal.file_name = xasprintf ("%s%s", output_path, "pspp.jnl"); } - - if (prefix) - fputs ("> ", journal_file); - fputs (line, journal_file); - if (strchr (line, '\n') == NULL) - putc ('\n', journal_file); - fflush (journal_file); + return journal.file_name; }