Merge from 2.4:
[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 <string.h>
40 #include <errno.h>
41 #ifdef HAVE_PWD_H
42 #include <pwd.h>
43 #endif
44 #include <sys/types.h>
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
47 #endif
48
49 /* implement gutils's inline functions
50  */
51 #define G_IMPLEMENT_INLINES 1
52 #define __G_UTILS_C__
53 #include "glib.h"
54 #include "gprintfint.h"
55
56 #ifdef  MAXPATHLEN
57 #define G_PATH_LENGTH   MAXPATHLEN
58 #elif   defined (PATH_MAX)
59 #define G_PATH_LENGTH   PATH_MAX
60 #elif   defined (_PC_PATH_MAX)
61 #define G_PATH_LENGTH   sysconf(_PC_PATH_MAX)
62 #else   
63 #define G_PATH_LENGTH   2048
64 #endif
65
66 #ifdef G_PLATFORM_WIN32
67 #  define STRICT                /* Strict typing, please */
68 #  include <windows.h>
69 #  undef STRICT
70 #  include <lmcons.h>           /* For UNLEN */
71 #  include <ctype.h>
72 #endif /* G_PLATFORM_WIN32 */
73
74 #ifdef G_OS_WIN32
75 #  include <direct.h>
76 #endif
77
78 #ifdef HAVE_CODESET
79 #include <langinfo.h>
80 #endif
81
82 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
83 #include <libintl.h>
84 #endif
85
86 /* G_IS_DIR_SEPARATOR probably should be made public in GLib 2.4 */
87 #ifdef G_OS_WIN32
88 #define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR || c == '/')
89 #else
90 #define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR)
91 #endif
92
93 const guint glib_major_version = GLIB_MAJOR_VERSION;
94 const guint glib_minor_version = GLIB_MINOR_VERSION;
95 const guint glib_micro_version = GLIB_MICRO_VERSION;
96 const guint glib_interface_age = GLIB_INTERFACE_AGE;
97 const guint glib_binary_age = GLIB_BINARY_AGE;
98
99 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
100 void 
101 g_memmove (gpointer dest, gconstpointer src, gulong len)
102 {
103   gchar* destptr = dest;
104   const gchar* srcptr = src;
105   if (src + len < dest || dest + len < src)
106     {
107       bcopy (src, dest, len);
108       return;
109     }
110   else if (dest <= src)
111     {
112       while (len--)
113         *(destptr++) = *(srcptr++);
114     }
115   else
116     {
117       destptr += len;
118       srcptr += len;
119       while (len--)
120         *(--destptr) = *(--srcptr);
121     }
122 }
123 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
124
125 void
126 g_atexit (GVoidFunc func)
127 {
128   gint result;
129   const gchar *error = NULL;
130
131   /* keep this in sync with glib.h */
132
133 #ifdef  G_NATIVE_ATEXIT
134   result = ATEXIT (func);
135   if (result)
136     error = g_strerror (errno);
137 #elif defined (HAVE_ATEXIT)
138 #  ifdef NeXT /* @#%@! NeXTStep */
139   result = !atexit ((void (*)(void)) func);
140   if (result)
141     error = g_strerror (errno);
142 #  else
143   result = atexit ((void (*)(void)) func);
144   if (result)
145     error = g_strerror (errno);
146 #  endif /* NeXT */
147 #elif defined (HAVE_ON_EXIT)
148   result = on_exit ((void (*)(int, void *)) func, NULL);
149   if (result)
150     error = g_strerror (errno);
151 #else
152   result = 0;
153   error = "no implementation";
154 #endif /* G_NATIVE_ATEXIT */
155
156   if (error)
157     g_error ("Could not register atexit() function: %s", error);
158 }
159
160 /* Based on execvp() from GNU Libc.
161  * Some of this code is cut-and-pasted into gspawn.c
162  */
163
164 static gchar*
165 my_strchrnul (const gchar *str, gchar c)
166 {
167   gchar *p = (gchar*)str;
168   while (*p && (*p != c))
169     ++p;
170
171   return p;
172 }
173
174 #ifdef G_OS_WIN32
175
176 static gchar *inner_find_program_in_path (const gchar *program);
177
178 gchar*
179 g_find_program_in_path (const gchar *program)
180 {
181   const gchar *last_dot = strrchr (program, '.');
182
183   if (last_dot == NULL || strchr (last_dot, '\\') != NULL)
184     {
185       const gint program_length = strlen (program);
186       const gchar *pathext = getenv ("PATHEXT");
187       const gchar *p;
188       gchar *decorated_program;
189       gchar *retval;
190
191       if (pathext == NULL)
192         pathext = ".com;.exe;.bat";
193
194       p = pathext;
195       do
196         {
197           pathext = p;
198           p = my_strchrnul (pathext, ';');
199
200           decorated_program = g_malloc (program_length + (p-pathext) + 1);
201           memcpy (decorated_program, program, program_length);
202           memcpy (decorated_program+program_length, pathext, p-pathext);
203           decorated_program [program_length + (p-pathext)] = '\0';
204           
205           retval = inner_find_program_in_path (decorated_program);
206           g_free (decorated_program);
207
208           if (retval != NULL)
209             return retval;
210         } while (*p++ != '\0');
211       return NULL;
212     }
213   else
214     return inner_find_program_in_path (program);
215 }
216
217 #define g_find_program_in_path inner_find_program_in_path
218 #endif
219
220 /**
221  * g_find_program_in_path:
222  * @program: a program name
223  * 
224  * Locates the first executable named @program in the user's path, in the
225  * same way that execvp() would locate it. Returns an allocated string
226  * with the absolute path name, or NULL if the program is not found in
227  * the path. If @program is already an absolute path, returns a copy of
228  * @program if @program exists and is executable, and NULL otherwise.
229  * 
230  * On Windows, if @program does not have a file type suffix, tries to
231  * append the suffixes in the PATHEXT environment variable (if that
232  * doesn't exists, the suffixes .com, .exe, and .bat) in turn, and
233  * then look for the resulting file name in the same way as
234  * CreateProcess() would. This means first in the directory where the
235  * program was loaded from, then in the current directory, then in the
236  * Windows 32-bit system directory, then in the Windows directory, and
237  * finally in the directories in the PATH environment variable. If
238  * the program is found, the return value contains the full name
239  * including the type suffix.
240  *
241  * Return value: absolute path, or NULL
242  **/
243 #ifdef G_OS_WIN32
244 static
245 #endif
246 gchar*
247 g_find_program_in_path (const gchar *program)
248 {
249   const gchar *path, *p;
250   gchar *name, *freeme;
251 #ifdef G_OS_WIN32
252   gchar *path_tmp;
253 #endif
254   size_t len;
255   size_t pathlen;
256
257   g_return_val_if_fail (program != NULL, NULL);
258
259   /* If it is an absolute path, or a relative path including subdirectories,
260    * don't look in PATH.
261    */
262   if (g_path_is_absolute (program)
263       || strchr (program, G_DIR_SEPARATOR) != NULL
264 #ifdef G_OS_WIN32
265       || strchr (program, '/') != NULL
266 #endif
267       )
268     {
269       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
270         return g_strdup (program);
271       else
272         return NULL;
273     }
274   
275   path = g_getenv ("PATH");
276 #ifdef G_OS_UNIX
277   if (path == NULL)
278     {
279       /* There is no `PATH' in the environment.  The default
280        * search path in GNU libc is the current directory followed by
281        * the path `confstr' returns for `_CS_PATH'.
282        */
283       
284       /* In GLib we put . last, for security, and don't use the
285        * unportable confstr(); UNIX98 does not actually specify
286        * what to search if PATH is unset. POSIX may, dunno.
287        */
288       
289       path = "/bin:/usr/bin:.";
290     }
291 #else
292   {
293     gchar *tmp;
294     gchar moddir[MAXPATHLEN], sysdir[MAXPATHLEN], windir[MAXPATHLEN];
295
296     GetModuleFileName (NULL, moddir, sizeof (moddir));
297     tmp = g_path_get_dirname (moddir);
298     GetSystemDirectory (sysdir, sizeof (sysdir));
299     GetWindowsDirectory (windir, sizeof (windir));
300     path_tmp = g_strconcat (tmp, ";.;", sysdir, ";", windir,
301                             (path != NULL ? ";" : NULL),
302                             (path != NULL ? path : NULL),
303                             NULL);
304     g_free (tmp);
305     path = path_tmp;
306   }
307 #endif
308   
309   len = strlen (program) + 1;
310   pathlen = strlen (path);
311   freeme = name = g_malloc (pathlen + len + 1);
312   
313   /* Copy the file name at the top, including '\0'  */
314   memcpy (name + pathlen + 1, program, len);
315   name = name + pathlen;
316   /* And add the slash before the filename  */
317   *name = G_DIR_SEPARATOR;
318   
319   p = path;
320   do
321     {
322       char *startp;
323
324       path = p;
325       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
326
327       if (p == path)
328         /* Two adjacent colons, or a colon at the beginning or the end
329          * of `PATH' means to search the current directory.
330          */
331         startp = name + 1;
332       else
333         startp = memcpy (name - (p - path), path, p - path);
334
335       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE))
336         {
337           gchar *ret;
338           ret = g_strdup (startp);
339           g_free (freeme);
340 #ifdef G_OS_WIN32
341           g_free (path_tmp);
342 #endif
343           return ret;
344         }
345     }
346   while (*p++ != '\0');
347   
348   g_free (freeme);
349 #ifdef G_OS_WIN32
350   g_free (path_tmp);
351 #endif
352
353   return NULL;
354 }
355
356 guint        
357 g_parse_debug_string  (const gchar     *string, 
358                        const GDebugKey *keys, 
359                        guint            nkeys)
360 {
361   guint i;
362   guint result = 0;
363   
364   g_return_val_if_fail (string != NULL, 0);
365   
366   if (!g_ascii_strcasecmp (string, "all"))
367     {
368       for (i=0; i<nkeys; i++)
369         result |= keys[i].value;
370     }
371   else
372     {
373       const gchar *p = string;
374       const gchar *q;
375       gboolean done = FALSE;
376       
377       while (*p && !done)
378         {
379           q = strchr (p, ':');
380           if (!q)
381             {
382               q = p + strlen(p);
383               done = TRUE;
384             }
385           
386           for (i=0; i<nkeys; i++)
387             if (g_ascii_strncasecmp(keys[i].key, p, q - p) == 0 &&
388                 keys[i].key[q - p] == '\0')
389               result |= keys[i].value;
390           
391           p = q + 1;
392         }
393     }
394   
395   return result;
396 }
397
398 /**
399  * g_basename:
400  * @file_name: the name of the file.
401  * 
402  * Gets the name of the file without any leading directory components.  
403  * It returns a pointer into the given file name string.
404  * 
405  * Return value: the name of the file without any leading directory components.
406  *
407  * Deprecated: Use g_path_get_basename() instead, but notice that
408  * g_path_get_basename() allocates new memory for the returned string, unlike
409  * this function which returns a pointer into the argument.
410  **/
411 G_CONST_RETURN gchar*
412 g_basename (const gchar    *file_name)
413 {
414   register gchar *base;
415   
416   g_return_val_if_fail (file_name != NULL, NULL);
417   
418   base = strrchr (file_name, G_DIR_SEPARATOR);
419
420 #ifdef G_OS_WIN32
421   {
422     gchar *q = strrchr (file_name, '/');
423     if (base == NULL || (q != NULL && q > base))
424         base = q;
425   }
426 #endif
427
428   if (base)
429     return base + 1;
430
431 #ifdef G_OS_WIN32
432   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
433     return (gchar*) file_name + 2;
434 #endif /* G_OS_WIN32 */
435   
436   return (gchar*) file_name;
437 }
438
439 /**
440  * g_path_get_basename:
441  * @file_name: the name of the file.
442  *
443  * Gets the last component of the filename. If @file_name ends with a 
444  * directory separator it gets the component before the last slash. If 
445  * @file_name consists only of directory separators (and on Windows, 
446  * possibly a drive letter), a single separator is returned. If
447  * @file_name is empty, it gets ".".
448  *
449  * Return value: a newly allocated string containing the last component of 
450  *   the filename.
451  */
452 gchar*
453 g_path_get_basename (const gchar   *file_name)
454 {
455   register gssize base;             
456   register gssize last_nonslash;    
457   gsize len;    
458   gchar *retval;
459  
460   g_return_val_if_fail (file_name != NULL, NULL);
461
462   if (file_name[0] == '\0')
463     /* empty string */
464     return g_strdup (".");
465   
466   last_nonslash = strlen (file_name) - 1;
467
468   while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
469     last_nonslash--;
470
471   if (last_nonslash == -1)
472     /* string only containing slashes */
473     return g_strdup (G_DIR_SEPARATOR_S);
474
475 #ifdef G_OS_WIN32
476   if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
477     /* string only containing slashes and a drive */
478     return g_strdup (G_DIR_SEPARATOR_S);
479 #endif /* G_OS_WIN32 */
480
481   base = last_nonslash;
482
483   while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
484     base--;
485
486 #ifdef G_OS_WIN32
487   if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
488     base = 1;
489 #endif /* G_OS_WIN32 */
490
491   len = last_nonslash - base;
492   retval = g_malloc (len + 1);
493   memcpy (retval, file_name + base + 1, len);
494   retval [len] = '\0';
495   return retval;
496 }
497
498 gboolean
499 g_path_is_absolute (const gchar *file_name)
500 {
501   g_return_val_if_fail (file_name != NULL, FALSE);
502   
503   if (G_IS_DIR_SEPARATOR (file_name[0]))
504     return TRUE;
505
506 #ifdef G_OS_WIN32
507   /* Recognize drive letter on native Windows */
508   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
509     return TRUE;
510 #endif /* G_OS_WIN32 */
511
512   return FALSE;
513 }
514
515 G_CONST_RETURN gchar*
516 g_path_skip_root (const gchar *file_name)
517 {
518   g_return_val_if_fail (file_name != NULL, NULL);
519   
520 #ifdef G_PLATFORM_WIN32
521   /* Skip \\server\share or //server/share */
522   if (G_IS_DIR_SEPARATOR (file_name[0]) &&
523       G_IS_DIR_SEPARATOR (file_name[1]) &&
524       file_name[2])
525     {
526       gchar *p;
527
528       p = strchr (file_name + 2, G_DIR_SEPARATOR);
529 #ifdef G_OS_WIN32
530       {
531         gchar *q = strchr (file_name + 2, '/');
532         if (p == NULL || (q != NULL && q < p))
533           p = q;
534       }
535 #endif
536       if (p &&
537           p > file_name + 2 &&
538           p[1])
539         {
540           file_name = p + 1;
541
542           while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
543             file_name++;
544
545           /* Possibly skip a backslash after the share name */
546           if (G_IS_DIR_SEPARATOR (file_name[0]))
547             file_name++;
548
549           return (gchar *)file_name;
550         }
551     }
552 #endif
553   
554   /* Skip initial slashes */
555   if (G_IS_DIR_SEPARATOR (file_name[0]))
556     {
557       while (G_IS_DIR_SEPARATOR (file_name[0]))
558         file_name++;
559       return (gchar *)file_name;
560     }
561
562 #ifdef G_OS_WIN32
563   /* Skip X:\ */
564   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
565     return (gchar *)file_name + 3;
566 #endif
567
568   return NULL;
569 }
570
571 gchar*
572 g_path_get_dirname (const gchar    *file_name)
573 {
574   register gchar *base;
575   register gsize len;    
576   
577   g_return_val_if_fail (file_name != NULL, NULL);
578   
579   base = strrchr (file_name, G_DIR_SEPARATOR);
580 #ifdef G_OS_WIN32
581   {
582     gchar *q = strrchr (file_name, '/');
583     if (base == NULL || (q != NULL && q > base))
584         base = q;
585   }
586 #endif
587   if (!base)
588     {
589 #ifdef G_OS_WIN32
590       if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
591         {
592           gchar drive_colon_dot[4];
593
594           drive_colon_dot[0] = file_name[0];
595           drive_colon_dot[1] = ':';
596           drive_colon_dot[2] = '.';
597           drive_colon_dot[3] = '\0';
598
599           return g_strdup (drive_colon_dot);
600         }
601 #endif
602     return g_strdup (".");
603     }
604
605   while (base > file_name && G_IS_DIR_SEPARATOR (*base))
606     base--;
607
608 #ifdef G_OS_WIN32
609   if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
610       base++;
611 #endif
612
613   len = (guint) 1 + base - file_name;
614   
615   base = g_new (gchar, len + 1);
616   g_memmove (base, file_name, len);
617   base[len] = 0;
618   
619   return base;
620 }
621
622 gchar*
623 g_get_current_dir (void)
624 {
625   gchar *buffer = NULL;
626   gchar *dir = NULL;
627   static gulong max_len = 0;
628
629   if (max_len == 0) 
630     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
631   
632   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
633    * and, if that wasn't bad enough, hangs in doing so.
634    */
635 #if     (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
636   buffer = g_new (gchar, max_len + 1);
637   *buffer = 0;
638   dir = getwd (buffer);
639 #else   /* !sun || !HAVE_GETCWD */
640   while (max_len < G_MAXULONG / 2)
641     {
642       buffer = g_new (gchar, max_len + 1);
643       *buffer = 0;
644       dir = getcwd (buffer, max_len);
645
646       if (dir || errno != ERANGE)
647         break;
648
649       g_free (buffer);
650       max_len *= 2;
651     }
652 #endif  /* !sun || !HAVE_GETCWD */
653   
654   if (!dir || !*buffer)
655     {
656       /* hm, should we g_error() out here?
657        * this can happen if e.g. "./" has mode \0000
658        */
659       buffer[0] = G_DIR_SEPARATOR;
660       buffer[1] = 0;
661     }
662
663   dir = g_strdup (buffer);
664   g_free (buffer);
665   
666   return dir;
667 }
668
669 /**
670  * g_getenv:
671  * @variable: the environment variable to get.
672  * 
673  * Returns an environment variable.
674  * 
675  * Return value: the value of the environment variable, or %NULL if the environment
676  * variable is not found. The returned string may be overwritten by the next call to g_getenv(),
677  * g_setenv() or g_unsetenv().
678  **/
679 G_CONST_RETURN gchar*
680 g_getenv (const gchar *variable)
681 {
682 #ifndef G_OS_WIN32
683   g_return_val_if_fail (variable != NULL, NULL);
684
685   return getenv (variable);
686 #else
687   GQuark quark;
688   gchar *system_env;
689   gchar *expanded_env;
690   guint length;
691   gchar dummy[2];
692
693   g_return_val_if_fail (variable != NULL, NULL);
694   
695   system_env = getenv (variable);
696   if (!system_env)
697     return NULL;
698
699   /* On Windows NT, it is relatively typical that environment
700    * variables contain references to other environment variables. If
701    * so, use ExpandEnvironmentStrings(). (If all software was written
702    * in the best possible way, such environment variables would be
703    * stored in the Registry as REG_EXPAND_SZ type values, and would
704    * then get automatically expanded before the program sees them. But
705    * there is broken software that stores environment variables as
706    * REG_SZ values even if they contain references to other
707    * environment variables.
708    */
709
710   if (strchr (system_env, '%') == NULL)
711     {
712       /* No reference to other variable(s), return value as such. */
713       return system_env;
714     }
715
716   /* First check how much space we need */
717   length = ExpandEnvironmentStrings (system_env, dummy, 2);
718   
719   expanded_env = g_malloc (length);
720   
721   ExpandEnvironmentStrings (system_env, expanded_env, length);
722   
723   quark = g_quark_from_string (expanded_env);
724   g_free (expanded_env);
725   
726   return g_quark_to_string (quark);
727 #endif
728 }
729
730 /**
731  * g_setenv:
732  * @variable: the environment variable to set, must not contain '='.
733  * @value: the value for to set the variable to.
734  * @overwrite: whether to change the variable if it already exists.
735  *
736  * Sets an environment variable.
737  *
738  * Note that on some systems, the memory used for the variable and its value 
739  * can't be reclaimed later.
740  *
741  * Returns: %FALSE if the environment variable couldn't be set.
742  *
743  * Since: 2.4
744  */
745 gboolean
746 g_setenv (const gchar *variable, 
747           const gchar *value, 
748           gboolean     overwrite)
749 {
750   gint result;
751 #ifndef HAVE_SETENV
752   gchar *string;
753 #endif
754
755   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
756
757 #ifdef HAVE_SETENV
758   result = setenv (variable, value, overwrite);
759 #else
760   if (!overwrite && g_getenv (variable) != NULL)
761     return TRUE;
762   
763   /* This results in a leak when you overwrite existing
764    * settings. It would be fairly easy to fix this by keeping
765    * our own parallel array or hash table.
766    */
767   string = g_strconcat (variable, "=", value, NULL);
768   result = putenv (string);
769 #endif
770   return result == 0;
771 }
772
773 #ifndef HAVE_UNSETENV     
774 /* According to the Single Unix Specification, environ is not in 
775  * any system header, although unistd.h often declares it.
776  */
777 extern char **environ;
778 #endif
779            
780 /**
781  * g_unsetenv:
782  * @variable: the environment variable to remove, must not contain '='.
783  * 
784  * Removes an environment variable from the environment.
785  *
786  * Note that on some systems, the memory used for the variable and its value 
787  * can't be reclaimed. Furthermore, this function can't be guaranteed to operate in a 
788  * threadsafe way.
789  *
790  * Since: 2.4 
791  **/
792 void
793 g_unsetenv (const gchar *variable)
794 {
795 #ifdef HAVE_UNSETENV
796   g_return_if_fail (strchr (variable, '=') == NULL);
797
798   unsetenv (variable);
799 #else
800   int len;
801   gchar **e, **f;
802
803   g_return_if_fail (strchr (variable, '=') == NULL);
804
805   len = strlen (variable);
806   
807   /* Mess directly with the environ array.
808    * This seems to be the only portable way to do this.
809    *
810    * Note that we remove *all* environment entries for
811    * the variable name, not just the first.
812    */
813   e = f = environ;
814   while (*e != NULL) 
815     {
816       if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') 
817         {
818           *f = *e;
819           f++;
820         }
821       e++;
822     }
823   *f = NULL;
824 #endif
825 }
826
827 G_LOCK_DEFINE_STATIC (g_utils_global);
828
829 static  gchar   *g_tmp_dir = NULL;
830 static  gchar   *g_user_name = NULL;
831 static  gchar   *g_real_name = NULL;
832 static  gchar   *g_home_dir = NULL;
833
834 /* HOLDS: g_utils_global_lock */
835 static void
836 g_get_any_init (void)
837 {
838   if (!g_tmp_dir)
839     {
840       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
841       if (!g_tmp_dir)
842         g_tmp_dir = g_strdup (g_getenv ("TMP"));
843       if (!g_tmp_dir)
844         g_tmp_dir = g_strdup (g_getenv ("TEMP"));
845       
846 #ifdef P_tmpdir
847       if (!g_tmp_dir)
848         {
849           gsize k;    
850           g_tmp_dir = g_strdup (P_tmpdir);
851           k = strlen (g_tmp_dir);
852           if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1]))
853             g_tmp_dir[k - 1] = '\0';
854         }
855 #endif
856       
857       if (!g_tmp_dir)
858         {
859 #ifndef G_OS_WIN32
860           g_tmp_dir = g_strdup ("/tmp");
861 #else /* G_OS_WIN32 */
862           g_tmp_dir = g_strdup ("C:\\");
863 #endif /* G_OS_WIN32 */
864         }
865       
866 #ifdef G_OS_WIN32
867       /* We check $HOME first for Win32, though it is a last resort for Unix
868        * where we prefer the results of getpwuid().
869        */
870       g_home_dir = g_strdup (g_getenv ("HOME"));
871       
872       /* In case HOME is Unix-style (it happens), convert it to
873        * Windows style.
874        */
875       if (g_home_dir)
876         {
877           gchar *p;
878           while ((p = strchr (g_home_dir, '/')) != NULL)
879             *p = '\\';
880         }
881
882       if (!g_home_dir)
883         {
884           /* USERPROFILE is probably the closest equivalent to $HOME? */
885           if (getenv ("USERPROFILE") != NULL)
886             g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
887         }
888
889       if (!g_home_dir)
890         {
891           /* At least at some time, HOMEDRIVE and HOMEPATH were used
892            * to point to the home directory, I think. But on Windows
893            * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
894            * HOMEPATH is its root "\"?
895            */
896           if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
897             {
898               gchar *homedrive, *homepath;
899               
900               homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
901               homepath = g_strdup (g_getenv ("HOMEPATH"));
902               
903               g_home_dir = g_strconcat (homedrive, homepath, NULL);
904               g_free (homedrive);
905               g_free (homepath);
906             }
907         }
908 #endif /* G_OS_WIN32 */
909       
910 #ifdef HAVE_PWD_H
911       {
912         struct passwd *pw = NULL;
913         gpointer buffer = NULL;
914         gint error;
915         
916 #  if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
917         struct passwd pwd;
918 #    ifdef _SC_GETPW_R_SIZE_MAX  
919         /* This reurns the maximum length */
920         glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
921         
922         if (bufsize < 0)
923           bufsize = 64;
924 #    else /* _SC_GETPW_R_SIZE_MAX */
925         glong bufsize = 64;
926 #    endif /* _SC_GETPW_R_SIZE_MAX */
927         
928         do
929           {
930             g_free (buffer);
931             buffer = g_malloc (bufsize);
932             errno = 0;
933             
934 #    ifdef HAVE_POSIX_GETPWUID_R
935             error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
936             error = error < 0 ? errno : error;
937 #    else /* HAVE_NONPOSIX_GETPWUID_R */
938        /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
939 #      if defined(_AIX) || defined(__hpux)
940             error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
941             pw = error == 0 ? &pwd : NULL;
942 #      else /* !_AIX */
943             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
944             error = pw ? 0 : errno;
945 #      endif /* !_AIX */            
946 #    endif /* HAVE_NONPOSIX_GETPWUID_R */
947             
948             if (!pw)
949               {
950                 /* we bail out prematurely if the user id can't be found
951                  * (should be pretty rare case actually), or if the buffer
952                  * should be sufficiently big and lookups are still not
953                  * successfull.
954                  */
955                 if (error == 0 || error == ENOENT)
956                   {
957                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
958                                (gulong) getuid ());
959                     break;
960                   }
961                 if (bufsize > 32 * 1024)
962                   {
963                     g_warning ("getpwuid_r(): failed due to: %s.",
964                                g_strerror (error));
965                     break;
966                   }
967                 
968                 bufsize *= 2;
969               }
970           }
971         while (!pw);
972 #  endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
973         
974         if (!pw)
975           {
976             setpwent ();
977             pw = getpwuid (getuid ());
978             endpwent ();
979           }
980         if (pw)
981           {
982             g_user_name = g_strdup (pw->pw_name);
983
984             if (pw->pw_gecos && *pw->pw_gecos != '\0') 
985               {
986                 gchar **gecos_fields;
987                 gchar **name_parts;
988
989                 /* split the gecos field and substitute '&' */
990                 gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
991                 name_parts = g_strsplit (gecos_fields[0], "&", 0);
992                 pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
993                 g_real_name = g_strjoinv (pw->pw_name, name_parts);
994                 g_strfreev (gecos_fields);
995                 g_strfreev (name_parts);
996               }
997
998             if (!g_home_dir)
999               g_home_dir = g_strdup (pw->pw_dir);
1000           }
1001         g_free (buffer);
1002       }
1003       
1004 #else /* !HAVE_PWD_H */
1005       
1006 #  ifdef G_OS_WIN32
1007       {
1008         guint len = UNLEN+1;
1009         gchar buffer[UNLEN+1];
1010         
1011         if (GetUserName ((LPTSTR) buffer, (LPDWORD) &len))
1012           {
1013             g_user_name = g_strdup (buffer);
1014             g_real_name = g_strdup (buffer);
1015           }
1016       }
1017 #  endif /* G_OS_WIN32 */
1018
1019 #endif /* !HAVE_PWD_H */
1020
1021       if (!g_home_dir)
1022         g_home_dir = g_strdup (g_getenv ("HOME"));
1023       
1024 #ifdef __EMX__
1025       /* change '\\' in %HOME% to '/' */
1026       g_strdelimit (g_home_dir, "\\",'/');
1027 #endif
1028       if (!g_user_name)
1029         g_user_name = g_strdup ("somebody");
1030       if (!g_real_name)
1031         g_real_name = g_strdup ("Unknown");
1032     }
1033 }
1034
1035 G_CONST_RETURN gchar*
1036 g_get_user_name (void)
1037 {
1038   G_LOCK (g_utils_global);
1039   if (!g_tmp_dir)
1040     g_get_any_init ();
1041   G_UNLOCK (g_utils_global);
1042   
1043   return g_user_name;
1044 }
1045
1046 G_CONST_RETURN gchar*
1047 g_get_real_name (void)
1048 {
1049   G_LOCK (g_utils_global);
1050   if (!g_tmp_dir)
1051     g_get_any_init ();
1052   G_UNLOCK (g_utils_global);
1053  
1054   return g_real_name;
1055 }
1056
1057 /* Return the home directory of the user. If there is a HOME
1058  * environment variable, its value is returned, otherwise use some
1059  * system-dependent way of finding it out. If no home directory can be
1060  * deduced, return NULL.
1061  */
1062
1063 G_CONST_RETURN gchar*
1064 g_get_home_dir (void)
1065 {
1066   G_LOCK (g_utils_global);
1067   if (!g_tmp_dir)
1068     g_get_any_init ();
1069   G_UNLOCK (g_utils_global);
1070   
1071   return g_home_dir;
1072 }
1073
1074 /* Return a directory to be used to store temporary files. This is the
1075  * value of the TMPDIR, TMP or TEMP environment variables (they are
1076  * checked in that order). If none of those exist, use P_tmpdir from
1077  * stdio.h.  If that isn't defined, return "/tmp" on POSIXly systems,
1078  * and C:\ on Windows.
1079  */
1080
1081 G_CONST_RETURN gchar*
1082 g_get_tmp_dir (void)
1083 {
1084   G_LOCK (g_utils_global);
1085   if (!g_tmp_dir)
1086     g_get_any_init ();
1087   G_UNLOCK (g_utils_global);
1088   
1089   return g_tmp_dir;
1090 }
1091
1092 G_LOCK_DEFINE_STATIC (g_prgname);
1093 static gchar *g_prgname = NULL;
1094
1095 gchar*
1096 g_get_prgname (void)
1097 {
1098   gchar* retval;
1099
1100   G_LOCK (g_prgname);
1101   retval = g_prgname;
1102   G_UNLOCK (g_prgname);
1103
1104   return retval;
1105 }
1106
1107 void
1108 g_set_prgname (const gchar *prgname)
1109 {
1110   G_LOCK (g_prgname);
1111   g_free (g_prgname);
1112   g_prgname = g_strdup (prgname);
1113   G_UNLOCK (g_prgname);
1114 }
1115
1116 G_LOCK_DEFINE_STATIC (g_application_name);
1117 static gchar *g_application_name = NULL;
1118
1119 /**
1120  * g_get_application_name:
1121  * 
1122  * Gets a human-readable name for the application, as set by
1123  * g_set_application_name(). This name should be localized if
1124  * possible, and is intended for display to the user.  Contrast with
1125  * g_get_prgname(), which gets a non-localized name. If
1126  * g_set_application_name() has not been called, returns the result of
1127  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
1128  * been called).
1129  * 
1130  * Return value: human-readable application name. may return %NULL
1131  *
1132  * Since: 2.2
1133  **/
1134 G_CONST_RETURN gchar*
1135 g_get_application_name (void)
1136 {
1137   gchar* retval;
1138
1139   G_LOCK (g_application_name);
1140   retval = g_application_name;
1141   G_UNLOCK (g_application_name);
1142
1143   if (retval == NULL)
1144     return g_get_prgname ();
1145   
1146   return retval;
1147 }
1148
1149 /**
1150  * g_set_application_name:
1151  * @application_name: localized name of the application
1152  *
1153  * Sets a human-readable name for the application. This name should be
1154  * localized if possible, and is intended for display to the user.
1155  * Contrast with g_set_prgname(), which sets a non-localized name.
1156  * g_set_prgname() will be called automatically by gtk_init(),
1157  * but g_set_application_name() will not.
1158  *
1159  * Note that for thread safety reasons, this function can only
1160  * be called once.
1161  *
1162  * The application name will be used in contexts such as error messages,
1163  * or when displaying an application's name in the task list.
1164  * 
1165  **/
1166 void
1167 g_set_application_name (const gchar *application_name)
1168 {
1169   gboolean already_set = FALSE;
1170         
1171   G_LOCK (g_application_name);
1172   if (g_application_name)
1173     already_set = TRUE;
1174   else
1175     g_application_name = g_strdup (application_name);
1176   G_UNLOCK (g_application_name);
1177
1178   if (already_set)
1179     g_warning ("g_set_application() name called multiple times");
1180 }
1181
1182 guint
1183 g_direct_hash (gconstpointer v)
1184 {
1185   return GPOINTER_TO_UINT (v);
1186 }
1187
1188 gboolean
1189 g_direct_equal (gconstpointer v1,
1190                 gconstpointer v2)
1191 {
1192   return v1 == v2;
1193 }
1194
1195 gboolean
1196 g_int_equal (gconstpointer v1,
1197              gconstpointer v2)
1198 {
1199   return *((const gint*) v1) == *((const gint*) v2);
1200 }
1201
1202 guint
1203 g_int_hash (gconstpointer v)
1204 {
1205   return *(const gint*) v;
1206 }
1207
1208 /**
1209  * g_nullify_pointer:
1210  * @nullify_location: the memory address of the pointer.
1211  * 
1212  * Set the pointer at the specified location to %NULL.
1213  **/
1214 void
1215 g_nullify_pointer (gpointer *nullify_location)
1216 {
1217   g_return_if_fail (nullify_location != NULL);
1218
1219   *nullify_location = NULL;
1220 }
1221
1222 /**
1223  * g_get_codeset:
1224  * 
1225  * Get the codeset for the current locale.
1226  * 
1227  * Return value: a newly allocated string containing the name
1228  * of the codeset. This string must be freed with g_free().
1229  **/
1230 gchar *
1231 g_get_codeset (void)
1232 {
1233   gchar *charset;
1234
1235   g_get_charset (&charset);
1236
1237   return charset;
1238 }
1239
1240 #ifdef ENABLE_NLS
1241
1242 #include <libintl.h>
1243
1244 #ifdef G_PLATFORM_WIN32
1245
1246 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
1247
1248 static const gchar *
1249 _glib_get_locale_dir (void)
1250 {
1251   static const gchar *cache = NULL;
1252   if (cache == NULL)
1253     cache = g_win32_get_package_installation_subdirectory
1254       (GETTEXT_PACKAGE, dll_name, "lib\\locale");
1255
1256   return cache;
1257 }
1258
1259 #undef GLIB_LOCALE_DIR
1260 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
1261
1262 #endif /* G_PLATFORM_WIN32 */
1263
1264 G_CONST_RETURN gchar *
1265 _glib_gettext (const gchar *str)
1266 {
1267   static gboolean _glib_gettext_initialized = FALSE;
1268
1269   if (!_glib_gettext_initialized)
1270     {
1271       bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1272 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1273       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1274 #    endif
1275       _glib_gettext_initialized = TRUE;
1276     }
1277   
1278   return dgettext (GETTEXT_PACKAGE, str);
1279 }
1280
1281 #endif /* ENABLE_NLS */