+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 */
+ };
+
+\f