+static void close_dir_table(void)
+{
+ int ret;
+
+ if (!dir_table)
+ return;
+ ret = osl(osl_close_table(dir_table, OSL_MARK_CLEAN));
+ if (ret < 0)
+ ERROR_LOG("failed to close dir table: %s\n", adu_strerror(-ret));
+ free((char *)dir_table_desc.dir);
+ dir_table = NULL;
+}
+
+static void close_user_table(struct user_info *ui)
+{
+ int ret;
+
+ if (!ui || !ui_used(ui) || !ui_admissible(ui))
+ return;
+ ret = osl(osl_close_table(ui->table, OSL_MARK_CLEAN));
+ if (ret < 0)
+ ERROR_LOG("failed to close user table %u: %s\n",
+ (unsigned) ui->uid, adu_strerror(-ret));
+ free((char *)ui->desc->name);
+ ui->desc->name = NULL;
+ free((char *)ui->desc->dir);
+ ui->desc->dir = NULL;
+ free(ui->pw_name);
+ ui->pw_name = NULL;
+ free(ui->desc);
+ ui->desc = NULL;
+ ui->table = NULL;
+ ui->flags = 0;
+}
+
+static void close_user_tables(void)
+{
+ struct user_info *ui;
+
+ FOR_EACH_USER(ui)
+ close_user_table(ui);
+}
+
+static void close_all_tables(void)
+{
+ close_dir_table();
+ close_user_tables();
+ free_hash_table();
+}
+
+static int signum;
+
+static void signal_handler(int s)
+{
+ signum = s;
+}
+
+static void check_signals(void)
+{
+ if (likely(!signum))
+ return;
+ EMERG_LOG("caught signal %d\n", signum);
+ close_all_tables();
+ exit(EXIT_FAILURE);
+}
+
+static int init_signals(void)
+{
+ if (signal(SIGINT, &signal_handler) == SIG_ERR)
+ return -E_SIGNAL_SIG_ERR;
+ if (signal(SIGTERM, &signal_handler) == SIG_ERR)
+ return -E_SIGNAL_SIG_ERR;
+ return 1;
+}
+