home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / libgimp / gimpenv.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-19  |  13.7 KB  |  561 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
  3.  *
  4.  * gimpenv.c
  5.  *
  6.  * Copyright (C) 1999 Tor Lillqvist
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU Lesser General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. #include "config.h"
  24.  
  25. #include <glib.h>
  26. #include <string.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32.  
  33. #include "gimpenv.h"
  34.  
  35. #ifdef G_OS_WIN32
  36. #define STRICT
  37. #include <windows.h>        /* For GetModuleFileName */
  38. #include <io.h>
  39. #ifndef S_IWUSR
  40. # define S_IWUSR _S_IWRITE
  41. #endif
  42. #ifndef S_IWGRP
  43. #define S_IWGRP (_S_IWRITE>>3)
  44. #define S_IWOTH (_S_IWRITE>>6)
  45. #endif
  46. #ifndef S_ISDIR
  47. # define __S_ISTYPE(mode, mask)    (((mode) & _S_IFMT) == (mask))
  48. # define S_ISDIR(mode)    __S_ISTYPE((mode), _S_IFDIR)
  49. #endif
  50. #define uid_t gint
  51. #define gid_t gint
  52. #define geteuid() 0
  53. #define getegid() 0
  54. #endif
  55.  
  56. #ifdef __EMX__
  57. extern const char *__XOS2RedirRoot(const char *);
  58. #endif
  59.  
  60. /**
  61.  * gimp_directory:
  62.  *
  63.  * Returns the user-specific GIMP settings directory. If the environment 
  64.  * variable GIMP_DIRECTORY exists, it is used. If it is an absolute path, 
  65.  * it is used as is.  If it is a relative path, it is taken to be a 
  66.  * subdirectory of the home directory. If it is relative path, and no home 
  67.  * directory can be determined, it is taken to be a subdirectory of
  68.  * gimp_data_directory().
  69.  *
  70.  * The usual case is that no GIMP_DIRECTORY environment variable exists, 
  71.  * and then we use the GIMPDIR subdirectory of the home directory. If no 
  72.  * home directory exists, we use a per-user subdirectory of
  73.  * gimp_data_directory().
  74.  * In any case, we always return some non-empty string, whether it
  75.  * corresponds to an existing directory or not.
  76.  *
  77.  * The returned string is allocated just once, and should *NOT* be
  78.  * freed with g_free().
  79.  *
  80.  * Returns: The user-specific GIMP settings directory.
  81.  **/
  82. gchar*
  83. gimp_directory (void)
  84. {
  85.   static gchar *gimp_dir = NULL;
  86.   gchar *env_gimp_dir;
  87.   gchar *home_dir;
  88.   gchar *home_dir_sep;
  89.  
  90.   if (gimp_dir != NULL)
  91.     return gimp_dir;
  92.  
  93.   env_gimp_dir = g_getenv ("GIMP_DIRECTORY");
  94.   home_dir = g_get_home_dir ();
  95.  
  96.   if (home_dir != NULL && home_dir[strlen (home_dir)-1] != G_DIR_SEPARATOR)
  97.     home_dir_sep = G_DIR_SEPARATOR_S;
  98.   else
  99.     home_dir_sep = "";
  100.  
  101.   if (NULL != env_gimp_dir)
  102.     {
  103.       if (g_path_is_absolute (env_gimp_dir))
  104.     gimp_dir = g_strdup (env_gimp_dir);
  105.       else
  106.     {
  107.       if (NULL != home_dir)
  108.         {
  109.           gimp_dir = g_strconcat (home_dir,
  110.                       home_dir_sep,
  111.                       env_gimp_dir,
  112.                       NULL);
  113.         }
  114.       else
  115.         {
  116.           gimp_dir = g_strconcat (gimp_data_directory (),
  117.                       G_DIR_SEPARATOR_S,
  118.                       env_gimp_dir,
  119.                       NULL);
  120.         }
  121.     }
  122.     }
  123.   else
  124.     {
  125. #ifdef __EMX__       
  126.     gimp_dir = g_strdup(__XOS2RedirRoot(GIMPDIR));
  127.     return gimp_dir;  
  128. #endif      
  129.     if (NULL != home_dir)
  130.     {
  131.       gimp_dir = g_strconcat (home_dir,
  132.                   home_dir_sep,
  133.                   GIMPDIR,
  134.                   NULL);
  135.     }
  136.       else
  137.     {
  138. #ifndef G_OS_WIN32
  139.       g_message ("warning: no home directory.");
  140. #endif
  141.       gimp_dir = g_strconcat (gimp_data_directory (),
  142.                   G_DIR_SEPARATOR_S,
  143.                   GIMPDIR,
  144.                   ".",
  145.                   g_get_user_name (),
  146.                   NULL);
  147.     }
  148.     }
  149.  
  150.   return gimp_dir;
  151. }
  152.  
  153. /**
  154.  * gimp_personal_rc_file:
  155.  * @basename: The basename of a rc_file.
  156.  *
  157.  * Returns the name of a file in the user-specific GIMP settings directory.
  158.  *
  159.  * The returned string is allocated dynamically and *SHOULD* be freed
  160.  * with g_free() after use.
  161.  *
  162.  * Returns: The name of a file in the user-specific GIMP settings directory.
  163.  **/
  164. gchar*
  165. gimp_personal_rc_file (gchar *basename)
  166. {
  167.   return g_strconcat (gimp_directory (),
  168.               G_DIR_SEPARATOR_S,
  169.               basename,
  170.               NULL);
  171. }
  172.  
  173. /**
  174.  * gimp_data_directory:
  175.  *
  176.  * Returns the top directory for GIMP data. If the environment variable 
  177.  * GIMP_DATADIR exists, that is used.  It should be an absolute pathname.
  178.  * Otherwise, on Unix the compile-time defined directory is used.  On
  179.  * Win32, the installation directory as deduced from the executable's
  180.  * name is used.
  181.  *
  182.  * The returned string is allocated just once, and should *NOT* be
  183.  * freed with g_free().
  184.  *
  185.  * Returns: The top directory for GIMP data.
  186.  **/
  187. gchar*
  188. gimp_data_directory (void)
  189. {
  190.   static gchar *gimp_data_dir = NULL;
  191.   gchar *env_gimp_data_dir = NULL;
  192.   
  193.   if (gimp_data_dir != NULL)
  194.     return gimp_data_dir;
  195.  
  196.   env_gimp_data_dir = g_getenv ("GIMP_DATADIR");
  197.  
  198.   if (NULL != env_gimp_data_dir)
  199.     {
  200.       if (!g_path_is_absolute (env_gimp_data_dir))
  201.     g_error ("GIMP_DATADIR environment variable should be an absolute path.");
  202. #ifndef __EMX__
  203.       gimp_data_dir = g_strdup (env_gimp_data_dir);
  204. #else      
  205.       gimp_data_dir = g_strdup (__XOS2RedirRoot(env_gimp_data_dir));
  206. #endif      
  207.     }
  208.   else
  209.     {
  210. #ifndef G_OS_WIN32
  211. #ifndef __EMX__
  212.       gimp_data_dir = DATADIR;
  213. #else
  214.       gimp_data_dir = g_strdup(__XOS2RedirRoot(DATADIR));
  215. #endif
  216. #else
  217.       /* Figure it out from the executable name */
  218.       gchar filename[MAX_PATH];
  219.       gchar *sep1, *sep2;
  220.  
  221.       if (GetModuleFileName (NULL, filename, sizeof (filename)) == 0)
  222.     g_error ("GetModuleFilename failed\n");
  223.       
  224.       /* If the executable file name is of the format
  225.        * <foobar>\bin\gimp.exe of <foobar>\plug-ins\filter.exe, * use
  226.        * <foobar>. Otherwise, use the directory where the executable
  227.        * is.
  228.        */
  229.  
  230.       sep1 = strrchr (filename, G_DIR_SEPARATOR);
  231.  
  232.       *sep1 = '\0';
  233.  
  234.       sep2 = strrchr (filename, G_DIR_SEPARATOR);
  235.  
  236.       if (sep2 != NULL)
  237.     {
  238.       if (g_strcasecmp (sep2 + 1, "bin") == 0
  239.           || g_strcasecmp (sep2 + 1, "plug-ins") == 0)
  240.         *sep2 = '\0';
  241.     }
  242.  
  243.       gimp_data_dir = g_strdup (filename);
  244. #endif
  245.     }
  246.   return gimp_data_dir;
  247. }
  248.  
  249. /**
  250.  * gimp_sysconf_directory:
  251.  *
  252.  * Returns the top directory for GIMP config files. If the environment
  253.  * variable GIMP_SYSCONFDIR exists, that is used.  It should be an
  254.  * absolute pathname.  Otherwise, on Unix the compile-time defined
  255.  * directory is used.  On Win32, the installation directory as deduced
  256.  * from the executable's name is used.
  257.  *
  258.  * The returned string is allocated just once, and should *NOT* be
  259.  * freed with g_free().
  260.  *
  261.  * Returns: The top directory for GIMP config files.
  262.  **/
  263. gchar*
  264. gimp_sysconf_directory (void)
  265. {
  266.   static gchar *gimp_sysconf_dir = NULL;
  267.   gchar *env_gimp_sysconf_dir = NULL;
  268.   
  269.   if (gimp_sysconf_dir != NULL)
  270.     return gimp_sysconf_dir;
  271.  
  272.   env_gimp_sysconf_dir = g_getenv ("GIMP_SYSCONFDIR");
  273.  
  274.   if (NULL != env_gimp_sysconf_dir)
  275.     {
  276.       if (!g_path_is_absolute (env_gimp_sysconf_dir))
  277.     g_error ("GIMP_SYSCONFDIR environment variable should be an absolute path.");
  278. #ifndef __EMX__
  279.       gimp_sysconf_dir = g_strdup (env_gimp_sysconf_dir);
  280. #else      
  281.       gimp_sysconf_dir = g_strdup (__XOS2RedirRoot(env_gimp_sysconf_dir));
  282. #endif      
  283.     }
  284.   else
  285.     {
  286. #ifndef G_OS_WIN32
  287. #ifndef __EMX__
  288.       gimp_sysconf_dir = SYSCONFDIR;
  289. #else
  290.       gimp_sysconf_dir = g_strdup(__XOS2RedirRoot(SYSCONFDIR));
  291. #endif
  292. #else
  293.       /* Figure it out from the executable name */
  294.       gchar filename[MAX_PATH];
  295.       gchar *sep1, *sep2;
  296.  
  297.       if (GetModuleFileName (NULL, filename, sizeof (filename)) == 0)
  298.     g_error ("GetModuleFilename failed\n");
  299.       
  300.       /* If the executable file name is of the format
  301.        * <foobar>\bin\gimp.exe of <foobar>\plug-ins\filter.exe, * use
  302.        * <foobar>. Otherwise, use the directory where the executable
  303.        * is.
  304.        */
  305.  
  306.       sep1 = strrchr (filename, G_DIR_SEPARATOR);
  307.  
  308.       *sep1 = '\0';
  309.  
  310.       sep2 = strrchr (filename, G_DIR_SEPARATOR);
  311.  
  312.       if (sep2 != NULL)
  313.     {
  314.       if (g_strcasecmp (sep2 + 1, "bin") == 0
  315.           || g_strcasecmp (sep2 + 1, "plug-ins") == 0)
  316.         *sep2 = '\0';
  317.     }
  318.  
  319.       gimp_sysconf_dir = g_strdup (filename);
  320. #endif
  321.     }
  322.   return gimp_sysconf_dir;
  323. }
  324.  
  325. /**
  326.  * gimp_gtkrc:
  327.  *
  328.  * Returns the name of the GIMP's application-specific gtkrc file.
  329.  *
  330.  * The returned string is allocated just once, and should *NOT* be
  331.  * freed with g_free().
  332.  *
  333.  * Returns: The name of the GIMP's application-specific gtkrc file.
  334.  **/ 
  335. gchar*
  336. gimp_gtkrc (void)
  337. {
  338.   static gchar *gimp_gtkrc_filename = NULL;
  339.  
  340.   if (gimp_gtkrc_filename != NULL)
  341.     return gimp_gtkrc_filename;
  342.   
  343.  
  344.   gimp_gtkrc_filename = g_strconcat (gimp_sysconf_directory (),
  345.                      G_DIR_SEPARATOR_S,
  346.                      "gtkrc",
  347.                      NULL);
  348.   return gimp_gtkrc_filename;
  349. }
  350.  
  351. /**
  352.  * gimp_path_parse:
  353.  * @path: A list of directories separated by #G_SEARCHPATH_SEPARATOR.
  354.  * @max_paths: The maximum number of directories to return.
  355.  * @check: #TRUE if you want the directories to be checked.
  356.  * @check_failed: Returns a #GList of path elements for which the
  357.  *                check failed. Each list element is guaranteed
  358.  *          to end with a #G_PATH_SEPARATOR.
  359.  *
  360.  * Returns: A #GList of all directories in @path. Each list element
  361.  *        is guaranteed to end with a #G_PATH_SEPARATOR.
  362.  **/
  363. GList *
  364. gimp_path_parse (gchar     *path,
  365.          gint       max_paths,
  366.          gboolean   check,
  367.          GList    **check_failed)
  368. {
  369.   gchar  *home;
  370.   gchar **patharray;
  371.   GList  *list = NULL;
  372.   GList  *fail_list = NULL;
  373.   gint    i;
  374.  
  375.   struct stat filestat;
  376.   gint        err = FALSE;
  377.  
  378.   if (!path || !*path || max_paths < 1 || max_paths > 256)
  379.     return NULL;
  380.  
  381.   home = g_get_home_dir ();
  382.  
  383.   patharray = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, max_paths);
  384.  
  385.   for (i = 0; i < max_paths; i++)
  386.     {
  387.       GString *dir;
  388.  
  389.       if (!patharray[i])
  390.     break;
  391.  
  392. #ifndef G_OS_WIN32
  393.       if (*patharray[i] == '~')
  394.     {
  395.       dir = g_string_new (home);
  396.       g_string_append (dir, patharray[i] + 1);
  397.     }
  398.       else
  399. #endif
  400.     {
  401.       dir = g_string_new (patharray[i]);
  402.     }
  403.  
  404. #ifdef __EMX__
  405.       _fnslashify (dir);
  406. #endif
  407.  
  408.       if (check)
  409.     {
  410.       /*  check if directory exists  */
  411.       err = stat (dir->str, &filestat);
  412.  
  413.       if (!err && S_ISDIR (filestat.st_mode))
  414.         {
  415.           if (dir->str[dir->len - 1] != G_DIR_SEPARATOR)
  416.         g_string_append_c (dir, G_DIR_SEPARATOR);
  417.         }
  418.     }
  419.  
  420.       if (!err)
  421.     list = g_list_prepend (list, g_strdup (dir->str));
  422.       else if (check_failed)
  423.     fail_list = g_list_prepend (fail_list, g_strdup (dir->str));
  424.  
  425.       g_string_free (dir, TRUE);
  426.     }
  427.  
  428.   g_strfreev (patharray);
  429.  
  430.   list = g_list_reverse (list);
  431.  
  432.   if (check && check_failed)
  433.     {
  434.       fail_list = g_list_reverse (fail_list);
  435.       *check_failed = fail_list;
  436.     }
  437.  
  438.   return list;
  439. }
  440.  
  441. /**
  442.  * gimp_path_to_str:
  443.  * @path: A list of directories as returned by gimp_path_parse().
  444.  *
  445.  * Returns: A searchpath string separated by #G_SEARCHPATH_SEPARATOR.
  446.  **/
  447. gchar *
  448. gimp_path_to_str (GList *path)
  449. {
  450.   GString *str = NULL;
  451.   GList   *list;
  452.   gchar   *retval = NULL;
  453.  
  454.   for (list = path; list; list = g_list_next (list))
  455.     {
  456.       if (str)
  457.     {
  458.       g_string_append_c (str, G_SEARCHPATH_SEPARATOR);
  459.       g_string_append (str, (gchar *) list->data);
  460.     }
  461.       else
  462.     {
  463.       str = g_string_new ((gchar *) list->data);
  464.     }
  465.     }
  466.  
  467.   if (str)
  468.     {
  469.       retval = str->str;
  470.       g_string_free (str, FALSE);
  471.     }
  472.  
  473.   return retval;
  474. }
  475.  
  476. /**
  477.  * gimp_path_free:
  478.  * @path: A list of directories as returned by gimp_path_parse().
  479.  *
  480.  * This function frees the memory allocated for the list and it's strings.
  481.  **/
  482. void
  483. gimp_path_free (GList *path)
  484. {
  485.   GList *list;
  486.  
  487.   if (path)
  488.     {
  489.       for (list = path; list; list = g_list_next (list))
  490.     {
  491.       g_free (list->data);
  492.     }
  493.  
  494.       g_list_free (path);
  495.     }
  496. }
  497.  
  498. /**
  499.  * gimp_path_get_user_writable_dir:
  500.  * @path: A list of directories as returned by gimp_path_parse().
  501.  *
  502.  * Note that you have to g_free() the returned string.
  503.  *
  504.  * Returns: The first directory in @path where the user has write permission.
  505.  **/
  506. gchar *
  507. gimp_path_get_user_writable_dir (GList *path)
  508. {
  509.   GList *list;
  510.  
  511.   uid_t euid;
  512.   gid_t egid;
  513.  
  514.   struct stat filestat;
  515.   gint        err;
  516.  
  517.   euid = geteuid ();
  518.   egid = getegid ();
  519.  
  520.   for (list = path; list; list = g_list_next (list))
  521.     {
  522.       /*  check if directory exists  */
  523.  
  524.       /* ugly hack to handle paths with an extra G_DIR_SEPARATOR
  525.        * attached. The stat() in MSVCRT doesn't like that.
  526.        */
  527.       gchar *dir = g_strdup ((gchar *) list->data);
  528.       gchar *p = dir;
  529.       gint pl;
  530.  
  531.       if (g_path_is_absolute (dir))
  532.     p = g_path_skip_root (dir);
  533.       pl = strlen (p);
  534.       if (pl > 0 && p[pl-1] == G_DIR_SEPARATOR)
  535.     p[pl-1] = '\0';
  536.       err = stat (dir, &filestat);
  537.       g_free (dir);
  538.  
  539.       /*  this is tricky:
  540.        *  if a file is e.g. owned by the current user but not user-writable,
  541.        *  the user has no permission to write to the file regardless
  542.        *  of his group's or other's write permissions
  543.        */
  544.       if (!err && S_ISDIR (filestat.st_mode) &&
  545.  
  546.       ((filestat.st_mode & S_IWUSR) ||
  547.  
  548.        ((filestat.st_mode & S_IWGRP) &&
  549.         (euid != filestat.st_uid)) ||
  550.  
  551.        ((filestat.st_mode & S_IWOTH) &&
  552.         (euid != filestat.st_uid) &&
  553.         (egid != filestat.st_gid))))
  554.     {
  555.       return g_strdup ((gchar *) list->data);
  556.     }
  557.     }
  558.  
  559.   return NULL;
  560. }
  561.