4ad4995705317a7fa50111c4c6821af6e609170f
[platform/upstream/glib.git] / glib / gutils.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
29  */
30
31 #include "config.h"
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <locale.h>
40 #include <string.h>
41 #include <errno.h>
42 #ifdef HAVE_PWD_H
43 #include <pwd.h>
44 #endif
45 #include <sys/types.h>
46 #ifdef HAVE_SYS_PARAM_H
47 #include <sys/param.h>
48 #endif
49
50 /* implement gutils's inline functions
51  */
52 #define G_IMPLEMENT_INLINES 1
53 #define __G_UTILS_C__
54 #include "glib.h"
55 #include "gprintfint.h"
56 #include "gthreadinit.h"
57 #include "galias.h"
58
59 #ifdef  MAXPATHLEN
60 #define G_PATH_LENGTH   MAXPATHLEN
61 #elif   defined (PATH_MAX)
62 #define G_PATH_LENGTH   PATH_MAX
63 #elif   defined (_PC_PATH_MAX)
64 #define G_PATH_LENGTH   sysconf(_PC_PATH_MAX)
65 #else   
66 #define G_PATH_LENGTH   2048
67 #endif
68
69 #ifdef G_PLATFORM_WIN32
70 #  define STRICT                /* Strict typing, please */
71 #  include <windows.h>
72 #  undef STRICT
73 #  include <lmcons.h>           /* For UNLEN */
74 #endif /* G_PLATFORM_WIN32 */
75
76 #ifdef G_OS_WIN32
77 #  include <direct.h>
78 #  include <shlobj.h>
79    /* older SDK (e.g. msvc 5.0) does not have these*/
80 #  ifndef CSIDL_INTERNET_CACHE
81 #    define CSIDL_INTERNET_CACHE 32
82 #  endif
83 #  ifndef CSIDL_COMMON_APPDATA
84 #    define CSIDL_COMMON_APPDATA 35
85 #  endif
86 #  ifndef CSIDL_COMMON_DOCUMENTS
87 #    define CSIDL_COMMON_DOCUMENTS 46
88 #  endif
89 #  ifndef CSIDL_PROFILE
90 #    define CSIDL_PROFILE 40
91 #  endif
92 #endif
93
94 #ifdef HAVE_CODESET
95 #include <langinfo.h>
96 #endif
97
98 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
99 #include <libintl.h>
100 #endif
101
102 const guint glib_major_version = GLIB_MAJOR_VERSION;
103 const guint glib_minor_version = GLIB_MINOR_VERSION;
104 const guint glib_micro_version = GLIB_MICRO_VERSION;
105 const guint glib_interface_age = GLIB_INTERFACE_AGE;
106 const guint glib_binary_age = GLIB_BINARY_AGE;
107
108 /**
109  * glib_check_version:
110  * @required_major: the required major version.
111  * @required_minor: the required major version.
112  * @required_micro: the required major version.
113  *
114  * Checks that the GLib library in use is compatible with the
115  * given version. Generally you would pass in the constants
116  * #GLIB_MAJOR_VERSION, #GLIB_MINOR_VERSION, #GLIB_MICRO_VERSION
117  * as the three arguments to this function; that produces
118  * a check that the library in use is compatible with
119  * the version of GLib the application or module was compiled
120  * against.
121  *
122  * Compatibility is defined by two things: first the version
123  * of the running library is newer than the version
124  * @required_major.required_minor.@required_micro. Second
125  * the running library must be binary compatible with the
126  * version @required_major.required_minor.@required_micro
127  * (same major version.)
128  *
129  * Return value: %NULL if the GLib library is compatible with the
130  *   given version, or a string describing the version mismatch.
131  *   The returned string is owned by GLib and must not be modified
132  *   or freed.
133  *
134  * Since: 2.6
135  **/
136 const gchar *
137 glib_check_version (guint required_major,
138                     guint required_minor,
139                     guint required_micro)
140 {
141   gint glib_effective_micro = 100 * GLIB_MINOR_VERSION + GLIB_MICRO_VERSION;
142   gint required_effective_micro = 100 * required_minor + required_micro;
143
144   if (required_major > GLIB_MAJOR_VERSION)
145     return "GLib version too old (major mismatch)";
146   if (required_major < GLIB_MAJOR_VERSION)
147     return "GLib version too new (major mismatch)";
148   if (required_effective_micro < glib_effective_micro - GLIB_BINARY_AGE)
149     return "GLib version too new (micro mismatch)";
150   if (required_effective_micro > glib_effective_micro)
151     return "GLib version too old (micro mismatch)";
152   return NULL;
153 }
154
155 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
156 /**
157  * g_memmove: 
158  * @dest: the destination address to copy the bytes to.
159  * @src: the source address to copy the bytes from.
160  * @len: the number of bytes to copy.
161  *
162  * Copies a block of memory @len bytes long, from @src to @dest.
163  * The source and destination areas may overlap.
164  *
165  * In order to use this function, you must include 
166  * <filename>string.h</filename> yourself, because this macro will 
167  * typically simply resolve to memmove() and GLib does not include 
168  * <filename>string.h</filename> for you.
169  */
170 void 
171 g_memmove (gpointer      dest, 
172            gconstpointer src, 
173            gulong        len)
174 {
175   gchar* destptr = dest;
176   const gchar* srcptr = src;
177   if (src + len < dest || dest + len < src)
178     {
179       bcopy (src, dest, len);
180       return;
181     }
182   else if (dest <= src)
183     {
184       while (len--)
185         *(destptr++) = *(srcptr++);
186     }
187   else
188     {
189       destptr += len;
190       srcptr += len;
191       while (len--)
192         *(--destptr) = *(--srcptr);
193     }
194 }
195 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
196
197 /**
198  * g_atexit:
199  * @func: the function to call on normal program termination.
200  * 
201  * Specifies a function to be called at normal program termination.
202  */
203 void
204 g_atexit (GVoidFunc func)
205 {
206   gint result;
207   const gchar *error = NULL;
208
209   /* keep this in sync with glib.h */
210
211 #ifdef  G_NATIVE_ATEXIT
212   result = ATEXIT (func);
213   if (result)
214     error = g_strerror (errno);
215 #elif defined (HAVE_ATEXIT)
216 #  ifdef NeXT /* @#%@! NeXTStep */
217   result = !atexit ((void (*)(void)) func);
218   if (result)
219     error = g_strerror (errno);
220 #  else
221   result = atexit ((void (*)(void)) func);
222   if (result)
223     error = g_strerror (errno);
224 #  endif /* NeXT */
225 #elif defined (HAVE_ON_EXIT)
226   result = on_exit ((void (*)(int, void *)) func, NULL);
227   if (result)
228     error = g_strerror (errno);
229 #else
230   result = 0;
231   error = "no implementation";
232 #endif /* G_NATIVE_ATEXIT */
233
234   if (error)
235     g_error ("Could not register atexit() function: %s", error);
236 }
237
238 /* Based on execvp() from GNU Libc.
239  * Some of this code is cut-and-pasted into gspawn.c
240  */
241
242 static gchar*
243 my_strchrnul (const gchar *str, 
244               gchar        c)
245 {
246   gchar *p = (gchar*)str;
247   while (*p && (*p != c))
248     ++p;
249
250   return p;
251 }
252
253 #ifdef G_OS_WIN32
254
255 static gchar *inner_find_program_in_path (const gchar *program);
256
257 gchar*
258 g_find_program_in_path (const gchar *program)
259 {
260   const gchar *last_dot = strrchr (program, '.');
261
262   if (last_dot == NULL ||
263       strchr (last_dot, '\\') != NULL ||
264       strchr (last_dot, '/') != NULL)
265     {
266       const gint program_length = strlen (program);
267       gchar *pathext = g_build_path (";",
268                                      ".exe;.cmd;.bat;.com",
269                                      g_getenv ("PATHEXT"),
270                                      NULL);
271       gchar *p;
272       gchar *decorated_program;
273       gchar *retval;
274
275       p = pathext;
276       do
277         {
278           gchar *q = my_strchrnul (p, ';');
279
280           decorated_program = g_malloc (program_length + (q-p) + 1);
281           memcpy (decorated_program, program, program_length);
282           memcpy (decorated_program+program_length, p, q-p);
283           decorated_program [program_length + (q-p)] = '\0';
284           
285           retval = inner_find_program_in_path (decorated_program);
286           g_free (decorated_program);
287
288           if (retval != NULL)
289             {
290               g_free (pathext);
291               return retval;
292             }
293           p = q;
294         } while (*p++ != '\0');
295       g_free (pathext);
296       return NULL;
297     }
298   else
299     return inner_find_program_in_path (program);
300 }
301
302 #endif
303
304 /**
305  * g_find_program_in_path:
306  * @program: a program name in the GLib file name encoding
307  * 
308  * Locates the first executable named @program in the user's path, in the
309  * same way that execvp() would locate it. Returns an allocated string
310  * with the absolute path name, or %NULL if the program is not found in
311  * the path. If @program is already an absolute path, returns a copy of
312  * @program if @program exists and is executable, and %NULL otherwise.
313  *  
314  * On Windows, if @program does not have a file type suffix, tries
315  * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
316  * the <envar>PATHEXT</envar> environment variable. 
317  * 
318  * On Windows, it looks for the file in the same way as CreateProcess() 
319  * would. This means first in the directory where the executing
320  * program was loaded from, then in the current directory, then in the
321  * Windows 32-bit system directory, then in the Windows directory, and
322  * finally in the directories in the <envar>PATH</envar> environment 
323  * variable. If the program is found, the return value contains the 
324  * full name including the type suffix.
325  *
326  * Return value: absolute path, or %NULL
327  **/
328 #ifdef G_OS_WIN32
329 static gchar *
330 inner_find_program_in_path (const gchar *program)
331 #else
332 gchar*
333 g_find_program_in_path (const gchar *program)
334 #endif
335 {
336   const gchar *path, *p;
337   gchar *name, *freeme;
338 #ifdef G_OS_WIN32
339   const gchar *path_copy;
340   gchar *filename = NULL, *appdir = NULL;
341   gchar *sysdir = NULL, *windir = NULL;
342 #endif
343   size_t len;
344   size_t pathlen;
345
346   g_return_val_if_fail (program != NULL, NULL);
347
348   /* If it is an absolute path, or a relative path including subdirectories,
349    * don't look in PATH.
350    */
351   if (g_path_is_absolute (program)
352       || strchr (program, G_DIR_SEPARATOR) != NULL
353 #ifdef G_OS_WIN32
354       || strchr (program, '/') != NULL
355 #endif
356       )
357     {
358       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
359           !g_file_test (program, G_FILE_TEST_IS_DIR))
360         return g_strdup (program);
361       else
362         return NULL;
363     }
364   
365   path = g_getenv ("PATH");
366 #ifdef G_OS_UNIX
367   if (path == NULL)
368     {
369       /* There is no `PATH' in the environment.  The default
370        * search path in GNU libc is the current directory followed by
371        * the path `confstr' returns for `_CS_PATH'.
372        */
373       
374       /* In GLib we put . last, for security, and don't use the
375        * unportable confstr(); UNIX98 does not actually specify
376        * what to search if PATH is unset. POSIX may, dunno.
377        */
378       
379       path = "/bin:/usr/bin:.";
380     }
381 #else
382   if (G_WIN32_HAVE_WIDECHAR_API ())
383     {
384       int n;
385       wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
386         wwindir[MAXPATHLEN];
387       
388       n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
389       if (n > 0 && n < MAXPATHLEN)
390         filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
391       
392       n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
393       if (n > 0 && n < MAXPATHLEN)
394         sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
395       
396       n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
397       if (n > 0 && n < MAXPATHLEN)
398         windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL);
399     }
400   else
401     {
402       int n;
403       gchar cpfilename[MAXPATHLEN], cpsysdir[MAXPATHLEN],
404         cpwindir[MAXPATHLEN];
405       
406       n = GetModuleFileNameA (NULL, cpfilename, MAXPATHLEN);
407       if (n > 0 && n < MAXPATHLEN)
408         filename = g_locale_to_utf8 (cpfilename, -1, NULL, NULL, NULL);
409       
410       n = GetSystemDirectoryA (cpsysdir, MAXPATHLEN);
411       if (n > 0 && n < MAXPATHLEN)
412         sysdir = g_locale_to_utf8 (cpsysdir, -1, NULL, NULL, NULL);
413       
414       n = GetWindowsDirectoryA (cpwindir, MAXPATHLEN);
415       if (n > 0 && n < MAXPATHLEN)
416         windir = g_locale_to_utf8 (cpwindir, -1, NULL, NULL, NULL);
417     }
418   
419   if (filename)
420     {
421       appdir = g_path_get_dirname (filename);
422       g_free (filename);
423     }
424   
425   path = g_strdup (path);
426
427   if (windir)
428     {
429       const gchar *tem = path;
430       path = g_strconcat (windir, ";", path, NULL);
431       g_free ((gchar *) tem);
432       g_free (windir);
433     }
434   
435   if (sysdir)
436     {
437       const gchar *tem = path;
438       path = g_strconcat (sysdir, ";", path, NULL);
439       g_free ((gchar *) tem);
440       g_free (sysdir);
441     }
442   
443   {
444     const gchar *tem = path;
445     path = g_strconcat (".;", path, NULL);
446     g_free ((gchar *) tem);
447   }
448   
449   if (appdir)
450     {
451       const gchar *tem = path;
452       path = g_strconcat (appdir, ";", path, NULL);
453       g_free ((gchar *) tem);
454       g_free (appdir);
455     }
456
457   path_copy = path;
458 #endif
459   
460   len = strlen (program) + 1;
461   pathlen = strlen (path);
462   freeme = name = g_malloc (pathlen + len + 1);
463   
464   /* Copy the file name at the top, including '\0'  */
465   memcpy (name + pathlen + 1, program, len);
466   name = name + pathlen;
467   /* And add the slash before the filename  */
468   *name = G_DIR_SEPARATOR;
469   
470   p = path;
471   do
472     {
473       char *startp;
474
475       path = p;
476       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
477
478       if (p == path)
479         /* Two adjacent colons, or a colon at the beginning or the end
480          * of `PATH' means to search the current directory.
481          */
482         startp = name + 1;
483       else
484         startp = memcpy (name - (p - path), path, p - path);
485
486       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
487           !g_file_test (startp, G_FILE_TEST_IS_DIR))
488         {
489           gchar *ret;
490           ret = g_strdup (startp);
491           g_free (freeme);
492 #ifdef G_OS_WIN32
493           g_free ((gchar *) path_copy);
494 #endif
495           return ret;
496         }
497     }
498   while (*p++ != '\0');
499   
500   g_free (freeme);
501 #ifdef G_OS_WIN32
502   g_free ((gchar *) path_copy);
503 #endif
504
505   return NULL;
506 }
507
508 /**
509  * g_parse_debug_string:
510  * @string: a list of debug options separated by ':' or "all" 
511  *     to set all flags.
512  * @keys: pointer to an array of #GDebugKey which associate 
513  *     strings with bit flags.
514  * @nkeys: the number of #GDebugKey<!-- -->s in the array.
515  *
516  * Parses a string containing debugging options separated 
517  * by ':' into a %guint containing bit flags. This is used 
518  * within GDK and GTK+ to parse the debug options passed on the
519  * command line or through environment variables.
520  *
521  * Returns: the combined set of bit flags.
522  */
523 guint        
524 g_parse_debug_string  (const gchar     *string, 
525                        const GDebugKey *keys, 
526                        guint            nkeys)
527 {
528   guint i;
529   guint result = 0;
530   
531   g_return_val_if_fail (string != NULL, 0);
532   
533   if (!g_ascii_strcasecmp (string, "all"))
534     {
535       for (i=0; i<nkeys; i++)
536         result |= keys[i].value;
537     }
538   else
539     {
540       const gchar *p = string;
541       const gchar *q;
542       gboolean done = FALSE;
543       
544       while (*p && !done)
545         {
546           q = strchr (p, ':');
547           if (!q)
548             {
549               q = p + strlen(p);
550               done = TRUE;
551             }
552           
553           for (i=0; i<nkeys; i++)
554             if (g_ascii_strncasecmp (keys[i].key, p, q - p) == 0 &&
555                 keys[i].key[q - p] == '\0')
556               result |= keys[i].value;
557           
558           p = q + 1;
559         }
560     }
561   
562   return result;
563 }
564
565 /**
566  * g_basename:
567  * @file_name: the name of the file.
568  * 
569  * Gets the name of the file without any leading directory components.  
570  * It returns a pointer into the given file name string.
571  * 
572  * Return value: the name of the file without any leading directory components.
573  *
574  * Deprecated: Use g_path_get_basename() instead, but notice that
575  * g_path_get_basename() allocates new memory for the returned string, unlike
576  * this function which returns a pointer into the argument.
577  **/
578 G_CONST_RETURN gchar*
579 g_basename (const gchar    *file_name)
580 {
581   register gchar *base;
582   
583   g_return_val_if_fail (file_name != NULL, NULL);
584   
585   base = strrchr (file_name, G_DIR_SEPARATOR);
586
587 #ifdef G_OS_WIN32
588   {
589     gchar *q = strrchr (file_name, '/');
590     if (base == NULL || (q != NULL && q > base))
591         base = q;
592   }
593 #endif
594
595   if (base)
596     return base + 1;
597
598 #ifdef G_OS_WIN32
599   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
600     return (gchar*) file_name + 2;
601 #endif /* G_OS_WIN32 */
602   
603   return (gchar*) file_name;
604 }
605
606 /**
607  * g_path_get_basename:
608  * @file_name: the name of the file.
609  *
610  * Gets the last component of the filename. If @file_name ends with a 
611  * directory separator it gets the component before the last slash. If 
612  * @file_name consists only of directory separators (and on Windows, 
613  * possibly a drive letter), a single separator is returned. If
614  * @file_name is empty, it gets ".".
615  *
616  * Return value: a newly allocated string containing the last component of 
617  *   the filename.
618  */
619 gchar*
620 g_path_get_basename (const gchar   *file_name)
621 {
622   register gssize base;             
623   register gssize last_nonslash;    
624   gsize len;    
625   gchar *retval;
626  
627   g_return_val_if_fail (file_name != NULL, NULL);
628
629   if (file_name[0] == '\0')
630     /* empty string */
631     return g_strdup (".");
632   
633   last_nonslash = strlen (file_name) - 1;
634
635   while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
636     last_nonslash--;
637
638   if (last_nonslash == -1)
639     /* string only containing slashes */
640     return g_strdup (G_DIR_SEPARATOR_S);
641
642 #ifdef G_OS_WIN32
643   if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
644     /* string only containing slashes and a drive */
645     return g_strdup (G_DIR_SEPARATOR_S);
646 #endif /* G_OS_WIN32 */
647
648   base = last_nonslash;
649
650   while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
651     base--;
652
653 #ifdef G_OS_WIN32
654   if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
655     base = 1;
656 #endif /* G_OS_WIN32 */
657
658   len = last_nonslash - base;
659   retval = g_malloc (len + 1);
660   memcpy (retval, file_name + base + 1, len);
661   retval [len] = '\0';
662   return retval;
663 }
664
665 /**
666  * g_path_is_absolute:
667  * @file_name: a file name.
668  *
669  * Returns %TRUE if the given @file_name is an absolute file name,
670  * i.e. it contains a full path from the root directory such as "/usr/local"
671  * on UNIX or "C:\windows" on Windows systems.
672  *
673  * Returns: %TRUE if @file_name is an absolute path. 
674  */
675 gboolean
676 g_path_is_absolute (const gchar *file_name)
677 {
678   g_return_val_if_fail (file_name != NULL, FALSE);
679   
680   if (G_IS_DIR_SEPARATOR (file_name[0]))
681     return TRUE;
682
683 #ifdef G_OS_WIN32
684   /* Recognize drive letter on native Windows */
685   if (g_ascii_isalpha (file_name[0]) && 
686       file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
687     return TRUE;
688 #endif /* G_OS_WIN32 */
689
690   return FALSE;
691 }
692
693 /**
694  * g_path_skip_root:
695  * @file_name: a file name.
696  *
697  * Returns a pointer into @file_name after the root component, i.e. after
698  * the "/" in UNIX or "C:\" under Windows. If @file_name is not an absolute
699  * path it returns %NULL.
700  *
701  * Returns: a pointer into @file_name after the root component.
702  */
703 G_CONST_RETURN gchar*
704 g_path_skip_root (const gchar *file_name)
705 {
706   g_return_val_if_fail (file_name != NULL, NULL);
707   
708 #ifdef G_PLATFORM_WIN32
709   /* Skip \\server\share or //server/share */
710   if (G_IS_DIR_SEPARATOR (file_name[0]) &&
711       G_IS_DIR_SEPARATOR (file_name[1]) &&
712       file_name[2] &&
713       !G_IS_DIR_SEPARATOR (file_name[2]))
714     {
715       gchar *p;
716
717       p = strchr (file_name + 2, G_DIR_SEPARATOR);
718 #ifdef G_OS_WIN32
719       {
720         gchar *q = strchr (file_name + 2, '/');
721         if (p == NULL || (q != NULL && q < p))
722           p = q;
723       }
724 #endif
725       if (p &&
726           p > file_name + 2 &&
727           p[1])
728         {
729           file_name = p + 1;
730
731           while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
732             file_name++;
733
734           /* Possibly skip a backslash after the share name */
735           if (G_IS_DIR_SEPARATOR (file_name[0]))
736             file_name++;
737
738           return (gchar *)file_name;
739         }
740     }
741 #endif
742   
743   /* Skip initial slashes */
744   if (G_IS_DIR_SEPARATOR (file_name[0]))
745     {
746       while (G_IS_DIR_SEPARATOR (file_name[0]))
747         file_name++;
748       return (gchar *)file_name;
749     }
750
751 #ifdef G_OS_WIN32
752   /* Skip X:\ */
753   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
754     return (gchar *)file_name + 3;
755 #endif
756
757   return NULL;
758 }
759
760 /**
761  * g_path_get_dirname:
762  * @file_name: the name of the file.
763  *
764  * Gets the directory components of a file name.  If the file name has no
765  * directory components "." is returned.  The returned string should be
766  * freed when no longer needed.
767  * 
768  * Returns: the directory components of the file.
769  */
770 gchar*
771 g_path_get_dirname (const gchar    *file_name)
772 {
773   register gchar *base;
774   register gsize len;    
775   
776   g_return_val_if_fail (file_name != NULL, NULL);
777   
778   base = strrchr (file_name, G_DIR_SEPARATOR);
779 #ifdef G_OS_WIN32
780   {
781     gchar *q = strrchr (file_name, '/');
782     if (base == NULL || (q != NULL && q > base))
783         base = q;
784   }
785 #endif
786   if (!base)
787     {
788 #ifdef G_OS_WIN32
789       if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
790         {
791           gchar drive_colon_dot[4];
792
793           drive_colon_dot[0] = file_name[0];
794           drive_colon_dot[1] = ':';
795           drive_colon_dot[2] = '.';
796           drive_colon_dot[3] = '\0';
797
798           return g_strdup (drive_colon_dot);
799         }
800 #endif
801     return g_strdup (".");
802     }
803
804   while (base > file_name && G_IS_DIR_SEPARATOR (*base))
805     base--;
806
807 #ifdef G_OS_WIN32
808   /* base points to the char before the last slash.
809    *
810    * In case file_name is the root of a drive (X:\) or a child of the
811    * root of a drive (X:\foo), include the slash.
812    *
813    * In case file_name is the root share of an UNC path
814    * (\\server\share), add a slash, returning \\server\share\ .
815    *
816    * In case file_name is a direct child of a share in an UNC path
817    * (\\server\share\foo), include the slash after the share name,
818    * returning \\server\share\ .
819    */
820   if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
821     base++;
822   else if (G_IS_DIR_SEPARATOR (file_name[0]) &&
823            G_IS_DIR_SEPARATOR (file_name[1]) &&
824            file_name[2] &&
825            !G_IS_DIR_SEPARATOR (file_name[2]) &&
826            base >= file_name + 2)
827     {
828       const gchar *p = file_name + 2;
829       while (*p && !G_IS_DIR_SEPARATOR (*p))
830         p++;
831       if (p == base + 1)
832         {
833           len = (guint) strlen (file_name) + 1;
834           base = g_new (gchar, len + 1);
835           strcpy (base, file_name);
836           base[len-1] = G_DIR_SEPARATOR;
837           base[len] = 0;
838           return base;
839         }
840       if (G_IS_DIR_SEPARATOR (*p))
841         {
842           p++;
843           while (*p && !G_IS_DIR_SEPARATOR (*p))
844             p++;
845           if (p == base + 1)
846             base++;
847         }
848     }
849 #endif
850
851   len = (guint) 1 + base - file_name;
852   
853   base = g_new (gchar, len + 1);
854   g_memmove (base, file_name, len);
855   base[len] = 0;
856   
857   return base;
858 }
859
860 /**
861  * g_get_current_dir:
862  *
863  * Gets the current directory.
864  * The returned string should be freed when no longer needed. The encoding 
865  * of the returned string is system defined. On Windows, it is always UTF-8.
866  * 
867  * Returns: the current directory.
868  */
869 gchar*
870 g_get_current_dir (void)
871 {
872 #ifdef G_OS_WIN32
873
874   gchar *dir = NULL;
875
876   if (G_WIN32_HAVE_WIDECHAR_API ())
877     {
878       wchar_t dummy[2], *wdir;
879       int len;
880
881       len = GetCurrentDirectoryW (2, dummy);
882       wdir = g_new (wchar_t, len);
883
884       if (GetCurrentDirectoryW (len, wdir) == len - 1)
885         dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL);
886
887       g_free (wdir);
888     }
889   else
890     {
891       gchar dummy[2], *cpdir;
892       int len;
893
894       len = GetCurrentDirectoryA (2, dummy);
895       cpdir = g_new (gchar, len);
896
897       if (GetCurrentDirectoryA (len, cpdir) == len - 1)
898         dir = g_locale_to_utf8 (cpdir, -1, NULL, NULL, NULL);
899
900       g_free (cpdir);
901     }
902
903   if (dir == NULL)
904     dir = g_strdup ("\\");
905
906   return dir;
907
908 #else
909
910   gchar *buffer = NULL;
911   gchar *dir = NULL;
912   static gulong max_len = 0;
913
914   if (max_len == 0) 
915     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
916   
917   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
918    * and, if that wasn't bad enough, hangs in doing so.
919    */
920 #if     (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
921   buffer = g_new (gchar, max_len + 1);
922   *buffer = 0;
923   dir = getwd (buffer);
924 #else   /* !sun || !HAVE_GETCWD */
925   while (max_len < G_MAXULONG / 2)
926     {
927       buffer = g_new (gchar, max_len + 1);
928       *buffer = 0;
929       dir = getcwd (buffer, max_len);
930
931       if (dir || errno != ERANGE)
932         break;
933
934       g_free (buffer);
935       max_len *= 2;
936     }
937 #endif  /* !sun || !HAVE_GETCWD */
938   
939   if (!dir || !*buffer)
940     {
941       /* hm, should we g_error() out here?
942        * this can happen if e.g. "./" has mode \0000
943        */
944       buffer[0] = G_DIR_SEPARATOR;
945       buffer[1] = 0;
946     }
947
948   dir = g_strdup (buffer);
949   g_free (buffer);
950   
951   return dir;
952 #endif /* !Win32 */
953 }
954
955 /**
956  * g_getenv:
957  * @variable: the environment variable to get, in the GLib file name encoding.
958  * 
959  * Returns the value of an environment variable. The name and value
960  * are in the GLib file name encoding. On UNIX, this means the actual
961  * bytes which might or might not be in some consistent character set
962  * and encoding. On Windows, it is in UTF-8. On Windows, in case the
963  * environment variable's value contains references to other
964  * environment variables, they are expanded.
965  * 
966  * Return value: the value of the environment variable, or %NULL if
967  * the environment variable is not found. The returned string may be
968  * overwritten by the next call to g_getenv(), g_setenv() or
969  * g_unsetenv().
970  **/
971 G_CONST_RETURN gchar*
972 g_getenv (const gchar *variable)
973 {
974 #ifndef G_OS_WIN32
975
976   g_return_val_if_fail (variable != NULL, NULL);
977
978   return getenv (variable);
979
980 #else /* G_OS_WIN32 */
981
982   GQuark quark;
983   gchar *value;
984
985   g_return_val_if_fail (variable != NULL, NULL);
986   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
987
988   /* On Windows NT, it is relatively typical that environment
989    * variables contain references to other environment variables. If
990    * so, use ExpandEnvironmentStrings(). (In an ideal world, such
991    * environment variables would be stored in the Registry as
992    * REG_EXPAND_SZ type values, and would then get automatically
993    * expanded before a program sees them. But there is broken software
994    * that stores environment variables as REG_SZ values even if they
995    * contain references to other environment variables.)
996    */
997
998   if (G_WIN32_HAVE_WIDECHAR_API ())
999     {
1000       wchar_t dummy[2], *wname, *wvalue;
1001       int len;
1002       
1003       wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1004
1005       len = GetEnvironmentVariableW (wname, dummy, 2);
1006
1007       if (len == 0)
1008         {
1009           g_free (wname);
1010           return NULL;
1011         }
1012       else if (len == 1)
1013         len = 2;
1014
1015       wvalue = g_new (wchar_t, len);
1016
1017       if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
1018         {
1019           g_free (wname);
1020           g_free (wvalue);
1021           return NULL;
1022         }
1023
1024       if (wcschr (wvalue, L'%') != NULL)
1025         {
1026           wchar_t *tem = wvalue;
1027
1028           len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
1029
1030           if (len > 0)
1031             {
1032               wvalue = g_new (wchar_t, len);
1033
1034               if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
1035                 {
1036                   g_free (wvalue);
1037                   wvalue = tem;
1038                 }
1039               else
1040                 g_free (tem);
1041             }
1042         }
1043
1044       value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
1045
1046       g_free (wname);
1047       g_free (wvalue);
1048     }
1049   else
1050     {
1051       gchar dummy[3], *cpname, *cpvalue;
1052       int len;
1053       
1054       cpname = g_locale_from_utf8 (variable, -1, NULL, NULL, NULL);
1055
1056       g_return_val_if_fail (cpname != NULL, NULL);
1057
1058       len = GetEnvironmentVariableA (cpname, dummy, 2);
1059
1060       if (len == 0)
1061         {
1062           g_free (cpname);
1063           return NULL;
1064         }
1065       else if (len == 1)
1066         len = 2;
1067
1068       cpvalue = g_new (gchar, len);
1069
1070       if (GetEnvironmentVariableA (cpname, cpvalue, len) != len - 1)
1071         {
1072           g_free (cpname);
1073           g_free (cpvalue);
1074           return NULL;
1075         }
1076
1077       if (strchr (cpvalue, '%') != NULL)
1078         {
1079           gchar *tem = cpvalue;
1080
1081           len = ExpandEnvironmentStringsA (cpvalue, dummy, 3);
1082
1083           if (len > 0)
1084             {
1085               cpvalue = g_new (gchar, len);
1086
1087               if (ExpandEnvironmentStringsA (tem, cpvalue, len) != len)
1088                 {
1089                   g_free (cpvalue);
1090                   cpvalue = tem;
1091                 }
1092               else
1093                 g_free (tem);
1094             }
1095         }
1096
1097       value = g_locale_to_utf8 (cpvalue, -1, NULL, NULL, NULL);
1098
1099       g_free (cpname);
1100       g_free (cpvalue);
1101     }
1102
1103   quark = g_quark_from_string (value);
1104   g_free (value);
1105   
1106   return g_quark_to_string (quark);
1107
1108 #endif /* G_OS_WIN32 */
1109 }
1110
1111 /**
1112  * g_setenv:
1113  * @variable: the environment variable to set, must not contain '='.
1114  * @value: the value for to set the variable to.
1115  * @overwrite: whether to change the variable if it already exists.
1116  *
1117  * Sets an environment variable. Both the variable's name and value
1118  * should be in the GLib file name encoding. On UNIX, this means that
1119  * they can be any sequence of bytes. On Windows, they should be in
1120  * UTF-8.
1121  *
1122  * Note that on some systems, when variables are overwritten, the memory 
1123  * used for the previous variables and its value isn't reclaimed.
1124  *
1125  * Returns: %FALSE if the environment variable couldn't be set.
1126  *
1127  * Since: 2.4
1128  */
1129 gboolean
1130 g_setenv (const gchar *variable, 
1131           const gchar *value, 
1132           gboolean     overwrite)
1133 {
1134 #ifndef G_OS_WIN32
1135
1136   gint result;
1137 #ifndef HAVE_SETENV
1138   gchar *string;
1139 #endif
1140
1141   g_return_val_if_fail (variable != NULL, FALSE);
1142   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
1143
1144 #ifdef HAVE_SETENV
1145   result = setenv (variable, value, overwrite);
1146 #else
1147   if (!overwrite && getenv (variable) != NULL)
1148     return TRUE;
1149   
1150   /* This results in a leak when you overwrite existing
1151    * settings. It would be fairly easy to fix this by keeping
1152    * our own parallel array or hash table.
1153    */
1154   string = g_strconcat (variable, "=", value, NULL);
1155   result = putenv (string);
1156 #endif
1157   return result == 0;
1158
1159 #else /* G_OS_WIN32 */
1160
1161   gboolean retval;
1162
1163   g_return_val_if_fail (variable != NULL, FALSE);
1164   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
1165   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
1166   g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
1167
1168   if (!overwrite && g_getenv (variable) != NULL)
1169     return TRUE;
1170
1171   /* We want to (if possible) set both the environment variable copy
1172    * kept by the C runtime and the one kept by the system.
1173    *
1174    * We can't use only the C runtime's putenv or _wputenv() as that
1175    * won't work for arbitrary Unicode strings in a "non-Unicode" app
1176    * (with main() and not wmain()). In a "main()" app the C runtime
1177    * initializes the C runtime's environment table by converting the
1178    * real (wide char) environment variables to system codepage, thus
1179    * breaking those that aren't representable in the system codepage.
1180    *
1181    * As the C runtime's putenv() will also set the system copy, we do
1182    * the putenv() first, then call SetEnvironmentValueW ourselves.
1183    */
1184
1185   if (G_WIN32_HAVE_WIDECHAR_API ())
1186     {
1187       wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1188       wchar_t *wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
1189       gchar *tem = g_strconcat (variable, "=", value, NULL);
1190       wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
1191       
1192       g_free (tem);
1193       _wputenv (wassignment);
1194       g_free (wassignment);
1195
1196       retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
1197
1198       g_free (wname);
1199       g_free (wvalue);
1200     }
1201   else
1202     {
1203       /* In the non-Unicode case (Win9x), just putenv() is good
1204        * enough.
1205        */
1206       gchar *tem = g_strconcat (variable, "=", value, NULL);
1207       gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
1208
1209       g_free (tem);
1210       
1211       retval = (putenv (cpassignment) == 0);
1212
1213       g_free (cpassignment);
1214     }
1215
1216   return retval;
1217
1218 #endif /* G_OS_WIN32 */
1219 }
1220
1221 #ifndef G_OS_WIN32
1222
1223 /* According to the Single Unix Specification, environ is not in 
1224  * any system header, although unistd.h often declares it.
1225  */
1226 extern char **environ;
1227
1228 #endif
1229            
1230 /**
1231  * g_unsetenv:
1232  * @variable: the environment variable to remove, must not contain '='.
1233  * 
1234  * Removes an environment variable from the environment.
1235  *
1236  * Note that on some systems, when variables are overwritten, the memory 
1237  * used for the previous variables and its value isn't reclaimed.
1238  * Furthermore, this function can't be guaranteed to operate in a 
1239  * threadsafe way.
1240  *
1241  * Since: 2.4 
1242  **/
1243 void
1244 g_unsetenv (const gchar *variable)
1245 {
1246 #ifndef G_OS_WIN32
1247
1248 #ifdef HAVE_UNSETENV
1249   g_return_if_fail (variable != NULL);
1250   g_return_if_fail (strchr (variable, '=') == NULL);
1251
1252   unsetenv (variable);
1253 #else /* !HAVE_UNSETENV */
1254   int len;
1255   gchar **e, **f;
1256
1257   g_return_if_fail (variable != NULL);
1258   g_return_if_fail (strchr (variable, '=') == NULL);
1259
1260   len = strlen (variable);
1261   
1262   /* Mess directly with the environ array.
1263    * This seems to be the only portable way to do this.
1264    *
1265    * Note that we remove *all* environment entries for
1266    * the variable name, not just the first.
1267    */
1268   e = f = environ;
1269   while (*e != NULL) 
1270     {
1271       if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') 
1272         {
1273           *f = *e;
1274           f++;
1275         }
1276       e++;
1277     }
1278   *f = NULL;
1279 #endif /* !HAVE_UNSETENV */
1280
1281 #else  /* G_OS_WIN32 */
1282
1283   g_return_if_fail (variable != NULL);
1284   g_return_if_fail (strchr (variable, '=') == NULL);
1285   g_return_if_fail (g_utf8_validate (variable, -1, NULL));
1286
1287   if (G_WIN32_HAVE_WIDECHAR_API ())
1288     {
1289       wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1290       gchar *tem = g_strconcat (variable, "=", NULL);
1291       wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
1292       
1293       g_free (tem);
1294       _wputenv (wassignment);
1295       g_free (wassignment);
1296
1297       SetEnvironmentVariableW (wname, NULL);
1298
1299       g_free (wname);
1300     }
1301   else
1302     {
1303       /* In the non-Unicode case (Win9x), just putenv() is good
1304        * enough.
1305        */
1306       gchar *tem = g_strconcat (variable, "=", NULL);
1307       gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
1308
1309       g_free (tem);
1310       
1311       putenv (cpassignment);
1312
1313       g_free (cpassignment);
1314     }
1315
1316 #endif /* G_OS_WIN32 */
1317 }
1318
1319 /**
1320  * g_listenv:
1321  *
1322  * Gets the names of all variables set in the environment.
1323  * 
1324  * Return: a NUL-terminated list of strings which must be freed
1325  * with g_strfreev().
1326  *
1327  * Since: 2.8
1328  */
1329 gchar **
1330 g_listenv (void)
1331 {
1332   gchar **result, *eq;
1333   gint len, i;
1334
1335   len = g_strv_length (environ);
1336   result = g_new0 (gchar *, len + 1);
1337   
1338   for (i = 0; i < len; i++)
1339     {
1340       eq = strchr (environ[i], '=');
1341       result[i] = g_strndup (environ[i], eq - environ[i]);
1342     }
1343
1344   result[len] = NULL;
1345
1346   return result;
1347 }
1348
1349 G_LOCK_DEFINE_STATIC (g_utils_global);
1350
1351 static  gchar   *g_tmp_dir = NULL;
1352 static  gchar   *g_user_name = NULL;
1353 static  gchar   *g_real_name = NULL;
1354 static  gchar   *g_home_dir = NULL;
1355
1356 #ifdef G_OS_WIN32
1357 /* System codepage versions of the above, kept at file level so that they,
1358  * too, are produced only once.
1359  */
1360 static  gchar   *g_tmp_dir_cp = NULL;
1361 static  gchar   *g_user_name_cp = NULL;
1362 static  gchar   *g_real_name_cp = NULL;
1363 static  gchar   *g_home_dir_cp = NULL;
1364 #endif
1365
1366 static  gchar   *g_user_data_dir = NULL;
1367 static  gchar  **g_system_data_dirs = NULL;
1368 static  gchar   *g_user_cache_dir = NULL;
1369 static  gchar   *g_user_config_dir = NULL;
1370 static  gchar  **g_system_config_dirs = NULL;
1371
1372 #ifdef G_OS_WIN32
1373
1374 static gchar *
1375 get_special_folder (int csidl)
1376 {
1377   union {
1378     char c[MAX_PATH+1];
1379     wchar_t wc[MAX_PATH+1];
1380   } path;
1381   HRESULT hr;
1382   LPITEMIDLIST pidl = NULL;
1383   BOOL b;
1384   gchar *retval = NULL;
1385
1386   hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
1387   if (hr == S_OK)
1388     {
1389       if (G_WIN32_HAVE_WIDECHAR_API ())
1390         {
1391           b = SHGetPathFromIDListW (pidl, path.wc);
1392           if (b)
1393             retval = g_utf16_to_utf8 (path.wc, -1, NULL, NULL, NULL);
1394         }
1395       else
1396         {
1397           b = SHGetPathFromIDListA (pidl, path.c);
1398           if (b)
1399             retval = g_locale_to_utf8 (path.c, -1, NULL, NULL, NULL);
1400         }
1401       CoTaskMemFree (pidl);
1402     }
1403   return retval;
1404 }
1405
1406 #endif
1407
1408 /* HOLDS: g_utils_global_lock */
1409 static void
1410 g_get_any_init (void)
1411 {
1412   if (!g_tmp_dir)
1413     {
1414       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
1415       if (!g_tmp_dir)
1416         g_tmp_dir = g_strdup (g_getenv ("TMP"));
1417       if (!g_tmp_dir)
1418         g_tmp_dir = g_strdup (g_getenv ("TEMP"));
1419       
1420 #ifdef P_tmpdir
1421       if (!g_tmp_dir)
1422         {
1423           gsize k;    
1424           g_tmp_dir = g_strdup (P_tmpdir);
1425           k = strlen (g_tmp_dir);
1426           if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1]))
1427             g_tmp_dir[k - 1] = '\0';
1428         }
1429 #endif
1430       
1431       if (!g_tmp_dir)
1432         {
1433 #ifndef G_OS_WIN32
1434           g_tmp_dir = g_strdup ("/tmp");
1435 #else /* G_OS_WIN32 */
1436           g_tmp_dir = g_strdup ("\\");
1437 #endif /* G_OS_WIN32 */
1438         }
1439       
1440 #ifdef G_OS_WIN32
1441       /* We check $HOME first for Win32, though it is a last resort for Unix
1442        * where we prefer the results of getpwuid().
1443        */
1444       g_home_dir = g_strdup (g_getenv ("HOME"));
1445
1446       /* Only believe HOME if it is an absolute path and exists */
1447       if (g_home_dir)
1448         {
1449           if (!(g_path_is_absolute (g_home_dir) &&
1450                 g_file_test (g_home_dir, G_FILE_TEST_IS_DIR)))
1451             {
1452               g_free (g_home_dir);
1453               g_home_dir = NULL;
1454             }
1455         }
1456       
1457       /* In case HOME is Unix-style (it happens), convert it to
1458        * Windows style.
1459        */
1460       if (g_home_dir)
1461         {
1462           gchar *p;
1463           while ((p = strchr (g_home_dir, '/')) != NULL)
1464             *p = '\\';
1465         }
1466
1467       if (!g_home_dir)
1468         {
1469           /* USERPROFILE is probably the closest equivalent to $HOME? */
1470           if (g_getenv ("USERPROFILE") != NULL)
1471             g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
1472         }
1473
1474       if (!g_home_dir)
1475         g_home_dir = get_special_folder (CSIDL_PROFILE);
1476       
1477       if (!g_home_dir)
1478         {
1479           /* At least at some time, HOMEDRIVE and HOMEPATH were used
1480            * to point to the home directory, I think. But on Windows
1481            * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
1482            * HOMEPATH is its root "\"?
1483            */
1484           if (g_getenv ("HOMEDRIVE") != NULL && g_getenv ("HOMEPATH") != NULL)
1485             g_home_dir = g_strconcat (g_getenv ("HOMEDRIVE"),
1486                                       g_getenv ("HOMEPATH"),
1487                                       NULL);
1488         }
1489 #endif /* G_OS_WIN32 */
1490       
1491 #ifdef HAVE_PWD_H
1492       {
1493         struct passwd *pw = NULL;
1494         gpointer buffer = NULL;
1495         gint error;
1496         
1497 #  if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
1498         struct passwd pwd;
1499 #    ifdef _SC_GETPW_R_SIZE_MAX  
1500         /* This reurns the maximum length */
1501         glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
1502         
1503         if (bufsize < 0)
1504           bufsize = 64;
1505 #    else /* _SC_GETPW_R_SIZE_MAX */
1506         glong bufsize = 64;
1507 #    endif /* _SC_GETPW_R_SIZE_MAX */
1508         
1509         do
1510           {
1511             g_free (buffer);
1512             /* we allocate 6 extra bytes to work around a bug in 
1513              * Mac OS < 10.3. See #156446
1514              */
1515             buffer = g_malloc (bufsize + 6);
1516             errno = 0;
1517             
1518 #    ifdef HAVE_POSIX_GETPWUID_R
1519             error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
1520             error = error < 0 ? errno : error;
1521 #    else /* HAVE_NONPOSIX_GETPWUID_R */
1522        /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
1523 #      if defined(_AIX) || defined(__hpux)
1524             error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
1525             pw = error == 0 ? &pwd : NULL;
1526 #      else /* !_AIX */
1527             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
1528             error = pw ? 0 : errno;
1529 #      endif /* !_AIX */            
1530 #    endif /* HAVE_NONPOSIX_GETPWUID_R */
1531             
1532             if (!pw)
1533               {
1534                 /* we bail out prematurely if the user id can't be found
1535                  * (should be pretty rare case actually), or if the buffer
1536                  * should be sufficiently big and lookups are still not
1537                  * successfull.
1538                  */
1539                 if (error == 0 || error == ENOENT)
1540                   {
1541                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
1542                                (gulong) getuid ());
1543                     break;
1544                   }
1545                 if (bufsize > 32 * 1024)
1546                   {
1547                     g_warning ("getpwuid_r(): failed due to: %s.",
1548                                g_strerror (error));
1549                     break;
1550                   }
1551                 
1552                 bufsize *= 2;
1553               }
1554           }
1555         while (!pw);
1556 #  endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
1557         
1558         if (!pw)
1559           {
1560             setpwent ();
1561             pw = getpwuid (getuid ());
1562             endpwent ();
1563           }
1564         if (pw)
1565           {
1566             g_user_name = g_strdup (pw->pw_name);
1567
1568             if (pw->pw_gecos && *pw->pw_gecos != '\0') 
1569               {
1570                 gchar **gecos_fields;
1571                 gchar **name_parts;
1572
1573                 /* split the gecos field and substitute '&' */
1574                 gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
1575                 name_parts = g_strsplit (gecos_fields[0], "&", 0);
1576                 pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
1577                 g_real_name = g_strjoinv (pw->pw_name, name_parts);
1578                 g_strfreev (gecos_fields);
1579                 g_strfreev (name_parts);
1580               }
1581
1582             if (!g_home_dir)
1583               g_home_dir = g_strdup (pw->pw_dir);
1584           }
1585         g_free (buffer);
1586       }
1587       
1588 #else /* !HAVE_PWD_H */
1589       
1590 #ifdef G_OS_WIN32
1591       if (G_WIN32_HAVE_WIDECHAR_API ())
1592         {
1593           guint len = UNLEN+1;
1594           wchar_t buffer[UNLEN+1];
1595           
1596           if (GetUserNameW (buffer, (LPDWORD) &len))
1597             {
1598               g_user_name = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
1599               g_real_name = g_strdup (g_user_name);
1600             }
1601         }
1602       else
1603         {
1604           guint len = UNLEN+1;
1605           char buffer[UNLEN+1];
1606           
1607           if (GetUserNameA (buffer, (LPDWORD) &len))
1608             {
1609               g_user_name = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
1610               g_real_name = g_strdup (g_user_name);
1611             }
1612         }
1613 #endif /* G_OS_WIN32 */
1614
1615 #endif /* !HAVE_PWD_H */
1616
1617 #ifndef G_OS_WIN32
1618       if (!g_home_dir)
1619         g_home_dir = g_strdup (g_getenv ("HOME"));
1620 #endif
1621
1622 #ifdef __EMX__
1623       /* change '\\' in %HOME% to '/' */
1624       g_strdelimit (g_home_dir, "\\",'/');
1625 #endif
1626       if (!g_user_name)
1627         g_user_name = g_strdup ("somebody");
1628       if (!g_real_name)
1629         g_real_name = g_strdup ("Unknown");
1630
1631 #ifdef G_OS_WIN32
1632       g_tmp_dir_cp = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL);
1633       g_user_name_cp = g_locale_from_utf8 (g_user_name, -1, NULL, NULL, NULL);
1634       g_real_name_cp = g_locale_from_utf8 (g_real_name, -1, NULL, NULL, NULL);
1635
1636       if (!g_tmp_dir_cp)
1637         g_tmp_dir_cp = g_strdup ("\\");
1638       if (!g_user_name_cp)
1639         g_user_name_cp = g_strdup ("somebody");
1640       if (!g_real_name_cp)
1641         g_real_name_cp = g_strdup ("Unknown");
1642
1643       /* home_dir might be NULL, unlike tmp_dir, user_name and
1644        * real_name.
1645        */
1646       if (g_home_dir)
1647         g_home_dir_cp = g_locale_from_utf8 (g_home_dir, -1, NULL, NULL, NULL);
1648       else
1649         g_home_dir_cp = NULL;
1650 #endif /* G_OS_WIN32 */
1651     }
1652 }
1653
1654 /**
1655  * g_get_user_name:
1656  *
1657  * Gets the user name of the current user. The encoding of the returned
1658  * string is system-defined. On UNIX, it might be the preferred file name
1659  * encoding, or something else, and there is no guarantee that it is even
1660  * consistent on a machine. On Windows, it is always UTF-8.
1661  *
1662  * Returns: the user name of the current user.
1663  */
1664 G_CONST_RETURN gchar*
1665 g_get_user_name (void)
1666 {
1667   G_LOCK (g_utils_global);
1668   if (!g_tmp_dir)
1669     g_get_any_init ();
1670   G_UNLOCK (g_utils_global);
1671   
1672   return g_user_name;
1673 }
1674
1675 /**
1676  * g_get_real_name:
1677  *
1678  * Gets the real name of the user. This usually comes from the user's entry 
1679  * in the <filename>passwd</filename> file. The encoding of the returned 
1680  * string is system-defined. (On Windows, it is, however, always UTF-8.) 
1681  * If the real user name cannot be determined, the string "Unknown" is 
1682  * returned.
1683  *
1684  * Returns: the user's real name.
1685  */
1686 G_CONST_RETURN gchar*
1687 g_get_real_name (void)
1688 {
1689   G_LOCK (g_utils_global);
1690   if (!g_tmp_dir)
1691     g_get_any_init ();
1692   G_UNLOCK (g_utils_global);
1693  
1694   return g_real_name;
1695 }
1696
1697 /**
1698  * g_get_home_dir:
1699  *
1700  * Gets the current user's home directory. 
1701  *
1702  * Note that in contrast to traditional UNIX tools, this function 
1703  * prefers <filename>passwd</filename> entries over the <envar>HOME</envar> 
1704  * environment variable.
1705  *
1706  * Returns: the current user's home directory.
1707  */
1708 G_CONST_RETURN gchar*
1709 g_get_home_dir (void)
1710 {
1711   G_LOCK (g_utils_global);
1712   if (!g_tmp_dir)
1713     g_get_any_init ();
1714   G_UNLOCK (g_utils_global);
1715   
1716   return g_home_dir;
1717 }
1718
1719 /**
1720  * g_get_tmp_dir:
1721  *
1722  * Gets the directory to use for temporary files. This is found from 
1723  * inspecting the environment variables <envar>TMPDIR</envar>, 
1724  * <envar>TMP</envar>, and <envar>TEMP</envar> in that order. If none 
1725  * of those are defined "/tmp" is returned on UNIX and "C:\" on Windows. 
1726  * The encoding of the returned string is system-defined. On Windows, 
1727  * it is always UTF-8. The return value is never %NULL.
1728  *
1729  * Returns: the directory to use for temporary files.
1730  */
1731 G_CONST_RETURN gchar*
1732 g_get_tmp_dir (void)
1733 {
1734   G_LOCK (g_utils_global);
1735   if (!g_tmp_dir)
1736     g_get_any_init ();
1737   G_UNLOCK (g_utils_global);
1738   
1739   return g_tmp_dir;
1740 }
1741
1742 G_LOCK_DEFINE_STATIC (g_prgname);
1743 static gchar *g_prgname = NULL;
1744
1745 /**
1746  * g_get_prgname:
1747  *
1748  * Gets the name of the program. This name should <emphasis>not</emphasis> 
1749  * be localized, contrast with g_get_application_name().
1750  * (If you are using GDK or GTK+ the program name is set in gdk_init(), 
1751  * which is called by gtk_init(). The program name is found by taking 
1752  * the last component of <literal>argv[0]</literal>.)
1753  *
1754  * Returns: the name of the program. The returned string belongs 
1755  * to GLib and must not be modified or freed.
1756  */
1757 gchar*
1758 g_get_prgname (void)
1759 {
1760   gchar* retval;
1761
1762   G_LOCK (g_prgname);
1763 #ifdef G_OS_WIN32
1764   if (g_prgname == NULL)
1765     {
1766       static gboolean beenhere = FALSE;
1767
1768       if (!beenhere)
1769         {
1770           gchar *utf8_buf = NULL;
1771
1772           beenhere = TRUE;
1773           if (G_WIN32_HAVE_WIDECHAR_API ())
1774             {
1775               wchar_t buf[MAX_PATH+1];
1776               if (GetModuleFileNameW (GetModuleHandle (NULL),
1777                                       buf, G_N_ELEMENTS (buf)) > 0)
1778                 utf8_buf = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL);
1779             }
1780           else
1781             {
1782               gchar buf[MAX_PATH+1];
1783               if (GetModuleFileNameA (GetModuleHandle (NULL),
1784                                       buf, G_N_ELEMENTS (buf)) > 0)
1785                 utf8_buf = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
1786             }
1787           if (utf8_buf)
1788             {
1789               g_prgname = g_path_get_basename (utf8_buf);
1790               g_free (utf8_buf);
1791             }
1792         }
1793     }
1794 #endif
1795   retval = g_prgname;
1796   G_UNLOCK (g_prgname);
1797
1798   return retval;
1799 }
1800
1801 /**
1802  * g_set_prgname:
1803  * @prgname: the name of the program.
1804  *
1805  * Sets the name of the program. This name should <emphasis>not</emphasis> 
1806  * be localized, contrast with g_set_application_name(). Note that for 
1807  * thread-safety reasons this function can only be called once.
1808  */
1809 void
1810 g_set_prgname (const gchar *prgname)
1811 {
1812   G_LOCK (g_prgname);
1813   g_free (g_prgname);
1814   g_prgname = g_strdup (prgname);
1815   G_UNLOCK (g_prgname);
1816 }
1817
1818 G_LOCK_DEFINE_STATIC (g_application_name);
1819 static gchar *g_application_name = NULL;
1820
1821 /**
1822  * g_get_application_name:
1823  * 
1824  * Gets a human-readable name for the application, as set by
1825  * g_set_application_name(). This name should be localized if
1826  * possible, and is intended for display to the user.  Contrast with
1827  * g_get_prgname(), which gets a non-localized name. If
1828  * g_set_application_name() has not been called, returns the result of
1829  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
1830  * been called).
1831  * 
1832  * Return value: human-readable application name. may return %NULL
1833  *
1834  * Since: 2.2
1835  **/
1836 G_CONST_RETURN gchar*
1837 g_get_application_name (void)
1838 {
1839   gchar* retval;
1840
1841   G_LOCK (g_application_name);
1842   retval = g_application_name;
1843   G_UNLOCK (g_application_name);
1844
1845   if (retval == NULL)
1846     return g_get_prgname ();
1847   
1848   return retval;
1849 }
1850
1851 /**
1852  * g_set_application_name:
1853  * @application_name: localized name of the application
1854  *
1855  * Sets a human-readable name for the application. This name should be
1856  * localized if possible, and is intended for display to the user.
1857  * Contrast with g_set_prgname(), which sets a non-localized name.
1858  * g_set_prgname() will be called automatically by gtk_init(),
1859  * but g_set_application_name() will not.
1860  *
1861  * Note that for thread safety reasons, this function can only
1862  * be called once.
1863  *
1864  * The application name will be used in contexts such as error messages,
1865  * or when displaying an application's name in the task list.
1866  * 
1867  **/
1868 void
1869 g_set_application_name (const gchar *application_name)
1870 {
1871   gboolean already_set = FALSE;
1872         
1873   G_LOCK (g_application_name);
1874   if (g_application_name)
1875     already_set = TRUE;
1876   else
1877     g_application_name = g_strdup (application_name);
1878   G_UNLOCK (g_application_name);
1879
1880   if (already_set)
1881     g_warning ("g_set_application() name called multiple times");
1882 }
1883
1884 /**
1885  * g_get_user_data_dir:
1886  * 
1887  * Returns a base directory in which to access application data such
1888  * as icons that is customized for a particular user.  
1889  *
1890  * On UNIX platforms this is determined using the mechanisms described in
1891  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1892  * XDG Base Directory Specification</ulink>
1893  * 
1894  * Return value: a string owned by GLib that must not be modified 
1895  *               or freed.
1896  * Since: 2.6
1897  **/
1898 G_CONST_RETURN gchar*
1899 g_get_user_data_dir (void)
1900 {
1901   gchar *data_dir;  
1902
1903   G_LOCK (g_utils_global);
1904
1905   if (!g_user_data_dir)
1906     {
1907 #ifdef G_OS_WIN32
1908       data_dir = get_special_folder (CSIDL_PERSONAL);
1909 #else
1910       data_dir = (gchar *) g_getenv ("XDG_DATA_HOME");
1911
1912       if (data_dir && data_dir[0])
1913         data_dir = g_strdup (data_dir);
1914 #endif
1915       if (!data_dir || !data_dir[0])
1916         {
1917           if (!g_tmp_dir)
1918             g_get_any_init ();
1919
1920           if (g_home_dir)
1921             data_dir = g_build_filename (g_home_dir, ".local", 
1922                                          "share", NULL);
1923           else
1924             data_dir = g_build_filename (g_tmp_dir, g_user_name, ".local",
1925                                          "share", NULL);
1926         }
1927
1928       g_user_data_dir = data_dir;
1929     }
1930   else
1931     data_dir = g_user_data_dir;
1932
1933   G_UNLOCK (g_utils_global);
1934
1935   return data_dir;
1936 }
1937
1938 /**
1939  * g_get_user_config_dir:
1940  * 
1941  * Returns a base directory in which to store user-specific application 
1942  * configuration information such as user preferences and settings. 
1943  *
1944  * On UNIX platforms this is determined using the mechanisms described in
1945  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1946  * XDG Base Directory Specification</ulink>
1947  * 
1948  * Return value: a string owned by GLib that must not be modified 
1949  *               or freed.
1950  * Since: 2.6
1951  **/
1952 G_CONST_RETURN gchar*
1953 g_get_user_config_dir (void)
1954 {
1955   gchar *config_dir;  
1956
1957   G_LOCK (g_utils_global);
1958
1959   if (!g_user_config_dir)
1960     {
1961 #ifdef G_OS_WIN32
1962       config_dir = get_special_folder (CSIDL_APPDATA);
1963 #else
1964       config_dir = (gchar *) g_getenv ("XDG_CONFIG_HOME");
1965
1966       if (config_dir && config_dir[0])
1967         config_dir = g_strdup (config_dir);
1968 #endif
1969       if (!config_dir || !config_dir[0])
1970         {
1971           if (!g_tmp_dir)
1972             g_get_any_init ();
1973           
1974           if (g_home_dir)
1975             config_dir = g_build_filename (g_home_dir, ".config", NULL);
1976           else
1977             config_dir = g_build_filename (g_tmp_dir, g_user_name, ".config", NULL);
1978         }
1979       g_user_config_dir = config_dir;
1980     }
1981   else
1982     config_dir = g_user_config_dir;
1983
1984   G_UNLOCK (g_utils_global);
1985
1986   return config_dir;
1987 }
1988
1989 /**
1990  * g_get_user_cache_dir:
1991  * 
1992  * Returns a base directory in which to store non-essential, cached
1993  * data specific to particular user.
1994  *
1995  * On UNIX platforms this is determined using the mechanisms described in
1996  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1997  * XDG Base Directory Specification</ulink>
1998  * 
1999  * Return value: a string owned by GLib that must not be modified 
2000  *               or freed.
2001  * Since: 2.6
2002  **/
2003 G_CONST_RETURN gchar*
2004 g_get_user_cache_dir (void)
2005 {
2006   gchar *cache_dir;  
2007
2008   G_LOCK (g_utils_global);
2009
2010   if (!g_user_cache_dir)
2011     {
2012 #ifdef G_OS_WIN32
2013       cache_dir = get_special_folder (CSIDL_INTERNET_CACHE); /* XXX correct? */
2014 #else
2015       cache_dir = (gchar *) g_getenv ("XDG_CACHE_HOME");
2016
2017       if (cache_dir && cache_dir[0])
2018           cache_dir = g_strdup (cache_dir);
2019 #endif
2020       if (!cache_dir || !cache_dir[0])
2021         {
2022           if (!g_tmp_dir)
2023             g_get_any_init ();
2024
2025           if (g_home_dir)
2026             cache_dir = g_build_filename (g_home_dir, ".cache", NULL);
2027           else
2028             cache_dir = g_build_filename (g_tmp_dir, g_user_name, ".cache", NULL);
2029         }
2030       g_user_cache_dir = cache_dir;
2031     }
2032   else
2033     cache_dir = g_user_cache_dir;
2034
2035   G_UNLOCK (g_utils_global);
2036
2037   return cache_dir;
2038 }
2039
2040 /**
2041  * g_get_system_data_dirs:
2042  * 
2043  * Returns an ordered list of base directories in which to access 
2044  * system-wide application data.
2045  *
2046  * On UNIX platforms this is determined using the mechanisms described in
2047  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
2048  * XDG Base Directory Specification</ulink>
2049  * 
2050  * Return value: a %NULL-terminated array of strings owned by GLib that must 
2051  *               not be modified or freed.
2052  * Since: 2.6
2053  **/
2054 G_CONST_RETURN gchar * G_CONST_RETURN * 
2055 g_get_system_data_dirs (void)
2056 {
2057   gchar *data_dirs, **data_dir_vector;
2058
2059   G_LOCK (g_utils_global);
2060
2061   if (!g_system_data_dirs)
2062     {
2063 #ifdef G_OS_WIN32
2064       char *appdata = get_special_folder (CSIDL_COMMON_APPDATA);
2065       char *docs = get_special_folder (CSIDL_COMMON_DOCUMENTS);
2066       
2067       if (appdata && docs)
2068         {
2069           data_dirs = g_strconcat (appdata,
2070                                    G_SEARCHPATH_SEPARATOR_S,
2071                                    docs,
2072                                    NULL);
2073           g_free (appdata);
2074           g_free (docs);
2075         }
2076       else if (appdata)
2077         data_dirs = appdata;
2078       else if (docs)
2079         data_dirs = docs;
2080       else
2081         data_dirs = NULL;
2082
2083       if (data_dirs)
2084         {
2085           data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2086           g_free (data_dirs);
2087         }
2088       else
2089         {
2090           /* Punt, return empty list */
2091           data_dir_vector = g_strsplit ("", G_SEARCHPATH_SEPARATOR_S, 0);
2092         }
2093 #else
2094       data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
2095
2096       if (!data_dirs || !data_dirs[0])
2097           data_dirs = "/usr/local/share/:/usr/share/";
2098
2099       data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2100 #endif
2101
2102       g_system_data_dirs = data_dir_vector;
2103     }
2104   else
2105     data_dir_vector = g_system_data_dirs;
2106
2107   G_UNLOCK (g_utils_global);
2108
2109   return (G_CONST_RETURN gchar * G_CONST_RETURN *) data_dir_vector;
2110 }
2111
2112 /**
2113  * g_get_system_config_dirs:
2114  * 
2115  * Returns an ordered list of base directories in which to access 
2116  * system-wide configuration information.
2117  *
2118  * On UNIX platforms this is determined using the mechanisms described in
2119  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
2120  * XDG Base Directory Specification</ulink>
2121  * 
2122  * Return value: a %NULL-terminated array of strings owned by GLib that must 
2123  *               not be modified or freed.
2124  * Since: 2.6
2125  **/
2126 G_CONST_RETURN gchar * G_CONST_RETURN *
2127 g_get_system_config_dirs (void)
2128 {
2129   gchar *conf_dirs, **conf_dir_vector;
2130
2131   G_LOCK (g_utils_global);
2132
2133   if (!g_system_config_dirs)
2134     {
2135 #ifdef G_OS_WIN32
2136       conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA);
2137       if (conf_dirs)
2138         {
2139           conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2140           g_free (conf_dirs);
2141         }
2142       else
2143         {
2144           /* Return empty list */
2145           conf_dir_vector = g_strsplit ("", G_SEARCHPATH_SEPARATOR_S, 0);
2146         }
2147 #else
2148       conf_dirs = (gchar *) g_getenv ("XDG_CONFIG_DIRS");
2149
2150       if (!conf_dirs || !conf_dirs[0])
2151           conf_dirs = "/etc/xdg";
2152
2153       conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2154 #endif
2155
2156       g_system_config_dirs = conf_dir_vector;
2157     }
2158   else
2159     conf_dir_vector = g_system_config_dirs;
2160   G_UNLOCK (g_utils_global);
2161
2162   return (G_CONST_RETURN gchar * G_CONST_RETURN *) conf_dir_vector;
2163 }
2164
2165 static GHashTable *alias_table = NULL;
2166
2167 /* read an alias file for the locales */
2168 static void
2169 read_aliases (gchar *file)
2170 {
2171   FILE *fp;
2172   char buf[256];
2173   
2174   if (!alias_table)
2175     alias_table = g_hash_table_new (g_str_hash, g_str_equal);
2176   fp = fopen (file,"r");
2177   if (!fp)
2178     return;
2179   while (fgets (buf, 256, fp))
2180     {
2181       char *p, *q;
2182
2183       g_strstrip (buf);
2184
2185       /* Line is a comment */
2186       if ((buf[0] == '#') || (buf[0] == '\0'))
2187         continue;
2188
2189       /* Reads first column */
2190       for (p = buf, q = NULL; *p; p++) {
2191         if ((*p == '\t') || (*p == ' ') || (*p == ':')) {
2192           *p = '\0';
2193           q = p+1;
2194           while ((*q == '\t') || (*q == ' ')) {
2195             q++;
2196           }
2197           break;
2198         }
2199       }
2200       /* The line only had one column */
2201       if (!q || *q == '\0')
2202         continue;
2203       
2204       /* Read second column */
2205       for (p = q; *p; p++) {
2206         if ((*p == '\t') || (*p == ' ')) {
2207           *p = '\0';
2208           break;
2209         }
2210       }
2211
2212       /* Add to alias table if necessary */
2213       if (!g_hash_table_lookup (alias_table, buf)) {
2214         g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (q));
2215       }
2216     }
2217   fclose (fp);
2218 }
2219
2220 static char *
2221 unalias_lang (char *lang)
2222 {
2223   char *p;
2224   int i;
2225
2226   if (!alias_table)
2227     read_aliases ("/usr/share/locale/locale.alias");
2228
2229   i = 0;
2230   while ((p = g_hash_table_lookup (alias_table, lang)) && (strcmp (p, lang) != 0))
2231     {
2232       lang = p;
2233       if (i++ == 30)
2234         {
2235           static gboolean said_before = FALSE;
2236           if (!said_before)
2237             g_warning ("Too many alias levels for a locale, "
2238                        "may indicate a loop");
2239           said_before = TRUE;
2240           return lang;
2241         }
2242     }
2243   return lang;
2244 }
2245
2246 /* Mask for components of locale spec. The ordering here is from
2247  * least significant to most significant
2248  */
2249 enum
2250 {
2251   COMPONENT_CODESET =   1 << 0,
2252   COMPONENT_TERRITORY = 1 << 1,
2253   COMPONENT_MODIFIER =  1 << 2
2254 };
2255
2256 /* Break an X/Open style locale specification into components
2257  */
2258 static guint
2259 explode_locale (const gchar *locale,
2260                 gchar      **language, 
2261                 gchar      **territory, 
2262                 gchar      **codeset, 
2263                 gchar      **modifier)
2264 {
2265   const gchar *uscore_pos;
2266   const gchar *at_pos;
2267   const gchar *dot_pos;
2268
2269   guint mask = 0;
2270
2271   uscore_pos = strchr (locale, '_');
2272   dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
2273   at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
2274
2275   if (at_pos)
2276     {
2277       mask |= COMPONENT_MODIFIER;
2278       *modifier = g_strdup (at_pos);
2279     }
2280   else
2281     at_pos = locale + strlen (locale);
2282
2283   if (dot_pos)
2284     {
2285       mask |= COMPONENT_CODESET;
2286       *codeset = g_strndup (dot_pos, at_pos - dot_pos);
2287     }
2288   else
2289     dot_pos = at_pos;
2290
2291   if (uscore_pos)
2292     {
2293       mask |= COMPONENT_TERRITORY;
2294       *territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
2295     }
2296   else
2297     uscore_pos = dot_pos;
2298
2299   *language = g_strndup (locale, uscore_pos - locale);
2300
2301   return mask;
2302 }
2303
2304 /*
2305  * Compute all interesting variants for a given locale name -
2306  * by stripping off different components of the value.
2307  *
2308  * For simplicity, we assume that the locale is in
2309  * X/Open format: language[_territory][.codeset][@modifier]
2310  *
2311  * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
2312  *       as well. We could just copy the code from glibc wholesale
2313  *       but it is big, ugly, and complicated, so I'm reluctant
2314  *       to do so when this should handle 99% of the time...
2315  */
2316 GSList *
2317 _g_compute_locale_variants (const gchar *locale)
2318 {
2319   GSList *retval = NULL;
2320
2321   gchar *language;
2322   gchar *territory;
2323   gchar *codeset;
2324   gchar *modifier;
2325
2326   guint mask;
2327   guint i;
2328
2329   g_return_val_if_fail (locale != NULL, NULL);
2330
2331   mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
2332
2333   /* Iterate through all possible combinations, from least attractive
2334    * to most attractive.
2335    */
2336   for (i = 0; i <= mask; i++)
2337     if ((i & ~mask) == 0)
2338       {
2339         gchar *val = g_strconcat (language,
2340                                   (i & COMPONENT_TERRITORY) ? territory : "",
2341                                   (i & COMPONENT_CODESET) ? codeset : "",
2342                                   (i & COMPONENT_MODIFIER) ? modifier : "",
2343                                   NULL);
2344         retval = g_slist_prepend (retval, val);
2345       }
2346
2347   g_free (language);
2348   if (mask & COMPONENT_CODESET)
2349     g_free (codeset);
2350   if (mask & COMPONENT_TERRITORY)
2351     g_free (territory);
2352   if (mask & COMPONENT_MODIFIER)
2353     g_free (modifier);
2354
2355   return retval;
2356 }
2357
2358 /* The following is (partly) taken from the gettext package.
2359    Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.  */
2360
2361 static const gchar *
2362 guess_category_value (const gchar *category_name)
2363 {
2364   const gchar *retval;
2365
2366   /* The highest priority value is the `LANGUAGE' environment
2367      variable.  This is a GNU extension.  */
2368   retval = g_getenv ("LANGUAGE");
2369   if ((retval != NULL) && (retval[0] != '\0'))
2370     return retval;
2371
2372   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
2373      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
2374      systems this can be done by the `setlocale' function itself.  */
2375
2376   /* Setting of LC_ALL overwrites all other.  */
2377   retval = g_getenv ("LC_ALL");  
2378   if ((retval != NULL) && (retval[0] != '\0'))
2379     return retval;
2380
2381   /* Next comes the name of the desired category.  */
2382   retval = g_getenv (category_name);
2383   if ((retval != NULL) && (retval[0] != '\0'))
2384     return retval;
2385
2386   /* Last possibility is the LANG environment variable.  */
2387   retval = g_getenv ("LANG");
2388   if ((retval != NULL) && (retval[0] != '\0'))
2389     return retval;
2390
2391 #ifdef G_PLATFORM_WIN32
2392   /* g_win32_getlocale() first checks for LC_ALL, LC_MESSAGES and
2393    * LANG, which we already did above. Oh well. The main point of
2394    * calling g_win32_getlocale() is to get the thread's locale as used
2395    * by Windows and the Microsoft C runtime (in the "English_United
2396    * States" format) translated into the Unixish format.
2397    */
2398   retval = g_win32_getlocale ();
2399   if ((retval != NULL) && (retval[0] != '\0'))
2400     return retval;
2401 #endif  
2402
2403   return NULL;
2404 }
2405
2406 typedef struct _GLanguageNamesCache GLanguageNamesCache;
2407
2408 struct _GLanguageNamesCache {
2409   gchar *languages;
2410   gchar **language_names;
2411 };
2412
2413 static void
2414 language_names_cache_free (gpointer data)
2415 {
2416   GLanguageNamesCache *cache = data;
2417   g_free (cache->languages);
2418   g_strfreev (cache->language_names);
2419   g_free (cache);
2420 }
2421
2422 /**
2423  * g_get_language_names:
2424  * 
2425  * Computes a list of applicable locale names, which can be used to 
2426  * e.g. construct locale-dependent filenames or search paths. The returned 
2427  * list is sorted from most desirable to least desirable and always contains 
2428  * the default locale "C".
2429  *
2430  * For example, if LANGUAGE=de:en_US, then the returned list is
2431  * "de", "en_US", "en", "C".
2432  *
2433  * This function consults the environment variables <envar>LANGUAGE</envar>, 
2434  * <envar>LC_ALL</envar>, <envar>LC_MESSAGES</envar> and <envar>LANG</envar> 
2435  * to find the list of locales specified by the user.
2436  * 
2437  * Return value: a %NULL-terminated array of strings owned by GLib 
2438  *    that must not be modified or freed.
2439  *
2440  * Since: 2.6
2441  **/
2442 G_CONST_RETURN gchar * G_CONST_RETURN * 
2443 g_get_language_names (void)
2444 {
2445   static GStaticPrivate cache_private = G_STATIC_PRIVATE_INIT;
2446   GLanguageNamesCache *cache = g_static_private_get (&cache_private);
2447   const gchar *value;
2448
2449   if (!cache)
2450     {
2451       cache = g_new0 (GLanguageNamesCache, 1);
2452       g_static_private_set (&cache_private, cache, language_names_cache_free);
2453     }
2454
2455   value = guess_category_value ("LC_MESSAGES");
2456   if (!value)
2457     value = "C";
2458
2459   if (!(cache->languages && strcmp (cache->languages, value) == 0))
2460     {
2461       gchar **languages;
2462       gchar **alist, **a;
2463       GSList *list, *l;
2464       gint i;
2465
2466       g_free (cache->languages);
2467       g_strfreev (cache->language_names);
2468       cache->languages = g_strdup (value);
2469
2470       alist = g_strsplit (value, ":", 0);
2471       list = NULL;
2472       for (a = alist; *a; a++)
2473         {
2474           gchar *b = unalias_lang (*a);
2475           list = g_slist_concat (list, _g_compute_locale_variants (b));
2476         }
2477       g_strfreev (alist);
2478       list = g_slist_append (list, g_strdup ("C"));
2479
2480       cache->language_names = languages = g_new (gchar *, g_slist_length (list) + 1);
2481       for (l = list, i = 0; l; l = l->next, i++)
2482         languages[i] = l->data;
2483       languages[i] = NULL;
2484
2485       g_slist_free (list);
2486     }
2487
2488   return (G_CONST_RETURN gchar * G_CONST_RETURN *) cache->language_names;
2489 }
2490
2491 /**
2492  * g_direct_hash:
2493  * @v: a #gpointer key
2494  *
2495  * Converts a gpointer to a hash value.
2496  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
2497  * when using pointers as keys in a #GHashTable.
2498  *
2499  * Returns: a hash value corresponding to the key.
2500  */
2501 guint
2502 g_direct_hash (gconstpointer v)
2503 {
2504   return GPOINTER_TO_UINT (v);
2505 }
2506
2507 /**
2508  * g_direct_equal:
2509  * @v1: a key.
2510  * @v2: a key to compare with @v1.
2511  *
2512  * Compares two #gpointer arguments and returns %TRUE if they are equal.
2513  * It can be passed to g_hash_table_new() as the @key_equal_func
2514  * parameter, when using pointers as keys in a #GHashTable.
2515  * 
2516  * Returns: %TRUE if the two keys match.
2517  */
2518 gboolean
2519 g_direct_equal (gconstpointer v1,
2520                 gconstpointer v2)
2521 {
2522   return v1 == v2;
2523 }
2524
2525 /**
2526  * g_int_equal:
2527  * @v1: a pointer to a #gint key.
2528  * @v2: a pointer to a #gint key to compare with @v1.
2529  *
2530  * Compares the two #gint values being pointed to and returns 
2531  * %TRUE if they are equal.
2532  * It can be passed to g_hash_table_new() as the @key_equal_func
2533  * parameter, when using pointers to integers as keys in a #GHashTable.
2534  * 
2535  * Returns: %TRUE if the two keys match.
2536  */
2537 gboolean
2538 g_int_equal (gconstpointer v1,
2539              gconstpointer v2)
2540 {
2541   return *((const gint*) v1) == *((const gint*) v2);
2542 }
2543
2544 /**
2545  * g_int_hash:
2546  * @v: a pointer to a #gint key
2547  *
2548  * Converts a pointer to a #gint to a hash value.
2549  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
2550  * when using pointers to integers values as keys in a #GHashTable.
2551  *
2552  * Returns: a hash value corresponding to the key.
2553  */
2554 guint
2555 g_int_hash (gconstpointer v)
2556 {
2557   return *(const gint*) v;
2558 }
2559
2560 /**
2561  * g_nullify_pointer:
2562  * @nullify_location: the memory address of the pointer.
2563  * 
2564  * Set the pointer at the specified location to %NULL.
2565  **/
2566 void
2567 g_nullify_pointer (gpointer *nullify_location)
2568 {
2569   g_return_if_fail (nullify_location != NULL);
2570
2571   *nullify_location = NULL;
2572 }
2573
2574 /**
2575  * g_get_codeset:
2576  * 
2577  * Get the codeset for the current locale.
2578  * 
2579  * Return value: a newly allocated string containing the name
2580  * of the codeset. This string must be freed with g_free().
2581  **/
2582 gchar *
2583 g_get_codeset (void)
2584 {
2585   const gchar *charset;
2586
2587   g_get_charset (&charset);
2588
2589   return g_strdup (charset);
2590 }
2591
2592 /* This is called from g_thread_init(). It's used to
2593  * initialize some static data in a threadsafe way.
2594  */
2595 void
2596 _g_utils_thread_init (void)
2597 {
2598   g_get_language_names ();
2599 }
2600
2601 #ifdef ENABLE_NLS
2602
2603 #include <libintl.h>
2604
2605 #ifdef G_PLATFORM_WIN32
2606
2607 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
2608
2609 static const gchar *
2610 _glib_get_locale_dir (void)
2611 {
2612   static const gchar *cache = NULL;
2613   if (cache == NULL)
2614     cache = g_win32_get_package_installation_subdirectory
2615       (GETTEXT_PACKAGE, dll_name, "lib\\locale");
2616
2617   return cache;
2618 }
2619
2620 #undef GLIB_LOCALE_DIR
2621 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
2622
2623 #endif /* G_PLATFORM_WIN32 */
2624
2625 G_CONST_RETURN gchar *
2626 _glib_gettext (const gchar *str)
2627 {
2628   static gboolean _glib_gettext_initialized = FALSE;
2629
2630   if (!_glib_gettext_initialized)
2631     {
2632       bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2633 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2634       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2635 #    endif
2636       _glib_gettext_initialized = TRUE;
2637     }
2638   
2639   return dgettext (GETTEXT_PACKAGE, str);
2640 }
2641
2642 #endif /* ENABLE_NLS */
2643
2644 #ifdef G_OS_WIN32
2645
2646 /* Binary compatibility versions. Not for newly compiled code. */
2647
2648 #undef g_find_program_in_path
2649
2650 gchar*
2651 g_find_program_in_path (const gchar *program)
2652 {
2653   gchar *utf8_program = g_locale_to_utf8 (program, -1, NULL, NULL, NULL);
2654   gchar *utf8_retval = g_find_program_in_path_utf8 (utf8_program);
2655   gchar *retval;
2656
2657   g_free (utf8_program);
2658   if (utf8_retval == NULL)
2659     return NULL;
2660   retval = g_locale_from_utf8 (utf8_retval, -1, NULL, NULL, NULL);
2661   g_free (utf8_retval);
2662
2663   return retval;
2664 }
2665
2666 #undef g_get_current_dir
2667
2668 gchar*
2669 g_get_current_dir (void)
2670 {
2671   gchar *utf8_dir = g_get_current_dir_utf8 ();
2672   gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL);
2673   g_free (utf8_dir);
2674   return dir;
2675 }
2676
2677 #undef g_getenv
2678
2679 G_CONST_RETURN gchar*
2680 g_getenv (const gchar *variable)
2681 {
2682   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
2683   const gchar *utf8_value = g_getenv_utf8 (utf8_variable);
2684   gchar *value;
2685   GQuark quark;
2686
2687   g_free (utf8_variable);
2688   if (!utf8_value)
2689     return NULL;
2690   value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL);
2691   quark = g_quark_from_string (value);
2692   g_free (value);
2693
2694   return g_quark_to_string (quark);
2695 }
2696
2697 #undef g_setenv
2698
2699 gboolean
2700 g_setenv (const gchar *variable, 
2701           const gchar *value, 
2702           gboolean     overwrite)
2703 {
2704   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
2705   gchar *utf8_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
2706   gboolean retval = g_setenv_utf8 (utf8_variable, utf8_value, overwrite);
2707
2708   g_free (utf8_variable);
2709   g_free (utf8_value);
2710
2711   return retval;
2712 }
2713
2714 #undef g_unsetenv
2715
2716 void
2717 g_unsetenv (const gchar *variable)
2718 {
2719   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
2720
2721   g_unsetenv_utf8 (utf8_variable);
2722
2723   g_free (utf8_variable);
2724 }
2725
2726 #undef g_get_user_name
2727
2728 G_CONST_RETURN gchar*
2729 g_get_user_name (void)
2730 {
2731   G_LOCK (g_utils_global);
2732   if (!g_tmp_dir)
2733     g_get_any_init ();
2734   G_UNLOCK (g_utils_global);
2735   
2736   return g_user_name_cp;
2737 }
2738
2739 #undef g_get_real_name
2740
2741 G_CONST_RETURN gchar*
2742 g_get_real_name (void)
2743 {
2744   G_LOCK (g_utils_global);
2745   if (!g_tmp_dir)
2746     g_get_any_init ();
2747   G_UNLOCK (g_utils_global);
2748  
2749   return g_real_name_cp;
2750 }
2751
2752 #undef g_get_home_dir
2753
2754 G_CONST_RETURN gchar*
2755 g_get_home_dir (void)
2756 {
2757   G_LOCK (g_utils_global);
2758   if (!g_tmp_dir)
2759     g_get_any_init ();
2760   G_UNLOCK (g_utils_global);
2761
2762   return g_home_dir_cp;
2763 }
2764
2765 #undef g_get_tmp_dir
2766
2767 G_CONST_RETURN gchar*
2768 g_get_tmp_dir (void)
2769 {
2770   G_LOCK (g_utils_global);
2771   if (!g_tmp_dir)
2772     g_get_any_init ();
2773   G_UNLOCK (g_utils_global);
2774
2775   return g_tmp_dir_cp;
2776 }
2777
2778 #endif
2779
2780 #define __G_UTILS_C__
2781 #include "galiasdef.c"