summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-05-30 23:33:21 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-05-30 23:33:21 +0100
commitd5ab728e85409b5074d4d61aaf5ba60862528e60 (patch)
tree4e2c9d687fb417668054a826bd30d1892bc3ea25
parentfd33289346881b96841a598a1f8980212b0bab62 (diff)
Implement daemon (background) mode by default with optional foreground mode that can be specified on the command line.
-rw-r--r--README8
-rw-r--r--TODO2
-rw-r--r--blabouncer.c74
3 files changed, 73 insertions, 11 deletions
diff --git a/README b/README
index 9bee79b..c399a62 100644
--- a/README
+++ b/README
@@ -8,6 +8,14 @@ To compile run "make".
To run from the current directory once compiled run "./blabouncer".
+Running with command line arguments takes the form:
+./blabouncer [-f] [-c /path/to/blabouncer.conf]
+
+-f sets foreground mode (without this, blabouncer will detach and run in the background as a daemon)
+-c sets a path to a configuration file (this is optional)
+
+Arguments are all optional, but they must be specified in the order shown above.
+
== Configuration ==
An example configuration file is provided named "blabouncer.conf".
diff --git a/TODO b/TODO
index 7d3fd57..81e62bc 100644
--- a/TODO
+++ b/TODO
@@ -9,4 +9,4 @@ Might need to #include <limits.h> in blabouncer.c to make some operating systems
Send a PING to the server before assuming a timeout is definite.
-Implement daemon (background) mode with optional foreground mode.
+Capture Ctrl-C/kill and exit cleanly.
diff --git a/blabouncer.c b/blabouncer.c
index f7e38a1..cd50a0a 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -114,6 +114,7 @@ struct settings {
char basedir[PATH_MAX];
int logging;
int replaylogging;
+ int background; // Whether or not we're running in the background (detached from the terminal as a daemon)
};
// Structure of connected clients, their socket/file descriptors, their authentication status, and their OpenSSL structures
@@ -2310,7 +2311,10 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
debugprint(DEBUG_FULL, "top of loop, fdmax %d.\n", fdmax);
FD_ZERO(&rfds); // clear entries from fd set
- FD_SET(STDIN, &rfds); // add STDIN (fd 0) to read fds to monitor
+ // Add STDIN (fd 0) to read fds to monitor if we're not in background/daemon mode
+ if (!settings->background) {
+ FD_SET(STDIN, &rfds);
+ }
FD_SET(*serversockfd, &rfds); // add our server network socket to monitor
FD_SET(*clientsockfd, &rfds); // add our client network socket to monitor
@@ -2416,8 +2420,8 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
}
}
- // see if there's anything from stdin
- if (FD_ISSET(STDIN, &rfds)) {
+ // see if there's anything from stdin (unless we're in background/daemon mode)
+ if (!settings->background && FD_ISSET(STDIN, &rfds)) {
debugprint(DEBUG_FULL, "reading stdin!\n");
char outgoingmsg[MAXDATASIZE]; // String to send to server
@@ -2577,19 +2581,43 @@ int main(int argc, char *argv[]) {
// Terminate our global debug file string in case it's referenced before being read from file
debugpath[0] = '\0';
- // Check to see if a configuration file was specified on the command line
- if (argc == 3) {
+ // Assume background/daemon mode unless specified otherwise on the command line
+ settings.background = 1;
+ // Set configuration file to string to blank for now
+ settings.conffile[0] = '\0';
+
+ // Check to see what was specified on the command line
+ // TODO - Do better command line argument handling (no required order)
+ char helptext[] = "usage: %s [-f] [-c /path/to/blabouncer.conf] (-f for foreground mode)\n";
+ if (argc == 2) {
+ if (strcmp(argv[1], "-f")) {
+ fprintf(stderr, helptext, argv[0]);
+ exit(1);
+ } else {
+ settings.background = 0;
+ }
+ } else if (argc == 3) {
if (strcmp(argv[1], "-c")) {
- fprintf(stderr,"usage: %s [-c /path/to/blabouncer.conf]\n", argv[0]);
+ fprintf(stderr, helptext, argv[0]);
exit(1);
} else {
strcpy(settings.conffile, argv[2]);
}
- } else if (argc == 2 || argc > 3) {
- fprintf(stderr,"usage: %s [-c /path/to/blabouncer.conf]\n", argv[0]);
+ } else if (argc == 4) {
+ if (strcmp(argv[1], "-f") || strcmp(argv[2], "-c")) {
+ fprintf(stderr, helptext, argv[0]);
+ exit(1);
+ } else {
+ settings.background = 0;
+ strcpy(settings.conffile, argv[3]);
+ }
+ } else if (argc > 4) {
+ fprintf(stderr, helptext, argv[0]);
exit(1);
- } else {
- // If none provided, set to default
+ }
+
+ // If a configuration file wasn't set on the command line, set it now
+ if (!settings.conffile[0]) {
snprintf(settings.conffile, PATH_MAX, "%s/.blabouncer/blabouncer.conf", getenv("HOME"));
// Since this is the default, it might not exist yet, so let's check...
struct stat st = {0};
@@ -2777,6 +2805,32 @@ int main(int argc, char *argv[]) {
debugprint(DEBUG_SOME, "Using configuration file '%s'.\n", settings.conffile);
+ // Unless specified otherwise on the command line, fork to background
+ if (settings.background) {
+ pid_t pid, sid;
+ // Fork from parent
+ if ((pid = fork()) < 0) {
+ printf("Couldn't fork, exiting.\n");
+ debugprint(DEBUG_CRIT, "Couldn't fork, exiting.\n");
+ exit(1);
+ }
+ // Exit parent (pid will be > 0 for the child)
+ if (pid > 0) {
+ exit(0);
+ }
+ umask(0);
+ // Let child become process group leader
+ if ((sid = setsid()) < 0) {
+ printf("Couldn't setsid() child, exiting.\n");
+ debugprint(DEBUG_CRIT, "Couldn't setsid() child, exiting.\n");
+ exit(1);
+ }
+ // In case our cwd changes
+ chdir("/");
+ // TODO - close() STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO here, might need to change fd number
+ // logic/assumptions elsewhere (such as fd 3 being server, fd 4 being clients, etc.)
+ }
+
// TODO: see if any of this can be shared (i.e. 1. avoid code duplication, and 2. see if variables can be shared between client/server sockets)
// I will try to keep to the notation of "server" meaning the real IRCd, "bouncer" meaning the bouncer, and "client" meaning the real IRC client