+/**
+ * @file main.c
+ * @purpose Contains main function, definition of options global variable, and the general signal handler
+ */
+
+// --- external includes --- //
#include <stdlib.h>
#include <stdio.h>
+#include <signal.h>
+
+// --- local includes --- //
#include "options.h"
#include "master.h"
#include "slave.h"
#include "daemon.h"
-#include <signal.h>
-Options options;
+// --- variable definitions --- //
+Options options; // basically all global variables are contained in this structure
+
+
+// --- function declarations --- //
+void signal_handler(int signal);
+
-void Cleanup();
-void Signal_handler(int signal);
+// --- function definitions --- //
+/**
+ * @funct main
+ * @purpose The main function; starts argument parsing function,
+ * starts appropriate main function based on the type of the instance (interactive, remote, daemon wrapper)
+ * @param argc - You should know what this is. But it's the size of the argv array. In case you didn't know.
+ * @param argv - You should also know what this is. It contains arguments passed to the program.
+ */
int main(int argc, char ** argv)
{
- atexit(Cleanup);
- Initialise(argc, argv, &options);
+ options_setup(argc, argv, &options); // fill in the options
- if (signal(SIGTERM, Signal_handler) == SIG_ERR)
+ // Setup signal handlers
+ if (signal(SIGTERM, signal_handler) == SIG_ERR)
error("main", "Setting signal handler");
- if (signal(SIGINT, Signal_handler) == SIG_ERR)
+ if (signal(SIGINT, signal_handler) == SIG_ERR)
error("main", "Setting signal handler");
- if (signal(SIGHUP, Signal_handler) == SIG_ERR)
+ if (signal(SIGHUP, signal_handler) == SIG_ERR)
error("main", "Setting signal handler");
- if (signal(SIGPIPE, Signal_handler) == SIG_ERR)
+ if (signal(SIGPIPE, signal_handler) == SIG_ERR)
error("main", "Setting signal handler");
- //if (signal(SIGSEGV, Signal_handler) == SIG_ERR)
+ //if (signal(SIGSEGV, signal_handler) == SIG_ERR)
// error("main", "Setting signal handler");
- if (options.master_addr == NULL)
+
+ // Start the appropriate actual main function
+ if (options.master_addr == NULL) // This is not a "remote" instance
{
if (options.daemon_wrapper)
+ {
+ // There is a daemon running; send commands to the daemon
Daemon_wrapper(&options);
+ }
else
+ {
+ // Daemons and interactive instances run this function
Master_main(&options);
+ }
}
else
{
- fprintf(stderr, "%p %s", options.master_addr, options.master_addr);
+ // Remote instance
Slave_main(&options);
}
return 0;
}
-void Signal_handler(int sig)
+/**
+ * @funct signal_handler
+ * @purpose Handle any signals that would cause the program to terminate
+ * @param sig - The signal number
+ */
+void signal_handler(int sig)
{
-
- signal(sig, SIG_IGN);
+ // There is a bit of a race condition with the SIGCHLD handler
+ // We can't be sure whether this handler gets called first, or SIGCHLD (due to a child getting the signal)
+ // We need to ignore SIGCHLD if this handler gets called first
signal(SIGCHLD, SIG_IGN);
+ signal(sig, SIG_IGN); // I'm not sure why we need this? //TODO: Remove?
+
log_print(2, "Signal_handler", "Got signal %d; exiting", sig);
exit(EXIT_SUCCESS);
}
-
-void Cleanup()
-{
-
-}