/* Giram: a simple 3D modeller * Copyright (C) 2001 DindinX * * LIBGIMP - The GIMP Library * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis * * giramenv.c * * Copyright (C) 1999 Tor Lillqvist * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "giramenv.h" /** * giram_directory: * * Returns the user-specific GIRAM settings directory. If the * environment variable GIRAM_DIRECTORY exists, it is used. If it is an * absolute path, it is used as is. If it is a relative path, it is * taken to be a subdirectory of the home directory. If it is a * relative path, and no home directory can be determined, it is taken * to be a subdirectory of giram_data_directory(). * * The usual case is that no GIRAM_DIRECTORY environment variable * exists, and then we use the GIRAMDIR subdirectory of the home * directory. If no home directory exists, we use a per-user * subdirectory of giram_data_directory(). In any case, we always * return some non-empty string, whether it corresponds to an existing * directory or not. * * The returned string is allocated just once, and should *NOT* be * freed with g_free(). * * Returns: The user-specific GIRAM settings directory. **/ const gchar *giram_directory(void) { static gchar *giram_dir = NULL; gchar *env_giram_dir; gchar *home_dir; gchar *home_dir_sep; if (giram_dir != NULL) return giram_dir; env_giram_dir = (gchar *)g_getenv("GIRAM_DIRECTORY"); home_dir = (gchar *)g_get_home_dir(); if (home_dir != NULL && home_dir[strlen(home_dir)-1] != G_DIR_SEPARATOR) home_dir_sep = G_DIR_SEPARATOR_S; else home_dir_sep = ""; if (NULL != env_giram_dir) { if (g_path_is_absolute(env_giram_dir)) giram_dir = g_strdup(env_giram_dir); else { if (NULL != home_dir) { giram_dir = g_strconcat(home_dir, home_dir_sep, env_giram_dir, NULL); } else { giram_dir = g_strconcat(giram_data_directory(), G_DIR_SEPARATOR_S, env_giram_dir, NULL); } } } else { if (NULL != home_dir) { giram_dir = g_strconcat(home_dir, home_dir_sep, GIRAMDIR, NULL); } else { g_message("warning: no home directory."); giram_dir = g_strconcat(giram_data_directory(), G_DIR_SEPARATOR_S, GIRAMDIR, ".", g_get_user_name(), NULL); } } return giram_dir; } /** * giram_personal_rc_file: * @basename: The basename of a rc_file. * * Returns the name of a file in the user-specific GIRAM settings directory. * * The returned string is allocated dynamically and *SHOULD* be freed * with g_free() after use. * * Returns: The name of a file in the user-specific GIRAM settings directory. **/ gchar *giram_personal_rc_file(const gchar *basename) { return g_strconcat(giram_directory(), G_DIR_SEPARATOR_S, basename, NULL); } /** * giram_data_directory: * * Returns the top directory for GIRAM data. If the environment variable * GIRAM_DATADIR exists, that is used. It should be an absolute pathname. * Otherwise, on Unix the compile-time defined directory is used. * * The returned string is allocated just once, and should *NOT* be * freed with g_free(). * * Returns: The top directory for GIRAM data. **/ const gchar *giram_data_directory(void) { static gchar *giram_data_dir = NULL; gchar *env_giram_data_dir = NULL; if (giram_data_dir != NULL) return giram_data_dir; env_giram_data_dir = (gchar*)g_getenv("GIRAM_DATADIR"); if (NULL != env_giram_data_dir) { if (!g_path_is_absolute(env_giram_data_dir)) g_error("GIRAM_DATADIR environment variable should be an absolute path."); giram_data_dir = g_strdup(env_giram_data_dir); } else { giram_data_dir = DATADIR; } return giram_data_dir; } /** * giram_sysconf_directory: * * Returns the top directory for GIRAM config files. If the environment * variable GIRAM_SYSCONFDIR exists, that is used. It should be an * absolute pathname. Otherwise, on Unix the compile-time defined * directory is used. * * The returned string is allocated just once, and should *NOT* be * freed with g_free(). * * Returns: The top directory for GIRAM config files. **/ const gchar *giram_sysconf_directory(void) { static gchar *giram_sysconf_dir = NULL; gchar *env_giram_sysconf_dir = NULL; if (giram_sysconf_dir != NULL) return giram_sysconf_dir; env_giram_sysconf_dir = (gchar *)g_getenv("GIRAM_SYSCONFDIR"); if (NULL != env_giram_sysconf_dir) { if (!g_path_is_absolute(env_giram_sysconf_dir)) g_error("GIRAM_SYSCONFDIR environment variable should be an absolute path."); giram_sysconf_dir = g_strdup(env_giram_sysconf_dir); } else { giram_sysconf_dir = SYSCONFDIR; } return giram_sysconf_dir; } /** * giram_gtkrc: * * Returns the name of the GIRAM's application-specific gtkrc file. * * The returned string is allocated just once, and should *NOT* be * freed with g_free(). * * Returns: The name of the GIRAM's application-specific gtkrc file. **/ const gchar *giram_gtkrc (void) { static gchar *giram_gtkrc_filename = NULL; if (giram_gtkrc_filename != NULL) return giram_gtkrc_filename; giram_gtkrc_filename = g_strconcat(giram_sysconf_directory(), G_DIR_SEPARATOR_S, "gtkrc", NULL); return giram_gtkrc_filename; } /** * giram_path_parse: * @path: A list of directories separated by #G_SEARCHPATH_SEPARATOR. * @max_paths: The maximum number of directories to return. * @check: #TRUE if you want the directories to be checked. * @check_failed: Returns a #GList of path elements for which the * check failed. Each list element is guaranteed * to end with a #G_PATH_SEPARATOR. * * Returns: A #GList of all directories in @path. Each list element * is guaranteed to end with a #G_PATH_SEPARATOR. **/ GList *giram_path_parse(const gchar *path, gint max_paths, gboolean check, GList **check_failed) { gchar *home; gchar **patharray; GList *list = NULL; GList *fail_list = NULL; gint i; struct stat filestat; gint err = FALSE; if (!path || !*path || max_paths < 1 || max_paths > 256) return NULL; home = (gchar*)g_get_home_dir(); patharray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, max_paths); for (i = 0; i < max_paths; i++) { GString *dir; if (!patharray[i]) break; if (*patharray[i] == '~') { dir = g_string_new(home); g_string_append(dir, patharray[i] + 1); } else { dir = g_string_new(patharray[i]); } if (check) { /* check if directory exists */ err = stat(dir->str, &filestat); if (!err && S_ISDIR(filestat.st_mode)) { if (dir->str[dir->len - 1] != G_DIR_SEPARATOR) g_string_append_c(dir, G_DIR_SEPARATOR); } } if (!err) list = g_list_prepend(list, g_strdup(dir->str)); else if (check_failed) fail_list = g_list_prepend(fail_list, g_strdup(dir->str)); g_string_free(dir, TRUE); } g_strfreev(patharray); list = g_list_reverse(list); if (check && check_failed) { fail_list = g_list_reverse(fail_list); *check_failed = fail_list; } return list; } /** * giram_path_to_str: * @path: A list of directories as returned by giram_path_parse(). * * Returns: A searchpath string separated by #G_SEARCHPATH_SEPARATOR. **/ gchar *giram_path_to_str(GList *path) { GString *str = NULL; GList *list; gchar *retval = NULL; for (list = path; list; list = g_list_next(list)) { if (str) { g_string_append_c(str, G_SEARCHPATH_SEPARATOR); g_string_append(str, (gchar *)list->data); } else { str = g_string_new((gchar *)list->data); } } if (str) { retval = str->str; g_string_free(str, FALSE); } return retval; } /** * giram_path_free: * @path: A list of directories as returned by giram_path_parse(). * * This function frees the memory allocated for the list and it's strings. **/ void giram_path_free(GList *path) { GList *list; if (path) { for (list = path; list; list = g_list_next(list)) { g_free(list->data); } g_list_free(path); } } /** * giram_path_get_user_writable_dir: * @path: A list of directories as returned by giram_path_parse(). * * Note that you have to g_free() the returned string. * * Returns: The first directory in @path where the user has write permission. **/ gchar *giram_path_get_user_writable_dir(GList *path) { GList *list; uid_t euid; gid_t egid; struct stat filestat; gint err; euid = geteuid(); egid = getegid(); for (list = path; list; list = g_list_next(list)) { /* check if directory exists */ /* ugly hack to handle paths with an extra G_DIR_SEPARATOR * attached. */ gchar *dir = g_strdup((gchar *)list->data); gchar *p = dir; gint pl; if (g_path_is_absolute(dir)) p = (gchar *)g_path_skip_root(dir); pl = strlen(p); if (pl > 0 && p[pl-1] == G_DIR_SEPARATOR) p[pl-1] = '\0'; err = stat(dir, &filestat); g_free(dir); /* this is tricky: * if a file is e.g. owned by the current user but not user-writable, * the user has no permission to write to the file regardless * of his group's or other's write permissions */ if (!err && S_ISDIR(filestat.st_mode) && ((filestat.st_mode & S_IWUSR) || ((filestat.st_mode & S_IWGRP) && (euid != filestat.st_uid)) || ((filestat.st_mode & S_IWOTH) && (euid != filestat.st_uid) && (egid != filestat.st_gid)))) { return g_strdup((gchar *)list->data); } } return NULL; }