]> jfr.im git - irc/evilnet/x3.git/blob - patches/log-pgsql.diff
Fix for issue with SASL account names
[irc/evilnet/x3.git] / patches / log-pgsql.diff
1 Index: src/Makefile.am
2 ===================================================================
3 RCS file: /cvsroot/srvx/services/src/Makefile.am,v
4 retrieving revision 1.59
5 diff -u -r1.59 Makefile.am
6 --- src/Makefile.am 9 Sep 2003 01:56:55 -0000 1.59
7 +++ src/Makefile.am 28 Sep 2003 14:16:39 -0000
8 @@ -9,7 +9,7 @@
9 ./expnhelp < $(srcdir)/nickserv.help.m4 > $@
10
11 EXTRA_srvx_SOURCES = proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
12 -srvx_LDADD = @MODULE_OBJS@
13 +srvx_LDADD = @MODULE_OBJS@ -lpq
14 srvx_DEPENDENCIES = @MODULE_OBJS@
15 srvx_SOURCES = \
16 chanserv.c chanserv.h \
17 Index: src/log.c
18 ===================================================================
19 RCS file: /cvsroot/srvx/services/src/log.c,v
20 retrieving revision 1.65
21 diff -u -r1.65 log.c
22 --- src/log.c 22 Aug 2003 00:26:21 -0000 1.65
23 +++ src/log.c 28 Sep 2003 14:16:40 -0000
24 @@ -22,6 +22,8 @@
25 #include "log.h"
26 #include "helpfile.h"
27 #include "nickserv.h"
28 +#include "ioset.h"
29 +#include <postgresql/libpq-fe.h>
30
31 struct logDestination;
32
33 @@ -992,6 +994,234 @@
34 ldIrc_module
35 };
36
37 +/* pgsql: log type */
38 +
39 +struct logDest_pgsql {
40 + struct logDestination base;
41 + struct string_list queue;
42 + PGconn *conn;
43 + struct io_fd *fd;
44 + int recurse_level;
45 +};
46 +static struct logDest_vtable ldPgsql_vtbl;
47 +
48 +static void ldPgsql_send_next_query(struct logDest_pgsql *ld) {
49 + int res;
50 +
51 + res = PQsendQuery(ld->conn, ld->queue.list[0]);
52 + if (!res) {
53 + ld->recurse_level++;
54 + log_module(MAIN_LOG, LOG_ERROR, "Error sending query \"%s\": %s", ld->queue.list[0], PQerrorMessage(ld->conn));
55 + ld->recurse_level--;
56 + return;
57 + }
58 + res = PQflush(ld->conn);
59 + if (res == EOF) {
60 + ld->recurse_level++;
61 + log_module(MAIN_LOG, LOG_ERROR, "Error flushing PgSql output: %s", PQerrorMessage(ld->conn));
62 + ld->recurse_level--;
63 + }
64 +}
65 +
66 +static void ldPgsql_readable(struct io_fd *fd) {
67 + struct logDest_pgsql *ld = fd->data;
68 + PGresult *pgres;
69 + unsigned int ii;
70 + int res;
71 + ExecStatusType st;
72 +
73 + res = PQconsumeInput(ld->conn);
74 + if (!res) {
75 + ld->recurse_level++;
76 + log_module(MAIN_LOG, LOG_ERROR, "Error consuming PgSql input: %s", PQerrorMessage(ld->conn));
77 + ld->recurse_level--;
78 + }
79 + if (PQisBusy(ld->conn))
80 + return;
81 + while ((pgres = PQgetResult(ld->conn))) {
82 + st = PQresultStatus(pgres);
83 + if (st != PGRES_COMMAND_OK) {
84 + ld->recurse_level++;
85 + log_module(MAIN_LOG, LOG_ERROR, "PgSql error in \"%s\": %s", ld->queue.list[0], PQresultErrorMessage(pgres));
86 + ld->recurse_level--;
87 + }
88 + PQclear(pgres);
89 + }
90 + if (ld->queue.used == 1)
91 + ld->queue.list[1] = NULL;
92 + free(ld->queue.list[0]);
93 + ld->queue.used--;
94 + for (ii = 0; ii < ld->queue.used; ++ii)
95 + ld->queue.list[ii] = ld->queue.list[ii+1];
96 + if (ld->queue.used)
97 + ldPgsql_send_next_query(ld);
98 +}
99 +
100 +static struct logDestination *
101 +ldPgsql_open(const char *args) {
102 + struct logDest_pgsql *ld;
103 + ld = calloc(1, sizeof(*ld));
104 + ld->base.vtbl = &ldPgsql_vtbl;
105 + ld->conn = PQconnectdb(args);
106 + ld->recurse_level++;
107 + if (!ld->conn) {
108 + log_module(MAIN_LOG, LOG_ERROR, "Unable to allocate pgsql connection");
109 + } else if (PQstatus(ld->conn) == CONNECTION_BAD) {
110 + log_module(MAIN_LOG, LOG_ERROR, "Pgsql connection failed: %s", PQerrorMessage(ld->conn));
111 + } else {
112 + int res;
113 + res = PQsetnonblocking(ld->conn, 1);
114 + if (res == -1)
115 + log_module(MAIN_LOG, LOG_ERROR, "Unable to make pgsql non-blocking");
116 + ld->fd = ioset_add(PQsocket(ld->conn));
117 + ld->fd->data = ld;
118 + ld->fd->connected = 1;
119 + ld->fd->wants_reads = 1;
120 + ld->fd->readable_cb = ldPgsql_readable;
121 + while (PQflush(ld->conn)) ;
122 + }
123 + ld->recurse_level--;
124 + return &ld->base;
125 +}
126 +
127 +static void
128 +ldPgsql_reopen(struct logDestination *self_) {
129 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
130 + PQreset(self->conn);
131 +}
132 +
133 +static void
134 +ldPgsql_close(struct logDestination *self_) {
135 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
136 + unsigned int ii;
137 +
138 + PQfinish(self->conn);
139 + ioset_close(self->fd->fd, 0);
140 + for (ii = 0; ii < self->queue.used; ++ii)
141 + free(self->queue.list[ii]);
142 + self->recurse_level--;
143 + free(self->queue.list);
144 + free(self);
145 +}
146 +
147 +static void
148 +string_buffer_append_quoted(struct string_buffer *dest, const char *src) {
149 + size_t len = strlen(src);
150 + if (dest->size < dest->used + len * 2) {
151 + if (dest->size < len * 2) {
152 + dest->size = len * 4;
153 + } else {
154 + dest->size = dest->size * 2;
155 + }
156 + dest->list = realloc(dest->list, dest->size);
157 + }
158 + dest->used += PQescapeString(dest->list+dest->used, src, len);
159 +}
160 +
161 +static void
162 +string_buffer_append_time(struct string_buffer *dest, time_t when) {
163 + struct tm gmt;
164 + if (dest->size < dest->used + 20) {
165 + if (dest->size < 20) {
166 + dest->size = 40;
167 + } else {
168 + dest->size = dest->size * 2;
169 + }
170 + dest->list = realloc(dest->list, dest->size);
171 + }
172 + dest->used += strftime(dest->list + dest->used, dest->size - dest->used, "%Y-%m-%d %H:%M:%S", gmtime_r(&when, &gmt));
173 +}
174 +
175 +static void
176 +string_buffer_append_quoted2(struct string_buffer *dest, const char *src) {
177 + if (src) {
178 + string_buffer_append_string(dest, ", '");
179 + string_buffer_append_quoted(dest, src);
180 + string_buffer_append(dest, '\'');
181 + } else {
182 + string_buffer_append_string(dest, ", NULL");
183 + }
184 +}
185 +
186 +static void
187 +pgsql_insert(struct logDest_pgsql *self, char *query) {
188 + string_list_append(&self->queue, query);
189 + if (self->queue.used == 1)
190 + ldPgsql_send_next_query(self);
191 +}
192 +
193 +static void
194 +ldPgsql_audit(struct logDestination *self_, struct log_type *type, struct logEntry *entry) {
195 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
196 + struct string_buffer query;
197 +
198 + if (self->recurse_level)
199 + return;
200 + query.size = 512;
201 + query.list = malloc(query.size);
202 + query.used = 0;
203 + string_buffer_append_printf(&query, "INSERT INTO srvx_audit (i_module, i_severity, i_bot, t_when, c_channel_name, c_user_nick, c_user_account, c_user_hostmask, c_command) VALUES (srvx_module_id('");
204 + string_buffer_append_quoted(&query, type->name);
205 + string_buffer_append_printf(&query, "'), %d, srvx_bot_id('", entry->slvl);
206 + string_buffer_append_quoted(&query, entry->bot->nick);
207 + string_buffer_append_string(&query, "'), '");
208 + string_buffer_append_time(&query, entry->time);
209 + string_buffer_append_string(&query, "'");
210 + string_buffer_append_quoted2(&query, entry->channel_name);
211 + string_buffer_append_quoted2(&query, entry->user_nick);
212 + string_buffer_append_quoted2(&query, entry->user_account);
213 + string_buffer_append_quoted2(&query, entry->user_hostmask);
214 + string_buffer_append_quoted2(&query, entry->command);
215 + string_buffer_append_string(&query, ");");
216 + pgsql_insert(self, query.list);
217 +}
218 +
219 +static void
220 +ldPgsql_replay(struct logDestination *self_, struct log_type *type, int is_write, const char *line) {
221 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
222 + struct string_buffer query;
223 +
224 + if (self->recurse_level)
225 + return;
226 + query.size = 512;
227 + query.list = malloc(query.size);
228 + query.used = 0;
229 + string_buffer_append_printf(&query, "INSERT INTO srvx_replay (i_module, b_is_write, c_text) VALUES (srvx_module_id('");
230 + string_buffer_append_quoted(&query, type->name);
231 + string_buffer_append_printf(&query, "'), %s, '", (is_write ? "true" : "false"));
232 + string_buffer_append_quoted(&query, line);
233 + string_buffer_append_string(&query, "');");
234 + pgsql_insert(self, query.list);
235 +}
236 +
237 +static void
238 +ldPgsql_module(struct logDestination *self_, struct log_type *type, enum log_severity sev, const char *message) {
239 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
240 + struct string_buffer query;
241 +
242 + if (self->recurse_level)
243 + return;
244 + query.size = 512;
245 + query.list = malloc(query.size);
246 + query.used = 0;
247 + string_buffer_append_printf(&query, "INSERT INTO srvx_log (i_module, i_severity, c_message) VALUES (srvx_module_id('");
248 + string_buffer_append_quoted(&query, type->name);
249 + string_buffer_append_printf(&query, "'), %d, '", sev);
250 + string_buffer_append_quoted(&query, message);
251 + string_buffer_append_string(&query, "');");
252 + pgsql_insert(self, query.list);
253 +}
254 +
255 +static struct logDest_vtable ldPgsql_vtbl = {
256 + "pgsql",
257 + ldPgsql_open,
258 + ldPgsql_reopen,
259 + ldPgsql_close,
260 + ldPgsql_audit,
261 + ldPgsql_replay,
262 + ldPgsql_module
263 +};
264 +
265 void
266 log_init(void)
267 {
268 @@ -1003,6 +1233,7 @@
269 dict_insert(log_dest_types, ldFile_vtbl.type_name, &ldFile_vtbl);
270 dict_insert(log_dest_types, ldStd_vtbl.type_name, &ldStd_vtbl);
271 dict_insert(log_dest_types, ldIrc_vtbl.type_name, &ldIrc_vtbl);
272 + dict_insert(log_dest_types, ldPgsql_vtbl.type_name, &ldPgsql_vtbl);
273 conf_register_reload(log_conf_read);
274 log_default = log_register_type("*", NULL);
275 reg_exit_func(cleanup_logs);