diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2021-05-02 11:56:25 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2021-05-11 21:06:34 +0200 |
commit | 0f9640a5f33d4d0c76df75cb7a6cb07baac049f0 (patch) | |
tree | 7d09fe5119b11d4d38313098e6846e2413ff0a19 | |
parent | 4c5fcb743b2e512c407a09ca95d155c9e6edd2bd (diff) | |
download | weechat-0f9640a5f33d4d0c76df75cb7a6cb07baac049f0.zip |
core: split WeeChat home in 4 directories, use XDG directories by default (issue #1285)
The 4 directories (which can be the same):
- config: configuration files, certificates
- data: log/upgrade files, local plugins, scripts, xfer files
- cache: script repository, scripts downloaded (temporary location)
- runtime: FIFO pipe, relay UNIX sockets
38 files changed, 1128 insertions, 362 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index fba0743fb..fb1778996 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -6483,7 +6483,7 @@ COMMAND_CALLBACK(upgrade) /* execute binary */ exec_args[0] = ptr_binary; - exec_args[3] = strdup (weechat_home); + exec_args[3] = dir_get_string_home_dirs (); execvp (exec_args[0], exec_args); /* this code should not be reached if execvp is OK */ @@ -8332,7 +8332,7 @@ command_init () "IMPORTANT: you must restore the session with exactly same " "configuration (files *.conf).\n" "It is possible to restore WeeChat session on another machine if you " - "copy the content of directory \"~/.weechat\"."), + "copy the content of WeeChat home directories (see /debug dirs)."), "%(filename)|-dummy|-quit", &command_upgrade, NULL, NULL); hook_command ( diff --git a/src/core/wee-completion.c b/src/core/wee-completion.c index 7f210dbd4..6e913d820 100644 --- a/src/core/wee-completion.c +++ b/src/core/wee-completion.c @@ -573,7 +573,7 @@ completion_list_add_filename_cb (const void *pointer, void *data, } } if (!real_prefix) - real_prefix = strdup (weechat_home); + real_prefix = strdup (weechat_data_dir); prefix = strdup (""); } else @@ -984,6 +984,7 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, { char *plugin_path, *dir_name, *extra_libdir; int length; + struct t_hashtable *options; /* make C compiler happy */ (void) pointer; @@ -1011,8 +1012,17 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, if (CONFIG_STRING(config_plugin_path) && CONFIG_STRING(config_plugin_path)[0]) { + options = hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + hashtable_set (options, "directory", "data"); plugin_path = string_eval_path_home (CONFIG_STRING(config_plugin_path), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + hashtable_free (options); if (plugin_path) { dir_exec_on_files (plugin_path, 1, 0, diff --git a/src/core/wee-config-file.c b/src/core/wee-config-file.c index 250e5a014..941df4795 100644 --- a/src/core/wee-config-file.c +++ b/src/core/wee-config-file.c @@ -2366,13 +2366,13 @@ config_file_write_internal (struct t_config_file *config_file, return WEECHAT_CONFIG_WRITE_ERROR; /* build filename */ - filename_length = strlen (weechat_home) + - strlen (config_file->filename) + 2; + filename_length = strlen (weechat_config_dir) + strlen (DIR_SEPARATOR) + + strlen (config_file->filename) + 1; filename = malloc (filename_length); if (!filename) return WEECHAT_CONFIG_WRITE_MEMORY_ERROR; snprintf (filename, filename_length, "%s%s%s", - weechat_home, DIR_SEPARATOR, config_file->filename); + weechat_config_dir, DIR_SEPARATOR, config_file->filename); /* * build temporary filename, this temp file will be renamed to filename @@ -2561,13 +2561,13 @@ config_file_read_internal (struct t_config_file *config_file, int reload) return WEECHAT_CONFIG_READ_FILE_NOT_FOUND; /* build filename */ - filename_length = strlen (weechat_home) + strlen (DIR_SEPARATOR) + + filename_length = strlen (weechat_config_dir) + strlen (DIR_SEPARATOR) + strlen (config_file->filename) + 1; filename = malloc (filename_length); if (!filename) return WEECHAT_CONFIG_READ_MEMORY_ERROR; snprintf (filename, filename_length, "%s%s%s", - weechat_home, DIR_SEPARATOR, config_file->filename); + weechat_config_dir, DIR_SEPARATOR, config_file->filename); /* create file with default options if it does not exist */ if (access (filename, F_OK) != 0) diff --git a/src/core/wee-debug.c b/src/core/wee-debug.c index cae470ba8..3315348ab 100644 --- a/src/core/wee-debug.c +++ b/src/core/wee-debug.c @@ -161,7 +161,7 @@ debug_sigsegv_cb () string_fprintf (stderr, "*** Full crash dump was saved to %s/weechat.log file." "\n", - weechat_home); + weechat_data_dir); } string_fprintf ( stderr, @@ -590,19 +590,27 @@ debug_libs_cb (const void *pointer, void *data, void debug_directories () { - char *extra_libdir; - const char *ptr_home = WEECHAT_HOME; + char *extra_libdir, str_temp[1024]; extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); + if (weechat_home_temp) + { + snprintf (str_temp, sizeof (str_temp), + " (%s)", _("TEMPORARY, deleted on exit")); + } + else + { + str_temp[0] = '\0'; + } + gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Directories:")); - gui_chat_printf (NULL, " home: %s%s%s", - weechat_home, - (weechat_home_temp) ? " " : "", - (weechat_home_temp) ? _("(TEMPORARY, deleted on exit)") : ""); - gui_chat_printf (NULL, _(" (default: %s)"), - (ptr_home && ptr_home[0]) ? ptr_home : "~/.weechat"); + gui_chat_printf (NULL, " home:"); + gui_chat_printf (NULL, " config: %s%s", weechat_config_dir, str_temp); + gui_chat_printf (NULL, " data: %s%s", weechat_data_dir, str_temp); + gui_chat_printf (NULL, " cache: %s%s", weechat_cache_dir, str_temp); + gui_chat_printf (NULL, " runtime: %s%s", weechat_runtime_dir, str_temp); gui_chat_printf (NULL, " lib: %s", WEECHAT_LIBDIR); gui_chat_printf (NULL, " lib (extra): %s", (extra_libdir && extra_libdir[0]) ? extra_libdir : "-"); diff --git a/src/core/wee-dir.c b/src/core/wee-dir.c index 96f98ada9..5949035ff 100644 --- a/src/core/wee-dir.c +++ b/src/core/wee-dir.c @@ -57,7 +57,7 @@ */ char * -dir_get_temp_dir() +dir_get_temp_dir () { char *tmpdir; struct stat buf; @@ -101,31 +101,70 @@ dir_get_temp_dir() int dir_mkdir_home (const char *directory, int mode) { - char *dir_name; - int dir_length; + char *dir, *dir1, *dir2, *dir3, *dir4; + int rc, dir_length; + + rc = 0; + dir = NULL; + dir1 = NULL; + dir2 = NULL; + dir3 = NULL; + dir4 = NULL; if (!directory) - return 0; + goto end; - /* build directory, adding WeeChat home */ - dir_length = strlen (weechat_home) + strlen (directory) + 2; - dir_name = malloc (dir_length); - if (!dir_name) - return 0; + if (strncmp (directory, "${", 2) == 0) + { + dir = strdup (directory); + } + else + { + /* build directory in data dir by default */ + dir_length = strlen (weechat_data_dir) + strlen (directory) + 2; + dir = malloc (dir_length); + if (!dir) + goto end; + snprintf (dir, dir_length, "%s/%s", weechat_data_dir, directory); + } + + dir1 = string_replace (dir, "${weechat_config_dir}", weechat_config_dir); + if (!dir1) + goto end; + + dir2 = string_replace (dir1, "${weechat_data_dir}", weechat_data_dir); + if (!dir2) + goto end; + + dir3 = string_replace (dir2, "${weechat_cache_dir}", weechat_cache_dir); + if (!dir3) + goto end; - snprintf (dir_name, dir_length, "%s/%s", weechat_home, directory); + dir4 = string_replace (dir3, "${weechat_runtime_dir}", weechat_runtime_dir); + if (!dir4) + goto end; - if (mkdir (dir_name, mode) < 0) + /* build directory, adding WeeChat home */ + if (mkdir (dir4, mode) < 0) { if (errno != EEXIST) - { - free (dir_name); - return 0; - } + goto end; } - free (dir_name); - return 1; + rc = 1; + +end: + if (dir) + free (dir); + if (dir1) + free (dir1); + if (dir2) + free (dir2); + if (dir3) + free (dir3); + if (dir4) + free (dir4); + return rc; } /* @@ -353,7 +392,7 @@ dir_search_full_lib_name_ext (const char *filename, const char *extension, } /* try WeeChat user's dir */ - length = strlen (weechat_home) + strlen (name_with_ext) + + length = strlen (weechat_data_dir) + strlen (name_with_ext) + strlen (plugins_dir) + 16; final_name = malloc (length); if (!final_name) @@ -363,7 +402,7 @@ dir_search_full_lib_name_ext (const char *filename, const char *extension, } snprintf (final_name, length, "%s%s%s%s%s", - weechat_home, + weechat_data_dir, DIR_SEPARATOR, plugins_dir, DIR_SEPARATOR, @@ -514,154 +553,404 @@ error: } /* - * Expands and assigns given path to "weechat_home". + * Uses one or four different paths for WeeChat home directories. + * + * If 4 paths are given, they must be separated by colons and given in this + * order: config, data, cache, runtime. + * + * Returns: + * 1: OK + * 0: error */ -void -dir_set_home_path (char *home_path) +int +dir_set_home_path (char *path) { - char *ptr_home; - int dir_length; + char **paths; + int rc, num_paths; + + rc = 0; + paths = NULL; - if (home_path[0] == '~') + if (!path) + goto end; + + paths = string_split (path, ":", NULL, 0, 0, &num_paths); + if (!paths) { - /* replace leading '~' by $HOME */ - ptr_home = getenv ("HOME"); - if (!ptr_home) - { - string_fprintf (stderr, _("Error: unable to get HOME directory\n")); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; - } - dir_length = strlen (ptr_home) + strlen (home_path + 1) + 1; - weechat_home = malloc (dir_length); - if (weechat_home) - { - snprintf (weechat_home, dir_length, - "%s%s", ptr_home, home_path + 1); - } + string_fprintf (stderr, _("Error: not enough memory\n")); + goto end; } - else + + if (num_paths == 1) { - weechat_home = strdup (home_path); + weechat_config_dir = string_expand_home (paths[0]); + weechat_data_dir = string_expand_home (paths[0]); + weechat_cache_dir = string_expand_home (paths[0]); + weechat_runtime_dir = string_expand_home (paths[0]); } - - if (!weechat_home) + else if (num_paths == 4) + { + weechat_config_dir = string_expand_home (paths[0]); + weechat_data_dir = string_expand_home (paths[1]); + weechat_cache_dir = string_expand_home (paths[2]); + weechat_runtime_dir = string_expand_home (paths[3]); + } + else { string_fprintf (stderr, - _("Error: not enough memory for home directory\n")); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; + _("Error: wrong number of paths for home directories " + "(expected: 1 or 4, received: %d)\n"), + num_paths); + goto end; } + + rc = 1; + +end: + if (paths) + string_free_split (paths); + return rc; } /* - * Creates WeeChat home directory (by default ~/.weechat). + * Creates WeeChat temporary home directory (deleted on exit). * - * Any error in this function is fatal: WeeChat can not run without a home - * directory. + * Returns: + * 1: OK + * 0: error */ -void -dir_create_home_dir () +int +dir_create_home_temp_dir () { char *temp_dir, *temp_home_template, *ptr_weechat_home; - char *config_weechat_home; - int length, add_separator; - struct stat statinfo; - - /* temporary WeeChat home */ - if (weechat_home_temp) + int rc, length, add_separator; + + rc = 0; + temp_dir = NULL; + temp_home_template = NULL; + + temp_dir = dir_get_temp_dir (); + if (!temp_dir || !temp_dir[0]) + goto memory_error; + + length = strlen (temp_dir) + 32 + 1; + temp_home_template = malloc (length); + if (!temp_home_template) + goto memory_error; + + add_separator = (temp_dir[strlen (temp_dir) - 1] != DIR_SEPARATOR_CHAR); + snprintf (temp_home_template, length, + "%s%sweechat_temp_XXXXXX", + temp_dir, + add_separator ? DIR_SEPARATOR : ""); + ptr_weechat_home = mkdtemp (temp_home_template); + if (!ptr_weechat_home) { - temp_dir = dir_get_temp_dir (); - if (!temp_dir || !temp_dir[0]) - { - string_fprintf (stderr, - _("Error: not enough memory for home " - "directory\n")); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; - } - length = strlen (temp_dir) + 32 + 1; - temp_home_template = malloc (length); - if (!temp_home_template) - { - free (temp_dir); - string_fprintf (stderr, - _("Error: not enough memory for home " - "directory\n")); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; - } - add_separator = (temp_dir[strlen (temp_dir) - 1] != DIR_SEPARATOR_CHAR); - snprintf (temp_home_template, length, - "%s%sweechat_temp_XXXXXX", - temp_dir, - add_separator ? DIR_SEPARATOR : ""); + string_fprintf (stderr, + _("Error: unable to create a temporary " + "home directory (using template: \"%s\")\n"), + temp_home_template); + goto end; + } + + weechat_config_dir = strdup (ptr_weechat_home); + weechat_data_dir = strdup (ptr_weechat_home); + weechat_cache_dir = strdup (ptr_weechat_home); + weechat_runtime_dir = strdup (ptr_weechat_home); + + weechat_home_delete_on_exit = 1; + + rc = 1; + goto end; + +memory_error: + string_fprintf (stderr, _("Error: not enough memory\n")); + +end: + if (temp_dir) free (temp_dir); - ptr_weechat_home = mkdtemp (temp_home_template); - if (!ptr_weechat_home) - { - string_fprintf (stderr, - _("Error: unable to create a temporary " - "home directory (using template: \"%s\")\n"), - temp_home_template); - free (temp_home_template); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; - } - weechat_home = strdup (ptr_weechat_home); + if (temp_home_template) free (temp_home_template); - weechat_home_delete_on_exit = 1; - return; + return rc; +} + +/* + * Finds XDG directories. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_find_xdg_dirs (char **config_dir, char **data_dir, char **cache_dir, + char **runtime_dir) +{ + char *ptr_home, path[PATH_MAX]; + char *xdg_config_home, *xdg_data_home, *xdg_cache_home, *xdg_runtime_dir; + + ptr_home = getenv ("HOME"); + xdg_config_home = getenv ("XDG_CONFIG_HOME"); + xdg_data_home = getenv ("XDG_DATA_HOME"); + xdg_cache_home = getenv ("XDG_CACHE_HOME"); + xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR"); + + /* set config dir: $XDG_CONFIG_HOME/weechat or $HOME/.config/weechat */ + if (xdg_config_home && xdg_config_home[0]) + { + snprintf (path, sizeof (path), + "%s%s%s", + xdg_config_home, DIR_SEPARATOR, "weechat"); } + else + { + snprintf (path, sizeof (path), + "%s%s%s%s%s", + ptr_home, DIR_SEPARATOR, ".config", DIR_SEPARATOR, "weechat"); + } + *config_dir = strdup (path); + if (!*config_dir) + goto error; - /* - * weechat_home is not set yet: look for environment variable - * "WEECHAT_HOME" - */ - if (!weechat_home) + /* set data dir: $XDG_DATA_HOME/weechat or $HOME/.local/share/weechat */ + if (xdg_data_home && xdg_data_home[0]) { - ptr_weechat_home = getenv ("WEECHAT_HOME"); - if (ptr_weechat_home && ptr_weechat_home[0]) - dir_set_home_path (ptr_weechat_home); + snprintf (path, sizeof (path), + "%s%s%s", + xdg_data_home, DIR_SEPARATOR, "weechat"); } + else + { + snprintf (path, sizeof (path), + "%s%s%s%s%s%s%s", + ptr_home, DIR_SEPARATOR, ".local", DIR_SEPARATOR, "share", + DIR_SEPARATOR, "weechat"); + } + *data_dir = strdup (path); + if (!*data_dir) + goto error; - /* weechat_home is still not set: try to use compile time default */ - if (!weechat_home) + /* set cache dir: $XDG_CACHE_HOME/weechat or $HOME/.cache/weechat */ + if (xdg_cache_home && xdg_cache_home[0]) { - config_weechat_home = WEECHAT_HOME; - dir_set_home_path ( - (config_weechat_home[0] ? config_weechat_home : "~/.weechat")); + snprintf (path, sizeof (path), + "%s%s%s", + xdg_cache_home, DIR_SEPARATOR, "weechat"); } + else + { + snprintf (path, sizeof (path), + "%s%s%s%s%s", + ptr_home, DIR_SEPARATOR, ".cache", DIR_SEPARATOR, "weechat"); + } + *cache_dir = strdup (path); + if (!*cache_dir) + goto error; + + /* set runtime dir: $XDG_RUNTIME_DIR/weechat or same as cache dir */ + if (xdg_runtime_dir && xdg_runtime_dir[0]) + { + snprintf (path, sizeof (path), + "%s%s%s", + xdg_runtime_dir, DIR_SEPARATOR, "weechat"); + *runtime_dir = strdup (path); + } + else + { + *runtime_dir = strdup (*cache_dir); + } + if (!*runtime_dir) + goto error; + + return 1; + +error: + string_fprintf (stderr, _("Error: not enough memory\n")); + return 0; +} + +/* + * Finds WeeChat home directories: it can be either XDG directories or the + * same directory for all files (like the legacy directory ~/.weechat). + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_find_home_dirs () +{ + char *ptr_home, *ptr_weechat_home, *config_weechat_home; + char *config_dir, *data_dir, *cache_dir, *runtime_dir; + char path[PATH_MAX]; + + /* temporary WeeChat home */ + if (weechat_home_temp) + return dir_create_home_temp_dir (); + + /* use a forced home with -d/--dir */ + if (weechat_home_force) + return dir_set_home_path (weechat_home_force); + + /* use environment variable "WEECHAT_HOME" (if set) */ + ptr_weechat_home = getenv ("WEECHAT_HOME"); + if (ptr_weechat_home && ptr_weechat_home[0]) + return dir_set_home_path (ptr_weechat_home); + + /* use the home forced at compilation time (if set) */ + config_weechat_home = WEECHAT_HOME; + if (config_weechat_home[0]) + return dir_set_home_path (config_weechat_home); + + if (!dir_find_xdg_dirs (&config_dir, &data_dir, &cache_dir, &runtime_dir)) + return 0; + + /* check if {weechat_config_dir}/weechat.conf exists */ + snprintf (path, sizeof (path), + "%s%s%s", + config_dir, DIR_SEPARATOR, "weechat.conf"); + if (access (path, F_OK) == 0) + goto use_xdg; + + /* + * check if $HOME/.weechat/weechat.conf exists + * (compatibility with old releases not supporting XDG directories) + */ + ptr_home = getenv ("HOME"); + snprintf (path, sizeof (path), + "%s%s%s%s%s", + ptr_home, DIR_SEPARATOR, ".weechat", DIR_SEPARATOR, "weechat.conf"); + if (access (path, F_OK) == 0) + { + snprintf (path, sizeof (path), + "%s%s%s", + ptr_home, DIR_SEPARATOR, ".weechat"); + weechat_config_dir = strdup (path); + weechat_data_dir = strdup (path); + weechat_cache_dir = strdup (path); + weechat_runtime_dir = strdup (path); + free (config_dir); + free (data_dir); + free (cache_dir); + free (runtime_dir); + return 1; + } + + /* use XDG directories */ +use_xdg: + weechat_config_dir = config_dir; + weechat_data_dir = data_dir; + weechat_cache_dir = cache_dir; + weechat_runtime_dir = runtime_dir; + return 1; +} + +/* + * Creates a home directory. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_create_home_dir (char *path) +{ + struct stat statinfo; /* if home already exists, it has to be a directory */ - if (stat (weechat_home, &statinfo) == 0) + if (stat (path, &statinfo) == 0) { if (!S_ISDIR (statinfo.st_mode)) { string_fprintf (stderr, - _("Error: home (%s) is not a directory\n"), - weechat_home); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; + _("Error: \"%s\" is not a directory\n"), + path); + return 0; } } /* create home directory; error is fatal */ - if (!dir_mkdir (weechat_home, 0755)) + if (!dir_mkdir_parents (path, 0700)) { string_fprintf (stderr, _("Error: cannot create directory \"%s\"\n"), - weechat_home); - weechat_shutdown (EXIT_FAILURE, 0); - /* make C static analyzer happy (never executed) */ - return; + path); + return 0; } + + return 1; +} + +/* + * Creates WeeChat home directories. + * + * Any error in this function (or a sub function called) is fatal: WeeChat + * can not run at all without the home directories. + */ + +void +dir_create_home_dirs () +{ + int rc; + + if (!dir_find_home_dirs ()) + goto error; + + rc = dir_create_home_dir (weechat_config_dir); + if (rc && (strcmp (weechat_config_dir, weechat_data_dir) != 0)) + rc = dir_create_home_dir (weechat_data_dir); + if (rc && (strcmp (weechat_config_dir, weechat_cache_dir) != 0)) + rc = dir_create_home_dir (weechat_cache_dir); + if (rc && (strcmp (weechat_config_dir, weechat_runtime_dir) != 0)) + rc = dir_create_home_dir (weechat_runtime_dir); + if (rc) + return; + +error: + weechat_shutdown (EXIT_FAILURE, 0); +} + +/* + * Removes WeeChat home directories (called when -t / --temp-dir is given). + */ + +void +dir_remove_home_dirs () +{ + dir_rmtree (weechat_config_dir); + if (strcmp (weechat_config_dir, weechat_data_dir) != 0) + dir_rmtree (weechat_data_dir); + if (strcmp (weechat_config_dir, weechat_cache_dir) != 0) + dir_rmtree (weechat_cache_dir); + if (strcmp (weechat_config_dir, weechat_runtime_dir) != 0) + dir_rmtree (weechat_runtime_dir); +} + +/* + * Returns a string with home directories separated by colons, in this order: + * config_dir, data_dir, cache_dir, runtime_dir. + * + * Example of value returned: + * /home/user/.config/weechat:/home/user/.local/share/weechat: + * /home/user/.cache/weechat:/run/user/1000/weechat + * + * Note: result must be freed after use. + */ + +char * +dir_get_string_home_dirs () +{ + char *dirs[5]; + + dirs[0] = weechat_config_dir; + dirs[1] = weechat_data_dir; + dirs[2] = weechat_cache_dir; + dirs[3] = weechat_runtime_dir; + dirs[4] = NULL; + + return string_build_with_split_string ((const char **)dirs, ":"); } diff --git a/src/core/wee-dir.h b/src/core/wee-dir.h index 8292eb1cc..489ca2a64 100644 --- a/src/core/wee-dir.h +++ b/src/core/wee-dir.h @@ -33,6 +33,8 @@ extern void dir_exec_on_files (const char *directory, int recurse_subdirs, extern char *dir_search_full_lib_name (const char *filename, const char *sys_directory); extern char *dir_file_get_content (const char *filename); -extern void dir_create_home_dir (); +extern void dir_create_home_dirs (); +extern void dir_remove_home_dirs (); +extern char *dir_get_string_home_dirs (); #endif /* WEECHAT_DIR_H */ diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c index 8fc2b4754..c8f82d890 100644 --- a/src/core/wee-eval.c +++ b/src/core/wee-eval.c @@ -1010,32 +1010,34 @@ end: * Replaces variables, which can be, by order of priority: * 1. the string itself without evaluation (format: raw:xxx) * 2. an extra variable from hashtable "extra_vars" - * 3. a string to evaluate (format: eval:xxx) - * 4. a condition to evaluate (format: eval_cond:xxx) - * 5. a string with escaped chars (format: esc:xxx or \xxx) - * 6. a string with chars to hide (format: hide:char,string) - * 7. a string with max chars (format: cut:max,suffix,string or + * 3. a WeeChat home directory, one of: "weechat_config_dir", + * "weechat_data_dir", "weechat_cache_dir", "weechat_runtime_dir" + * 4. a string to evaluate (format: eval:xxx) + * 5. a condition to evaluate (format: eval_cond:xxx) + * 6. a string with escaped chars (format: esc:xxx or \xxx) + * 7. a string with chars to hide (format: hide:char,string) + * 8. a string with max chars (format: cut:max,suffix,string or * cut:+max,suffix,string) or max chars on screen * (format: cutscr:max,suffix,string or cutscr:+max,suffix,string) - * 8. a reversed string (format: rev:xxx) or reversed string for screen, + * 9. a reversed string (format: rev:xxx) or reversed string for screen, * color codes are not reversed (format: revscr:xxx) - * 9. a repeated string (format: repeat:count,string) - * 10. length of a string (format: length:xxx) or length of a string on screen + * 10. a repeated string (format: repeat:count,string) + * 11. length of a string (format: length:xxx) or length of a string on screen * (format: lengthscr:xxx); color codes are ignored - * 11. a regex group captured (format: re:N (0.99) or re:+) - * 12. a color (format: color:xxx) - * 13. a modifier (format: modifier:name,data,xxx) - * 14. an info (format: info:name,arguments) - * 15. a base 16/32/64 encoded/decoded string (format: base_encode:base,xxx + * 12. a regex group captured (format: re:N (0.99) or re:+) + * 13. a color (format: color:xxx) + * 14. a modifier (format: modifier:name,data,xxx) + * 15. an info (format: info:name,arguments) + * 16. a base 16/32/64 encoded/decoded string (format: base_encode:base,xxx * or base_decode:base,xxx) - * 16. current date/time (format: date or date:xxx) - * 17. an environment variable (format: env:XXX) - * 18. a ternary operator (format: if:condition?value_if_true:value_if_false) - * 19. calculate result of an expression (format: calc:xxx) - * 20. an option (format: file.section.option) - * 21. a buffer local variable - * 22. a pointer name from hashtable "pointers" - * 23. a hdata variable (format: hdata.var1.var2 or hdata[list].var1.var2 + * 17. current date/time (format: date or date:xxx) + * 18. an environment variable (format: env:XXX) + * 19. a ternary operator (format: if:condition?value_if_true:value_if_false) + * 20. calculate result of an expression (format: calc:xxx) + * 21. an option (format: file.section.option) + * 22. a buffer local variable + * 23. a pointer name from hashtable "pointers" + * 24. a hdata variable (format: hdata.var1.var2 or hdata[list].var1.var2 * or hdata[ptr].var1.var2 or hdata[ptr_name].var1.var2) * * See /help in WeeChat for examples. @@ -1093,8 +1095,30 @@ eval_replace_vars_cb (void *data, const char *text) } } + /* 3. WeeChat home directory */ + if (strcmp (text, "weechat_config_dir") == 0) + { + value = strdup (weechat_config_dir); + goto end; + } + if (strcmp (text, "weechat_data_dir") == 0) + { + value = strdup (weechat_data_dir); + goto end; + } + if (strcmp (text, "weechat_cache_dir") == 0) + { + value = strdup (weechat_cache_dir); + goto end; + } + if (strcmp (text, "weechat_runtime_dir") == 0) + { + value = strdup (weechat_runtime_dir); + goto end; + } + /* - * 3. force evaluation of string (recursive call) + * 4. force evaluation of string (recursive call) * --> use with caution: the text must be safe! */ if (strncmp (text, "eval:", 5) == 0) @@ -1104,7 +1128,7 @@ eval_replace_vars_cb (void *data, const char *text) } /* - * 4. force evaluation of condition (recursive call) + * 5. force evaluation of condition (recursive call) * --> use with caution: the text must be safe! */ if (strncmp (text, "eval_cond:", 10) == 0) @@ -1113,7 +1137,7 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 5. convert escaped chars */ + /* 6. convert escaped chars */ if (strncmp (text, "esc:", 4) == 0) { value = string_convert_escaped_chars (text + 4); @@ -1125,7 +1149,7 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 6. hide chars: replace all chars by a given char/string */ + /* 7. hide chars: replace all chars by a given char/string */ if (strncmp (text, "hide:", 5) == 0) { value = eval_string_hide (text + 5); @@ -1133,7 +1157,7 @@ eval_replace_vars_cb (void *data, const char *text) } /* - * 7. cut chars: + * 8. cut chars: * cut: max number of chars, and add an optional suffix when the * string is cut * cutscr: max number of chars displayed on screen, and add an optional @@ -1150,7 +1174,7 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 8. reverse string */ + /* 9. reverse string */ if (strncmp (text, "rev:", 4) == 0) { value = string_reverse (text + 4); @@ -1162,7 +1186,7 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 9. repeated string */ + /* 10. repeated string */ if (strncmp (text, "repeat:", 7) == 0) { value = eval_string_repeat (text + 7); @@ -1170,7 +1194,7 @@ eval_replace_vars_cb (void *data, const char *text) } /* - * 10. length of string: + * 11. length of string: * length: number of chars * lengthscr: number of chars displayed on screen */ @@ -1189,35 +1213,35 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 11. regex group captured */ + /* 12. regex group captured */ if (strncmp (text, "re:", 3) == 0) { value = eval_string_regex_group (text + 3, eval_context); goto end; } - /* 12. color code */ + /* 13. color code */ if (strncmp (text, "color:", 6) == 0) { value = eval_string_color (text + 6); goto end; } - /* 13. modifier */ + /* 14. modifier */ if (strncmp (text, "modifier:", 9) == 0) { value = eval_string_modifier (text + 9); goto end; } - /* 14. info */ + /* 15. info */ if (strncmp (text, "info:", 5) == 0) { value = eval_string_info (text + 5); goto end; } - /* 15. base_encode/base_decode */ + /* 16. base_encode/base_decode */ if (strncmp (text, "base_encode:", 12) == 0) { value = eval_string_base_encode (text + 12); @@ -1229,14 +1253,14 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 16. current date/time */ + /* 17. current date/time */ if ((strncmp (text, "date", 4) == 0) && (!text[4] || (text[4] == ':'))) { value = eval_string_date (text + 4); goto end; } - /* 17. environment variable */ + /* 18. environment variable */ if (strncmp (text, "env:", 4) == 0) { ptr_value = getenv (text + 4); @@ -1244,7 +1268,7 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 18: ternary operator: if:condition?value_if_true:value_if_false */ + /* 19: ternary operator: if:condition?value_if_true:value_if_false */ if (strncmp (text, "if:", 3) == 0) { value = eval_string_if (text + 3, eval_context); @@ -1252,7 +1276,7 @@ eval_replace_vars_cb (void *data, const char *text) } /* - * 19. calculate the result of an expression + * 20. calculate the result of an expression * (with number, operators and parentheses) */ if (strncmp (text, "calc:", 5) == 0) @@ -1261,7 +1285,7 @@ eval_replace_vars_cb (void *data, const char *text) goto end; } - /* 20. option: if found, return this value */ + /* 21. option: if found, return this value */ if (strncmp (text, "sec.data.", 9) == 0) { ptr_value = hashtable_get (secure_hashtable_data, text + 9); @@ -1304,7 +1328,7 @@ eval_replace_vars_cb (void *data, const char *text) } } - /* 21. local variable in buffer */ + /* 22. local variable in buffer */ ptr_buffer = hashtable_get (eval_context->pointers, "buffer"); if (ptr_buffer) { @@ -1316,7 +1340,7 @@ eval_replace_vars_cb (void *data, const char *text) } } - /* 22. hdata */ + /* 23. hdata */ value = eval_string_hdata (text, eval_context); end: diff --git a/src/core/wee-log.c b/src/core/wee-log.c index 7ef81a16a..b0454d500 100644 --- a/src/core/wee-log.c +++ b/src/core/wee-log.c @@ -45,7 +45,7 @@ #include "../plugins/plugin.h" -char *weechat_log_filename = NULL; /* log name (~/.weechat/weechat.log) */ +char *weechat_log_filename = NULL; /* WeeChat log filename (weechat.log) */ FILE *weechat_log_file = NULL; /* WeeChat log file */ int weechat_log_use_time = 1; /* 0 to temporary disable time in log, */ /* for example when dumping data */ @@ -79,10 +79,10 @@ log_open (const char *filename, const char *mode) } else { - filename_length = strlen (weechat_home) + 64; + filename_length = strlen (weechat_data_dir) + 64; weechat_log_filename = malloc (filename_length); snprintf (weechat_log_filename, filename_length, - "%s/%s", weechat_home, WEECHAT_LOG_NAME); + "%s/%s", weechat_data_dir, WEECHAT_LOG_NAME); weechat_log_file = fopen (weechat_log_filename, mode); } @@ -122,10 +122,12 @@ log_init () { if (!log_open (NULL, "w")) { - string_fprintf (stderr, - _("Error: unable to create/append to log file (weechat.log)\n" - "If another WeeChat process is using this file, try to run WeeChat\n" - "with another home using the \"--dir\" command line option.\n")); + string_fprintf ( + stderr, + _("Error: unable to create/append to log file (weechat.log)\n" + "If another WeeChat process is using this file, try to run " + "WeeChat with a specific home directory using the \"--dir\" " + "command line option.\n")); exit (1); } log_printf ("WeeChat %s (%s %s %s)", @@ -271,7 +273,7 @@ log_crash_rename () log_close (); - length = strlen (weechat_home) + 128; + length = strlen (weechat_data_dir) + 128; new_name = malloc (length); if (new_name) { @@ -279,7 +281,7 @@ log_crash_rename () local_time = localtime (&time_now); snprintf (new_name, length, "%s/weechat_crash_%04d%02d%02d_%d.log", - weechat_home, + weechat_data_dir, local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday, diff --git a/src/core/wee-network.c b/src/core/wee-network.c index 7f7dc4d14..3fdaf01b6 100644 --- a/src/core/wee-network.c +++ b/src/core/wee-network.c @@ -57,6 +57,7 @@ #include "weechat.h" #include "wee-network.h" #include "wee-eval.h" +#include "wee-hashtable.h" #include "wee-hook.h" #include "wee-config.h" #include "wee-proxy.h" @@ -93,13 +94,24 @@ void network_set_gnutls_ca_file () { char *ca_path; + struct t_hashtable *options; if (weechat_no_gnutls) return; + options = hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + hashtable_set (options, "directory", "config"); ca_path = string_eval_path_home ( CONFIG_STRING(config_network_gnutls_ca_file), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + hashtable_free (options); + if (ca_path) { if (access (ca_path, R_OK) == 0) diff --git a/src/core/wee-string.c b/src/core/wee-string.c index 321cea877..48fdd7ef2 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -774,7 +774,7 @@ string_expand_home (const char *path) /* * Evaluate a path by replacing (in this order): - * 1. "%h" (at beginning of string) by WeeChat home directory. + * 1. "%h" (at beginning of string) by WeeChat home directory (deprecated) * 2. "~" by user home directory (call to string_expand_home) * 3. evaluated variables (see /help eval) * @@ -790,6 +790,7 @@ string_eval_path_home (const char *path, struct t_hashtable *options) { char *path1, *path2, *path3; + const char *ptr_option_directory, *ptr_directory; int length; if (!path) @@ -799,13 +800,29 @@ string_eval_path_home (const char *path, path2 = NULL; path3 = NULL; - /* replace "%h" by WeeChat home */ + /* + * replace "%h" by WeeChat home + * (deprecated: "%h" should not be used any more with WeeChat ≥ 3.2) + */ if (strncmp (path, "%h", 2) == 0) { - length = strlen (weechat_home) + strlen (path + 2) + 1; + ptr_directory = weechat_data_dir; + ptr_option_directory = hashtable_get (options, "directory"); + if (ptr_option_directory) + { + if (strcmp (ptr_option_directory, "config") == 0) + ptr_directory = weechat_config_dir; + else if (strcmp (ptr_option_directory, "data") == 0) + ptr_directory = weechat_data_dir; + else if (strcmp (ptr_option_directory, "cache") == 0) + ptr_directory = weechat_cache_dir; + else if (strcmp (ptr_option_directory, "runtime") == 0) + ptr_directory = weechat_runtime_dir; + } + length = strlen (ptr_directory) + strlen (path + 2) + 1; path1 = malloc (length); if (path1) - snprintf (path1, length, "%s%s", weechat_home, path + 2); + snprintf (path1, length, "%s%s", ptr_directory, path + 2); } else path1 = strdup (path); diff --git a/src/core/wee-upgrade-file.c b/src/core/wee-upgrade-file.c index 491648a0a..0a41ec025 100644 --- a/src/core/wee-upgrade-file.c +++ b/src/core/wee-upgrade-file.c @@ -203,7 +203,7 @@ upgrade_file_new (const char *filename, if (new_upgrade_file) { /* build name of file */ - length = strlen (weechat_home) + 1 + strlen (filename) + 16 + 1; + length = strlen (weechat_data_dir) + 1 + strlen (filename) + 16 + 1; new_upgrade_file->filename = malloc (length); if (!new_upgrade_file->filename) { @@ -211,7 +211,7 @@ upgrade_file_new (const char *filename, return NULL; } snprintf (new_upgrade_file->filename, length, "%s/%s.upgrade", - weechat_home, filename); + weechat_data_dir, filename); new_upgrade_file->callback_read = callback_read; new_upgrade_file->callback_read_pointer = callback_read_pointer; new_upgrade_file->callback_read_data = callback_read_data; diff --git a/src/core/wee-upgrade.c b/src/core/wee-upgrade.c index 3d5967e1b..ba197a135 100644 --- a/src/core/wee-upgrade.c +++ b/src/core/wee-upgrade.c @@ -925,7 +925,7 @@ upgrade_weechat_end () long long time_diff; /* remove .upgrade files */ - dir_exec_on_files (weechat_home, + dir_exec_on_files (weechat_data_dir, 0, 0, &upgrade_weechat_remove_file_cb, NULL); diff --git a/src/core/weechat.c b/src/core/weechat.c index fa8f0fa29..888be9e93 100644 --- a/src/core/weechat.c +++ b/src/core/weechat.c @@ -106,9 +106,13 @@ volatile sig_atomic_t weechat_quit_signal = 0; /* signal received, */ /* WeeChat must quit */ volatile sig_atomic_t weechat_reload_signal = 0; /* signal received, */ /* WeeChat must reload configuration */ -char *weechat_home = NULL; /* home dir. (default: ~/.weechat) */ +char *weechat_home_force = NULL; /* forced home (with -d/--dir) */ int weechat_home_temp = 0; /* 1 if using a temporary home */ int weechat_home_delete_on_exit = 0; /* 1 if home is deleted on exit */ +char *weechat_config_dir = NULL; /* config directory */ +char *weechat_data_dir = NULL; /* data directory */ +char *weechat_cache_dir = NULL; /* cache directory */ +char *weechat_runtime_dir = NULL; /* runtime directory */ int weechat_locale_ok = 0; /* is locale OK? */ char *weechat_local_charset = NULL; /* example: ISO-8859-1, UTF-8 */ int weechat_server_cmd_line = 0; /* at least 1 server on cmd line */ @@ -164,8 +168,7 @@ weechat_display_usage () _(" -a, --no-connect disable auto-connect to servers at " "startup\n" " -c, --colors display default colors in terminal\n" - " -d, --dir <path> set WeeChat home directory " - "(default: ~/.weechat)\n" + " -d, --dir <path> force a single WeeChat home directory\n" " (environment variable WEECHAT_HOME is " "read if this option is not given)\n" " -t, --temp-dir create a temporary WeeChat home" @@ -255,7 +258,7 @@ weechat_parse_args (int argc, char *argv[]) weechat_argv0 = (argv[0]) ? strdup (argv[0]) : NULL; weechat_upgrading = 0; - weechat_home = NULL; + weechat_home_force = NULL; weechat_home_temp = 0; weechat_home_delete_on_exit = 0; weechat_server_cmd_line = 0; @@ -280,16 +283,16 @@ weechat_parse_args (int argc, char *argv[]) break; case 'd': /* -d / --dir */ weechat_home_temp = 0; - if (weechat_home) - free (weechat_home); - weechat_home = strdup (optarg); + if (weechat_home_force) + free (weechat_home_force); + weechat_home_force = strdup (optarg); break; case 't': /* -t / --temp-dir */ weechat_home_temp = 1; - if (weechat_home) + if (weechat_home_force) { - free (weechat_home); - weechat_home = NULL; + free (weechat_home_force); + weechat_home_force = NULL; } break; case 'h': /* -h / --help */ @@ -545,13 +548,21 @@ weechat_shutdown (int return_code, int crash) if (!crash && weechat_home_delete_on_exit) { /* remove temporary home (only if not crashing) */ - dir_rmtree (weechat_home); + dir_remove_home_dirs (); } if (weechat_argv0) free (weechat_argv0); - if (weechat_home) - free (weechat_home); + if (weechat_home_force) + free (weechat_home_force); + if (weechat_config_dir) + free (weechat_config_dir); + if (weechat_data_dir) + free (weechat_data_dir); + if (weechat_cache_dir) + free (weechat_cache_dir); + if (weechat_runtime_dir) + free (weechat_runtime_dir); if (weechat_local_charset) free (weechat_local_charset); if (weechat_force_plugin_autoload) @@ -614,7 +625,7 @@ weechat_init (int argc, char *argv[], void (*gui_init_cb)()) if (!config_weechat_init ()) /* init WeeChat options (weechat.*) */ weechat_shutdown (EXIT_FAILURE, 0); weechat_parse_args (argc, argv); /* parse command line args */ - dir_create_home_dir (); /* create WeeChat home directory */ + dir_create_home_dirs (); /* create WeeChat home directories */ log_init (); /* init log file */ plugin_api_init (); /* create some hooks (info,hdata,..)*/ secure_config_read (); /* read secured data options */ diff --git a/src/core/weechat.h b/src/core/weechat.h index b642b5e1a..50246984a 100644 --- a/src/core/weechat.h +++ b/src/core/weechat.h @@ -112,9 +112,13 @@ extern int weechat_upgrade_count; extern int weechat_quit; extern volatile sig_atomic_t weechat_quit_signal; extern volatile sig_atomic_t weechat_reload_signal; -extern char *weechat_home; +extern char *weechat_home_force; extern int weechat_home_temp; extern int weechat_home_delete_on_exit; +extern char *weechat_config_dir; +extern char *weechat_data_dir; +extern char *weechat_cache_dir; +extern char *weechat_runtime_dir; extern char *weechat_local_charset; extern int weechat_plugin_no_dlclose; extern int weechat_no_gnutls; diff --git a/src/plugins/fifo/fifo-command.c b/src/plugins/fifo/fifo-command.c index 3995fe379..11567d2bf 100644 --- a/src/plugins/fifo/fifo-command.c +++ b/src/plugins/fifo/fifo-command.c @@ -102,7 +102,8 @@ fifo_command_init () "\n" "FIFO pipe is used as remote control of WeeChat: you can send " "commands or text to the FIFO pipe from your shell.\n" - "By default the FIFO pipe is in ~/.weechat/weechat_fifo\n" + "By default the FIFO pipe is called weechat_fifo and saved in the " + "WeeChat runtime directory (see /debug dirs).\n" "\n" "The expected format is one of:\n" " plugin.buffer *text or command here\n" @@ -110,7 +111,7 @@ fifo_command_init () "\n" "For example to change your freenode nick:\n" " echo 'irc.server.freenode */nick newnick' " - ">~/.weechat/weechat_fifo\n" + ">/run/user/1000/weechat/weechat_fifo\n" "\n" "Please read the user's guide for more info and examples.\n" "\n" diff --git a/src/plugins/fifo/fifo.c b/src/plugins/fifo/fifo.c index a266f7f69..d9d8f3ac7 100644 --- a/src/plugins/fifo/fifo.c +++ b/src/plugins/fifo/fifo.c @@ -65,16 +65,26 @@ void fifo_create () { struct stat st; + struct t_hashtable *options; if (!weechat_config_boolean (fifo_config_file_enabled)) return; if (!fifo_filename) { - /* replace %h and "~", evaluate path */ + /* evaluate path */ + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "runtime"); fifo_filename = weechat_string_eval_path_home ( weechat_config_string (fifo_config_file_path), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + weechat_hashtable_free (options); } if (!fifo_filename) diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index 81ea2156e..48581dfb2 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -6570,7 +6570,8 @@ irc_command_init () " /dcc send toto /home/foo/bar.txt"), "chat %(nicks)" " || send %(nicks) " - "%(filename:${modifier:eval_path_home,,${xfer.file.upload_path}})", + "%(filename:${modifier:eval_path_home,directory=data," + "${xfer.file.upload_path}})", &irc_command_dcc, NULL, NULL); weechat_hook_command ( "dehalfop", diff --git a/src/plugins/irc/irc-sasl.c b/src/plugins/irc/irc-sasl.c index 78cc571fe..6a0e42f40 100644 --- a/src/plugins/irc/irc-sasl.c +++ b/src/plugins/irc/irc-sasl.c @@ -95,13 +95,23 @@ char * irc_sasl_get_key_content (struct t_irc_server *server, const char *sasl_key) { char *key_path, *content; + struct t_hashtable *options; if (!sasl_key) return NULL; content = NULL; - key_path = weechat_string_eval_path_home (sasl_key, NULL, NULL, NULL); + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "config"); + key_path = weechat_string_eval_path_home (sasl_key, NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (key_path) content = weechat_file_get_content (key_path); diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index e1cb8ea44..a8fc93ea4 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -4481,6 +4481,7 @@ irc_server_gnutls_callback (const void *pointer, void *data, char *ssl_password; const char *ptr_cert_path, *ptr_fingerprint; int rc, ret, fingerprint_match, hostname_match, cert_temp_init; + struct t_hashtable *options; #if LIBGNUTLS_VERSION_NUMBER >= 0x010706 /* 1.7.6 */ gnutls_datum_t cinfo; int rinfo; @@ -4724,8 +4725,17 @@ irc_server_gnutls_callback (const void *pointer, void *data, IRC_SERVER_OPTION_SSL_CERT); if (ptr_cert_path && ptr_cert_path[0]) { + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "config"); cert_path = weechat_string_eval_path_home (ptr_cert_path, - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (cert_path) { cert_str = weechat_file_get_content (cert_path); diff --git a/src/plugins/logger/logger.c b/src/plugins/logger/logger.c index 1fd9acc0e..fae9c17b3 100644 --- a/src/plugins/logger/logger.c +++ b/src/plugins/logger/logger.c @@ -59,8 +59,7 @@ struct t_hook *logger_hook_print = NULL; * Gets logger file path option. * * Special vars are replaced: - * - "%h" (at beginning of string): WeeChat home - * - "~": user home + * - with call to function string_eval_path_home * - date/time specifiers (see man strftime) * * Note: result must be freed after use. @@ -73,13 +72,23 @@ logger_get_file_path () int length; time_t seconds; struct tm *date_tmp; + struct t_hashtable *options; path = NULL; path2 = NULL; - /* replace %h and "~", evaluate path */ + /* evaluate path */ + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "data"); path = weechat_string_eval_path_home ( - weechat_config_string (logger_config_file_path), NULL, NULL, NULL); + weechat_config_string (logger_config_file_path), NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (!path) goto end; diff --git a/src/plugins/plugin-api-info.c b/src/plugins/plugin-api-info.c index 773742581..4dd6e1d47 100644 --- a/src/plugins/plugin-api-info.c +++ b/src/plugins/plugin-api-info.c @@ -183,27 +183,91 @@ plugin_api_info_dir_separator_cb (const void *pointer, void *data, } /* - * Returns WeeChat info "weechat_dir". + * Returns an absolute path to directory. + * + * Note: result must be freed after use. */ char * -plugin_api_info_weechat_dir_cb (const void *pointer, void *data, - const char *info_name, - const char *arguments) +plugin_api_info_absolute_path (const char *directory) { - char weechat_dir_absolute_path[PATH_MAX]; + char absolute_path[PATH_MAX]; + + if (!realpath (directory, absolute_path)) + return NULL; + return strdup ((absolute_path[0]) ? absolute_path : directory); +} + +/* + * Returns WeeChat info "weechat_config_dir". + */ +char * +plugin_api_info_weechat_config_dir_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ /* make C compiler happy */ (void) pointer; (void) data; (void) info_name; (void) arguments; - if (!realpath (weechat_home, weechat_dir_absolute_path)) - return NULL; + return plugin_api_info_absolute_path (weechat_config_dir); +} + +/* + * Returns WeeChat info "weechat_data_dir". + */ + +char * +plugin_api_info_weechat_data_dir_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + (void) arguments; + + return plugin_api_info_absolute_path (weechat_data_dir); +} + +/* + * Returns WeeChat info "weechat_cache_dir". + */ + +char * +plugin_api_info_weechat_cache_dir_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + (void) arguments; + + return plugin_api_info_absolute_path (weechat_cache_dir); +} + +/* + * Returns WeeChat info "weechat_runtime_dir". + */ + +char * +plugin_api_info_weechat_runtime_dir_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + (void) arguments; - return strdup ((weechat_dir_absolute_path[0]) ? - weechat_dir_absolute_path : weechat_home); + return plugin_api_info_absolute_path (weechat_runtime_dir); } /* @@ -1802,8 +1866,23 @@ plugin_api_info_init () N_("directory separator"), NULL, &plugin_api_info_dir_separator_cb, NULL, NULL); hook_info (NULL, "weechat_dir", - N_("WeeChat directory"), - NULL, &plugin_api_info_weechat_dir_cb, NULL, NULL); + N_("WeeChat directory " + "(*deprecated* since version 3.2, replaced by " + "\"weechat_config_dir\", \"weechat_data_dir\", " + "\"weechat_cache_dir\" and \"weechat_runtime_dir\")"), + NULL, &plugin_api_info_weechat_data_dir_cb, NULL, NULL); + hook_info (NULL, "weechat_config_dir", + N_("WeeChat config directory"), + NULL, &plugin_api_info_weechat_config_dir_cb, NULL, NULL); + hook_info (NULL, "weechat_data_dir", + N_("WeeChat data directory"), + NULL, &plugin_api_info_weechat_data_dir_cb, NULL, NULL); + hook_info (NULL, "weechat_cache_dir", + N_("WeeChat cache directory"), + NULL, &plugin_api_info_weechat_cache_dir_cb, NULL, NULL); + hook_info (NULL, "weechat_runtime_dir", + N_("WeeChat runtime directory"), + NULL, &plugin_api_info_weechat_runtime_dir_cb, NULL, NULL); hook_info (NULL, "weechat_libdir", N_("WeeChat \"lib\" directory"), NULL, &plugin_api_info_weechat_libdir_cb, NULL, NULL); diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c index b22e0be69..95d46bf4c 100644 --- a/src/plugins/plugin-api.c +++ b/src/plugins/plugin-api.c @@ -431,13 +431,36 @@ plugin_api_modifier_eval_path_home_cb (const void *pointer, void *data, const char *modifier_data, const char *string) { + struct t_hashtable *options; + const char *ptr_directory; + char *result; + /* make C compiler happy */ (void) pointer; (void) data; (void) modifier; - (void) modifier_data; - return string_eval_path_home (string, NULL, NULL, NULL); + options = NULL; + ptr_directory = (modifier_data + && (strncmp (modifier_data, "directory=", 10) == 0)) ? + modifier_data + 10 : NULL; + if (ptr_directory) + { + options = hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + hashtable_set (options, "directory", ptr_directory); + } + + result = string_eval_path_home (string, NULL, NULL, options); + + if (options) + hashtable_free (options); + + return result; } /* diff --git a/src/plugins/plugin-script.c b/src/plugins/plugin-script.c index d643e4df8..3feb4b44b 100644 --- a/src/plugins/plugin-script.c +++ b/src/plugins/plugin-script.c @@ -134,26 +134,22 @@ plugin_script_info_version_cb (const void *pointer, void *data, } /* - * Creates directories for plugin in WeeChat home: - * - ~/.weechat/XXX/ - * - ~/.weechat/XXX/autoload/ + * Creates directories for plugin in WeeChat data directory: + * - ${weechat_data_dir}/xxx + * - ${weechat_data_dir}/xxx/autoload */ void plugin_script_create_dirs (struct t_weechat_plugin *weechat_plugin) { - char *string; - int length; - - weechat_mkdir_home (weechat_plugin->name, 0755); - length = strlen (weechat_plugin->name) + strlen ("/autoload") + 1; - string = malloc (length); - if (string) - { - snprintf (string, length, "%s/autoload", weechat_plugin->name); - weechat_mkdir_home (string, 0755); - free (string); - } + char path[PATH_MAX]; + + snprintf (path, sizeof (path), + "${weechat_data_dir}/%s", weechat_plugin->name); + weechat_mkdir_home (path, 0755); + snprintf (path, sizeof (path), + "${weechat_data_dir}/%s/autoload", weechat_plugin->name); + weechat_mkdir_home (path, 0755); } /* @@ -461,26 +457,26 @@ plugin_script_auto_load (struct t_weechat_plugin *weechat_plugin, void (*callback)(void *data, const char *filename)) { - char *dir_home, *dir_name; + char *weechat_data_dir, *dir_name; int dir_length; - /* build directory, adding WeeChat home */ - dir_home = weechat_info_get ("weechat_dir", ""); - if (!dir_home) + /* build directory, adding WeeChat data directory */ + weechat_data_dir = weechat_info_get ("weechat_data_dir", ""); + if (!weechat_data_dir) return; - dir_length = strlen (dir_home) + strlen (weechat_plugin->name) + 16; + dir_length = strlen (weechat_data_dir) + strlen (weechat_plugin->name) + 16; dir_name = malloc (dir_length); if (!dir_name) { - free (dir_home); + free (weechat_data_dir); return; } snprintf (dir_name, dir_length, - "%s/%s/autoload", dir_home, weechat_plugin->name); + "%s/%s/autoload", weechat_data_dir, weechat_plugin->name); weechat_exec_on_files (dir_name, 0, 0, callback, NULL); - free (dir_home); + free (weechat_data_dir); free (dir_name); } @@ -542,64 +538,64 @@ char * plugin_script_search_path (struct t_weechat_plugin *weechat_plugin, const char *filename) { - char *final_name, *dir_home, *dir_system; + char *final_name, *weechat_data_dir, *dir_system; int length; struct stat st; if (filename[0] == '~') return weechat_string_expand_home (filename); - dir_home = weechat_info_get ("weechat_dir", ""); - if (dir_home) + weechat_data_dir = weechat_info_get ("weechat_data_dir", ""); + if (weechat_data_dir) { /* try WeeChat user's autoload dir */ - length = strlen (dir_home) + strlen (weechat_plugin->name) + 8 + + length = strlen (weechat_data_dir) + strlen (weechat_plugin->name) + 8 + strlen (filename) + 16; final_name = malloc (length); if (final_name) { snprintf (final_name, length, "%s/%s/autoload/%s", - dir_home, weechat_plugin->name, filename); + weechat_data_dir, weechat_plugin->name, filename); if ((stat (final_name, &st) == 0) && (st.st_size > 0)) { - free (dir_home); + free (weechat_data_dir); return final_name; } free (final_name); } /* try WeeChat language user's dir */ - length = strlen (dir_home) + strlen (weechat_plugin->name) + + length = strlen (weechat_data_dir) + strlen (weechat_plugin->name) + strlen (filename) + 16; final_name = malloc (length); if (final_name) { snprintf (final_name, length, - "%s/%s/%s", dir_home, weechat_plugin->name, filename); + "%s/%s/%s", weechat_data_dir, weechat_plugin->name, filename); if ((stat (final_name, &st) == 0) && (st.st_size > 0)) { - free (dir_home); + free (weechat_data_dir); return final_name; } free (final_name); } /* try WeeChat user's dir */ - length = strlen (dir_home) + strlen (filename) + 16; + length = strlen (weechat_data_dir) + strlen (filename) + 16; final_name = malloc (length); if (final_name) { snprintf (final_name, length, - "%s/%s", dir_home, filename); + "%s/%s", weechat_data_dir, filename); if ((stat (final_name, &st) == 0) && (st.st_size > 0)) { - free (dir_home); + free (weechat_data_dir); return final_name; } free (final_name); } - free (dir_home); + free (weechat_data_dir); } /* try WeeChat system dir */ @@ -1218,7 +1214,7 @@ plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, char **list) { char **argv, *name, *ptr_base_name, *base_name, *new_path, *autoload_path; - char *symlink_path, str_signal[128], *ptr_list, *dir_home, *dir_separator; + char *symlink_path, str_signal[128], *ptr_list, *weechat_data_dir, *dir_separator; int argc, i, length, rc, autoload, existing_script, script_loaded; struct t_plugin_script *ptr_script; @@ -1283,20 +1279,20 @@ plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, *quiet, 0); /* move file from install dir to language dir */ - dir_home = weechat_info_get ("weechat_dir", ""); - length = strlen (dir_home) + strlen (weechat_plugin->name) + + weechat_data_dir = weechat_info_get ("weechat_data_dir", ""); + length = strlen (weechat_data_dir) + strlen (weechat_plugin->name) + strlen (base_name) + 16; new_path = malloc (length); if (new_path) { snprintf (new_path, length, "%s/%s/%s", - dir_home, weechat_plugin->name, base_name); + weechat_data_dir, weechat_plugin->name, base_name); if (rename (name, new_path) == 0) { /* make link in autoload dir */ if (autoload) { - length = strlen (dir_home) + + length = strlen (weechat_data_dir) + strlen (weechat_plugin->name) + 8 + strlen (base_name) + 16; autoload_path = malloc (length); @@ -1304,7 +1300,7 @@ plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, { snprintf (autoload_path, length, "%s/%s/autoload/%s", - dir_home, weechat_plugin->name, + weechat_data_dir, weechat_plugin->name, base_name); dir_separator = weechat_info_get ("dir_separator", ""); length = 2 + strlen (dir_separator) + @@ -1347,8 +1343,8 @@ plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, free (new_path); } free (base_name); - if (dir_home) - free (dir_home); + if (weechat_data_dir) + free (weechat_data_dir); } free (name); } @@ -1442,7 +1438,7 @@ plugin_script_action_autoload (struct t_weechat_plugin *weechat_plugin, char **list) { char **argv, *name, *ptr_base_name, *base_name, *autoload_path; - char *symlink_path, *ptr_list, *dir_home, *dir_separator; + char *symlink_path, *ptr_list, *weechat_data_dir, *dir_separator; int argc, i, length, rc, autoload; if (!*list) @@ -1490,8 +1486,8 @@ plugin_script_action_autoload (struct t_weechat_plugin *weechat_plugin, base_name = strdup (ptr_base_name); if (base_name) { - dir_home = weechat_info_get ("weechat_dir", ""); - length = strlen (dir_home) + + weechat_data_dir = weechat_info_get ("weechat_data_dir", ""); + length = strlen (weechat_data_dir) + strlen (weechat_plugin->name) + 8 + strlen (base_name) + 16; autoload_path = malloc (length); @@ -1499,7 +1495,7 @@ plugin_script_action_autoload (struct t_weechat_plugin *weechat_plugin, { snprintf (autoload_path, length, "%s/%s/autoload/%s", - dir_home, weechat_plugin->name, + weechat_data_dir, weechat_plugin->name, base_name); if (autoload) { @@ -1525,8 +1521,8 @@ plugin_script_action_autoload (struct t_weechat_plugin *weechat_plugin, free (autoload_path); } free (base_name); - if (dir_home) - free (dir_home); + if (weechat_data_dir) + free (weechat_data_dir); } free (name); } diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 3982e04c5..26cbff783 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -1017,6 +1017,7 @@ plugin_auto_load (char *force_plugin_autoload, struct t_weechat_plugin *ptr_plugin; struct t_plugin_args plugin_args; struct t_arraylist *arraylist; + struct t_hashtable *options; int length, i; plugin_args.argc = argc; @@ -1046,8 +1047,17 @@ plugin_auto_load (char *force_plugin_autoload, && CONFIG_STRING(config_plugin_path) && CONFIG_STRING(config_plugin_path)[0]) { + options = hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + hashtable_set (options, "directory", "data"); plugin_path = string_eval_path_home (CONFIG_STRING(config_plugin_path), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + hashtable_free (options); if (plugin_path) { dir_exec_on_files (plugin_path, 1, 0, diff --git a/src/plugins/python/weechat-python.c b/src/plugins/python/weechat-python.c index 19ad02179..1e84a6cbd 100644 --- a/src/plugins/python/weechat-python.c +++ b/src/plugins/python/weechat-python.c @@ -797,7 +797,7 @@ weechat_python_load (const char *filename, const char *code) #endif /* PY_MAJOR_VERSION >= 3 */ FILE *fp; PyObject *python_path, *path, *module_main, *globals, *rc; - char *weechat_sharedir, *weechat_home; + char *weechat_sharedir, *weechat_data_dir; char *str_sharedir, *str_home; int len; @@ -889,15 +889,15 @@ weechat_python_load (const char *filename, const char *code) free (weechat_sharedir); } - /* adding $weechat_dir/python in $PYTHONPATH */ - weechat_home = weechat_info_get ("weechat_dir", ""); - if (weechat_home) + /* add {weechat_data_dir}/python in $PYTHONPATH */ + weechat_data_dir = weechat_info_get ("weechat_data_dir", ""); + if (weechat_data_dir) { - len = strlen (weechat_home) + 1 + strlen (PYTHON_PLUGIN_NAME) + 1; + len = strlen (weechat_data_dir) + 1 + strlen (PYTHON_PLUGIN_NAME) + 1; str_home = malloc (len); if (str_home) { - snprintf (str_home, len, "%s/python", weechat_home); + snprintf (str_home, len, "%s/python", weechat_data_dir); #if PY_MAJOR_VERSION >= 3 /* python >= 3.x */ path = PyUnicode_FromString (str_home); @@ -912,7 +912,7 @@ weechat_python_load (const char *filename, const char *code) } free (str_home); } - free (weechat_home); + free (weechat_data_dir); } diff --git a/src/plugins/relay/relay-network.c b/src/plugins/relay/relay-network.c index cc0cc83b9..53d6f65e1 100644 --- a/src/plugins/relay/relay-network.c +++ b/src/plugins/relay/relay-network.c @@ -49,15 +49,25 @@ relay_network_set_ssl_cert_key (int verbose) { char *certkey_path; int ret; + struct t_hashtable *options; gnutls_certificate_free_credentials (relay_gnutls_x509_cred); gnutls_certificate_allocate_credentials (&relay_gnutls_x509_cred); relay_network_init_ssl_cert_key_ok = 0; + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "config"); certkey_path = weechat_string_eval_path_home ( weechat_config_string (relay_config_network_ssl_cert_key), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (certkey_path) { ret = gnutls_certificate_set_x509_key_file (relay_gnutls_x509_cred, diff --git a/src/plugins/relay/relay-server.c b/src/plugins/relay/relay-server.c index 8c9b74fde..557ff5b17 100644 --- a/src/plugins/relay/relay-server.c +++ b/src/plugins/relay/relay-server.c @@ -791,6 +791,7 @@ relay_server_new (const char *protocol_string, enum t_relay_protocol protocol, int ipv4, int ipv6, int ssl, int unix_socket) { struct t_relay_server *new_server, *dup_server; + struct t_hashtable *options; if (!protocol_string) return NULL; @@ -823,8 +824,17 @@ relay_server_new (const char *protocol_string, enum t_relay_protocol protocol, new_server->protocol_args = (protocol_args) ? strdup (protocol_args) : NULL; new_server->port = port; + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "runtime"); new_server->path = weechat_string_eval_path_home (path, - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + weechat_hashtable_free (options); new_server->ipv4 = ipv4; new_server->ipv6 = ipv6; new_server->ssl = ssl; @@ -862,8 +872,18 @@ void relay_server_update_path (struct t_relay_server *server, const char *path) { char *new_path; - - new_path = weechat_string_eval_path_home (path, NULL, NULL, NULL); + struct t_hashtable *options; + + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "runtime"); + new_path = weechat_string_eval_path_home (path, NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (!new_path) return; diff --git a/src/plugins/script/script-action.c b/src/plugins/script/script-action.c index 6f4f4b8e9..2113de911 100644 --- a/src/plugins/script/script-action.c +++ b/src/plugins/script/script-action.c @@ -1523,7 +1523,7 @@ script_action_schedule (const char *action, int quiet) { /* create again "script" directory, just in case it has been removed */ - if (!weechat_mkdir_home (SCRIPT_PLUGIN_NAME, 0755)) + if (!weechat_mkdir_home ("${weechat_cache_dir}/" SCRIPT_PLUGIN_NAME, 0755)) return; script_action_add (action); diff --git a/src/plugins/script/script-completion.c b/src/plugins/script/script-completion.c index 5ec3199e9..f0653ea3a 100644 --- a/src/plugins/script/script-completion.c +++ b/src/plugins/script/script-completion.c @@ -189,7 +189,7 @@ script_completion_scripts_files_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { - char *weechat_home, *directory; + char *weechat_data_dir, *directory; int length, i; void *pointers[2]; @@ -199,9 +199,9 @@ script_completion_scripts_files_cb (const void *pointer, void *data, (void) completion_item; (void) buffer; - weechat_home = weechat_info_get ("weechat_dir", NULL); + weechat_data_dir = weechat_info_get ("weechat_data_dir", NULL); - length = strlen (weechat_home) + 128 + 1; + length = strlen (weechat_data_dir) + 128 + 1; directory = malloc (length); if (directory) { @@ -210,16 +210,16 @@ script_completion_scripts_files_cb (const void *pointer, void *data, pointers[0] = completion; pointers[1] = script_extension[i]; - /* look for files in "~/.weechat/<language>/" */ + /* look for files in <weechat_data_dir>/<language> */ snprintf (directory, length, - "%s/%s", weechat_home, script_language[i]); + "%s/%s", weechat_data_dir, script_language[i]); weechat_exec_on_files (directory, 0, 0, &script_completion_exec_file_cb, pointers); - /* look for files in "~/.weechat/<language>/autoload/" */ + /* look for files in <weechat_data_dir>/<language>/autoload */ snprintf (directory, length, - "%s/%s/autoload", weechat_home, script_language[i]); + "%s/%s/autoload", weechat_data_dir, script_language[i]); weechat_exec_on_files (directory, 0, 0, &script_completion_exec_file_cb, pointers); @@ -227,8 +227,8 @@ script_completion_scripts_files_cb (const void *pointer, void *data, free (directory); } - if (weechat_home) - free (weechat_home); + if (weechat_data_dir) + free (weechat_data_dir); return WEECHAT_RC_OK; } diff --git a/src/plugins/script/script-config.c b/src/plugins/script/script-config.c index 79a30ef7a..303857c07 100644 --- a/src/plugins/script/script-config.c +++ b/src/plugins/script/script-config.c @@ -148,8 +148,7 @@ script_config_get_diff_command () } /* - * Gets filename with script - * (by default "/home/xxx/.weechat/script/plugins.xml.gz"). + * Gets filename with list of scripts. * * Note: result must be freed after use. */ @@ -159,9 +158,19 @@ script_config_get_xml_filename () { char *path, *filename; int length; - + struct t_hashtable *options; + + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "cache"); path = weechat_string_eval_path_home ( - weechat_config_string (script_config_scripts_path), NULL, NULL, NULL); + weechat_config_string (script_config_scripts_path), NULL, NULL, options); + if (options) + weechat_hashtable_free (options); length = strlen (path) + 64; filename = malloc (length); if (filename) @@ -172,11 +181,8 @@ script_config_get_xml_filename () /* * Gets filename for a script to download. - * * If suffix is not NULL, it is added to filename. * - * Example: "/home/xxx/.weechat/script/go.py" - * * Note: result must be freed after use. */ @@ -186,9 +192,19 @@ script_config_get_script_download_filename (struct t_script_repo *script, { char *path, *filename; int length; - + struct t_hashtable *options; + + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "cache"); path = weechat_string_eval_path_home ( - weechat_config_string (script_config_scripts_path), NULL, NULL, NULL); + weechat_config_string (script_config_scripts_path), NULL, NULL, options); + if (options) + weechat_hashtable_free (options); length = strlen (path) + 1 + strlen (script->name_with_extension) + ((suffix) ? strlen (suffix) : 0) + 1; filename = malloc (length); diff --git a/src/plugins/script/script-repo.c b/src/plugins/script/script-repo.c index 3627ad2b9..0d4bdd1c0 100644 --- a/src/plugins/script/script-repo.c +++ b/src/plugins/script/script-repo.c @@ -165,28 +165,28 @@ script_repo_search_by_name_ext (const char *name_with_extension) char * script_repo_get_filename_loaded (struct t_script_repo *script) { - char *weechat_home, *filename, resolved_path[PATH_MAX]; + char *weechat_data_dir, *filename, resolved_path[PATH_MAX]; int length; struct stat st; - weechat_home = weechat_info_get ("weechat_dir", NULL); - length = strlen (weechat_home) + strlen (script->name_with_extension) + 64; + weechat_data_dir = weechat_info_get ("weechat_data_dir", NULL); + length = strlen (weechat_data_dir) + strlen (script->name_with_extension) + 64; filename = malloc (length); if (!filename) { - if (weechat_home) - free (weechat_home); + if (weechat_data_dir) + free (weechat_data_dir); return NULL; } snprintf (filename, length, "%s/%s/autoload/%s", - weechat_home, + weechat_data_dir, script_language[script->language], script->name_with_extension); if (stat (filename, &st) != 0) { snprintf (filename, length, "%s/%s/%s", - weechat_home, + weechat_data_dir, script_language[script->language], script->name_with_extension); if (stat (filename, &st) != 0) @@ -195,8 +195,8 @@ script_repo_get_filename_loaded (struct t_script_repo *script) } } - if (weechat_home) - free (weechat_home); + if (weechat_data_dir) + free (weechat_data_dir); if (!filename[0]) { @@ -798,7 +798,7 @@ void script_repo_update_status (struct t_script_repo *script) { const char *version; - char *weechat_home, *filename, *sha512sum; + char *weechat_data_dir, *filename, *sha512sum; struct stat st; int length; struct t_script_repo *ptr_script; @@ -807,13 +807,13 @@ script_repo_update_status (struct t_script_repo *script) sha512sum = NULL; /* check if script is installed (file found on disk) */ - weechat_home = weechat_info_get ("weechat_dir", NULL); - length = strlen (weechat_home) + strlen (script->name_with_extension) + 64; + weechat_data_dir = weechat_info_get ("weechat_data_dir", NULL); + length = strlen (weechat_data_dir) + strlen (script->name_with_extension) + 64; filename = malloc (length); if (filename) { snprintf (filename, length, "%s/%s/autoload/%s", - weechat_home, + weechat_data_dir, script_language[script->language], script->name_with_extension); if (stat (filename, &st) == 0) @@ -825,7 +825,7 @@ script_repo_update_status (struct t_script_repo *script) else { snprintf (filename, length, "%s/%s/%s", - weechat_home, + weechat_data_dir, script_language[script->language], script->name_with_extension); if (stat (filename, &st) == 0) @@ -837,8 +837,8 @@ script_repo_update_status (struct t_script_repo *script) free (filename); } - if (weechat_home) - free (weechat_home); + if (weechat_data_dir) + free (weechat_data_dir); /* check if script is held */ if (script_repo_script_is_held (script)) diff --git a/src/plugins/script/script.c b/src/plugins/script/script.c index b8fe7319d..4cb9189ba 100644 --- a/src/plugins/script/script.c +++ b/src/plugins/script/script.c @@ -371,7 +371,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) script_config_read (); - weechat_mkdir_home (SCRIPT_PLUGIN_NAME, 0755); + weechat_mkdir_home ("${weechat_cache_dir}/" SCRIPT_PLUGIN_NAME, 0755); script_command_init (); script_completion_init (); diff --git a/src/plugins/spell/spell.c b/src/plugins/spell/spell.c index e47fd6ee8..38e6ef5a8 100644 --- a/src/plugins/spell/spell.c +++ b/src/plugins/spell/spell.c @@ -195,9 +195,9 @@ spell_warning_aspell_config () char *aspell_filename, *spell_filename; aspell_filename = weechat_string_eval_path_home ( - "%h/aspell.conf", NULL, NULL, NULL); + "${weechat_config_dir}/aspell.conf", NULL, NULL, NULL); spell_filename = weechat_string_eval_path_home ( - "%h/" SPELL_CONFIG_NAME ".conf", NULL, NULL, NULL); + "${weechat_config_dir}/" SPELL_CONFIG_NAME ".conf", NULL, NULL, NULL); /* if aspell.conf is there and not spell.conf, display a warning */ if (aspell_filename && spell_filename diff --git a/src/plugins/xfer/xfer-file.c b/src/plugins/xfer/xfer-file.c index 0ba198eef..8acae7de1 100644 --- a/src/plugins/xfer/xfer-file.c +++ b/src/plugins/xfer/xfer-file.c @@ -210,13 +210,23 @@ void xfer_file_find_filename (struct t_xfer *xfer) { char *dir_separator, *path; + struct t_hashtable *options; if (!XFER_IS_FILE(xfer->type)) return; + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "data"); path = weechat_string_eval_path_home ( weechat_config_string (xfer_config_file_download_path), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (!path) return; diff --git a/src/plugins/xfer/xfer.c b/src/plugins/xfer/xfer.c index 5eb203b09..447dbc92c 100644 --- a/src/plugins/xfer/xfer.c +++ b/src/plugins/xfer/xfer.c @@ -145,11 +145,20 @@ void xfer_create_directories () { char *path; + struct t_hashtable *options; + + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "data"); /* create download directory */ path = weechat_string_eval_path_home ( weechat_config_string (xfer_config_file_download_path), - NULL, NULL, NULL); + NULL, NULL, options); if (path) { (void) weechat_mkdir_parents (path, 0700); @@ -159,12 +168,15 @@ xfer_create_directories () /* create upload directory */ path = weechat_string_eval_path_home ( weechat_config_string (xfer_config_file_upload_path), - NULL, NULL, NULL); + NULL, NULL, options); if (path) { (void) weechat_mkdir_parents (path, 0700); free (path); } + + if (options) + weechat_hashtable_free (options); } /* @@ -1072,6 +1084,7 @@ xfer_add_cb (const void *pointer, void *data, socklen_t length, bind_addr_len; unsigned long long file_size; struct t_xfer *ptr_xfer; + struct t_hashtable *options; /* make C compiler happy */ (void) pointer; @@ -1170,9 +1183,18 @@ xfer_add_cb (const void *pointer, void *data, filename2 = weechat_string_expand_home (filename); else { + options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (options) + weechat_hashtable_set (options, "directory", "data"); path = weechat_string_eval_path_home ( weechat_config_string (xfer_config_file_upload_path), - NULL, NULL, NULL); + NULL, NULL, options); + if (options) + weechat_hashtable_free (options); if (!path) { weechat_printf (NULL, diff --git a/tests/scripts/test-scripts.cpp b/tests/scripts/test-scripts.cpp index 92aaca9fc..96d408c2f 100644 --- a/tests/scripts/test-scripts.cpp +++ b/tests/scripts/test-scripts.cpp @@ -160,8 +160,9 @@ TEST(Scripts, API) test_scripts_dir, DIR_SEPARATOR, "testapi.py"); - path_testapi_output_dir = string_eval_path_home ("%h/testapi", - NULL, NULL, NULL); + path_testapi_output_dir = string_eval_path_home ( + "${weechat_data_dir}/testapi", + NULL, NULL, NULL); CHECK(path_testapi_output_dir); api_tests_ok = 0; diff --git a/tests/unit/core/test-core-dir.cpp b/tests/unit/core/test-core-dir.cpp index a1a3505a0..361630693 100644 --- a/tests/unit/core/test-core-dir.cpp +++ b/tests/unit/core/test-core-dir.cpp @@ -37,6 +37,16 @@ TEST_GROUP(CoreDir) /* * Tests functions: + * dir_get_temp_dir + */ + +TEST(CoreDir, GetTempDir) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: * dir_mkdir_home * dir_mkdir * dir_mkdir_parents @@ -49,6 +59,16 @@ TEST(CoreDir, Mkdir) /* * Tests functions: + * dir_rmtree + */ + +TEST(CoreDir, Rmtree) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: * dir_exec_on_files */ @@ -62,7 +82,7 @@ TEST(CoreDir, ExecOnFiles) * dir_search_full_lib_name */ -TEST(CoreDir, LibName) +TEST(CoreDir, SearchFullLibName) { /* TODO: write tests */ } @@ -84,7 +104,8 @@ TEST(CoreDir, FileGetContent) POINTERS_EQUAL(NULL, dir_file_get_content ("")); POINTERS_EQUAL(NULL, dir_file_get_content ("/tmp/does/not/exist.xyz")); - path = string_eval_path_home ("%h/test_file.txt", NULL, NULL, NULL); + path = string_eval_path_home ("${weechat_data_dir}/test_file.txt", + NULL, NULL, NULL); /* small file */ length = strlen (content_small); @@ -125,6 +146,37 @@ TEST(CoreDir, FileGetContent) TEST(CoreDir, SetHomePath) { + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_create_home_temp_dir + */ + +TEST(CoreDir, CreateHomeTempDir) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_find_xdg_dirs + */ + +TEST(CoreDir, FindXdgDirs) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_find_home_dirs + */ + +TEST(CoreDir, FindHomeDirs) +{ + /* TODO: write tests */ } /* @@ -134,4 +186,35 @@ TEST(CoreDir, SetHomePath) TEST(CoreDir, CreateHomeDir) { + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_create_home_dirs + */ + +TEST(CoreDir, CreateHomeDirs) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_remove_home_dirs + */ + +TEST(CoreDir, RemoveHomeDirs) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_get_string_home_dirs + */ + +TEST(CoreDir, GetStringHomeDirs) +{ + /* TODO: write tests */ } diff --git a/tests/unit/core/test-core-string.cpp b/tests/unit/core/test-core-string.cpp index 9dd398ac2..b1dddbb2c 100644 --- a/tests/unit/core/test-core-string.cpp +++ b/tests/unit/core/test-core-string.cpp @@ -664,13 +664,17 @@ TEST(CoreString, ExpandHome) TEST(CoreString, EvalPathHome) { char *home, *result; - int length_home, length_weechat_home; - struct t_hashtable *extra_vars; + int length_home, length_weechat_config_dir, length_weechat_data_dir; + int length_weechat_cache_dir, length_weechat_runtime_dir; + struct t_hashtable *extra_vars, *options; home = getenv ("HOME"); length_home = strlen (home); - length_weechat_home = strlen (weechat_home); + length_weechat_config_dir = strlen (weechat_config_dir); + length_weechat_data_dir = strlen (weechat_data_dir); + length_weechat_cache_dir = strlen (weechat_cache_dir); + length_weechat_runtime_dir = strlen (weechat_runtime_dir); POINTERS_EQUAL(NULL, string_eval_path_home (NULL, NULL, NULL, NULL)); @@ -684,19 +688,91 @@ TEST(CoreString, EvalPathHome) STRCMP_EQUAL(result + length_home, "/test"); free (result); + /* "%h" is weechat_data_dir by default */ result = string_eval_path_home ("%h/test", NULL, NULL, NULL); - CHECK(strncmp (result, weechat_home, length_weechat_home) == 0); - LONGS_EQUAL(length_weechat_home + 5, strlen (result)); - STRCMP_EQUAL(result + length_weechat_home, "/test"); + CHECK(strncmp (result, weechat_data_dir, length_weechat_data_dir) == 0); + LONGS_EQUAL(length_weechat_data_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_data_dir, "/test"); + free (result); + + options = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + + /* "%h" with forced config dir */ + hashtable_set (options, "directory", "config"); + result = string_eval_path_home ("%h/test", NULL, NULL, options); + CHECK(strncmp (result, weechat_config_dir, length_weechat_config_dir) == 0); + LONGS_EQUAL(length_weechat_config_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_config_dir, "/test"); + free (result); + + /* "%h" with forced data dir */ + hashtable_set (options, "directory", "data"); + result = string_eval_path_home ("%h/test", NULL, NULL, options); + CHECK(strncmp (result, weechat_data_dir, length_weechat_data_dir) == 0); + LONGS_EQUAL(length_weechat_data_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_data_dir, "/test"); + free (result); + + /* "%h" with forced cache dir */ + hashtable_set (options, "directory", "cache"); + result = string_eval_path_home ("%h/test", NULL, NULL, options); + CHECK(strncmp (result, weechat_cache_dir, length_weechat_cache_dir) == 0); + LONGS_EQUAL(length_weechat_cache_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_cache_dir, "/test"); + free (result); + + /* "%h" with forced runtime dir */ + hashtable_set (options, "directory", "runtime"); + result = string_eval_path_home ("%h/test", NULL, NULL, options); + CHECK(strncmp (result, weechat_runtime_dir, length_weechat_runtime_dir) == 0); + LONGS_EQUAL(length_weechat_runtime_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_runtime_dir, "/test"); + free (result); + + hashtable_free (options); + + /* config dir */ + result = string_eval_path_home ("${weechat_config_dir}/path", + NULL, NULL, NULL); + CHECK(strncmp (result, weechat_config_dir, length_weechat_config_dir) == 0); + LONGS_EQUAL(length_weechat_config_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_config_dir, "/path"); + free (result); + + /* data dir */ + result = string_eval_path_home ("${weechat_data_dir}/path", + NULL, NULL, NULL); + CHECK(strncmp (result, weechat_data_dir, length_weechat_data_dir) == 0); + LONGS_EQUAL(length_weechat_data_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_data_dir, "/path"); + free (result); + + /* cache dir */ + result = string_eval_path_home ("${weechat_cache_dir}/path", + NULL, NULL, NULL); + CHECK(strncmp (result, weechat_cache_dir, length_weechat_cache_dir) == 0); + LONGS_EQUAL(length_weechat_cache_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_cache_dir, "/path"); + free (result); + + /* runtime dir */ + result = string_eval_path_home ("${weechat_runtime_dir}/path", + NULL, NULL, NULL); + CHECK(strncmp (result, weechat_runtime_dir, length_weechat_runtime_dir) == 0); + LONGS_EQUAL(length_weechat_runtime_dir + 5, strlen (result)); + STRCMP_EQUAL(result + length_weechat_runtime_dir, "/path"); free (result); setenv ("WEECHAT_TEST_PATH", "path1", 1); result = string_eval_path_home ("%h/${env:WEECHAT_TEST_PATH}/path2", NULL, NULL, NULL); - CHECK(strncmp (result, weechat_home, length_weechat_home) == 0); - LONGS_EQUAL(length_weechat_home + 12, strlen (result)); - STRCMP_EQUAL(result + length_weechat_home, "/path1/path2"); + CHECK(strncmp (result, weechat_data_dir, length_weechat_data_dir) == 0); + LONGS_EQUAL(length_weechat_data_dir + 12, strlen (result)); + STRCMP_EQUAL(result + length_weechat_data_dir, "/path1/path2"); free (result); extra_vars = hashtable_new (32, @@ -708,9 +784,9 @@ TEST(CoreString, EvalPathHome) result = string_eval_path_home ("%h/${env:WEECHAT_TEST_PATH}/${path2}", NULL, extra_vars, NULL); - CHECK(strncmp (result, weechat_home, length_weechat_home) == 0); - LONGS_EQUAL(length_weechat_home + 12, strlen (result)); - STRCMP_EQUAL(result + length_weechat_home, "/path1/value"); + CHECK(strncmp (result, weechat_data_dir, length_weechat_data_dir) == 0); + LONGS_EQUAL(length_weechat_data_dir + 12, strlen (result)); + STRCMP_EQUAL(result + length_weechat_data_dir, "/path1/value"); free (result); hashtable_free (extra_vars); |