From 7ba93e4d9e3e722d8771d665c5217510105375d2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 31 Jan 2018 22:03:27 +0100
Subject: Avoided to pollute the configuration directory with old UNIX family
 sockets.

---
 ChangeLog                |  6 +++
 src/analysis/db/server.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/main.c               |  6 +++
 3 files changed, 103 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1b59d2b..7995646 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 18-01-31  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/db/server.c:
+	* src/main.c:
+	Avoid to pollute the configuration directory with old UNIX family sockets.
+
+18-01-31  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/mangling/dex/shorty_tok.l:
 	* src/mangling/dex/type_tok.l:
 	Fix a mistake in the previous commit.
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index 219b8b6..bbc7415 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -35,6 +35,9 @@
 #include <sys/un.h>
 
 
+#include <i18n.h>
+
+
 #include "cdb.h"
 #include "keymgn.h"
 #include "protocol.h"
@@ -66,6 +69,11 @@ typedef union _gen_sockaddr_t
 #   define UNIX_PATH_MAX 108
 #endif
 
+
+/* Assure que le point de connexion est vierge. */
+typedef bool (* clean_server_socket_cb) (GDbServer *);
+
+
 /* Description de serveur à l'écoute (instance) */
 struct _GDbServer
 {
@@ -80,6 +88,8 @@ struct _GDbServer
     socklen_t sock_len;                     /* Taille de cette adresse     */
     char *desc;                             /* Désignation du serveur      */
 
+    clean_server_socket_cb clean_socket;    /* Procédure de nettoyage ?    */
+
     char *basedir;                          /* Répertoire de stockage      */
 
     GThread *listener;                      /* Procédure de traitement     */
@@ -106,6 +116,9 @@ static void g_db_server_init(GDbServer *);
 /* Procède à la libération totale de la mémoire. */
 static void g_db_server_finalize(GDbServer *);
 
+/* Assure que le point de connexion est vierge. */
+static bool g_db_server_clean_internal_socket(GDbServer *);
+
 /* Supprime toute trace d'utilisateur inscrit. */
 static void g_db_server_unregister_all_user(GDbServer *);
 
@@ -207,16 +220,17 @@ static void g_db_server_finalize(GDbServer *server)
 GDbServer *g_db_server_new_internal(const char *author, char *kfile)
 {
     GDbServer *result;                      /* Adresse à retourner         */
-    bool ret;                               /* Bilan d'un appel            */
+    bool status;                            /* Bilan d'un chargement       */
     char *suffix;                           /* Suffixe pour un fichier     */
+    size_t sock_length;                     /* Taille du chemin complet    */
     char *sock_path;                        /* Chemin vers le canal UNIX   */
 
     result = g_object_new(G_TYPE_DB_SERVER, NULL);
 
     /* Chargement du profil */
 
-    ret = g_db_server_register_user(result, author, kfile);
-    if (!ret) goto gdsni_error;
+    status = g_db_server_register_user(result, author, kfile);
+    if (!status) goto gdsni_error;
 
     /* Détermination du point d'écoute */
 
@@ -226,6 +240,17 @@ GDbServer *g_db_server_new_internal(const char *author, char *kfile)
     sock_path = get_xdg_config_dir(suffix);
     free(suffix);
 
+    sock_length = strlen(sock_path) + 1;
+
+    if (sock_length > UNIX_PATH_MAX)
+    {
+        log_variadic_message(LMT_ERROR,
+                             _("Impossible to use '%s' for the internal server: path is too long ! (%zu vs %u)\n"),
+                             sock_path, sock_length, UNIX_PATH_MAX);
+
+        goto gdsni_too_long;
+    }
+
     memset(&result->addr, 0, sizeof(struct sockaddr_un));
 
     result->addr.unix_addr.sun_family = AF_UNIX;
@@ -239,12 +264,20 @@ GDbServer *g_db_server_new_internal(const char *author, char *kfile)
 
     asprintf(&result->desc, "unix://.internal_server.%d", getpid());
 
+    /* Aide pour une sortie propre ? */
+
+    result->clean_socket = g_db_server_clean_internal_socket;
+
     /* Répertoire de stockage */
 
     result->basedir = get_xdg_config_dir("chrysalide" G_DIR_SEPARATOR_S "cdbs");
 
     return result;
 
+ gdsni_too_long:
+
+    free(sock_path);
+
  gdsni_error:
 
     g_object_unref(G_OBJECT(result));
@@ -256,6 +289,47 @@ GDbServer *g_db_server_new_internal(const char *author, char *kfile)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : server = instance à consulter et préparer.                   *
+*                                                                             *
+*  Description : Assure que le point de connexion est vierge.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_server_clean_internal_socket(GDbServer *server)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    char *sock_path;                        /* Chemin vers le canal UNIX   */
+    int ret;                                /* Bilan d'un appel            */
+
+    result = true;
+
+    sock_path = server->addr.unix_addr.sun_path;
+
+    ret = access(sock_path, F_OK);
+
+    if (ret == 0)
+    {
+        ret = unlink(sock_path);
+
+        if (ret != 0)
+        {
+            perror("unlink");
+            result = false;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : conf = fichier de configuration à interpréter.               *
 *                                                                             *
 *  Description : Prépare un serveur de BD pour les clients distants.          *
@@ -324,6 +398,10 @@ GDbServer *g_db_server_new_remote(const char *conf)
 
     snprintf(result->desc + strlen(ip), 1 + 5, ":%hu", port);
 
+    /* Aide pour une sortie propre ? */
+
+    result->clean_socket = NULL;
+
     /* Répertoire de stockage */
 
 
@@ -738,6 +816,7 @@ static void *g_db_server_listener(GDbServer *server)
 bool g_db_server_start(GDbServer *server)
 {
     int ret;                                /* Bilan d'un appel            */
+    bool status;                            /* Bilan d'un nettoyage        */
     int backlog;                            /* Nombre de connexions maximal*/
 
     server->fd = socket(server->domain, SOCK_STREAM, 0);
@@ -751,10 +830,15 @@ bool g_db_server_start(GDbServer *server)
     if (ret == -1)
     {
         perror("setsockopt");
-        exit(0);
         goto gdss_error;
     }
 
+    if (server->clean_socket != NULL)
+    {
+        status = server->clean_socket(server);
+        if (!status) goto gdss_error;
+    }
+
     ret = bind(server->fd, (struct sockaddr *)&server->addr, server->sock_len);
     if (ret == -1)
     {
@@ -817,6 +901,9 @@ void g_db_server_stop(GDbServer *server)
 
     server->fd = -1;
 
+    if (server->clean_socket != NULL)
+        server->clean_socket(server);
+
     /* TODO : s'occuper des archives ouvertes */
 
 }
diff --git a/src/main.c b/src/main.c
index 20a443d..f112842 100644
--- a/src/main.c
+++ b/src/main.c
@@ -279,6 +279,8 @@ int main(int argc, char **argv)
     pub = get_xdg_config_dir("chrysalide" G_DIR_SEPARATOR_S "id_rsa.pub");
 
     server = g_db_server_new_internal(author, pub);
+    if (server == NULL) goto no_internal_server;
+
     g_db_server_start(server);
 
     /* Charge le dernier projet ? */
@@ -306,6 +308,10 @@ int main(int argc, char **argv)
 
     g_db_server_stop(server);
 
+    g_object_unref(G_OBJECT(server));
+
+ no_internal_server:
+
  exit_complete_gui:
 
     exit_all_plugins();
-- 
cgit v0.11.2-87-g4458