#include "ConfigParser.h"
#include "ssl.h"
#include "QServer.h"
+#include "version.h"
time_t start_time;
static int running, hard_restart;
int statistics_enabled;
TIMEQ_CALLBACK(main_statistics);
TIMEQ_CALLBACK(main_checkauths);
+static int daemonized = 0;
+static int print_loglevel = 0;
+static FILE *log_fptr = NULL;
static int process_argc;
static char **process_argv;
#ifdef HAVE_THREADS
int running_threads;
pthread_mutex_t cache_sync;
pthread_mutex_t whohandler_sync, whohandler_mass_sync;
+static pthread_mutex_t log_sync;
#endif
void cleanup() {
static int load_mysql_config() {
char *mysql_host, *mysql_user, *mysql_pass, *mysql_base;
int mysql_serverport;
- if(loadConfig("neonserv.conf")) {
- mysql_host = get_string_field("MySQL.host");
- if(!mysql_host) {
- perror("invalid neonserv.conf: missing MySQL.host");
- return 0;
- }
- mysql_serverport = get_int_field("MySQL.port");
- if(!mysql_serverport)
- mysql_serverport = 3306;
- mysql_user = get_string_field("MySQL.user");
- if(!mysql_user) {
- perror("invalid neonserv.conf: missing MySQL.user");
- return 0;
- }
- mysql_pass = get_string_field("MySQL.pass");
- if(!mysql_pass) {
- perror("invalid neonserv.conf: missing MySQL.pass");
- return 0;
- }
- mysql_base = get_string_field("MySQL.base");
- if(!mysql_base) {
- perror("invalid neonserv.conf: missing MySQL base");
- return 0;
- }
- } else {
- perror("Unable to load neonserv.conf");
+
+ mysql_host = get_string_field("MySQL.host");
+ if(!mysql_host) {
+ perror("invalid neonserv.conf: missing MySQL.host");
+ return 0;
+ }
+ mysql_serverport = get_int_field("MySQL.port");
+ if(!mysql_serverport)
+ mysql_serverport = 3306;
+ mysql_user = get_string_field("MySQL.user");
+ if(!mysql_user) {
+ perror("invalid neonserv.conf: missing MySQL.user");
+ return 0;
+ }
+ mysql_pass = get_string_field("MySQL.pass");
+ if(!mysql_pass) {
+ perror("invalid neonserv.conf: missing MySQL.pass");
+ return 0;
+ }
+ mysql_base = get_string_field("MySQL.base");
+ if(!mysql_base) {
+ perror("invalid neonserv.conf: missing MySQL base");
return 0;
}
init_mysql(mysql_host, mysql_serverport, mysql_user, mysql_pass, mysql_base);
#endif
+void exit_daemon() {
+ if(daemonized) {
+ remove(PID_FILE);
+ }
+}
+
int main(int argc, char *argv[]) {
-main:
+ int run_as_daemon = 1;
+ int argi;
process_argv = argv;
process_argc = argc;
+ printf("NeonServ v%s\n\n", NEONSERV_VERSION);
+ for(argi = 1; argi < argc; argi++) {
+ if(!strcmp(argv[argi], "-f") || !strcmp(argv[argi], "--foreground")) {
+ run_as_daemon = 0;
+ } else if(!strcmp(argv[argi], "-s") || !strcmp(argv[argi], "--show")) {
+ if(argi+1 == argc) break;
+ argi++;
+ print_loglevel = atoi(argv[argi]);
+ } else if(!strcmp(argv[argi], "-v") || !strcmp(argv[argi], "--version")) {
+ printf("Version: %s.%d (%s)\n", NEONSERV_VERSION, patchlevel, (strcmp(revision, "") ? revision : "-"));
+ printf("Build: #%s %s (%s lines, " COMPILER ")\n", compilation, creation, codelines);
+ exit(0);
+ } else if(!strcmp(argv[argi], "-h") || !strcmp(argv[argi], "--help")) {
+ printf("Usage: ./neonserv [-s loglevel] [-f] [-h|-v]\n");
+ printf(" -s, --show show log lines matching loglevel in stdout.\n");
+ printf(" -f, --foreground run NeonServ in the foreground.\n");
+ printf(" -h, --help prints this usage message.\n");
+ printf(" -v, --version prints this program's version.\n");
+ exit(0);
+ }
+ }
+ if(geteuid() == 0 || getuid() == 0) {
+ fprintf(stderr, "NeonServ may not be run with super user privileges.\n");
+ exit(0);
+ }
+ if(!loadConfig(CONF_FILE)) {
+ fprintf(stderr, "Unable to load " CONF_FILE "\n");
+ exit(0);
+ }
+ #if HAVE_THREADS
+ THREAD_MUTEX_INIT(log_sync);
+ #endif
+ if (run_as_daemon) {
+ /* Attempt to fork into the background if daemon mode is on. */
+ pid_t pid = fork();
+ if (pid < 0) {
+ fprintf(stderr, "Unable to fork: %s\n", strerror(errno));
+ } else if (pid > 0) {
+ printf("Forking into the background (pid: %d)...\n", pid);
+ putlog(LOGLEVEL_INFO, "Forking into the background (pid: %d)...\n", pid);
+ exit(0);
+ }
+ setsid();
+ daemonized = 1;
+ atexit(exit_daemon);
+ FILE *pidfile = fopen(PID_FILE, "w");
+ if (pidfile == NULL) {
+ fprintf(stderr, "Unable to create PID file: %s", strerror(errno));
+ putlog(LOGLEVEL_ERROR, "Unable to create PID file: %s", strerror(errno));
+ } else {
+ fprintf(pidfile, "%i\n", (int)getpid());
+ fclose(pidfile);
+ }
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+ }
+main:
signal(SIGABRT, sighandler);
signal(SIGFPE, sighandler);
signal(SIGILL, sighandler);
}
void reload_config() {
- loadConfig("neonserv.conf");
+ loadConfig(CONF_FILE);
}
static int getCurrentSecondsOfDay() {
system(command);
}
}
+
+void write_log(int loglevel, const char *line, int len) {
+ SYNCHRONIZE(log_sync);
+ if(!daemonized && (print_loglevel & loglevel)) {
+ printf("%s", line);
+ } else if(!daemonized && loglevel == LOGLEVEL_ERROR) {
+ fprintf(stderr, "%s", line);
+ }
+ if(get_int_field("log.loglevel") & loglevel) {
+ if(!log_fptr) {
+ log_fptr = fopen(LOG_FILE, "a");
+ if(!log_fptr) goto write_log_end;
+ }
+ time_t rawtime;
+ struct tm *timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ char timestr[20];
+ int timepos = strftime(timestr, 20, "%x %X ", timeinfo);
+ fwrite(timestr, 1, timepos, log_fptr);
+ fwrite(line, 1, len, log_fptr);
+ }
+ write_log_end:
+ DESYNCHRONIZE(log_sync);
+}
+
+void putlog(int loglevel, const char *text, ...) {
+ va_list arg_list;
+ char logBuf[MAXLOGLEN];
+ int pos;
+ logBuf[0] = '\0';
+ va_start(arg_list, text);
+ pos = vsnprintf(logBuf, MAXLOGLEN - 1, text, arg_list);
+ va_end(arg_list);
+ if (pos < 0 || pos > (MAXLOGLEN - 1)) pos = MAXLOGLEN - 1;
+ logBuf[pos] = '\0';
+ write_log(loglevel, logBuf, pos);
+}
+
#include "memoryDebug.h"
#endif
+#define PID_FILE "neonserv.pid"
+#define CONF_FILE "neonserv.conf"
+#define LOG_FILE "neonserv.log"
+
#define SOCKET_SELECT_TIME 1
#define SOCKET_RECONNECT_TIME 20
#define TOPICLEN 500
#define CHANNELLEN 200
#define MAXLEN 512
+#define MAXLOGLEN 1024
#define TRIGGERLEN 50
#define MAXNUMPARAMS 200 /* maximum number of parameters in one line */
#define MAXLANGUAGES 5
#define TEMPUSER_LIST_INDEX VALID_NICK_CHARS_FIRST_LEN
+#define LOGLEVEL_INFO 0x01
+#define LOGLEVEL_ERROR 0x02
+#define LOGLEVEL_RAW 0x04
+#define LOGLEVEL_MYSQL 0x08
+
#define timeval_is_bigger(x,y) ((x.tv_sec > y.tv_sec) || (x.tv_sec == y.tv_sec && x.tv_usec > y.tv_usec))
extern time_t start_time;
int getCurrentThreadID();
#endif
+void exit_daemon();
+
int stricmp (const char *s1, const char *s2);
int stricmplen (const char *s1, const char *s2, int len);
void statistics_update();
+void putlog(int loglevel, const char *text, ...) PRINTF_LIKE(2, 3);
+
+#define perror(errmsg) (putlog(LOGLEVEL_ERROR, "ERROR (%s:%d) %s", __FILE__, __LINE__, errmsg))
+
#endif
\ No newline at end of file