From 48c9b8d2e31bd59745904f1bd9127b7383661080 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 2 Aug 2016 11:58:10 +1000 Subject: [PATCH] Config now loads at startup not connection, ability to run as a daemon --- bbs.c | 469 +++++++---------------------------------- bbs.h | 11 +- config_default/bbs.ini | 2 + main.c | 431 ++++++++++++++++++++++++++++++++++--- 4 files changed, 486 insertions(+), 427 deletions(-) diff --git a/bbs.c b/bbs.c index f826200..f46e277 100644 --- a/bbs.c +++ b/bbs.c @@ -10,14 +10,13 @@ #include #include #include -#include "inih/ini.h" -#include "bbs.h" +#include "bbs.h" #include "lua/lua.h" #include "lua/lualib.h" #include "lua/lauxlib.h" int mynode; -struct bbs_config conf; +struct bbs_config conf; struct user_record *gUser; int gSocket; @@ -32,13 +31,13 @@ void dolog(char *fmt, ...) { struct tm time_now; time_t timen; FILE *logfptr; - + if (conf.log_path == NULL) return; - + timen = time(NULL); - + localtime_r(&timen, &time_now); - + snprintf(buffer, 512, "%s/%04d%02d%02d.log", conf.log_path, time_now.tm_year + 1900, time_now.tm_mon + 1, time_now.tm_mday); logfptr = fopen(buffer, "a"); if (!logfptr) { @@ -49,9 +48,9 @@ void dolog(char *fmt, ...) { va_start(ap, fmt); vsnprintf(buffer, 512, fmt, ap); va_end(ap); - + fprintf(logfptr, "%02d:%02d:%02d [%s] %s\n", time_now.tm_hour, time_now.tm_min, time_now.tm_sec, ipaddress, buffer); - + fclose(logfptr); } @@ -59,12 +58,12 @@ struct fido_addr *parse_fido_addr(const char *str) { struct fido_addr *ret = (struct fido_addr *)malloc(sizeof(struct fido_addr)); int c; int state = 0; - + ret->zone = 0; ret->net = 0; ret->node = 0; ret->point = 0; - + for (c=0;ctimeleft--; - + if (gUser->timeleft <= 0) { s_putstring(gSocket, "\r\n\r\nSorry, you're out of time today..\r\n"); disconnect(gSocket, "Out of Time"); } - + - } + } if (timeoutpaused == 0) { usertimeout--; } if (usertimeout <= 0) { s_putstring(gSocket, "\r\n\r\nTimeout waiting for input..\r\n"); disconnect(gSocket, "Timeout"); - } + } } } -static int door_config_handler(void* user, const char* section, const char* name, - const char* value) -{ - struct bbs_config *conf = (struct bbs_config *)user; - int i; - - for (i=0;idoor_count;i++) { - if (strcasecmp(conf->doors[i]->name, section) == 0) { - // found it - if (strcasecmp(name, "key") == 0) { - conf->doors[i]->key = value[0]; - } else if (strcasecmp(name, "command") == 0) { - conf->doors[i]->command = strdup(value); - } else if (strcasecmp(name, "stdio") == 0) { - if (strcasecmp(value, "true") == 0) { - conf->doors[i]->stdio = 1; - } else { - conf->doors[i]->stdio = 0; - } - } - return 1; - } - } - - if (conf->door_count == 0) { - conf->doors = (struct door_config **)malloc(sizeof(struct door_config *)); - } else { - conf->doors = (struct door_config **)realloc(conf->doors, sizeof(struct door_config *) * (conf->door_count + 1)); - } - - conf->doors[conf->door_count] = (struct door_config *)malloc(sizeof(struct door_config)); - - conf->doors[conf->door_count]->name = strdup(section); - - if (strcasecmp(name, "key") == 0) { - conf->doors[conf->door_count]->key = value[0]; - } else if (strcasecmp(name, "command") == 0) { - conf->doors[conf->door_count]->command = strdup(value); - } else if (strcasecmp(name, "stdio") == 0) { - if (strcasecmp(value, "true") == 0) { - conf->doors[conf->door_count]->stdio = 1; - } else { - conf->doors[conf->door_count]->stdio = 0; - } - } - conf->door_count++; - - return 1; -} - -static int file_sub_handler(void* user, const char* section, const char* name, - const char* value) -{ - struct file_directory *fd = (struct file_directory *)user; - int i; - - if (strcasecmp(section, "main") == 0) { - if (strcasecmp(name, "visible sec level")) { - fd->sec_level = atoi(value); - } - } else { - // check if it's partially filled in - for (i=0;ifile_sub_count;i++) { - if (strcasecmp(fd->file_subs[i]->name, section) == 0) { - if (strcasecmp(name, "upload sec level") == 0) { - fd->file_subs[i]->upload_sec_level = atoi(value); - } else if (strcasecmp(name, "download sec level") == 0) { - fd->file_subs[i]->download_sec_level = atoi(value); - } else if (strcasecmp(name, "database") == 0) { - fd->file_subs[i]->database = strdup(value); - } else if (strcasecmp(name, "upload path") == 0) { - fd->file_subs[i]->upload_path = strdup(value); - } - return 1; - } - } - if (fd->file_sub_count == 0) { - fd->file_subs = (struct file_sub **)malloc(sizeof(struct file_sub *)); - } else { - fd->file_subs = (struct file_sub **)realloc(fd->file_subs, sizeof(struct file_sub *) * (fd->file_sub_count + 1)); - } - - fd->file_subs[fd->file_sub_count] = (struct file_sub *)malloc(sizeof(struct file_sub)); - - fd->file_subs[fd->file_sub_count]->name = strdup(section); - if (strcasecmp(name, "upload sec level") == 0) { - fd->file_subs[fd->file_sub_count]->upload_sec_level = atoi(value); - } else if (strcasecmp(name, "download sec level") == 0) { - fd->file_subs[fd->file_sub_count]->download_sec_level = atoi(value); - } else if (strcasecmp(name, "database") == 0) { - fd->file_subs[fd->file_sub_count]->database = strdup(value); - } else if (strcasecmp(name, "upload path") == 0) { - fd->file_subs[fd->file_sub_count]->upload_path = strdup(value); - } - fd->file_sub_count++; - } - return 1; -} - - -static int mail_area_handler(void* user, const char* section, const char* name, - const char* value) -{ - struct mail_conference *mc = (struct mail_conference *)user; - int i; - - if (strcasecmp(section, "main") == 0) { - if (strcasecmp(name, "visible sec level") == 0) { - mc->sec_level = atoi(value); - } else if (strcasecmp(name, "networked") == 0) { - if (strcasecmp(value, "true") == 0) { - mc->networked = 1; - } else { - mc->networked = 0; - } - } else if (strcasecmp(name, "real names") == 0) { - if (strcasecmp(value, "true") == 0) { - mc->realnames = 1; - } else { - mc->realnames = 0; - } - } else if (strcasecmp(name, "tagline") == 0) { - mc->tagline = strdup(value); - } - } else if (strcasecmp(section, "network") == 0) { - if (strcasecmp(name, "type") == 0) { - if (strcasecmp(value, "fido") == 0) { - mc->nettype = NETWORK_FIDO; - } else if (strcasecmp(value, "wwiv") == 0) { - mc->nettype = NETWORK_WWIV; - } - } else if (strcasecmp(name, "fido node") == 0) { - mc->fidoaddr = parse_fido_addr(value); - } else if (strcasecmp(name, "wwiv node") == 0) { - mc->wwivnode = atoi(value); - } - } else { - // check if it's partially filled in - for (i=0;imail_area_count;i++) { - if (strcasecmp(mc->mail_areas[i]->name, section) == 0) { - if (strcasecmp(name, "read sec level") == 0) { - mc->mail_areas[i]->read_sec_level = atoi(value); - } else if (strcasecmp(name, "write sec level") == 0) { - mc->mail_areas[i]->write_sec_level = atoi(value); - } else if (strcasecmp(name, "path") == 0) { - mc->mail_areas[i]->path = strdup(value); - } else if (strcasecmp(name, "type") == 0) { - if (strcasecmp(value, "local") == 0) { - mc->mail_areas[i]->type = TYPE_LOCAL_AREA; - } else if (strcasecmp(value, "echo") == 0) { - mc->mail_areas[i]->type = TYPE_ECHOMAIL_AREA; - } else if (strcasecmp(value, "netmail") == 0) { - mc->mail_areas[i]->type = TYPE_NETMAIL_AREA; - } - } - return 1; - } - } - if (mc->mail_area_count == 0) { - mc->mail_areas = (struct mail_area **)malloc(sizeof(struct mail_area *)); - } else { - mc->mail_areas = (struct mail_area **)realloc(mc->mail_areas, sizeof(struct mail_area *) * (mc->mail_area_count + 1)); - } - - mc->mail_areas[mc->mail_area_count] = (struct mail_area *)malloc(sizeof(struct mail_area)); - - mc->mail_areas[mc->mail_area_count]->name = strdup(section); - if (strcasecmp(name, "read sec level") == 0) { - mc->mail_areas[mc->mail_area_count]->read_sec_level = atoi(value); - } else if (strcasecmp(name, "write sec level") == 0) { - mc->mail_areas[mc->mail_area_count]->write_sec_level = atoi(value); - } else if (strcasecmp(name, "path") == 0) { - mc->mail_areas[mc->mail_area_count]->path = strdup(value); - } else if (strcasecmp(name, "type") == 0) { - if (strcasecmp(value, "local") == 0) { - mc->mail_areas[mc->mail_area_count]->type = TYPE_LOCAL_AREA; - } else if (strcasecmp(value, "echo") == 0) { - mc->mail_areas[mc->mail_area_count]->type = TYPE_ECHOMAIL_AREA; - } else if (strcasecmp(value, "netmail") == 0) { - mc->mail_areas[mc->mail_area_count]->type = TYPE_NETMAIL_AREA; - } - } - mc->mail_area_count++; - } - return 1; -} - -static int handler(void* user, const char* section, const char* name, - const char* value) -{ - struct bbs_config *conf = (struct bbs_config *)user; - - if (strcasecmp(section, "main") == 0) { - if (strcasecmp(name, "bbs name") == 0) { - conf->bbs_name = strdup(value); - } else if (strcasecmp(name, "sysop name") == 0) { - conf->sysop_name = strdup(value); - } else if (strcasecmp(name, "nodes") == 0) { - conf->nodes = atoi(value); - } else if (strcasecmp(name, "new user level") == 0) { - conf->newuserlvl = atoi(value); - } else if (strcasecmp(name, "irc server") == 0) { - conf->irc_server = strdup(value); - } else if (strcasecmp(name, "irc port") == 0) { - conf->irc_port = atoi(value); - } else if (strcasecmp(name, "irc channel") == 0) { - conf->irc_channel = strdup(value); - } else if (strcasecmp(name, "default tagline") == 0) { - conf->default_tagline = strdup(value); - } else if (strcasecmp(name, "external editor cmd") == 0) { - conf->external_editor_cmd = strdup(value); - } else if (strcasecmp(name, "external editor stdio") == 0) { - if (strcasecmp(value, "true") == 0) { - conf->external_editor_stdio = 1; - } else { - conf->external_editor_stdio = 0; - } - } else if (strcasecmp(name, "automessage write level") == 0) { - conf->automsgwritelvl = atoi(value); - } - } else if (strcasecmp(section, "paths") == 0){ - if (strcasecmp(name, "ansi path") == 0) { - conf->ansi_path = strdup(value); - } else if (strcasecmp(name, "bbs path") == 0) { - conf->bbs_path = strdup(value); - } else if (strcasecmp(name, "log path") == 0) { - conf->log_path = strdup(value); - } else if (strcasecmp(name, "script path") == 0) { - conf->script_path = strdup(value); - } else if (strcasecmp(name, "echomail semaphore") == 0) { - conf->echomail_sem = strdup(value); - } else if (strcasecmp(name, "netmail semaphore") == 0) { - conf->netmail_sem = strdup(value); - } - } else if (strcasecmp(section, "mail conferences") == 0) { - if (conf->mail_conference_count == 0) { - conf->mail_conferences = (struct mail_conference **)malloc(sizeof(struct mail_conference *)); - } else { - conf->mail_conferences = (struct mail_conference **)realloc(conf->mail_conferences, sizeof(struct mail_conference *) * (conf->mail_conference_count + 1)); - } - - conf->mail_conferences[conf->mail_conference_count] = (struct mail_conference *)malloc(sizeof(struct mail_conference)); - conf->mail_conferences[conf->mail_conference_count]->name = strdup(name); - conf->mail_conferences[conf->mail_conference_count]->path = strdup(value); - conf->mail_conferences[conf->mail_conference_count]->tagline = NULL; - conf->mail_conferences[conf->mail_conference_count]->mail_area_count = 0; - conf->mail_conferences[conf->mail_conference_count]->nettype = 0; - conf->mail_conference_count++; - } else if (strcasecmp(section, "file directories") == 0) { - if (conf->file_directory_count == 0) { - conf->file_directories = (struct file_directory **)malloc(sizeof(struct file_directory *)); - } else { - conf->file_directories = (struct file_directory **)realloc(conf->file_directories, sizeof(struct file_directory *) * (conf->file_directory_count + 1)); - } - - conf->file_directories[conf->file_directory_count] = (struct file_directory *)malloc(sizeof(struct file_directory)); - conf->file_directories[conf->file_directory_count]->name = strdup(name); - conf->file_directories[conf->file_directory_count]->path = strdup(value); - conf->file_directories[conf->file_directory_count]->file_sub_count = 0; - conf->file_directory_count++; - } else if (strcasecmp(section, "text files") == 0) { - if (conf->text_file_count == 0) { - conf->text_files = (struct text_file **)malloc(sizeof(struct text_file *)); - } else { - conf->text_files = (struct text_file **)realloc(conf->text_files, sizeof(struct text_file *) * (conf->text_file_count + 1)); - } - - conf->text_files[conf->text_file_count] = (struct text_file *)malloc(sizeof(struct text_file)); - conf->text_files[conf->text_file_count]->name = strdup(name); - conf->text_files[conf->text_file_count]->path = strdup(value); - conf->text_file_count++; - - } - - return 1; -} - + void s_putchar(int socket, char c) { write(socket, &c, 1); } @@ -421,7 +144,7 @@ void s_putstring(int socket, char *c) { void s_displayansi_p(int socket, char *file) { FILE *fptr; char c; - + fptr = fopen(file, "r"); if (!fptr) { return; @@ -438,11 +161,11 @@ void s_displayansi_p(int socket, char *file) { void s_displayansi(int socket, char *file) { FILE *fptr; char c; - + char buffer[256]; - + sprintf(buffer, "%s/%s.ans", conf.ansi_path, file); - + fptr = fopen(buffer, "r"); if (!fptr) { return; @@ -466,7 +189,7 @@ char s_getchar(int socket) { if (len == 0) { disconnect(socket, "Socket Closed"); } - + while (c == 255) { len = read(socket, &c, 1); if (len == 0) { @@ -482,11 +205,11 @@ char s_getchar(int socket) { len = read(socket, &c, 1); if (len == 0) { disconnect(socket, "Socket Closed"); - } + } } - + if (c == '\r') { if (len == 0) { disconnect(socket, "Socket Closed"); @@ -507,9 +230,9 @@ char s_getc(int socket) { void s_readstring(int socket, char *buffer, int max) { int i; char c; - + memset(buffer, 0, max); - + for (i=0;i 0) { @@ -518,7 +241,7 @@ void s_readstring(int socket, char *buffer, int max) { s_putstring(socket, "\e[D \e[D"); continue; } - + if (c == '\n' || c == '\r') { return; } @@ -531,7 +254,7 @@ void s_readstring(int socket, char *buffer, int max) { void s_readpass(int socket, char *buffer, int max) { int i; char c; - + for (i=0;iloginname) != 0 ) { memset(&new_entry, 0, sizeof(struct last10_callers)); strcpy(new_entry.name, user->loginname); strcpy(new_entry.location, user->location); new_entry.time = time(NULL); - + if (i == 10) { j = 1; } else { @@ -610,23 +333,23 @@ void display_last10_callers(int socket, struct user_record *user) { char buffer[256]; struct tm l10_time; FILE *fptr = fopen("last10.dat", "rb"); - + s_putstring(socket, "\r\n\e[1;37mLast 10 callers:\r\n"); s_putstring(socket, "\e[1;30m-------------------------------------------------------------------------------\r\n"); - + if (fptr != NULL) { - + for (i=0;i<10;i++) { if (fread(&callers[i], sizeof(struct last10_callers), 1, fptr) < 1) { break; } } - + fclose(fptr); } else { i = 0; } - + for (z=0;zsec_level >= conf.automsgwritelvl) { timen = time(NULL); localtime_r(&timen, &timenow); - + sprintf(automsg, "Automessage Posted by %s @ %s", user->loginname, asctime(&timenow)); - + automsg[strlen(automsg) - 1] = '\r'; automsg[strlen(automsg)] = '\n'; s_putstring(socket, "\r\nEnter your message (4 lines):\r\n"); @@ -693,7 +416,7 @@ void automessage_write(int socket, struct user_record *user) { strcat(automsg, buffer); strcat(automsg, "\r\n"); } - + fptr = fopen("automessage.txt", "w"); if (fptr) { fwrite(automsg, strlen(automsg), 1, fptr); @@ -701,7 +424,7 @@ void automessage_write(int socket, struct user_record *user) { } else { printf("Unable to open automessage.txt for writing\n"); } - } + } } void automessage_display(int socket) { @@ -718,21 +441,21 @@ void automessage_display(int socket) { fgets(buffer, 88, fptr); buffer[strlen(buffer) - 1] = '\r'; buffer[strlen(buffer)] = '\n'; - + s_putstring(socket, buffer); } fclose(fptr); } else { printf("Error opening automessage.txt\n"); - } + } } else { s_putstring(socket, "No automessage!\r\n"); } s_putstring(socket, "\e[0mPress any key to continue...\r\n"); - s_getc(socket); + s_getc(socket); } -void runbbs(int socket, char *config_path, char *ip) { +void runbbs(int socket, char *ip) { char buffer[256]; char password[17]; @@ -749,9 +472,9 @@ void runbbs(int socket, char *config_path, char *ip) { struct sigaction sa; lua_State *L; int do_internal_login = 0; - + ipaddress = ip; - + write(socket, iac_echo, 3); write(socket, iac_sga, 3); @@ -760,45 +483,7 @@ void runbbs(int socket, char *config_path, char *ip) { sprintf(buffer, "Magicka BBS v%d.%d (%s), Loading...\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_STR); s_putstring(socket, buffer); - conf.mail_conference_count = 0; - conf.door_count = 0; - conf.file_directory_count = 0; - conf.irc_server = NULL; - conf.irc_port = 6667; - conf.text_file_count = 0; - conf.external_editor_cmd = NULL; - conf.log_path = NULL; - conf.script_path = NULL; - conf.automsgwritelvl = 10; - conf.echomail_sem = NULL; - conf.netmail_sem = NULL; - - // Load BBS data - if (ini_parse(config_path, handler, &conf) <0) { - printf("Unable to load configuration ini (%s)!\n", config_path); - exit(-1); - } - // Load mail Areas - for (i=0;ipath, mail_area_handler, conf.mail_conferences[i]) <0) { - printf("Unable to load configuration ini (%s)!\n", conf.mail_conferences[i]->path); - exit(-1); - } - } - // Load file Subs - for (i=0;ipath, file_sub_handler, conf.file_directories[i]) <0) { - printf("Unable to load configuration ini (%s)!\n", conf.file_directories[i]->path); - exit(-1); - } - } - - if (ini_parse("config/doors.ini", door_config_handler, &conf) <0) { - printf("Unable to load configuration ini (doors.ini)!\n"); - exit(-1); - } - - // find out which node we are + // find out which node we are mynode = 0; for (i=1;i<=conf.nodes;i++) { sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i); @@ -810,14 +495,14 @@ void runbbs(int socket, char *config_path, char *ip) { close(socket); exit(1); } - + fputs("UNKNOWN", nodefile); fclose(nodefile); - + break; } } - + if (mynode == 0) { s_putstring(socket, "Sorry, all nodes are in use. Please try later\r\n"); close(socket); @@ -827,24 +512,24 @@ void runbbs(int socket, char *config_path, char *ip) { gSocket = socket; usertimeout = 10; timeoutpaused = 0; - + memset (&sa, 0, sizeof (sa)); sa.sa_handler = &timer_handler; sa.sa_flags = SA_RESTART; sigaction (SIGALRM, &sa, 0); - + itime.it_interval.tv_sec = 60; itime.it_interval.tv_usec = 0; itime.it_value.tv_sec = 60; itime.it_value.tv_usec = 0; - + setitimer (ITIMER_REAL, &itime, 0); - + s_displayansi(socket, "issue"); - + s_putstring(socket, "\e[0mEnter your Login Name or NEW to create an account\r\n"); s_putstring(socket, "Login:> "); - + s_readstring(socket, buffer, 25); if (strcasecmp(buffer, "new") == 0) { @@ -857,7 +542,7 @@ void runbbs(int socket, char *config_path, char *ip) { s_putstring(socket, "\r\nIncorrect Login.\r\n"); disconnect(socket, "Incorrect Login"); } - + for (i=1;i<=conf.nodes;i++) { sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i); if (stat(buffer, &s) == 0) { @@ -867,17 +552,17 @@ void runbbs(int socket, char *config_path, char *ip) { disconnect(socket, "Error opening nodefile!"); } fgets(buffer, 256, nodefile); - + if (strcasecmp(user->loginname, buffer) == 0) { fclose(nodefile); s_putstring(socket, "\r\nYou are already logged in.\r\n"); disconnect(socket, "Already Logged in"); - } + } fclose(nodefile); } } } - + sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode); nodefile = fopen(buffer, "w"); if (!nodefile) { @@ -885,24 +570,24 @@ void runbbs(int socket, char *config_path, char *ip) { close(socket); exit(1); } - + fputs(user->loginname, nodefile); - fclose(nodefile); - - - + fclose(nodefile); + + + // do post-login dolog("%s logged in, on node %d", user->loginname, mynode); // check time left now = time(NULL); localtime_r(&now, &thetime); localtime_r(&user->laston, &oldtime); - + if (thetime.tm_mday != oldtime.tm_mday || thetime.tm_mon != oldtime.tm_mon || thetime.tm_year != oldtime.tm_year) { user->timeleft = user->sec_info->timeperday; user->laston = now; save_user(user); - } + } gUser = user; user->timeson++; @@ -927,7 +612,7 @@ void runbbs(int socket, char *config_path, char *ip) { // bulletins i = 0; sprintf(buffer, "%s/bulletin%d.ans", conf.ansi_path, i); - + while (stat(buffer, &s) == 0) { sprintf(buffer, "bulletin%d", i); s_displayansi(socket, buffer); @@ -937,14 +622,14 @@ void runbbs(int socket, char *config_path, char *ip) { i++; sprintf(buffer, "%s/bulletin%d.ans", conf.ansi_path, i); } - + // external login cmd - + // display info display_info(socket); - + display_last10_callers(socket, user); - + // check email i = mail_getemailcount(user); if (i > 0) { @@ -953,15 +638,15 @@ void runbbs(int socket, char *config_path, char *ip) { } else { s_putstring(socket, "\r\nYou have no e-mail.\r\n"); } - + mail_scan(socket, user); - + automessage_display(socket); } record_last10_callers(user); // main menu main_menu(socket, user); - + s_displayansi(socket, "goodbye"); dolog("%s is logging out, on node %d", user->loginname, mynode); disconnect(socket, "Log out"); diff --git a/bbs.h b/bbs.h index ef95312..4cb7b28 100644 --- a/bbs.h +++ b/bbs.h @@ -82,7 +82,7 @@ struct file_directory { struct bbs_config { char *bbs_name; char *sysop_name; - + char *pid_file; char *ansi_path; char *bbs_path; char *log_path; @@ -90,14 +90,15 @@ struct bbs_config { char *echomail_sem; char *netmail_sem; char *default_tagline; - + char *irc_server; int irc_port; char *irc_channel; - + char *external_editor_cmd; int external_editor_stdio; - + int fork; + int nodes; int newuserlvl; int automsgwritelvl; @@ -137,7 +138,7 @@ struct user_record { extern void automessage_write(int socket, struct user_record *user); extern void automessage_display(int socket); extern void dolog(char *fmt, ...); -extern void runbbs(int sock, char *config, char *ipaddress); +extern void runbbs(int sock, char *ipaddress); extern struct fido_addr *parse_fido_addr(const char *str); extern void s_putchar(int socket, char c); extern void s_putstring(int socket, char *c); diff --git a/config_default/bbs.ini b/config_default/bbs.ini index 3a4c4e3..17fc636 100644 --- a/config_default/bbs.ini +++ b/config_default/bbs.ini @@ -10,8 +10,10 @@ Default Tagline = Brought to you by Another Magicka BBS! External Editor cmd = /home/andrew/MagickaBBS/doors/oedit.sh External Editor stdio = false Automessage Write Level = 10 +Fork = false [paths] +PID File = /home/andrew/MagickaBBS/magicka.pid ANSI Path = /home/andrew/MagickaBBS/ansis BBS Path = /home/andrew/MagickaBBS Log Path = /home/andrew/MagickaBBS/logs diff --git a/main.c b/main.c index b57b306..5ef88d0 100644 --- a/main.c +++ b/main.c @@ -11,6 +11,15 @@ #include #include #include "bbs.h" +#include "inih/ini.h" + +extern struct bbs_config conf; + +void sigterm_handler(int s) +{ + remove(conf.pid_file); + exit(0); +} void sigchld_handler(int s) { @@ -23,68 +32,430 @@ void sigchld_handler(int s) } -int main(int argc, char **argv) { +static int door_config_handler(void* user, const char* section, const char* name, + const char* value) +{ + struct bbs_config *conf = (struct bbs_config *)user; + int i; + + for (i=0;idoor_count;i++) { + if (strcasecmp(conf->doors[i]->name, section) == 0) { + // found it + if (strcasecmp(name, "key") == 0) { + conf->doors[i]->key = value[0]; + } else if (strcasecmp(name, "command") == 0) { + conf->doors[i]->command = strdup(value); + } else if (strcasecmp(name, "stdio") == 0) { + if (strcasecmp(value, "true") == 0) { + conf->doors[i]->stdio = 1; + } else { + conf->doors[i]->stdio = 0; + } + } + return 1; + } + } + + if (conf->door_count == 0) { + conf->doors = (struct door_config **)malloc(sizeof(struct door_config *)); + } else { + conf->doors = (struct door_config **)realloc(conf->doors, sizeof(struct door_config *) * (conf->door_count + 1)); + } + + conf->doors[conf->door_count] = (struct door_config *)malloc(sizeof(struct door_config)); + + conf->doors[conf->door_count]->name = strdup(section); + + if (strcasecmp(name, "key") == 0) { + conf->doors[conf->door_count]->key = value[0]; + } else if (strcasecmp(name, "command") == 0) { + conf->doors[conf->door_count]->command = strdup(value); + } else if (strcasecmp(name, "stdio") == 0) { + if (strcasecmp(value, "true") == 0) { + conf->doors[conf->door_count]->stdio = 1; + } else { + conf->doors[conf->door_count]->stdio = 0; + } + } + conf->door_count++; + + return 1; +} + +static int file_sub_handler(void* user, const char* section, const char* name, + const char* value) +{ + struct file_directory *fd = (struct file_directory *)user; + int i; + + if (strcasecmp(section, "main") == 0) { + if (strcasecmp(name, "visible sec level")) { + fd->sec_level = atoi(value); + } + } else { + // check if it's partially filled in + for (i=0;ifile_sub_count;i++) { + if (strcasecmp(fd->file_subs[i]->name, section) == 0) { + if (strcasecmp(name, "upload sec level") == 0) { + fd->file_subs[i]->upload_sec_level = atoi(value); + } else if (strcasecmp(name, "download sec level") == 0) { + fd->file_subs[i]->download_sec_level = atoi(value); + } else if (strcasecmp(name, "database") == 0) { + fd->file_subs[i]->database = strdup(value); + } else if (strcasecmp(name, "upload path") == 0) { + fd->file_subs[i]->upload_path = strdup(value); + } + return 1; + } + } + if (fd->file_sub_count == 0) { + fd->file_subs = (struct file_sub **)malloc(sizeof(struct file_sub *)); + } else { + fd->file_subs = (struct file_sub **)realloc(fd->file_subs, sizeof(struct file_sub *) * (fd->file_sub_count + 1)); + } + + fd->file_subs[fd->file_sub_count] = (struct file_sub *)malloc(sizeof(struct file_sub)); + + fd->file_subs[fd->file_sub_count]->name = strdup(section); + if (strcasecmp(name, "upload sec level") == 0) { + fd->file_subs[fd->file_sub_count]->upload_sec_level = atoi(value); + } else if (strcasecmp(name, "download sec level") == 0) { + fd->file_subs[fd->file_sub_count]->download_sec_level = atoi(value); + } else if (strcasecmp(name, "database") == 0) { + fd->file_subs[fd->file_sub_count]->database = strdup(value); + } else if (strcasecmp(name, "upload path") == 0) { + fd->file_subs[fd->file_sub_count]->upload_path = strdup(value); + } + fd->file_sub_count++; + } + return 1; +} + + +static int mail_area_handler(void* user, const char* section, const char* name, + const char* value) +{ + struct mail_conference *mc = (struct mail_conference *)user; + int i; + + if (strcasecmp(section, "main") == 0) { + if (strcasecmp(name, "visible sec level") == 0) { + mc->sec_level = atoi(value); + } else if (strcasecmp(name, "networked") == 0) { + if (strcasecmp(value, "true") == 0) { + mc->networked = 1; + } else { + mc->networked = 0; + } + } else if (strcasecmp(name, "real names") == 0) { + if (strcasecmp(value, "true") == 0) { + mc->realnames = 1; + } else { + mc->realnames = 0; + } + } else if (strcasecmp(name, "tagline") == 0) { + mc->tagline = strdup(value); + } + } else if (strcasecmp(section, "network") == 0) { + if (strcasecmp(name, "type") == 0) { + if (strcasecmp(value, "fido") == 0) { + mc->nettype = NETWORK_FIDO; + } else if (strcasecmp(value, "wwiv") == 0) { + mc->nettype = NETWORK_WWIV; + } + } else if (strcasecmp(name, "fido node") == 0) { + mc->fidoaddr = parse_fido_addr(value); + } else if (strcasecmp(name, "wwiv node") == 0) { + mc->wwivnode = atoi(value); + } + } else { + // check if it's partially filled in + for (i=0;imail_area_count;i++) { + if (strcasecmp(mc->mail_areas[i]->name, section) == 0) { + if (strcasecmp(name, "read sec level") == 0) { + mc->mail_areas[i]->read_sec_level = atoi(value); + } else if (strcasecmp(name, "write sec level") == 0) { + mc->mail_areas[i]->write_sec_level = atoi(value); + } else if (strcasecmp(name, "path") == 0) { + mc->mail_areas[i]->path = strdup(value); + } else if (strcasecmp(name, "type") == 0) { + if (strcasecmp(value, "local") == 0) { + mc->mail_areas[i]->type = TYPE_LOCAL_AREA; + } else if (strcasecmp(value, "echo") == 0) { + mc->mail_areas[i]->type = TYPE_ECHOMAIL_AREA; + } else if (strcasecmp(value, "netmail") == 0) { + mc->mail_areas[i]->type = TYPE_NETMAIL_AREA; + } + } + return 1; + } + } + if (mc->mail_area_count == 0) { + mc->mail_areas = (struct mail_area **)malloc(sizeof(struct mail_area *)); + } else { + mc->mail_areas = (struct mail_area **)realloc(mc->mail_areas, sizeof(struct mail_area *) * (mc->mail_area_count + 1)); + } + + mc->mail_areas[mc->mail_area_count] = (struct mail_area *)malloc(sizeof(struct mail_area)); + + mc->mail_areas[mc->mail_area_count]->name = strdup(section); + if (strcasecmp(name, "read sec level") == 0) { + mc->mail_areas[mc->mail_area_count]->read_sec_level = atoi(value); + } else if (strcasecmp(name, "write sec level") == 0) { + mc->mail_areas[mc->mail_area_count]->write_sec_level = atoi(value); + } else if (strcasecmp(name, "path") == 0) { + mc->mail_areas[mc->mail_area_count]->path = strdup(value); + } else if (strcasecmp(name, "type") == 0) { + if (strcasecmp(value, "local") == 0) { + mc->mail_areas[mc->mail_area_count]->type = TYPE_LOCAL_AREA; + } else if (strcasecmp(value, "echo") == 0) { + mc->mail_areas[mc->mail_area_count]->type = TYPE_ECHOMAIL_AREA; + } else if (strcasecmp(value, "netmail") == 0) { + mc->mail_areas[mc->mail_area_count]->type = TYPE_NETMAIL_AREA; + } + } + mc->mail_area_count++; + } + return 1; +} + +static int handler(void* user, const char* section, const char* name, + const char* value) +{ + struct bbs_config *conf = (struct bbs_config *)user; + + if (strcasecmp(section, "main") == 0) { + if (strcasecmp(name, "bbs name") == 0) { + conf->bbs_name = strdup(value); + } else if (strcasecmp(name, "sysop name") == 0) { + conf->sysop_name = strdup(value); + } else if (strcasecmp(name, "nodes") == 0) { + conf->nodes = atoi(value); + } else if (strcasecmp(name, "new user level") == 0) { + conf->newuserlvl = atoi(value); + } else if (strcasecmp(name, "irc server") == 0) { + conf->irc_server = strdup(value); + } else if (strcasecmp(name, "irc port") == 0) { + conf->irc_port = atoi(value); + } else if (strcasecmp(name, "irc channel") == 0) { + conf->irc_channel = strdup(value); + } else if (strcasecmp(name, "default tagline") == 0) { + conf->default_tagline = strdup(value); + } else if (strcasecmp(name, "external editor cmd") == 0) { + conf->external_editor_cmd = strdup(value); + } else if (strcasecmp(name, "external editor stdio") == 0) { + if (strcasecmp(value, "true") == 0) { + conf->external_editor_stdio = 1; + } else { + conf->external_editor_stdio = 0; + } + } else if (strcasecmp(name, "automessage write level") == 0) { + conf->automsgwritelvl = atoi(value); + } else if (strcasecmp(name, "fork") == 0) { + if (strcasecmp(value, "true") == 0) { + conf->fork = 1; + } else { + conf->fork = 0; + } + } + } else if (strcasecmp(section, "paths") == 0){ + if (strcasecmp(name, "ansi path") == 0) { + conf->ansi_path = strdup(value); + } else if (strcasecmp(name, "bbs path") == 0) { + conf->bbs_path = strdup(value); + } else if (strcasecmp(name, "log path") == 0) { + conf->log_path = strdup(value); + } else if (strcasecmp(name, "script path") == 0) { + conf->script_path = strdup(value); + } else if (strcasecmp(name, "echomail semaphore") == 0) { + conf->echomail_sem = strdup(value); + } else if (strcasecmp(name, "netmail semaphore") == 0) { + conf->netmail_sem = strdup(value); + } else if (strcasecmp(name, "pid file") == 0) { + conf->pid_file = strdup(value); + } + } else if (strcasecmp(section, "mail conferences") == 0) { + if (conf->mail_conference_count == 0) { + conf->mail_conferences = (struct mail_conference **)malloc(sizeof(struct mail_conference *)); + } else { + conf->mail_conferences = (struct mail_conference **)realloc(conf->mail_conferences, sizeof(struct mail_conference *) * (conf->mail_conference_count + 1)); + } + + conf->mail_conferences[conf->mail_conference_count] = (struct mail_conference *)malloc(sizeof(struct mail_conference)); + conf->mail_conferences[conf->mail_conference_count]->name = strdup(name); + conf->mail_conferences[conf->mail_conference_count]->path = strdup(value); + conf->mail_conferences[conf->mail_conference_count]->tagline = NULL; + conf->mail_conferences[conf->mail_conference_count]->mail_area_count = 0; + conf->mail_conferences[conf->mail_conference_count]->nettype = 0; + conf->mail_conference_count++; + } else if (strcasecmp(section, "file directories") == 0) { + if (conf->file_directory_count == 0) { + conf->file_directories = (struct file_directory **)malloc(sizeof(struct file_directory *)); + } else { + conf->file_directories = (struct file_directory **)realloc(conf->file_directories, sizeof(struct file_directory *) * (conf->file_directory_count + 1)); + } + + conf->file_directories[conf->file_directory_count] = (struct file_directory *)malloc(sizeof(struct file_directory)); + conf->file_directories[conf->file_directory_count]->name = strdup(name); + conf->file_directories[conf->file_directory_count]->path = strdup(value); + conf->file_directories[conf->file_directory_count]->file_sub_count = 0; + conf->file_directory_count++; + } else if (strcasecmp(section, "text files") == 0) { + if (conf->text_file_count == 0) { + conf->text_files = (struct text_file **)malloc(sizeof(struct text_file *)); + } else { + conf->text_files = (struct text_file **)realloc(conf->text_files, sizeof(struct text_file *) * (conf->text_file_count + 1)); + } + + conf->text_files[conf->text_file_count] = (struct text_file *)malloc(sizeof(struct text_file)); + conf->text_files[conf->text_file_count]->name = strdup(name); + conf->text_files[conf->text_file_count]->path = strdup(value); + conf->text_file_count++; + + } + + return 1; +} + +void server(int port) { + struct sigaction sa; + struct sigaction st; int socket_desc, client_sock, c, *new_sock; int pid; struct sockaddr_in server, client; - int port; - struct sigaction sa; - - if (argc < 3) { - printf("Usage ./magicka config/bbs.ini port\n"); - exit(1); - } - + sa.sa_handler = sigchld_handler; // reap all dead processes - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction(SIGCHLD, &sa, NULL) == -1) { - perror("sigaction"); - exit(1); - } - + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } + + st.sa_handler = sigterm_handler; + sigemptyset(&st.sa_mask); + if (sigaction(SIGTERM, &st, NULL) == -1) { + perror("sigaction"); + exit(1); + } + socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Couldn't create socket..\n"); - return 1; + exit(1); } - port = atoi(argv[2]); - + + server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(port); - + if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { perror("Bind Failed, Error\n"); - return 1; + exit(1); } - + listen(socket_desc, 3); - + c = sizeof(struct sockaddr_in); - + while ((client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) { if (client_sock == -1) { - if (errno == EINTR) { + if (errno == EINTR) { continue; } else { exit(-1); } } pid = fork(); - + if (pid < 0) { perror("Error on fork\n"); - return 1; + exit(1); } - + if (pid == 0) { close(socket_desc); - runbbs(client_sock, argv[1], strdup(inet_ntoa(client.sin_addr))); - + runbbs(client_sock, strdup(inet_ntoa(client.sin_addr))); + exit(0); } else { close(client_sock); } } } + +int main(int argc, char **argv) { + int port; + + int i; + int main_pid; + FILE *fptr; + + if (argc < 3) { + printf("Usage ./magicka config/bbs.ini port\n"); + exit(1); + } + + conf.mail_conference_count = 0; + conf.door_count = 0; + conf.file_directory_count = 0; + conf.irc_server = NULL; + conf.irc_port = 6667; + conf.text_file_count = 0; + conf.external_editor_cmd = NULL; + conf.log_path = NULL; + conf.script_path = NULL; + conf.automsgwritelvl = 10; + conf.echomail_sem = NULL; + conf.netmail_sem = NULL; + + // Load BBS data + if (ini_parse(argv[1], handler, &conf) <0) { + printf("Unable to load configuration ini (%s)!\n", argv[1]); + exit(-1); + } + // Load mail Areas + for (i=0;ipath, mail_area_handler, conf.mail_conferences[i]) <0) { + printf("Unable to load configuration ini (%s)!\n", conf.mail_conferences[i]->path); + exit(-1); + } + } + // Load file Subs + for (i=0;ipath, file_sub_handler, conf.file_directories[i]) <0) { + printf("Unable to load configuration ini (%s)!\n", conf.file_directories[i]->path); + exit(-1); + } + } + + if (ini_parse("config/doors.ini", door_config_handler, &conf) <0) { + printf("Unable to load configuration ini (doors.ini)!\n"); + exit(-1); + } + + port = atoi(argv[2]); + + if (conf.fork) { + main_pid = fork(); + + if (main_pid < 0) { + fprintf(stderr, "Error forking.\n"); + exit(-1); + } else + if (main_pid > 0) { + fptr = fopen(conf.pid_file, "w"); + if (!fptr) { + fprintf(stderr, "Unable to open pid file for writing.\n"); + } else { + fprintf(fptr, "%d", main_pid); + fclose(fptr); + } + } else { + server(port); + } + } else { + server(port); + } +}