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
9 ./expnhelp < $(srcdir)/nickserv.help.m4 > $@
11 EXTRA_srvx_SOURCES = proto-bahamut.c 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@
16 chanserv.c chanserv.h \
18 ===================================================================
19 RCS file: /cvsroot/srvx/services/src/log.c,v
20 retrieving revision 1.65
22 --- src/log.c 22 Aug 2003 00:26:21 -0000 1.65
23 +++ src/log.c 28 Sep 2003 14:16:40 -0000
29 +#include <postgresql/libpq-fe.h>
31 struct logDestination;
37 +/* pgsql: log type */
39 +struct logDest_pgsql {
40 + struct logDestination base;
41 + struct string_list queue;
46 +static struct logDest_vtable ldPgsql_vtbl;
48 +static void ldPgsql_send_next_query(struct logDest_pgsql *ld) {
51 + res = PQsendQuery(ld->conn, ld->queue.list[0]);
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--;
58 + res = PQflush(ld->conn);
60 + ld->recurse_level++;
61 + log_module(MAIN_LOG, LOG_ERROR, "Error flushing PgSql output: %s", PQerrorMessage(ld->conn));
62 + ld->recurse_level--;
66 +static void ldPgsql_readable(struct io_fd *fd) {
67 + struct logDest_pgsql *ld = fd->data;
73 + res = PQconsumeInput(ld->conn);
75 + ld->recurse_level++;
76 + log_module(MAIN_LOG, LOG_ERROR, "Error consuming PgSql input: %s", PQerrorMessage(ld->conn));
77 + ld->recurse_level--;
79 + if (PQisBusy(ld->conn))
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--;
90 + if (ld->queue.used == 1)
91 + ld->queue.list[1] = NULL;
92 + free(ld->queue.list[0]);
94 + for (ii = 0; ii < ld->queue.used; ++ii)
95 + ld->queue.list[ii] = ld->queue.list[ii+1];
97 + ldPgsql_send_next_query(ld);
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++;
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));
113 + res = PQsetnonblocking(ld->conn, 1);
115 + log_module(MAIN_LOG, LOG_ERROR, "Unable to make pgsql non-blocking");
116 + ld->fd = ioset_add(PQsocket(ld->conn));
118 + ld->fd->connected = 1;
119 + ld->fd->wants_reads = 1;
120 + ld->fd->readable_cb = ldPgsql_readable;
121 + while (PQflush(ld->conn)) ;
123 + ld->recurse_level--;
128 +ldPgsql_reopen(struct logDestination *self_) {
129 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
130 + PQreset(self->conn);
134 +ldPgsql_close(struct logDestination *self_) {
135 + struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
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);
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;
154 + dest->size = dest->size * 2;
156 + dest->list = realloc(dest->list, dest->size);
158 + dest->used += PQescapeString(dest->list+dest->used, src, len);
162 +string_buffer_append_time(struct string_buffer *dest, time_t when) {
164 + if (dest->size < dest->used + 20) {
165 + if (dest->size < 20) {
168 + dest->size = dest->size * 2;
170 + dest->list = realloc(dest->list, dest->size);
172 + dest->used += strftime(dest->list + dest->used, dest->size - dest->used, "%Y-%m-%d %H:%M:%S", gmtime_r(&when, &gmt));
176 +string_buffer_append_quoted2(struct string_buffer *dest, const char *src) {
178 + string_buffer_append_string(dest, ", '");
179 + string_buffer_append_quoted(dest, src);
180 + string_buffer_append(dest, '\'');
182 + string_buffer_append_string(dest, ", NULL");
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);
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;
198 + if (self->recurse_level)
201 + query.list = malloc(query.size);
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);
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;
224 + if (self->recurse_level)
227 + query.list = malloc(query.size);
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);
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;
242 + if (self->recurse_level)
245 + query.list = malloc(query.size);
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);
255 +static struct logDest_vtable ldPgsql_vtbl = {
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);