summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-05-16 00:15:47 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-05-16 00:15:47 +0100
commita299b62e913df71bdd1c4b41d61d3fb098f12be7 (patch)
tree4e3061c884ef8636a94a773de30893bbff84cd52
parent0cebf7c6d557d0b76d069af908a2a47366033fde (diff)
Implement normal logging (file per channel/user).
-rw-r--r--Makefile6
-rw-r--r--blabouncer.c10
-rw-r--r--logging.c90
-rw-r--r--logging.h26
-rw-r--r--replay.c2
5 files changed, 128 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index f297c74..3316e82 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
CC=gcc
-DEPS = functions.h sockets.h config.h replay.h
+DEPS = functions.h sockets.h config.h replay.h logging.h
%.o: %.c $(DEPS)
$(CC) -Wall -Wextra -c -o $@ $<
-blabouncer: blabouncer.o functions.o sockets.o config.o replay.o
- $(CC) -Wall -Wextra -lssl -lcrypto -o blabouncer blabouncer.o functions.o sockets.o config.o replay.o
+blabouncer: blabouncer.o functions.o sockets.o config.o replay.o logging.o
+ $(CC) -Wall -Wextra -lssl -lcrypto -o blabouncer blabouncer.o functions.o sockets.o config.o replay.o logging.o
diff --git a/blabouncer.c b/blabouncer.c
index 2bf2138..3f9004d 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -5,7 +5,6 @@
// - Might need to change channel struct nicks to be channel struct user struct with its own nick/modes/etc.
// - Do we actually need to store the modes in the channel struct?
// - Get CAP from server and relay to client
-// - Add blabouncer MOTD (375, 372, 376)
// - "01:53:47 -!- ServerMode/#test [b] by irc.tghost.co.uk" on existing clients when new client connects
// - Keep track of changing user nicks/modes
// - Should replay log do more than PRIVMSGs?
@@ -14,7 +13,7 @@
// - Configurable auto channels
// - Comma separated channel list in JOINs/PARTs
// - Only send some things to the requesting client (e.g. LIST replies)
-// - Normal (non-replay) log
+// - Customise logging (disabling it, log file location)
// - Alert when clients connect/authenticate/disconnect
// - Perhaps rename arr_ssl and server_ssl since they may not even be OpenSSL sockets
//
@@ -44,6 +43,7 @@
#include "sockets.h"
#include "config.h"
#include "replay.h"
+#include "logging.h"
#define SOURCE_SERVER 0
#define SOURCE_CLIENT 1
@@ -688,6 +688,9 @@ int processircmessage(SSL *server_ssl, int *clientsockfd, char *str, int source,
// Write to replay log
writereplayline(str);
+ // Write to normal log
+ logprivmsg(str, settings->ircnick);
+
return 1;
}
}
@@ -872,6 +875,9 @@ int processircmessage(SSL *server_ssl, int *clientsockfd, char *str, int source,
// Write to replay log
writereplayline(outgoingmsg);
+ // Write to normal log
+ logprivmsg(outgoingmsg, settings->ircnick);
+
return 1;
}
diff --git a/logging.c b/logging.c
new file mode 100644
index 0000000..e0f5f1f
--- /dev/null
+++ b/logging.c
@@ -0,0 +1,90 @@
+#include "logging.h"
+
+// Write the line 'str' to the relevant log file such as
+// '#channel.log' or 'nickname.log'. 'ournick' is our own
+// nick and is used to determine which log file to write to.
+// Expects a string in the format:
+// :from!bar@baz PRIVMSG to :hello world
+// With the ":foo!bar@baz "prefix being important.
+// Returns 1 on success or 0 on failure.
+int logprivmsg(char *str, char *ournick) {
+ // First, extract the "from" nick and the "to" nick or channel by splitting up the string
+
+ // Track which space-separated token within this response we're on
+ int counter = 0;
+ // Build array of each space-separated token (TODO - Use counter to stop splitting once we reach some reasonable value - i.e. once we're definitely past commands and into just free text)
+ char tokens[MAXTOKENS][MAXDATASIZE];
+ char *token;
+
+ // Split out the first three space-separated parts of the string, leaving the rest.
+ // This gets us the prefix (containing the "from" nick), the PRIVMSG command (not needed),
+ // and the "to" nick or channel. Plus the rest of the string intact (which is the actual
+ // message).
+ for (int i = 0; i < 3; i++) {
+ // Try to split
+ if ((token = strsep(&str, " ")) == NULL) {
+ printf("Error splitting string for logging, exiting!\n");
+ exit(1);
+ }
+ // Copy into the token array (strlen + 1 to get the NULL terminator)
+ strncpy(tokens[i], token, strlen(token) + 1);
+ counter++;
+ }
+
+ // Extract the username from the prefix
+ extractnickfromprefix(tokens[0]);
+
+ // Remove the leading ":" from the real message
+ stripprefix(str);
+
+ // Build the log filename
+ char filename[MAXCHAR];
+ // If the message was sent to us, then log it in the sender's log file
+ if (strncmp(tokens[2], ournick, strlen(tokens[0])) == 0) {
+ snprintf(filename, MAXCHAR, "%s.log", tokens[0]);
+ } else {
+ // Otherwise log it in the "to" log file
+ snprintf(filename, MAXCHAR, "%s.log", tokens[2]);
+ }
+
+ printf("logprivmsg(): Logging from '%s' to '%s' message '%s' in filename '%s'.\n", tokens[0], tokens[2], str, filename);
+
+ FILE *fp;
+ char line[MAXCHAR];
+
+ int bytes = 0;
+
+ fp = fopen(filename, "a");
+
+ if (fp == NULL) {
+ printf("error: could not open log file '%s' for writing.\n", filename);
+ exit(1);
+ }
+
+ // Get a current time string to prepend - TODO - Make this customisable.
+ time_t rawtime;
+ struct tm * timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ // Strip the trailing newline
+ char timestr[MAXCHAR];
+ snprintf(timestr, MAXCHAR, "%s", asctime(timeinfo));
+ timestr[strlen(timestr) - 1] = '\0';
+
+ // Prepend the time string and "from" nick
+ if (!snprintf(line, MAXCHAR, "%s <%s> %s", timestr, tokens[0], str)) {
+ fprintf(stderr, "Error while log string to write!\n");
+ exit(1);
+ }
+
+ printf("Complete log string to write: '%s', length '%ld'.\n", line, strlen(line));
+
+ // Write complete line to file
+ if ((bytes = fprintf(fp, line)) < 0) {
+ printf("error: could not write to log file.\n");
+ exit(1);
+ }
+
+ fclose(fp);
+ return bytes;
+}
diff --git a/logging.h b/logging.h
new file mode 100644
index 0000000..289f348
--- /dev/null
+++ b/logging.h
@@ -0,0 +1,26 @@
+#ifndef LOGGING_H_INCLUDED
+#define LOGGING_H_INCLUDED
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "functions.h"
+
+#define MAXTOKENS 100
+#define MAXDATASIZE 513 // max number of bytes we can get at once (RFC2812 says 512, plus one for null terminator)
+#define MAXCHAR 1000
+
+#define SOURCE_SERVER 0
+#define SOURCE_CLIENT 1
+
+// Write the line 'str' to the relevant log file such as
+// '#channel.log' or 'nickname.log'. 'ournick' is our own
+// nick and is used to determine which log file to write to.
+// Expects a string in the format:
+// :from!bar@baz PRIVMSG to :hello world
+// With the ":foo!bar@baz "prefix being important.
+// Returns 1 on success or 0 on failure.
+int logprivmsg(char *str, char *ournick);
+
+#endif
diff --git a/replay.c b/replay.c
index 1563c17..3c2c920 100644
--- a/replay.c
+++ b/replay.c
@@ -228,7 +228,7 @@ int readreplayline(int seconds, int linenum, char *str) {
// Write the line 'str' to the replay log file after prepending it with
// the current unixtime timestamp.
// Expects a string in the format:
-// :foo!bar@baz PRIVMSG foo :[17:41:41] hello world
+// :from!bar@baz PRIVMSG to :hello world
// With the ":foo!bar@baz "prefix being important.
// Returns 1 on success or 0 on failure.
int writereplayline(char *str) {