6b7332771c0f5e7727ffe631c04d11e1ab63a5ac
[pspp-builds.git] / src / output / journal.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007, 2010 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "output/journal.h"
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "data/file-name.h"
26 #include "libpspp/cast.h"
27 #include "libpspp/str.h"
28 #include "output/driver-provider.h"
29 #include "output/message-item.h"
30 #include "output/text-item.h"
31
32 #include "gl/error.h"
33 #include "gl/fwriteerror.h"
34 #include "gl/xalloc.h"
35
36 #include "gettext.h"
37 #define _(msgid) gettext (msgid)
38
39 struct journal_driver
40   {
41     struct output_driver driver;
42     FILE *file;
43     char *command_name;
44   };
45
46 static const struct output_driver_class journal_class;
47
48 /* Journal driver, if journaling is enabled. */
49 static struct journal_driver *journal;
50
51 /* Name of journal file. */
52 static char *journal_file_name;
53
54 static struct journal_driver *
55 journal_driver_cast (struct output_driver *driver)
56 {
57   assert (driver->class == &journal_class);
58   return UP_CAST (driver, struct journal_driver, driver);
59 }
60
61 static void
62 journal_close (void)
63 {
64   if (journal != NULL && journal->file != NULL)
65     {
66       if (fwriteerror (journal->file))
67         error (0, errno, _("error writing \"%s\""), journal_file_name);
68       journal->file = NULL;
69     }
70 }
71
72 static void
73 journal_destroy (struct output_driver *driver)
74 {
75   struct journal_driver *j = journal_driver_cast (driver);
76
77   journal_close ();
78   free (j->command_name);
79   free (j);
80
81   journal = NULL;
82 }
83
84 static void
85 journal_output (struct journal_driver *j, const char *s)
86 {
87   if (j->file == NULL)
88     {
89       j->file = fopen (journal_file_name, "a");
90       if (j->file == NULL)
91         {
92           error (0, errno, _("%s: open failed"), journal_file_name);
93           output_driver_destroy (&j->driver);
94           return;
95         }
96     }
97
98   fprintf (j->file, "%s\n", s);
99 }
100
101 static void
102 journal_submit (struct output_driver *driver, const struct output_item *item)
103 {
104   struct journal_driver *j = journal_driver_cast (driver);
105
106   output_driver_track_current_command (item, &j->command_name);
107
108   if (is_text_item (item))
109     {
110       const struct text_item *text_item = to_text_item (item);
111       enum text_item_type type = text_item_get_type (text_item);
112
113       if (type == TEXT_ITEM_SYNTAX)
114         journal_output (j, text_item_get_text (text_item));
115     }
116   else if (is_message_item (item))
117     {
118       const struct message_item *message_item = to_message_item (item);
119       const struct msg *msg = message_item_get_msg (message_item);
120       char *s = msg_to_string (msg, j->command_name);
121       journal_output (j, s);
122       free (s);
123     }
124 }
125
126 static const struct output_driver_class journal_class =
127   {
128     "journal",
129     journal_destroy,
130     journal_submit,
131     NULL                        /* flush */
132   };
133 \f
134 /* Enables journaling. */
135 void
136 journal_enable (void)
137 {
138   if (journal == NULL)
139     {
140       /* If no journal file name is configured, use the default. */
141       if (journal_file_name == NULL)
142         {
143           const char *output_path = default_output_path ();
144           journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl");
145         }
146
147       /* Create journal driver. */
148       journal = xzalloc (sizeof *journal);
149       output_driver_init (&journal->driver, &journal_class, "journal",
150                           SETTINGS_DEVICE_UNFILTERED);
151       journal->file = NULL;
152       journal->command_name = NULL;
153
154       /* Register journal driver. */
155       output_driver_register (&journal->driver);
156     }
157 }
158
159 /* Disables journaling. */
160 void
161 journal_disable (void)
162 {
163   if (journal != NULL)
164     output_driver_destroy (&journal->driver);
165 }
166
167 /* Sets the name of the journal file to FILE_NAME. */
168 void
169 journal_set_file_name (const char *file_name)
170 {
171   journal_close ();
172   free (journal_file_name);
173   journal_file_name = xstrdup (file_name);
174 }