From 5c0e98fe5693a28854f5a9968afe67609586ce58 Mon Sep 17 00:00:00 2001
From: Mike Black W9MDB <mdblack98@yahoo.com>
Date: Fri, 29 Apr 2022 16:30:00 -0500
Subject: [PATCH] First phase of .hamlib_settings -- currently saves sharekey
 in current directory when rigctld -A is run
 https://github.com/Hamlib/Hamlib/issues/813
 https://github.com/Hamlib/Hamlib/issues/985

---
 NEWS            |   2 +
 src/misc.h      |  10 ++++
 src/settings.c  | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/rigctld.c |   1 +
 4 files changed, 160 insertions(+)

diff --git a/NEWS b/NEWS
index 78a0aa010..69a59e522 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ Version 5.x -- future
 
 Version 4.5
         * 2022-04-XX
+        * Add SDRPlay SDRUno rig -- can now use Data/Pkt in WSJTX
+        * Add ability to use cat_string to FLRig via the "w" and "W" commands
         * Add -B/--mapa2b to rigctlcom
           Allows rigctlcom to map set_freq on VFOA to VFOB instead
           This will allow CW Skimmer to work with some rigs (e.g. IC7300) using FM
diff --git a/src/misc.h b/src/misc.h
index ee8877596..1d697f37c 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -197,6 +197,16 @@ void errmsg(int err, char *s, const char *func, const char *file, int line);
     elapsed_ms(&rig->state.cache.time_split, HAMLIB_ELAPSED_INVALIDATE);\
      }
 
+
+typedef enum settings_value_e
+{
+    e_CHAR, e_INT, e_LONG, e_FLOAT, e_DOUBLE
+} settings_value_t;
+
+
+extern HAMLIB_EXPORT(int) rig_settings_save(char *setting, void *value, settings_value_t valuet);
+extern HAMLIB_EXPORT(int) rig_settings_load(char *setting, void *value, settings_value_t valuet);
+
 __END_DECLS
 
 #endif /* _MISC_H */
diff --git a/src/settings.c b/src/settings.c
index 063604cf7..29ebdadc3 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -37,9 +37,12 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>   /* Error number definitions */
 
 #include <hamlib/rig.h>
 #include "cal.h"
+#include "misc.h"
 
 
 #ifndef DOC_HIDDEN
@@ -946,4 +949,148 @@ int HAMLIB_API rig_setting2idx(setting_t s)
     return 0;
 }
 
+#include <unistd.h>  /* UNIX standard function definitions */
+
+#if 0
+#include <hamlib/config.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>   /* Standard input/output definitions */
+#include <string.h>  /* String function definitions */
+
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#  include <sys/time.h>
+#endif
+
+#include <math.h>
+
+#include <hamlib/rig.h>
+#endif
+
+
+#define SETTINGS_FILE ".hamlib_settings"
+char *settings_file = SETTINGS_FILE;
+
+/**
+ * \brief Save setting parameter
+ * \param setting
+ * \param value
+ * \return RIG_OK or error
+ *
+ * \sa rig_setting_load()
+ */
+HAMLIB_EXPORT(int) rig_settings_save(char *setting, void *value,
+                                 settings_value_t valuetype)
+{
+    FILE *fp = fopen(settings_file, "r");
+    FILE *fptmp;
+    char buf[4096];
+    char *cvalue = (char*)value;
+    int *ivalue = (int*)value;
+    long *lvalue = (long*) value;
+    float *fvalue = (float*) value;
+    double *dvalue = (double*) value;
+    char *vformat;
+    char template[64];
+
+    strcpy(template,"hamlib_settings_XXXXXX");
+    switch (valuetype)
+    {
+    case e_CHAR: cvalue = (char *)value; vformat = "%s=%s\n"; break;
+
+    case e_INT: ivalue = (int *)value; vformat = "%s=%d\n"; break;
+
+    case e_LONG: lvalue = (long *)value; vformat = "%s=%l\n"; break;
+
+    case e_FLOAT: fvalue = (float *)value; vformat = "%s=%f\n"; break;
+
+    case e_DOUBLE: dvalue = (double *)value; vformat = "%s=%f\n"; break;
+
+    default:
+        rig_debug(RIG_DEBUG_ERR, "%s: Uknown valuetype=%d\n", __func__, valuetype);
+    }
+
+    if (fp == NULL)
+    {
+        // first time for this file
+        fp = fopen(settings_file, "w");
+
+        switch (valuetype)
+        {
+        case e_CHAR: fprintf(fp, vformat, setting, cvalue); break;
+
+        case e_INT: fprintf(fp, vformat, setting, *ivalue); break;
+
+        case e_LONG: fprintf(fp, vformat, setting, *lvalue); break;
+
+        case e_FLOAT: fprintf(fp, vformat, setting, *fvalue); break;
+
+        case e_DOUBLE: fprintf(fp, vformat, setting, *dvalue); break;
+
+        default:
+            rig_debug(RIG_DEBUG_ERR, "%s: Uknown valuetype=%d\n", __func__, valuetype);
+        }
+
+        fclose(fp);
+        return RIG_OK;
+    }
+
+    mkstemp(template);
+    printf("template=%s\n",template);
+    fptmp = fopen(template, "w");
+
+    if (fptmp == NULL)
+    {
+        rig_debug(RIG_DEBUG_ERR, "%s: error opening for write %s: %s\n", __func__,
+                  template, strerror(errno));
+        fclose(fp);
+        return -RIG_EIO;
+    }
+
+    while (fgets(buf, sizeof(buf), fp))
+    {
+        char *tmp = strdup(buf);
+        char *s = strtok(tmp, "=");
+
+        if (s == NULL)
+        {
+            rig_debug(RIG_DEBUG_ERR, "%s: unable to parse setting from '%s'\n", __func__,
+                      strtok(buf, "\r\n"));
+            fclose(fp);
+            fclose(fptmp);
+            return -RIG_EINTERNAL;
+        }
+
+        char *v = strtok(NULL, "\r\n");
+
+        if (v == NULL)
+        {
+            rig_debug(RIG_DEBUG_ERR, "%s: unable to parse value from '%s'\n", __func__,
+                      strtok(buf, "\r\n"));
+            fclose(fp);
+            fclose(fptmp);
+            return -RIG_EINTERNAL;
+        }
+        fprintf(fptmp, vformat, s, value);
+    }
+
+    fclose(fp);
+    fclose(fptmp);
+    remove(settings_file);
+    rename(template, settings_file);
+    return -RIG_ENIMPL;
+}
+
+HAMLIB_EXPORT(int) rig_settings_load(char *setting, void *value,
+                                 settings_value_t valuetype)
+{
+    return -RIG_ENIMPL;
+}
+
+
 /*! @} */
diff --git a/tests/rigctld.c b/tests/rigctld.c
index b48d70404..3e2efa3c6 100644
--- a/tests/rigctld.c
+++ b/tests/rigctld.c
@@ -307,6 +307,7 @@ int main(int argc, char *argv[])
             strncpy(rigctld_password, optarg, sizeof(rigctld_password) - 1);
             char *md5 = rig_make_md5(rigctld_password);
             printf("Secret key: %s\n", md5);
+            rig_settings_save("sharedkey", md5, e_CHAR);
             break;
 
         case 'm':