]> source.dussan.org Git - tigervnc.git/commitdiff
Begin work on XDGBDS compliance and overrideable configs
author90 <hi@90.gripe>
Fri, 15 Mar 2024 22:00:17 +0000 (22:00 +0000)
committer90 <hi@90.gripe>
Fri, 15 Mar 2024 22:00:17 +0000 (22:00 +0000)
.gitignore
common/os/os.cxx
common/os/os.h
common/rfb/CSecurityTLS.cxx
unix/vncpasswd/vncpasswd.cxx
unix/vncserver/vncserver.in
vncviewer/ServerDialog.cxx
vncviewer/parameters.cxx
vncviewer/vncviewer.cxx

index 2e86442253dcbd278d35a21bb749dc5343138c20..c8a0172d488f04c2122602072f04df2804231116 100644 (file)
@@ -2,6 +2,8 @@
 *.mo
 *.la
 *.lo
+*.class
+*.jar
 .deps
 .libs
 
@@ -10,3 +12,18 @@ CMakeCache.txt
 Makefile
 Makefile.in
 config.h
+
+*.xml
+*.man
+*.service
+cmake_install.cmake
+cmake_uninstall.cmake
+install_manifest.txt
+tests/unit/[a-z]*
+!tests/unit/[a-z]*\.
+
+timestamp
+vncserver
+!unix/vncserver
+vncsession
+vncsession-start
index 2dfabc46e0ad3b5047585d7ae8a5dbe1af68b6d4..5c49ce123b6faf58f15266e0e5afe04cd045ff0d 100644 (file)
@@ -32,6 +32,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #else
 #include <windows.h>
 #include <shlobj.h>
 #endif
 
-static const char* gethomedir(bool userDir)
+static const char* getvncdir(bool userDir, const char *xdg_env, const char *xdg_def)
 {
   static char dir[PATH_MAX];
 
 #ifndef WIN32
-  char *homedir;
+  char *homedir, *xdgdir;
   uid_t uid;
   struct passwd *passwd;
 #else
@@ -66,7 +67,20 @@ static const char* gethomedir(bool userDir)
   if (userDir)
     return homedir;
 
+  // check if (deprecated) legacy path exists and use that if so
   snprintf(dir, sizeof(dir), "%s/.vnc", homedir);
+  struct stat st;
+
+  if (stat(dir, &st) == 0)
+    return dir;
+
+  if (xdg_def != NULL) {
+    xdgdir = getenv(xdg_env);
+    if (xdgdir != NULL)
+      snprintf(dir, sizeof(dir), "%s/tigervnc", xdgdir);
+    else
+      snprintf(dir, sizeof(dir), "%s/%s/tigervnc", homedir, xdg_def);
+  }
 
   return dir;
 #else
@@ -90,13 +104,23 @@ static const char* gethomedir(bool userDir)
 #endif
 }
 
-const char* os::getvnchomedir()
+const char* os::getuserhomedir()
 {
-  return gethomedir(false);
+  return getvncdir(true, NULL, NULL);
 }
 
-const char* os::getuserhomedir()
+const char* os::getvncconfigdir()
 {
-  return gethomedir(true);
+  return getvncdir(false, "XDG_CONFIG_HOME", ".config");
 }
 
+const char* os::getvncstatedir()
+{
+  return getvncdir(false, "XDG_STATE_HOME", ".local/state");
+}
+
+/* deprecated */
+const char* os::getvnchomedir()
+{
+  return getvncdir(false, NULL, NULL);
+}
index 5f927fef1d09598b6b57c38830a67c4b69910c2f..0561d36c1f00f070ce7161ef8280794b93f15bf6 100644 (file)
 namespace os {
 
   /*
-   * Get VNC home directory ($HOME/.vnc or %APPDATA%/vnc/).
+   * Get user home directory.
    * If HOME environment variable is set then it is used.
    * Otherwise home directory is obtained via getpwuid function.
    *
    * Returns NULL on failure.
    */
-  const char* getvnchomedir();
+  const char* getuserhomedir();
 
   /*
-   * Get user home directory.
+   * Get VNC config directory. On Unix-like systems, this is either:
+   * - $XDG_CONFIG_HOME/tigervnc
+   * - $HOME/.config/tigervnc
+   * On Windows, this is simply %APPDATA%/vnc/.
+   *
+   * Returns NULL on failure.
+   */
+  const char* getvncconfigdir();
+
+  /*
+   * Get VNC state (logs) directory. On Unix-like systems, this is either:
+   * - $XDG_STATE_HOME/tigervnc
+   * - $HOME/.local/state/tigervnc
+   * On Windows, this is simply %APPDATA%/vnc/.
+   *
+   * Returns NULL on failure.
+   */
+  const char* getvncstatedir();
+
+  /*
+   * Get legacy VNC home directory ($HOME/.vnc on Unix-likes).
    * If HOME environment variable is set then it is used.
    * Otherwise home directory is obtained via getpwuid function.
    *
    * Returns NULL on failure.
+   *
+   * Deprecated.
    */
-  const char* getuserhomedir();
+  const char* getvnchomedir();
 
 }
 
index 905409597bee370afc116f55d7dd25a709417d14..e2edde8962f5cdeca071d557d6e0dc98005a745d 100644 (file)
 
 using namespace rfb;
 
-static const char* homedirfn(const char* fn);
+static const char* configdirfn(const char* fn);
 
 StringParameter CSecurityTLS::X509CA("X509CA", "X509 CA certificate",
-                                     homedirfn("x509_ca.pem"),
+                                     configdirfn("x509_ca.pem"),
                                      ConfViewer);
 StringParameter CSecurityTLS::X509CRL("X509CRL", "X509 CRL file",
-                                     homedirfn("x509_crl.pem"),
+                                     configdirfn("x509_crl.pem"),
                                      ConfViewer);
 
 static LogWriter vlog("TLS");
 
-static const char* homedirfn(const char* fn)
+static const char* configdirfn(const char* fn)
 {
   static char full_path[PATH_MAX];
-  const char* homedir;
+  const char* configdir;
 
-  homedir = os::getvnchomedir();
-  if (homedir == NULL)
+  configdir = os::getvncconfigdir();
+  if (configdir == NULL)
     return "";
 
-  snprintf(full_path, sizeof(full_path), "%s/%s", homedir, fn);
+  snprintf(full_path, sizeof(full_path), "%s/%s", configdir, fn);
 
   return full_path;
 }
@@ -308,7 +308,7 @@ void CSecurityTLS::checkSession()
   int err;
   bool hostname_match;
 
-  const char *homeDir;
+  const char *configDir;
   gnutls_datum_t info;
   size_t len;
 
@@ -385,14 +385,14 @@ void CSecurityTLS::checkSession()
 
   /* Certificate has some user overridable problems, so TOFU time */
 
-  homeDir = os::getvnchomedir();
-  if (homeDir == NULL) {
-    throw AuthFailureException("Could not obtain VNC home directory "
+  configDir = os::getvncconfigdir();
+  if (configDir == NULL) {
+    throw AuthFailureException("Could not obtain VNC config directory "
                                "path for known hosts storage");
   }
 
   std::string dbPath;
-  dbPath = (std::string)homeDir + "/x509_known_hosts";
+  dbPath = (std::string)configDir + "/x509_known_hosts";
 
   err = gnutls_verify_stored_pubkey(dbPath.c_str(), NULL,
                                     client->getServerName(), NULL,
index 93ad6f6f26bb8c07ee22c6df456587326ded8575..8c26588be7079d3456a3e982f714aa9ca41871c5 100644 (file)
@@ -156,13 +156,13 @@ int main(int argc, char** argv)
   }
 
   if (fname[0] == '\0') {
-    const char *homeDir = os::getvnchomedir();
-    if (homeDir == NULL) {
-      fprintf(stderr, "Can't obtain VNC home directory\n");
+    const char *configDir = os::getvncconfigdir();
+    if (configDir == NULL) {
+      fprintf(stderr, "Can't obtain VNC config directory\n");
       exit(1);
     }
-    mkdir(homeDir, 0777);
-    snprintf(fname, sizeof(fname), "%s/passwd", homeDir);
+    mkdir(configDir, 0777);
+    snprintf(fname, sizeof(fname), "%s/passwd", configDir);
   }
 
   while (true) {
index 95d672b17d698a15ec7847b1eb50f163a9b49190..4f67489768b70b48ba7ac09cd6f7c8b640146cc4 100755 (executable)
 # your site
 #
 
+# Start with legacy ~/.vnc user dir
 $vncUserDir = "$ENV{HOME}/.vnc";
+if (stat($vncUserDir)) {
+  warn "~/.vnc is deprecated, please migrate to XDGBDS-compliant paths!";
+} else {
+  # Legacy path doesn't exist, start using new XDG-alike path
+  $vncUserDir = "$ENV{HOME}/.config/tigervnc";
+}
+
 $vncUserConfig = "$vncUserDir/config";
 
 $vncSystemConfigDir = "@CMAKE_INSTALL_FULL_SYSCONFDIR@/tigervnc";
@@ -111,8 +119,8 @@ $default_opts{pn} = undef;
 # Load user-overrideable system defaults
 LoadConfig($vncSystemConfigDefaultsFile);
 
-# Then the user's settings
-LoadConfig($vncUserConfig);
+# Then the user's settings (location overrideable by previous system defaults)
+LoadConfig($config{'userconfig'} || $vncUserConfig);
 
 # And then override anything set above if mandatory settings exist.
 # WARNING: "Mandatory" is used loosely here! As the man page says,
index 6a76629509d480241418abca9cc8c4dba5a918c2..4d57b5fbb9ab1b98258ac4f50491349b61a47023 100644 (file)
@@ -315,12 +315,12 @@ void ServerDialog::loadServerHistory()
   return;
 #endif
 
-  const char* homeDir = os::getvnchomedir();
-  if (homeDir == NULL)
-    throw Exception(_("Could not obtain the home directory path"));
+  const char* stateDir = os::getvncstatedir();
+  if (stateDir == NULL)
+    throw Exception(_("Could not obtain the state directory path"));
 
   char filepath[PATH_MAX];
-  snprintf(filepath, sizeof(filepath), "%s/%s", homeDir, SERVER_HISTORY);
+  snprintf(filepath, sizeof(filepath), "%s/%s", stateDir, SERVER_HISTORY);
 
   /* Read server history from file */
   FILE* f = fopen(filepath, "r");
@@ -381,12 +381,12 @@ void ServerDialog::saveServerHistory()
   return;
 #endif
 
-  const char* homeDir = os::getvnchomedir();
-  if (homeDir == NULL)
-    throw Exception(_("Could not obtain the home directory path"));
+  const char* stateDir = os::getvncstatedir();
+  if (stateDir == NULL)
+    throw Exception(_("Could not obtain the state directory path"));
 
   char filepath[PATH_MAX];
-  snprintf(filepath, sizeof(filepath), "%s/%s", homeDir, SERVER_HISTORY);
+  snprintf(filepath, sizeof(filepath), "%s/%s", stateDir, SERVER_HISTORY);
 
   /* Write server history to file */
   FILE* f = fopen(filepath, "w+");
index 75d46dcab83569095f90158e6f6bb4805b090155..15ea4ee80ce74f30e1db89651caff836880155b7 100644 (file)
@@ -629,11 +629,11 @@ void saveViewerParameters(const char *filename, const char *servername) {
     return;
 #endif
     
-    const char* homeDir = os::getvnchomedir();
-    if (homeDir == NULL)
-      throw Exception(_("Could not obtain the home directory path"));
+    const char* configDir = os::getvncconfigdir();
+    if (configDir == NULL)
+      throw Exception(_("Could not obtain the config directory path"));
 
-    snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", homeDir);
+    snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", configDir);
   } else {
     snprintf(filepath, sizeof(filepath), "%s", filename);
   }
@@ -733,11 +733,11 @@ char* loadViewerParameters(const char *filename) {
     return loadFromReg();
 #endif
 
-    const char* homeDir = os::getvnchomedir();
-    if (homeDir == NULL)
-      throw Exception(_("Could not obtain the home directory path"));
+    const char* configDir = os::getvncconfigdir();
+    if (configDir == NULL)
+      throw Exception(_("Could not obtain the config directory path"));
 
-    snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", homeDir);
+    snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", configDir);
   } else {
     snprintf(filepath, sizeof(filepath), "%s", filename);
   }
index 6eebf3d0405ff7c6fe6e774a1546fb1cc4118457..c5d6082ea69526272f3ccea2514d8475bd8ee6c5 100644 (file)
@@ -429,17 +429,34 @@ static void init_fltk()
 #endif
 }
 
-static void mkvnchomedir()
+static int mkvncdir(const char *dir)
 {
-  // Create .vnc in the user's home directory if it doesn't already exist
-  const char* homeDir = os::getvnchomedir();
-  if (homeDir == NULL) {
-    vlog.error(_("Could not obtain the home directory path"));
-  } else {
-    int result = mkdir(homeDir, 0755);
-    if (result == -1 && errno != EEXIST)
-      vlog.error(_("Could not create VNC home directory: %s"), strerror(errno));
+  int result = mkdir(dir, 0755);
+  if (result == -1 && errno != EEXIST) {
+    vlog.error(_("Could not create VNC directory %s: %s"), dir, strerror(errno));
+    return result;
+  }
+  return 0;
+}
+
+static void mkdirrecursive(const char *dir)
+{
+  char *path = strdup(dir);
+  char *p;
+
+  for (p = path + 1; *p; p++) {
+    if (*p == '/') {
+      *p = '\0';
+      if (mkvncdir(path) != 0) {
+        free(path);
+        return;
+      }
+      *p = '/';
+    }
   }
+
+  mkvncdir(path);
+  free(path);
 }
 
 static void usage(const char *programName)
@@ -728,7 +745,14 @@ int main(int argc, char** argv)
 
   migrateDeprecatedOptions();
 
-  mkvnchomedir();
+#ifndef WIN32
+  // Check if config and state dirs are both the same legacy ~/.vnc dir
+  struct stat st;
+  if (stat(os::getvnchomedir(), &st) == 0)
+    vlog.info(_("~/.vnc is deprecated, please migrate to XDGBDS-compliant paths!"));
+#endif
+  mkdirrecursive(os::getvncconfigdir());
+  mkdirrecursive(os::getvncstatedir());
 
   CSecurity::upg = &dlg;
 #if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE)