*.mo
*.la
*.lo
+*.class
+*.jar
.deps
.libs
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
#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
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
#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);
+}
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();
}
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;
}
int err;
bool hostname_match;
- const char *homeDir;
+ const char *configDir;
gnutls_datum_t info;
size_t len;
/* 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,
}
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) {
# 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";
# 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,
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");
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+");
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);
}
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);
}
#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)
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)