Make public. (#155589, Tim-Philipp Müller)
[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 #include <ctype.h>
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <locale.h>
42 #include <string.h>
43 #include <errno.h>
44 #ifdef HAVE_PWD_H
45 #include <pwd.h>
46 #endif
47 #include <sys/types.h>
48 #ifdef HAVE_SYS_PARAM_H
49 #include <sys/param.h>
50 #endif
51
52 /* implement gutils's inline functions
53  */
54 #define G_IMPLEMENT_INLINES 1
55 #define __G_UTILS_C__
56 #include "galias.h"
57 #include "glib.h"
58 #include "gprintfint.h"
59
60 #ifdef  MAXPATHLEN
61 #define G_PATH_LENGTH   MAXPATHLEN
62 #elif   defined (PATH_MAX)
63 #define G_PATH_LENGTH   PATH_MAX
64 #elif   defined (_PC_PATH_MAX)
65 #define G_PATH_LENGTH   sysconf(_PC_PATH_MAX)
66 #else   
67 #define G_PATH_LENGTH   2048
68 #endif
69
70 #ifdef G_PLATFORM_WIN32
71 #  define STRICT                /* Strict typing, please */
72 #  include <windows.h>
73 #  undef STRICT
74 #  include <lmcons.h>           /* For UNLEN */
75 #  include <ctype.h>
76 #endif /* G_PLATFORM_WIN32 */
77
78 #ifdef G_OS_WIN32
79 #  include <direct.h>
80 #  include <shlobj.h>
81 #endif
82
83 #ifdef HAVE_CODESET
84 #include <langinfo.h>
85 #endif
86
87 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
88 #include <libintl.h>
89 #endif
90
91 const guint glib_major_version = GLIB_MAJOR_VERSION;
92 const guint glib_minor_version = GLIB_MINOR_VERSION;
93 const guint glib_micro_version = GLIB_MICRO_VERSION;
94 const guint glib_interface_age = GLIB_INTERFACE_AGE;
95 const guint glib_binary_age = GLIB_BINARY_AGE;
96
97 /**
98  * glib_check_version:
99  * @required_major: the required major version.
100  * @required_minor: the required major version.
101  * @required_micro: the required major version.
102  *
103  * Checks that the GLib library in use is compatible with the
104  * given version. Generally you would pass in the constants
105  * #GLIB_MAJOR_VERSION, #GLIB_MINOR_VERSION, #GLIB_MICRO_VERSION
106  * as the three arguments to this function; that produces
107  * a check that the library in use is compatible with
108  * the version of GLib the application or module was compiled
109  * against.
110  *
111  * Compatibility is defined by two things: first the version
112  * of the running library is newer than the version
113  * @required_major.required_minor.@required_micro. Second
114  * the running library must be binary compatible with the
115  * version @required_major.required_minor.@required_micro
116  * (same major version.)
117  *
118  * Return value: %NULL if the GLib library is compatible with the
119  *   given version, or a string describing the version mismatch.
120  *   The returned string is owned by GLib and must not be modified
121  *   or freed.
122  *
123  * Since: 2.6
124  **/
125 const gchar *
126 glib_check_version (guint required_major,
127                     guint required_minor,
128                     guint required_micro)
129 {
130   gint glib_effective_micro = 100 * GLIB_MINOR_VERSION + GLIB_MICRO_VERSION;
131   gint required_effective_micro = 100 * required_minor + required_micro;
132
133   if (required_major > GLIB_MAJOR_VERSION)
134     return "GLib version too old (major mismatch)";
135   if (required_major < GLIB_MAJOR_VERSION)
136     return "GLib version too new (major mismatch)";
137   if (required_effective_micro < glib_effective_micro - GLIB_BINARY_AGE)
138     return "GLib version too new (micro mismatch)";
139   if (required_effective_micro > glib_effective_micro)
140     return "GLib version too old (micro mismatch)";
141   return NULL;
142 }
143
144 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
145 void 
146 g_memmove (gpointer dest, gconstpointer src, gulong len)
147 {
148   gchar* destptr = dest;
149   const gchar* srcptr = src;
150   if (src + len < dest || dest + len < src)
151     {
152       bcopy (src, dest, len);
153       return;
154     }
155   else if (dest <= src)
156     {
157       while (len--)
158         *(destptr++) = *(srcptr++);
159     }
160   else
161     {
162       destptr += len;
163       srcptr += len;
164       while (len--)
165         *(--destptr) = *(--srcptr);
166     }
167 }
168 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
169
170 void
171 g_atexit (GVoidFunc func)
172 {
173   gint result;
174   const gchar *error = NULL;
175
176   /* keep this in sync with glib.h */
177
178 #ifdef  G_NATIVE_ATEXIT
179   result = ATEXIT (func);
180   if (result)
181     error = g_strerror (errno);
182 #elif defined (HAVE_ATEXIT)
183 #  ifdef NeXT /* @#%@! NeXTStep */
184   result = !atexit ((void (*)(void)) func);
185   if (result)
186     error = g_strerror (errno);
187 #  else
188   result = atexit ((void (*)(void)) func);
189   if (result)
190     error = g_strerror (errno);
191 #  endif /* NeXT */
192 #elif defined (HAVE_ON_EXIT)
193   result = on_exit ((void (*)(int, void *)) func, NULL);
194   if (result)
195     error = g_strerror (errno);
196 #else
197   result = 0;
198   error = "no implementation";
199 #endif /* G_NATIVE_ATEXIT */
200
201   if (error)
202     g_error ("Could not register atexit() function: %s", error);
203 }
204
205 /* Based on execvp() from GNU Libc.
206  * Some of this code is cut-and-pasted into gspawn.c
207  */
208
209 static gchar*
210 my_strchrnul (const gchar *str, gchar c)
211 {
212   gchar *p = (gchar*)str;
213   while (*p && (*p != c))
214     ++p;
215
216   return p;
217 }
218
219 #ifdef G_OS_WIN32
220
221 static gchar *inner_find_program_in_path (const gchar *program);
222
223 gchar*
224 g_find_program_in_path (const gchar *program)
225 {
226   const gchar *last_dot = strrchr (program, '.');
227
228   if (last_dot == NULL || strchr (last_dot, '\\') != NULL)
229     {
230       const gint program_length = strlen (program);
231       const gchar *pathext = getenv ("PATHEXT");
232       const gchar *p;
233       gchar *decorated_program;
234       gchar *retval;
235
236       if (pathext == NULL)
237         pathext = ".com;.exe;.bat";
238
239       p = pathext;
240       do
241         {
242           pathext = p;
243           p = my_strchrnul (pathext, ';');
244
245           decorated_program = g_malloc (program_length + (p-pathext) + 1);
246           memcpy (decorated_program, program, program_length);
247           memcpy (decorated_program+program_length, pathext, p-pathext);
248           decorated_program [program_length + (p-pathext)] = '\0';
249           
250           retval = inner_find_program_in_path (decorated_program);
251           g_free (decorated_program);
252
253           if (retval != NULL)
254             return retval;
255         } while (*p++ != '\0');
256       return NULL;
257     }
258   else
259     return inner_find_program_in_path (program);
260 }
261
262 #define g_find_program_in_path inner_find_program_in_path
263 #endif
264
265 /**
266  * g_find_program_in_path:
267  * @program: a program name
268  * 
269  * Locates the first executable named @program in the user's path, in the
270  * same way that execvp() would locate it. Returns an allocated string
271  * with the absolute path name, or NULL if the program is not found in
272  * the path. If @program is already an absolute path, returns a copy of
273  * @program if @program exists and is executable, and NULL otherwise.
274  * 
275  * On Windows, if @program does not have a file type suffix, tries to
276  * append the suffixes in the PATHEXT environment variable (if that
277  * doesn't exists, the suffixes .com, .exe, and .bat) in turn, and
278  * then look for the resulting file name in the same way as
279  * CreateProcess() would. This means first in the directory where the
280  * program was loaded from, then in the current directory, then in the
281  * Windows 32-bit system directory, then in the Windows directory, and
282  * finally in the directories in the PATH environment variable. If
283  * the program is found, the return value contains the full name
284  * including the type suffix.
285  *
286  * Return value: absolute path, or NULL
287  **/
288 #ifdef G_OS_WIN32
289 static
290 #endif
291 gchar*
292 g_find_program_in_path (const gchar *program)
293 {
294   const gchar *path, *p;
295   gchar *name, *freeme;
296 #ifdef G_OS_WIN32
297   gchar *path_tmp;
298 #endif
299   size_t len;
300   size_t pathlen;
301
302   g_return_val_if_fail (program != NULL, NULL);
303
304   /* If it is an absolute path, or a relative path including subdirectories,
305    * don't look in PATH.
306    */
307   if (g_path_is_absolute (program)
308       || strchr (program, G_DIR_SEPARATOR) != NULL
309 #ifdef G_OS_WIN32
310       || strchr (program, '/') != NULL
311 #endif
312       )
313     {
314       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
315         return g_strdup (program);
316       else
317         return NULL;
318     }
319   
320   path = g_getenv ("PATH");
321 #ifdef G_OS_UNIX
322   if (path == NULL)
323     {
324       /* There is no `PATH' in the environment.  The default
325        * search path in GNU libc is the current directory followed by
326        * the path `confstr' returns for `_CS_PATH'.
327        */
328       
329       /* In GLib we put . last, for security, and don't use the
330        * unportable confstr(); UNIX98 does not actually specify
331        * what to search if PATH is unset. POSIX may, dunno.
332        */
333       
334       path = "/bin:/usr/bin:.";
335     }
336 #else
337   {
338     gchar *tmp;
339     gchar moddir[MAXPATHLEN], sysdir[MAXPATHLEN], windir[MAXPATHLEN];
340
341     GetModuleFileName (NULL, moddir, sizeof (moddir));
342     tmp = g_path_get_dirname (moddir);
343     GetSystemDirectory (sysdir, sizeof (sysdir));
344     GetWindowsDirectory (windir, sizeof (windir));
345     path_tmp = g_strconcat (tmp, ";.;", sysdir, ";", windir,
346                             (path != NULL ? ";" : NULL),
347                             (path != NULL ? path : NULL),
348                             NULL);
349     g_free (tmp);
350     path = path_tmp;
351   }
352 #endif
353   
354   len = strlen (program) + 1;
355   pathlen = strlen (path);
356   freeme = name = g_malloc (pathlen + len + 1);
357   
358   /* Copy the file name at the top, including '\0'  */
359   memcpy (name + pathlen + 1, program, len);
360   name = name + pathlen;
361   /* And add the slash before the filename  */
362   *name = G_DIR_SEPARATOR;
363   
364   p = path;
365   do
366     {
367       char *startp;
368
369       path = p;
370       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
371
372       if (p == path)
373         /* Two adjacent colons, or a colon at the beginning or the end
374          * of `PATH' means to search the current directory.
375          */
376         startp = name + 1;
377       else
378         startp = memcpy (name - (p - path), path, p - path);
379
380       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE))
381         {
382           gchar *ret;
383           ret = g_strdup (startp);
384           g_free (freeme);
385 #ifdef G_OS_WIN32
386           g_free (path_tmp);
387 #endif
388           return ret;
389         }
390     }
391   while (*p++ != '\0');
392   
393   g_free (freeme);
394 #ifdef G_OS_WIN32
395   g_free (path_tmp);
396 #endif
397
398   return NULL;
399 }
400
401 guint        
402 g_parse_debug_string  (const gchar     *string, 
403                        const GDebugKey *keys, 
404                        guint            nkeys)
405 {
406   guint i;
407   guint result = 0;
408   
409   g_return_val_if_fail (string != NULL, 0);
410   
411   if (!g_ascii_strcasecmp (string, "all"))
412     {
413       for (i=0; i<nkeys; i++)
414         result |= keys[i].value;
415     }
416   else
417     {
418       const gchar *p = string;
419       const gchar *q;
420       gboolean done = FALSE;
421       
422       while (*p && !done)
423         {
424           q = strchr (p, ':');
425           if (!q)
426             {
427               q = p + strlen(p);
428               done = TRUE;
429             }
430           
431           for (i=0; i<nkeys; i++)
432             if (g_ascii_strncasecmp(keys[i].key, p, q - p) == 0 &&
433                 keys[i].key[q - p] == '\0')
434               result |= keys[i].value;
435           
436           p = q + 1;
437         }
438     }
439   
440   return result;
441 }
442
443 /**
444  * g_basename:
445  * @file_name: the name of the file.
446  * 
447  * Gets the name of the file without any leading directory components.  
448  * It returns a pointer into the given file name string.
449  * 
450  * Return value: the name of the file without any leading directory components.
451  *
452  * Deprecated: Use g_path_get_basename() instead, but notice that
453  * g_path_get_basename() allocates new memory for the returned string, unlike
454  * this function which returns a pointer into the argument.
455  **/
456 G_CONST_RETURN gchar*
457 g_basename (const gchar    *file_name)
458 {
459   register gchar *base;
460   
461   g_return_val_if_fail (file_name != NULL, NULL);
462   
463   base = strrchr (file_name, G_DIR_SEPARATOR);
464
465 #ifdef G_OS_WIN32
466   {
467     gchar *q = strrchr (file_name, '/');
468     if (base == NULL || (q != NULL && q > base))
469         base = q;
470   }
471 #endif
472
473   if (base)
474     return base + 1;
475
476 #ifdef G_OS_WIN32
477   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
478     return (gchar*) file_name + 2;
479 #endif /* G_OS_WIN32 */
480   
481   return (gchar*) file_name;
482 }
483
484 /**
485  * g_path_get_basename:
486  * @file_name: the name of the file.
487  *
488  * Gets the last component of the filename. If @file_name ends with a 
489  * directory separator it gets the component before the last slash. If 
490  * @file_name consists only of directory separators (and on Windows, 
491  * possibly a drive letter), a single separator is returned. If
492  * @file_name is empty, it gets ".".
493  *
494  * Return value: a newly allocated string containing the last component of 
495  *   the filename.
496  */
497 gchar*
498 g_path_get_basename (const gchar   *file_name)
499 {
500   register gssize base;             
501   register gssize last_nonslash;    
502   gsize len;    
503   gchar *retval;
504  
505   g_return_val_if_fail (file_name != NULL, NULL);
506
507   if (file_name[0] == '\0')
508     /* empty string */
509     return g_strdup (".");
510   
511   last_nonslash = strlen (file_name) - 1;
512
513   while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
514     last_nonslash--;
515
516   if (last_nonslash == -1)
517     /* string only containing slashes */
518     return g_strdup (G_DIR_SEPARATOR_S);
519
520 #ifdef G_OS_WIN32
521   if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
522     /* string only containing slashes and a drive */
523     return g_strdup (G_DIR_SEPARATOR_S);
524 #endif /* G_OS_WIN32 */
525
526   base = last_nonslash;
527
528   while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
529     base--;
530
531 #ifdef G_OS_WIN32
532   if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
533     base = 1;
534 #endif /* G_OS_WIN32 */
535
536   len = last_nonslash - base;
537   retval = g_malloc (len + 1);
538   memcpy (retval, file_name + base + 1, len);
539   retval [len] = '\0';
540   return retval;
541 }
542
543 gboolean
544 g_path_is_absolute (const gchar *file_name)
545 {
546   g_return_val_if_fail (file_name != NULL, FALSE);
547   
548   if (G_IS_DIR_SEPARATOR (file_name[0]))
549     return TRUE;
550
551 #ifdef G_OS_WIN32
552   /* Recognize drive letter on native Windows */
553   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
554     return TRUE;
555 #endif /* G_OS_WIN32 */
556
557   return FALSE;
558 }
559
560 G_CONST_RETURN gchar*
561 g_path_skip_root (const gchar *file_name)
562 {
563   g_return_val_if_fail (file_name != NULL, NULL);
564   
565 #ifdef G_PLATFORM_WIN32
566   /* Skip \\server\share or //server/share */
567   if (G_IS_DIR_SEPARATOR (file_name[0]) &&
568       G_IS_DIR_SEPARATOR (file_name[1]) &&
569       file_name[2])
570     {
571       gchar *p;
572
573       p = strchr (file_name + 2, G_DIR_SEPARATOR);
574 #ifdef G_OS_WIN32
575       {
576         gchar *q = strchr (file_name + 2, '/');
577         if (p == NULL || (q != NULL && q < p))
578           p = q;
579       }
580 #endif
581       if (p &&
582           p > file_name + 2 &&
583           p[1])
584         {
585           file_name = p + 1;
586
587           while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
588             file_name++;
589
590           /* Possibly skip a backslash after the share name */
591           if (G_IS_DIR_SEPARATOR (file_name[0]))
592             file_name++;
593
594           return (gchar *)file_name;
595         }
596     }
597 #endif
598   
599   /* Skip initial slashes */
600   if (G_IS_DIR_SEPARATOR (file_name[0]))
601     {
602       while (G_IS_DIR_SEPARATOR (file_name[0]))
603         file_name++;
604       return (gchar *)file_name;
605     }
606
607 #ifdef G_OS_WIN32
608   /* Skip X:\ */
609   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
610     return (gchar *)file_name + 3;
611 #endif
612
613   return NULL;
614 }
615
616 gchar*
617 g_path_get_dirname (const gchar    *file_name)
618 {
619   register gchar *base;
620   register gsize len;    
621   
622   g_return_val_if_fail (file_name != NULL, NULL);
623   
624   base = strrchr (file_name, G_DIR_SEPARATOR);
625 #ifdef G_OS_WIN32
626   {
627     gchar *q = strrchr (file_name, '/');
628     if (base == NULL || (q != NULL && q > base))
629         base = q;
630   }
631 #endif
632   if (!base)
633     {
634 #ifdef G_OS_WIN32
635       if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
636         {
637           gchar drive_colon_dot[4];
638
639           drive_colon_dot[0] = file_name[0];
640           drive_colon_dot[1] = ':';
641           drive_colon_dot[2] = '.';
642           drive_colon_dot[3] = '\0';
643
644           return g_strdup (drive_colon_dot);
645         }
646 #endif
647     return g_strdup (".");
648     }
649
650   while (base > file_name && G_IS_DIR_SEPARATOR (*base))
651     base--;
652
653 #ifdef G_OS_WIN32
654   if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
655       base++;
656 #endif
657
658   len = (guint) 1 + base - file_name;
659   
660   base = g_new (gchar, len + 1);
661   g_memmove (base, file_name, len);
662   base[len] = 0;
663   
664   return base;
665 }
666
667 gchar*
668 g_get_current_dir (void)
669 {
670   gchar *buffer = NULL;
671   gchar *dir = NULL;
672   static gulong max_len = 0;
673
674   if (max_len == 0) 
675     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
676   
677   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
678    * and, if that wasn't bad enough, hangs in doing so.
679    */
680 #if     (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
681   buffer = g_new (gchar, max_len + 1);
682   *buffer = 0;
683   dir = getwd (buffer);
684 #else   /* !sun || !HAVE_GETCWD */
685   while (max_len < G_MAXULONG / 2)
686     {
687       buffer = g_new (gchar, max_len + 1);
688       *buffer = 0;
689       dir = getcwd (buffer, max_len);
690
691       if (dir || errno != ERANGE)
692         break;
693
694       g_free (buffer);
695       max_len *= 2;
696     }
697 #endif  /* !sun || !HAVE_GETCWD */
698   
699   if (!dir || !*buffer)
700     {
701       /* hm, should we g_error() out here?
702        * this can happen if e.g. "./" has mode \0000
703        */
704       buffer[0] = G_DIR_SEPARATOR;
705       buffer[1] = 0;
706     }
707
708   dir = g_strdup (buffer);
709   g_free (buffer);
710   
711   return dir;
712 }
713
714 /**
715  * g_getenv:
716  * @variable: the environment variable to get.
717  * 
718  * Returns an environment variable.
719  * 
720  * Return value: the value of the environment variable, or %NULL if the environment
721  * variable is not found. The returned string may be overwritten by the next call to g_getenv(),
722  * g_setenv() or g_unsetenv().
723  **/
724 G_CONST_RETURN gchar*
725 g_getenv (const gchar *variable)
726 {
727 #ifndef G_OS_WIN32
728   g_return_val_if_fail (variable != NULL, NULL);
729
730   return getenv (variable);
731 #else
732   GQuark quark;
733   gchar *system_env;
734   gchar *expanded_env;
735   guint length;
736   gchar dummy[2];
737
738   g_return_val_if_fail (variable != NULL, NULL);
739   
740   system_env = getenv (variable);
741   if (!system_env)
742     return NULL;
743
744   /* On Windows NT, it is relatively typical that environment
745    * variables contain references to other environment variables. If
746    * so, use ExpandEnvironmentStrings(). (If all software was written
747    * in the best possible way, such environment variables would be
748    * stored in the Registry as REG_EXPAND_SZ type values, and would
749    * then get automatically expanded before the program sees them. But
750    * there is broken software that stores environment variables as
751    * REG_SZ values even if they contain references to other
752    * environment variables.
753    */
754
755   if (strchr (system_env, '%') == NULL)
756     {
757       /* No reference to other variable(s), return value as such. */
758       return system_env;
759     }
760
761   /* First check how much space we need */
762   length = ExpandEnvironmentStrings (system_env, dummy, 2);
763   
764   expanded_env = g_malloc (length);
765   
766   ExpandEnvironmentStrings (system_env, expanded_env, length);
767   
768   quark = g_quark_from_string (expanded_env);
769   g_free (expanded_env);
770   
771   return g_quark_to_string (quark);
772 #endif
773 }
774
775 /**
776  * g_setenv:
777  * @variable: the environment variable to set, must not contain '='.
778  * @value: the value for to set the variable to.
779  * @overwrite: whether to change the variable if it already exists.
780  *
781  * Sets an environment variable.
782  *
783  * Note that on some systems, the memory used for the variable and its value 
784  * can't be reclaimed later.
785  *
786  * Returns: %FALSE if the environment variable couldn't be set.
787  *
788  * Since: 2.4
789  */
790 gboolean
791 g_setenv (const gchar *variable, 
792           const gchar *value, 
793           gboolean     overwrite)
794 {
795   gint result;
796 #ifndef HAVE_SETENV
797   gchar *string;
798 #endif
799
800   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
801
802 #ifdef HAVE_SETENV
803   result = setenv (variable, value, overwrite);
804 #else
805   if (!overwrite && g_getenv (variable) != NULL)
806     return TRUE;
807   
808   /* This results in a leak when you overwrite existing
809    * settings. It would be fairly easy to fix this by keeping
810    * our own parallel array or hash table.
811    */
812   string = g_strconcat (variable, "=", value, NULL);
813   result = putenv (string);
814 #endif
815   return result == 0;
816 }
817
818 #ifndef HAVE_UNSETENV     
819 /* According to the Single Unix Specification, environ is not in 
820  * any system header, although unistd.h often declares it.
821  */
822 #  ifndef _MSC_VER
823 /*
824  * Win32 - at least msvc headers declare it so let's avoid
825  *   warning C4273: '__p__environ' : inconsistent dll linkage.  dllexport assumed.
826  */
827 extern char **environ;
828 #  endif
829 #endif
830            
831 /**
832  * g_unsetenv:
833  * @variable: the environment variable to remove, must not contain '='.
834  * 
835  * Removes an environment variable from the environment.
836  *
837  * Note that on some systems, the memory used for the variable and its value 
838  * can't be reclaimed. Furthermore, this function can't be guaranteed to operate in a 
839  * threadsafe way.
840  *
841  * Since: 2.4 
842  **/
843 void
844 g_unsetenv (const gchar *variable)
845 {
846 #ifdef HAVE_UNSETENV
847   g_return_if_fail (strchr (variable, '=') == NULL);
848
849   unsetenv (variable);
850 #else
851   int len;
852   gchar **e, **f;
853
854   g_return_if_fail (strchr (variable, '=') == NULL);
855
856   len = strlen (variable);
857   
858   /* Mess directly with the environ array.
859    * This seems to be the only portable way to do this.
860    *
861    * Note that we remove *all* environment entries for
862    * the variable name, not just the first.
863    */
864   e = f = environ;
865   while (*e != NULL) 
866     {
867       if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') 
868         {
869           *f = *e;
870           f++;
871         }
872       e++;
873     }
874   *f = NULL;
875 #endif
876 }
877
878 G_LOCK_DEFINE_STATIC (g_utils_global);
879
880 static  gchar   *g_tmp_dir = NULL;
881 static  gchar   *g_user_name = NULL;
882 static  gchar   *g_real_name = NULL;
883 static  gchar   *g_home_dir = NULL;
884
885 static  gchar   *g_user_data_dir = NULL;
886 static  gchar  **g_system_data_dirs = NULL;
887 static  gchar   *g_user_cache_dir = NULL;
888 static  gchar   *g_user_config_dir = NULL;
889 static  gchar  **g_system_config_dirs = NULL;
890
891 #ifdef G_OS_WIN32
892
893 static gchar *
894 get_special_folder (int csidl)
895 {
896   union {
897     char c[MAX_PATH+1];
898     wchar_t wc[MAX_PATH+1];
899   } path;
900   HRESULT hr;
901   LPITEMIDLIST pidl = NULL;
902   BOOL b;
903   gchar *retval = NULL;
904
905   hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
906   if (hr == S_OK)
907     {
908       if (G_WIN32_HAVE_WIDECHAR_API ())
909         {
910           b = SHGetPathFromIDListW (pidl, path.wc);
911           if (b)
912             retval = g_utf16_to_utf8 (path.wc, -1, NULL, NULL, NULL);
913         }
914       else
915         {
916           b = SHGetPathFromIDListA (pidl, path.c);
917           if (b)
918             retval = g_locale_to_utf8 (path.c, -1, NULL, NULL, NULL);
919         }
920       CoTaskMemFree (pidl);
921     }
922   if (retval == NULL)
923     return "C:\\";
924   else
925     return retval;
926 }
927
928 #endif
929
930 /* HOLDS: g_utils_global_lock */
931 static void
932 g_get_any_init (void)
933 {
934   if (!g_tmp_dir)
935     {
936       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
937       if (!g_tmp_dir)
938         g_tmp_dir = g_strdup (g_getenv ("TMP"));
939       if (!g_tmp_dir)
940         g_tmp_dir = g_strdup (g_getenv ("TEMP"));
941       
942 #ifdef P_tmpdir
943       if (!g_tmp_dir)
944         {
945           gsize k;    
946           g_tmp_dir = g_strdup (P_tmpdir);
947           k = strlen (g_tmp_dir);
948           if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1]))
949             g_tmp_dir[k - 1] = '\0';
950         }
951 #endif
952       
953       if (!g_tmp_dir)
954         {
955 #ifndef G_OS_WIN32
956           g_tmp_dir = g_strdup ("/tmp");
957 #else /* G_OS_WIN32 */
958           g_tmp_dir = g_strdup ("C:\\");
959 #endif /* G_OS_WIN32 */
960         }
961       
962 #ifdef G_OS_WIN32
963       /* We check $HOME first for Win32, though it is a last resort for Unix
964        * where we prefer the results of getpwuid().
965        */
966       {
967         gchar *home = g_getenv ("HOME");
968       
969         /* Only believe HOME if it is an absolute path and exists */
970         if (home && g_path_is_absolute (home) && g_file_test (home, G_FILE_TEST_IS_DIR))
971           g_home_dir = g_strdup (home);
972       }
973       
974       /* In case HOME is Unix-style (it happens), convert it to
975        * Windows style.
976        */
977       if (g_home_dir)
978         {
979           gchar *p;
980           while ((p = strchr (g_home_dir, '/')) != NULL)
981             *p = '\\';
982         }
983
984       if (!g_home_dir)
985         {
986           /* USERPROFILE is probably the closest equivalent to $HOME? */
987           if (getenv ("USERPROFILE") != NULL)
988             g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
989         }
990
991       if (!g_home_dir)
992         g_home_dir = get_special_folder (CSIDL_PROFILE);
993
994       if (!g_home_dir)
995         {
996           /* At least at some time, HOMEDRIVE and HOMEPATH were used
997            * to point to the home directory, I think. But on Windows
998            * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
999            * HOMEPATH is its root "\"?
1000            */
1001           if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
1002             {
1003               gchar *homedrive, *homepath;
1004               
1005               homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
1006               homepath = g_strdup (g_getenv ("HOMEPATH"));
1007               
1008               g_home_dir = g_strconcat (homedrive, homepath, NULL);
1009               g_free (homedrive);
1010               g_free (homepath);
1011             }
1012         }
1013 #endif /* G_OS_WIN32 */
1014       
1015 #ifdef HAVE_PWD_H
1016       {
1017         struct passwd *pw = NULL;
1018         gpointer buffer = NULL;
1019         gint error;
1020         
1021 #  if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
1022         struct passwd pwd;
1023 #    ifdef _SC_GETPW_R_SIZE_MAX  
1024         /* This reurns the maximum length */
1025         glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
1026         
1027         if (bufsize < 0)
1028           bufsize = 64;
1029 #    else /* _SC_GETPW_R_SIZE_MAX */
1030         glong bufsize = 64;
1031 #    endif /* _SC_GETPW_R_SIZE_MAX */
1032         
1033         do
1034           {
1035             g_free (buffer);
1036             buffer = g_malloc (bufsize);
1037             errno = 0;
1038             
1039 #    ifdef HAVE_POSIX_GETPWUID_R
1040             error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
1041             error = error < 0 ? errno : error;
1042 #    else /* HAVE_NONPOSIX_GETPWUID_R */
1043        /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
1044 #      if defined(_AIX) || defined(__hpux)
1045             error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
1046             pw = error == 0 ? &pwd : NULL;
1047 #      else /* !_AIX */
1048             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
1049             error = pw ? 0 : errno;
1050 #      endif /* !_AIX */            
1051 #    endif /* HAVE_NONPOSIX_GETPWUID_R */
1052             
1053             if (!pw)
1054               {
1055                 /* we bail out prematurely if the user id can't be found
1056                  * (should be pretty rare case actually), or if the buffer
1057                  * should be sufficiently big and lookups are still not
1058                  * successfull.
1059                  */
1060                 if (error == 0 || error == ENOENT)
1061                   {
1062                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
1063                                (gulong) getuid ());
1064                     break;
1065                   }
1066                 if (bufsize > 32 * 1024)
1067                   {
1068                     g_warning ("getpwuid_r(): failed due to: %s.",
1069                                g_strerror (error));
1070                     break;
1071                   }
1072                 
1073                 bufsize *= 2;
1074               }
1075           }
1076         while (!pw);
1077 #  endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
1078         
1079         if (!pw)
1080           {
1081             setpwent ();
1082             pw = getpwuid (getuid ());
1083             endpwent ();
1084           }
1085         if (pw)
1086           {
1087             g_user_name = g_strdup (pw->pw_name);
1088
1089             if (pw->pw_gecos && *pw->pw_gecos != '\0') 
1090               {
1091                 gchar **gecos_fields;
1092                 gchar **name_parts;
1093
1094                 /* split the gecos field and substitute '&' */
1095                 gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
1096                 name_parts = g_strsplit (gecos_fields[0], "&", 0);
1097                 pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
1098                 g_real_name = g_strjoinv (pw->pw_name, name_parts);
1099                 g_strfreev (gecos_fields);
1100                 g_strfreev (name_parts);
1101               }
1102
1103             if (!g_home_dir)
1104               g_home_dir = g_strdup (pw->pw_dir);
1105           }
1106         g_free (buffer);
1107       }
1108       
1109 #else /* !HAVE_PWD_H */
1110       
1111 #  ifdef G_OS_WIN32
1112       {
1113         guint len = UNLEN+1;
1114         gchar buffer[UNLEN+1];
1115         
1116         if (GetUserName ((LPTSTR) buffer, (LPDWORD) &len))
1117           {
1118             g_user_name = g_strdup (buffer);
1119             g_real_name = g_strdup (buffer);
1120           }
1121       }
1122 #  endif /* G_OS_WIN32 */
1123
1124 #endif /* !HAVE_PWD_H */
1125
1126       if (!g_home_dir)
1127         g_home_dir = g_strdup (g_getenv ("HOME"));
1128       
1129 #ifdef __EMX__
1130       /* change '\\' in %HOME% to '/' */
1131       g_strdelimit (g_home_dir, "\\",'/');
1132 #endif
1133       if (!g_user_name)
1134         g_user_name = g_strdup ("somebody");
1135       if (!g_real_name)
1136         g_real_name = g_strdup ("Unknown");
1137     }
1138 }
1139
1140 G_CONST_RETURN gchar*
1141 g_get_user_name (void)
1142 {
1143   G_LOCK (g_utils_global);
1144   if (!g_tmp_dir)
1145     g_get_any_init ();
1146   G_UNLOCK (g_utils_global);
1147   
1148   return g_user_name;
1149 }
1150
1151 G_CONST_RETURN gchar*
1152 g_get_real_name (void)
1153 {
1154   G_LOCK (g_utils_global);
1155   if (!g_tmp_dir)
1156     g_get_any_init ();
1157   G_UNLOCK (g_utils_global);
1158  
1159   return g_real_name;
1160 }
1161
1162 G_CONST_RETURN gchar*
1163 g_get_home_dir (void)
1164 {
1165   G_LOCK (g_utils_global);
1166   if (!g_tmp_dir)
1167     g_get_any_init ();
1168   G_UNLOCK (g_utils_global);
1169   
1170   return g_home_dir;
1171 }
1172
1173 /* Return a directory to be used to store temporary files. This is the
1174  * value of the TMPDIR, TMP or TEMP environment variables (they are
1175  * checked in that order). If none of those exist, use P_tmpdir from
1176  * stdio.h.  If that isn't defined, return "/tmp" on POSIXly systems,
1177  * and C:\ on Windows.
1178  */
1179
1180 G_CONST_RETURN gchar*
1181 g_get_tmp_dir (void)
1182 {
1183   G_LOCK (g_utils_global);
1184   if (!g_tmp_dir)
1185     g_get_any_init ();
1186   G_UNLOCK (g_utils_global);
1187   
1188   return g_tmp_dir;
1189 }
1190
1191 G_LOCK_DEFINE_STATIC (g_prgname);
1192 static gchar *g_prgname = NULL;
1193
1194 gchar*
1195 g_get_prgname (void)
1196 {
1197   gchar* retval;
1198
1199   G_LOCK (g_prgname);
1200   retval = g_prgname;
1201   G_UNLOCK (g_prgname);
1202
1203   return retval;
1204 }
1205
1206 void
1207 g_set_prgname (const gchar *prgname)
1208 {
1209   G_LOCK (g_prgname);
1210   g_free (g_prgname);
1211   g_prgname = g_strdup (prgname);
1212   G_UNLOCK (g_prgname);
1213 }
1214
1215 G_LOCK_DEFINE_STATIC (g_application_name);
1216 static gchar *g_application_name = NULL;
1217
1218 /**
1219  * g_get_application_name:
1220  * 
1221  * Gets a human-readable name for the application, as set by
1222  * g_set_application_name(). This name should be localized if
1223  * possible, and is intended for display to the user.  Contrast with
1224  * g_get_prgname(), which gets a non-localized name. If
1225  * g_set_application_name() has not been called, returns the result of
1226  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
1227  * been called).
1228  * 
1229  * Return value: human-readable application name. may return %NULL
1230  *
1231  * Since: 2.2
1232  **/
1233 G_CONST_RETURN gchar*
1234 g_get_application_name (void)
1235 {
1236   gchar* retval;
1237
1238   G_LOCK (g_application_name);
1239   retval = g_application_name;
1240   G_UNLOCK (g_application_name);
1241
1242   if (retval == NULL)
1243     return g_get_prgname ();
1244   
1245   return retval;
1246 }
1247
1248 /**
1249  * g_set_application_name:
1250  * @application_name: localized name of the application
1251  *
1252  * Sets a human-readable name for the application. This name should be
1253  * localized if possible, and is intended for display to the user.
1254  * Contrast with g_set_prgname(), which sets a non-localized name.
1255  * g_set_prgname() will be called automatically by gtk_init(),
1256  * but g_set_application_name() will not.
1257  *
1258  * Note that for thread safety reasons, this function can only
1259  * be called once.
1260  *
1261  * The application name will be used in contexts such as error messages,
1262  * or when displaying an application's name in the task list.
1263  * 
1264  **/
1265 void
1266 g_set_application_name (const gchar *application_name)
1267 {
1268   gboolean already_set = FALSE;
1269         
1270   G_LOCK (g_application_name);
1271   if (g_application_name)
1272     already_set = TRUE;
1273   else
1274     g_application_name = g_strdup (application_name);
1275   G_UNLOCK (g_application_name);
1276
1277   if (already_set)
1278     g_warning ("g_set_application() name called multiple times");
1279 }
1280
1281 /**
1282  * g_get_user_data_dir:
1283  * 
1284  * Returns a base directory in which to access application data such
1285  * as icons that is customized for a particular user.  
1286  *
1287  * On Unix platforms this is determined using the mechanisms described in
1288  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1289  * XDG Base Directory Specification</ulink>
1290  * 
1291  * Return value: a string owned by GLib that must not be modified 
1292  *               or freed.
1293  * Since: 2.6
1294  **/
1295 G_CONST_RETURN gchar*
1296 g_get_user_data_dir (void)
1297 {
1298   gchar *data_dir;  
1299
1300   G_LOCK (g_utils_global);
1301
1302   if (!g_user_data_dir)
1303     {
1304 #ifdef G_OS_WIN32
1305       data_dir = get_special_folder (CSIDL_PERSONAL);
1306 #else
1307       data_dir = (gchar *) g_getenv ("XDG_DATA_HOME");
1308
1309       if (data_dir && data_dir[0])
1310         data_dir = g_strdup (data_dir);
1311       else
1312         {
1313           if (!g_tmp_dir)
1314             g_get_any_init ();
1315
1316           data_dir = g_build_filename (g_home_dir, ".local", 
1317                                        "share", NULL);
1318         }
1319 #endif
1320       g_user_data_dir = data_dir;
1321     }
1322   else
1323     data_dir = g_user_data_dir;
1324
1325   G_UNLOCK (g_utils_global);
1326
1327   return data_dir;
1328 }
1329
1330 /**
1331  * g_get_user_config_dir:
1332  * 
1333  * Returns a base directory in which to store user-specific application 
1334  * configuration information such as user preferences and settings. 
1335  *
1336  * On Unix platforms this is determined using the mechanisms described in
1337  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1338  * XDG Base Directory Specification</ulink>
1339  * 
1340  * Return value: a string owned by GLib that must not be modified 
1341  *               or freed.
1342  * Since: 2.6
1343  **/
1344 G_CONST_RETURN gchar*
1345 g_get_user_config_dir (void)
1346 {
1347   gchar *config_dir;  
1348
1349   G_LOCK (g_utils_global);
1350
1351   if (!g_user_config_dir)
1352     {
1353 #ifdef G_OS_WIN32
1354       config_dir = get_special_folder (CSIDL_APPDATA);
1355 #else
1356       config_dir = (gchar *) g_getenv ("XDG_CONFIG_HOME");
1357       
1358       if (config_dir && config_dir[0])
1359         config_dir = g_strdup (config_dir);
1360       else
1361         {
1362           if (!g_tmp_dir)
1363             g_get_any_init ();
1364           
1365           config_dir = g_build_filename (g_home_dir, ".config", NULL);
1366         }
1367 #endif      
1368       g_user_config_dir = config_dir;
1369     }
1370   else
1371     config_dir = g_user_config_dir;
1372
1373   G_UNLOCK (g_utils_global);
1374
1375   return config_dir;
1376 }
1377
1378 /**
1379  * g_get_user_cache_dir:
1380  * 
1381  * Returns a base directory in which to store non-essential, cached
1382  * data specific to particular user.
1383  *
1384  * On Unix platforms this is determined using the mechanisms described in
1385  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1386  * XDG Base Directory Specification</ulink>
1387  * 
1388  * Return value: a string owned by GLib that must not be modified 
1389  *               or freed.
1390  * Since: 2.6
1391  **/
1392 G_CONST_RETURN gchar*
1393 g_get_user_cache_dir (void)
1394 {
1395   gchar *cache_dir;  
1396
1397   G_LOCK (g_utils_global);
1398
1399   if (!g_user_cache_dir)
1400     {
1401 #ifdef G_OS_WIN32
1402       cache_dir = get_special_folder (CSIDL_INTERNET_CACHE); /* XXX correct? */
1403 #else
1404       cache_dir = (gchar *) g_getenv ("XDG_CACHE_HOME");
1405
1406       if (cache_dir && cache_dir[0])
1407           cache_dir = g_strdup (cache_dir);
1408       else
1409         {
1410           if (!g_tmp_dir)
1411             g_get_any_init ();
1412
1413           cache_dir = g_build_filename (g_home_dir, ".cache", NULL);
1414         }
1415 #endif
1416       g_user_cache_dir = cache_dir;
1417     }
1418   else
1419     cache_dir = g_user_cache_dir;
1420
1421   G_UNLOCK (g_utils_global);
1422
1423   return cache_dir;
1424 }
1425
1426 /**
1427  * g_get_system_data_dirs:
1428  * 
1429  * Returns an ordered list of base directories in which to access 
1430  * system-wide application data.
1431  *
1432  * On Unix platforms this is determined using the mechanisms described in
1433  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1434  * XDG Base Directory Specification</ulink>
1435  * 
1436  * Return value: a %NULL-terminated array of strings owned by GLib that must 
1437  *               not be modified or freed.
1438  * Since: 2.6
1439  **/
1440 G_CONST_RETURN gchar * G_CONST_RETURN * 
1441 g_get_system_data_dirs (void)
1442 {
1443   gchar *data_dirs, **data_dir_vector;
1444
1445   G_LOCK (g_utils_global);
1446
1447   if (!g_system_data_dirs)
1448     {
1449 #ifdef G_OS_WIN32
1450       data_dirs = g_strconcat (get_special_folder (CSIDL_COMMON_APPDATA),
1451                                G_SEARCHPATH_SEPARATOR_S,
1452                                get_special_folder (CSIDL_COMMON_DOCUMENTS),
1453                                NULL);
1454 #else
1455       data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
1456
1457       if (!data_dirs || !data_dirs[0])
1458           data_dirs = "/usr/local/share/:/usr/share/";
1459 #endif
1460       data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
1461
1462       g_system_data_dirs = data_dir_vector;
1463     }
1464   else
1465     data_dir_vector = g_system_data_dirs;
1466
1467   G_UNLOCK (g_utils_global);
1468
1469   return (G_CONST_RETURN gchar * G_CONST_RETURN *) data_dir_vector;
1470 }
1471
1472 /**
1473  * g_get_system_config_dirs:
1474  * 
1475  * Returns an ordered list of base directories in which to access 
1476  * system-wide configuration information.
1477  *
1478  * On Unix platforms this is determined using the mechanisms described in
1479  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1480  * XDG Base Directory Specification</ulink>
1481  * 
1482  * Return value: a %NULL-terminated array of strings owned by GLib that must 
1483  *               not be modified or freed.
1484  * Since: 2.6
1485  **/
1486 G_CONST_RETURN gchar * G_CONST_RETURN *
1487 g_get_system_config_dirs (void)
1488 {
1489   gchar *conf_dirs, **conf_dir_vector;
1490
1491   G_LOCK (g_utils_global);
1492
1493   if (!g_system_config_dirs)
1494     {
1495 #ifdef G_OS_WIN32
1496       conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA);
1497 #else
1498       conf_dirs = (gchar *) g_getenv ("XDG_CONFIG_DIRS");
1499
1500       if (!conf_dirs || !conf_dirs[0])
1501           conf_dirs = "/etc/xdg";
1502 #endif
1503       conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
1504     }
1505   else
1506     conf_dir_vector = g_system_config_dirs;
1507   G_UNLOCK (g_utils_global);
1508
1509   return (G_CONST_RETURN gchar * G_CONST_RETURN *) conf_dir_vector;
1510 }
1511
1512 static GHashTable *alias_table = NULL;
1513
1514 /* read an alias file for the locales */
1515 static void
1516 read_aliases (gchar *file)
1517 {
1518   FILE *fp;
1519   char buf[256];
1520   
1521   if (!alias_table)
1522     alias_table = g_hash_table_new (g_str_hash, g_str_equal);
1523   fp = fopen (file,"r");
1524   if (!fp)
1525     return;
1526   while (fgets (buf, 256, fp))
1527     {
1528       char *p, *q;
1529
1530       g_strstrip (buf);
1531
1532       /* Line is a comment */
1533       if ((buf[0] == '#') || (buf[0] == '\0'))
1534         continue;
1535
1536       /* Reads first column */
1537       for (p = buf, q = NULL; *p; p++) {
1538         if ((*p == '\t') || (*p == ' ') || (*p == ':')) {
1539           *p = '\0';
1540           q = p+1;
1541           while ((*q == '\t') || (*q == ' ')) {
1542             q++;
1543           }
1544           break;
1545         }
1546       }
1547       /* The line only had one column */
1548       if (!q || *q == '\0')
1549         continue;
1550       
1551       /* Read second column */
1552       for (p = q; *p; p++) {
1553         if ((*p == '\t') || (*p == ' ')) {
1554           *p = '\0';
1555           break;
1556         }
1557       }
1558
1559       /* Add to alias table if necessary */
1560       if (!g_hash_table_lookup (alias_table, buf)) {
1561         g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (q));
1562       }
1563     }
1564   fclose (fp);
1565 }
1566
1567 static char *
1568 unalias_lang (char *lang)
1569 {
1570   char *p;
1571   int i;
1572
1573   if (!alias_table)
1574     read_aliases ("/usr/share/locale/locale.alias");
1575
1576   i = 0;
1577   while ((p = g_hash_table_lookup (alias_table, lang)) && (strcmp (p, lang) != 0))
1578     {
1579       lang = p;
1580       if (i++ == 30)
1581         {
1582           static gboolean said_before = FALSE;
1583           if (!said_before)
1584             g_warning ("Too many alias levels for a locale, "
1585                        "may indicate a loop");
1586           said_before = TRUE;
1587           return lang;
1588         }
1589     }
1590   return lang;
1591 }
1592
1593 /* Mask for components of locale spec. The ordering here is from
1594  * least significant to most significant
1595  */
1596 enum
1597 {
1598   COMPONENT_CODESET =   1 << 0,
1599   COMPONENT_TERRITORY = 1 << 1,
1600   COMPONENT_MODIFIER =  1 << 2
1601 };
1602
1603 /* Break an X/Open style locale specification into components
1604  */
1605 static guint
1606 explode_locale (const gchar *locale,
1607                 gchar      **language, 
1608                 gchar      **territory, 
1609                 gchar      **codeset, 
1610                 gchar      **modifier)
1611 {
1612   const gchar *uscore_pos;
1613   const gchar *at_pos;
1614   const gchar *dot_pos;
1615
1616   guint mask = 0;
1617
1618   uscore_pos = strchr (locale, '_');
1619   dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
1620   at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
1621
1622   if (at_pos)
1623     {
1624       mask |= COMPONENT_MODIFIER;
1625       *modifier = g_strdup (at_pos);
1626     }
1627   else
1628     at_pos = locale + strlen (locale);
1629
1630   if (dot_pos)
1631     {
1632       mask |= COMPONENT_CODESET;
1633       *codeset = g_strndup (dot_pos, at_pos - dot_pos);
1634     }
1635   else
1636     dot_pos = at_pos;
1637
1638   if (uscore_pos)
1639     {
1640       mask |= COMPONENT_TERRITORY;
1641       *territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
1642     }
1643   else
1644     uscore_pos = dot_pos;
1645
1646   *language = g_strndup (locale, uscore_pos - locale);
1647
1648   return mask;
1649 }
1650
1651 /*
1652  * Compute all interesting variants for a given locale name -
1653  * by stripping off different components of the value.
1654  *
1655  * For simplicity, we assume that the locale is in
1656  * X/Open format: language[_territory][.codeset][@modifier]
1657  *
1658  * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
1659  *       as well. We could just copy the code from glibc wholesale
1660  *       but it is big, ugly, and complicated, so I'm reluctant
1661  *       to do so when this should handle 99% of the time...
1662  */
1663 static GSList *
1664 compute_locale_variants (const gchar *locale)
1665 {
1666   GSList *retval = NULL;
1667
1668   gchar *language;
1669   gchar *territory;
1670   gchar *codeset;
1671   gchar *modifier;
1672
1673   guint mask;
1674   guint i;
1675
1676   g_return_val_if_fail (locale != NULL, NULL);
1677
1678   mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
1679
1680   /* Iterate through all possible combinations, from least attractive
1681    * to most attractive.
1682    */
1683   for (i = 0; i <= mask; i++)
1684     if ((i & ~mask) == 0)
1685       {
1686         gchar *val = g_strconcat (language,
1687                                   (i & COMPONENT_TERRITORY) ? territory : "",
1688                                   (i & COMPONENT_CODESET) ? codeset : "",
1689                                   (i & COMPONENT_MODIFIER) ? modifier : "",
1690                                   NULL);
1691         retval = g_slist_prepend (retval, val);
1692       }
1693
1694   g_free (language);
1695   if (mask & COMPONENT_CODESET)
1696     g_free (codeset);
1697   if (mask & COMPONENT_TERRITORY)
1698     g_free (territory);
1699   if (mask & COMPONENT_MODIFIER)
1700     g_free (modifier);
1701
1702   return retval;
1703 }
1704
1705 /* The following is (partly) taken from the gettext package.
1706    Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.  */
1707
1708 static const gchar *
1709 guess_category_value (const gchar *category_name)
1710 {
1711   const gchar *retval;
1712
1713   /* The highest priority value is the `LANGUAGE' environment
1714      variable.  This is a GNU extension.  */
1715   retval = g_getenv ("LANGUAGE");
1716   if ((retval != NULL) && (retval[0] != '\0'))
1717     return retval;
1718
1719   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
1720      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
1721      systems this can be done by the `setlocale' function itself.  */
1722
1723   /* Setting of LC_ALL overwrites all other.  */
1724   retval = g_getenv ("LC_ALL");  
1725   if ((retval != NULL) && (retval[0] != '\0'))
1726     return retval;
1727
1728   /* Next comes the name of the desired category.  */
1729   retval = g_getenv (category_name);
1730   if ((retval != NULL) && (retval[0] != '\0'))
1731     return retval;
1732
1733   /* Last possibility is the LANG environment variable.  */
1734   retval = g_getenv ("LANG");
1735   if ((retval != NULL) && (retval[0] != '\0'))
1736     return retval;
1737
1738 #ifdef G_PLATFORM_WIN32
1739   /* g_win32_getlocale() first checks for LC_ALL, LC_MESSAGES and
1740    * LANG, which we already did above. Oh well. The main point of
1741    * calling g_win32_getlocale() is to get the thread's locale as used
1742    * by Windows and the Microsoft C runtime (in the "English_United
1743    * States" format) translated into the Unixish format.
1744    */
1745   retval = g_win32_getlocale ();
1746   if ((retval != NULL) && (retval[0] != '\0'))
1747     return retval;
1748 #endif  
1749
1750   return NULL;
1751 }
1752
1753 static gchar **languages = NULL;
1754
1755 /**
1756  * g_get_language_names:
1757  * 
1758  * Computes a list of applicable locale names, which can be used to 
1759  * e.g. construct locale-dependent filenames or search paths. The returned 
1760  * list is sorted from most desirable to least desirable and always contains 
1761  * the default locale "C".
1762  *
1763  * For example, if LANGUAGE=de:en_US, then the returned list is
1764  * "de", "en_US", "en", "C".
1765  *
1766  * This function consults the environment variables <envar>LANGUAGE</envar>, 
1767  * <envar>LC_ALL</envar>, <envar>LC_MESSAGES</envar> and <envar>LANG</envar> 
1768  * to find the list of locales specified by the user.
1769  * 
1770  * Return value: a %NULL-terminated array of strings owned by GLib 
1771  *    that must not be modified or freed.
1772  *
1773  * Since: 2.6
1774  **/
1775 G_CONST_RETURN gchar * G_CONST_RETURN * 
1776 g_get_language_names ()
1777 {
1778   G_LOCK (g_utils_global);
1779
1780   if (!languages)
1781     {
1782       const gchar *value;
1783       gchar **alist, **a;
1784       GSList *list, *l;
1785       gint i;
1786
1787       value = guess_category_value ("LC_MESSAGES");
1788       if (!value)
1789         value = "C";
1790
1791       alist = g_strsplit (value, ":", 0);
1792       list = NULL;
1793       for (a = alist; *a; a++)
1794         {
1795           gchar *b = unalias_lang (*a);
1796           list = g_slist_concat (list, compute_locale_variants (b));
1797         }
1798       g_strfreev (alist);
1799       list = g_slist_append (list, "C");
1800
1801       languages = g_new (gchar *, g_slist_length (list) + 1);
1802       for (l = list, i = 0; l; l = l->next, i++)
1803         languages[i] = l->data;
1804       languages[i] = NULL;
1805
1806       g_slist_free (list);
1807     }
1808
1809   G_UNLOCK (g_utils_global);
1810
1811   return (G_CONST_RETURN gchar * G_CONST_RETURN *) languages;
1812 }
1813
1814 guint
1815 g_direct_hash (gconstpointer v)
1816 {
1817   return GPOINTER_TO_UINT (v);
1818 }
1819
1820 gboolean
1821 g_direct_equal (gconstpointer v1,
1822                 gconstpointer v2)
1823 {
1824   return v1 == v2;
1825 }
1826
1827 gboolean
1828 g_int_equal (gconstpointer v1,
1829              gconstpointer v2)
1830 {
1831   return *((const gint*) v1) == *((const gint*) v2);
1832 }
1833
1834 guint
1835 g_int_hash (gconstpointer v)
1836 {
1837   return *(const gint*) v;
1838 }
1839
1840 /**
1841  * g_nullify_pointer:
1842  * @nullify_location: the memory address of the pointer.
1843  * 
1844  * Set the pointer at the specified location to %NULL.
1845  **/
1846 void
1847 g_nullify_pointer (gpointer *nullify_location)
1848 {
1849   g_return_if_fail (nullify_location != NULL);
1850
1851   *nullify_location = NULL;
1852 }
1853
1854 /**
1855  * g_get_codeset:
1856  * 
1857  * Get the codeset for the current locale.
1858  * 
1859  * Return value: a newly allocated string containing the name
1860  * of the codeset. This string must be freed with g_free().
1861  **/
1862 gchar *
1863 g_get_codeset (void)
1864 {
1865   const gchar *charset;
1866
1867   g_get_charset (&charset);
1868
1869   return g_strdup (charset);
1870 }
1871
1872 #ifdef ENABLE_NLS
1873
1874 #include <libintl.h>
1875
1876 #ifdef G_PLATFORM_WIN32
1877
1878 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
1879
1880 static const gchar *
1881 _glib_get_locale_dir (void)
1882 {
1883   static const gchar *cache = NULL;
1884   if (cache == NULL)
1885     cache = g_win32_get_package_installation_subdirectory
1886       (GETTEXT_PACKAGE, dll_name, "lib\\locale");
1887
1888   return cache;
1889 }
1890
1891 #undef GLIB_LOCALE_DIR
1892 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
1893
1894 #endif /* G_PLATFORM_WIN32 */
1895
1896 G_CONST_RETURN gchar *
1897 _glib_gettext (const gchar *str)
1898 {
1899   static gboolean _glib_gettext_initialized = FALSE;
1900
1901   if (!_glib_gettext_initialized)
1902     {
1903       bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1904 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1905       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1906 #    endif
1907       _glib_gettext_initialized = TRUE;
1908     }
1909   
1910   return dgettext (GETTEXT_PACKAGE, str);
1911 }
1912
1913 #endif /* ENABLE_NLS */