diff --git a/configure.ac b/configure.ac index 34a600a..5f0868e 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,14 @@ AM_INIT_AUTOMAKE([wMUD], [0.1.0]) AC_PROG_CC PKG_PROG_PKG_CONFIG +AC_CHECK_HEADERS([crypt.h]) +AC_SEARCH_LIBS([crypt], [crypt]) +AC_CHECK_FUNC([crypt], ac_have_crypt=yes, ac_have_crypt=no) +if test "$ac_have_crypt" != "yes"; then + echo "The crypt() function call can not be found." + exit 1 +fi + AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Enable debugging support (default: disabled)]), [enable_debug=yes; CFLAGS="$CFLAGS -g -Wall"], [enable_debug=no]) AM_CONDITIONAL([ENABLE_DEBUG], [test "$enable_debug" = "yes"]) if test "$enable_debug" = "yes"; then diff --git a/src/main.c b/src/main.c index f64993d..78078fe 100644 --- a/src/main.c +++ b/src/main.c @@ -1,14 +1,19 @@ -#include -#include #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include +#include +#ifdef HAVE_CRYPT_H +#include +#endif + #include "wmud_types.h" #include "main.h" #include "networking.h" #include "interpreter.h" #include "db.h" +#include "players.h" struct { char *file; @@ -48,6 +53,68 @@ rl_sec_elapsed(gpointer user_data) return TRUE; } +gchar * +wmud_random_string(gint len) +{ + gchar *ret = g_malloc0(len + 1); + gint i; + + for (i = 0; i < len; i++) + { + gchar c = 0; + /* Include only printable characters, but exclude $ because of + * salt generation */ + while (!g_ascii_isprint(c) || (c == '$')) + c = random_number(1, 127); + + ret[i] = c; + } + + return ret; +} + +void +wmud_maintenance_check_new_players(wmudPlayer *player, gpointer user_data) +{ + if (player->cpassword == NULL) + { + gchar *pw, + *salt, + *cpw; + GString *full_salt; + + pw = wmud_random_string(8); + salt = wmud_random_string(8); + full_salt = g_string_new("$1$"); + g_string_append(full_salt, salt); + cpw = g_strdup(crypt(pw, full_salt->str)); + + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Player %s has no" + " password set", player->player_name); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "New password will be %s", pw); + player->cpassword = cpw; + /* TODO: Send e-mail about the new password. Upon completion, + * set it in the database */ + + g_free(pw); + g_free(salt); + g_string_free(full_salt, TRUE); + } +} + +gboolean +wmud_maintenance(gpointer user_data) +{ + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Starting maintenance..."); + /* Run through the player list, and generate a random password for each + * newly registered player */ + g_slist_foreach(players, (GFunc)wmud_maintenance_check_new_players, NULL); + + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Finished maintenance..."); + + return TRUE; +} + #ifdef DEBUG void /* debug_context() @@ -164,6 +231,14 @@ game_thread_func(GMainLoop *game_loop) return NULL; } +gpointer +maint_thread_func(GMainLoop *maint_loop) +{ + g_main_loop_run(maint_loop); + + return NULL; +} + int main(int argc, char **argv) { @@ -171,7 +246,10 @@ main(int argc, char **argv) GSource *timeout_source; guint timeout_id; GError *err = NULL; - GThread *game_thread; + GThread *game_thread, + *maint_thread; + GMainContext *maint_context; + GMainLoop *maint_loop; /* Initialize the thread and type system */ g_thread_init(NULL); @@ -187,6 +265,10 @@ main(int argc, char **argv) game_context = g_main_context_new(); game_loop = g_main_loop_new(game_context, FALSE); + /* Create the maintenance context and main loop */ + maint_context = g_main_context_new(); + maint_loop = g_main_loop_new(maint_context, FALSE); + /* Create the timeout source which keeps track of elapsed real-world * time */ timeout_source = g_timeout_source_new(1000); @@ -194,6 +276,12 @@ main(int argc, char **argv) timeout_id = g_source_attach(timeout_source, game_context); g_source_unref(timeout_source); + /* Create the timeout source which will do the maintenance tasks */ + timeout_source = g_timeout_source_new_seconds(3); + g_source_set_callback(timeout_source, wmud_maintenance, NULL, NULL); + timeout_id = g_source_attach(timeout_source, maint_context); + g_source_unref(timeout_source); + /* TODO: Create signal handlers! */ if (!wmud_config_init(&err)) @@ -250,6 +338,9 @@ main(int argc, char **argv) g_clear_error(&err); game_thread = g_thread_create((GThreadFunc)game_thread_func, game_loop, TRUE, &err); + g_clear_error(&err); + maint_thread = g_thread_create((GThreadFunc)maint_thread_func, maint_loop, FALSE, &err); + /* Initialize other threads here */ g_thread_join(game_thread);