gutils.c gutils.h gfileutils.c Actually, g_mkstemp() is better suited in
[platform/upstream/glib.git] / 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 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
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 <string.h>
42 #include <errno.h>
43 #ifdef HAVE_PWD_H
44 #include <pwd.h>
45 #endif
46 #include <sys/types.h>
47 #ifdef HAVE_SYS_PARAM_H
48 #include <sys/param.h>
49 #endif
50
51 /* implement Glib's inline functions
52  */
53 #define G_IMPLEMENT_INLINES 1
54 #define __G_UTILS_C__
55 #include "glib.h"
56
57 #ifdef  MAXPATHLEN
58 #define G_PATH_LENGTH   MAXPATHLEN
59 #elif   defined (PATH_MAX)
60 #define G_PATH_LENGTH   PATH_MAX
61 #elif   defined (_PC_PATH_MAX)
62 #define G_PATH_LENGTH   sysconf(_PC_PATH_MAX)
63 #else   
64 #define G_PATH_LENGTH   2048
65 #endif
66
67 #ifdef G_OS_WIN32
68 #  define STRICT                        /* Strict typing, please */
69 #  include <windows.h>
70 #  include <ctype.h>
71 #  include <direct.h>
72 #  include <io.h>
73 #endif /* G_OS_WIN32 */
74
75 #ifdef HAVE_CODESET
76 #include <langinfo.h>
77 #endif
78
79 #ifndef O_BINARY
80 #define O_BINARY 0
81 #endif
82
83 const guint glib_major_version = GLIB_MAJOR_VERSION;
84 const guint glib_minor_version = GLIB_MINOR_VERSION;
85 const guint glib_micro_version = GLIB_MICRO_VERSION;
86 const guint glib_interface_age = GLIB_INTERFACE_AGE;
87 const guint glib_binary_age = GLIB_BINARY_AGE;
88
89 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
90 void 
91 g_memmove (gpointer dest, gconstpointer src, gulong len)
92 {
93   gchar* destptr = dest;
94   const gchar* srcptr = src;
95   if (src + len < dest || dest + len < src)
96     {
97       bcopy (src, dest, len);
98       return;
99     }
100   else if (dest <= src)
101     {
102       while (len--)
103         *(destptr++) = *(srcptr++);
104     }
105   else
106     {
107       destptr += len;
108       srcptr += len;
109       while (len--)
110         *(--destptr) = *(--srcptr);
111     }
112 }
113 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
114
115 void
116 g_atexit (GVoidFunc func)
117 {
118   gint result;
119   gchar *error = NULL;
120
121   /* keep this in sync with glib.h */
122
123 #ifdef  G_NATIVE_ATEXIT
124   result = ATEXIT (func);
125   if (result)
126     error = g_strerror (errno);
127 #elif defined (HAVE_ATEXIT)
128 #  ifdef NeXT /* @#%@! NeXTStep */
129   result = !atexit ((void (*)(void)) func);
130   if (result)
131     error = g_strerror (errno);
132 #  else
133   result = atexit ((void (*)(void)) func);
134   if (result)
135     error = g_strerror (errno);
136 #  endif /* NeXT */
137 #elif defined (HAVE_ON_EXIT)
138   result = on_exit ((void (*)(int, void *)) func, NULL);
139   if (result)
140     error = g_strerror (errno);
141 #else
142   result = 0;
143   error = "no implementation";
144 #endif /* G_NATIVE_ATEXIT */
145
146   if (error)
147     g_error ("Could not register atexit() function: %s", error);
148 }
149
150 /* Based on execvp() from GNU Libc.
151  * Some of this code is cut-and-pasted into gspawn.c
152  */
153
154 static gchar*
155 my_strchrnul (const gchar *str, gchar c)
156 {
157   gchar *p = (gchar*)str;
158   while (*p && (*p != c))
159     ++p;
160
161   return p;
162 }
163
164 /**
165  * g_find_program_in_path:
166  * @file: a program name
167  * 
168  * Locates the first executable named @file in the user's path, in the
169  * same way that execvp() would locate it. Returns an allocated string
170  * with the absolute path name, or NULL if the program is not found in
171  * the path. If @file is already an absolute path, returns a copy of
172  * @file if @file exists and is executable, and NULL otherwise.
173  * 
174  * Return value: absolute path, or NULL
175  **/
176 gchar*
177 g_find_program_in_path (const gchar *file)
178 {
179   gchar *path, *p, *name, *freeme;
180   size_t len;
181   size_t pathlen;
182
183   g_return_val_if_fail (file != NULL, NULL);
184
185   if (*file == '/')
186     {
187       if (g_file_test (file, G_FILE_TEST_IS_EXECUTABLE))
188         return g_strdup (file);
189       else
190         return NULL;
191     }
192   
193   path = g_getenv ("PATH");
194   if (path == NULL)
195     {
196       /* There is no `PATH' in the environment.  The default
197        * search path in libc is the current directory followed by
198        * the path `confstr' returns for `_CS_PATH'.
199        */
200       
201       /* In GLib we put . last, for security, and don't use the
202        * unportable confstr(); UNIX98 does not actually specify
203        * what to search if PATH is unset. POSIX may, dunno.
204        */
205       
206       path = "/bin:/usr/bin:.";
207     }
208   
209   len = strlen (file) + 1;
210   pathlen = strlen (path);
211   freeme = name = g_malloc (pathlen + len + 1);
212   
213   /* Copy the file name at the top, including '\0'  */
214   memcpy (name + pathlen + 1, file, len);
215   name = name + pathlen;
216   /* And add the slash before the filename  */
217   *name = '/';
218   
219   p = path;
220   do
221     {
222       char *startp;
223
224       path = p;
225       p = my_strchrnul (path, ':');
226
227       if (p == path)
228         /* Two adjacent colons, or a colon at the beginning or the end
229          * of `PATH' means to search the current directory.
230          */
231         startp = name + 1;
232       else
233         startp = memcpy (name - (p - path), path, p - path);
234
235       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE))
236         {
237           gchar *ret;
238           ret = g_strdup (startp);
239           g_free (freeme);
240           return ret;
241         }
242     }
243   while (*p++ != '\0');
244   
245   g_free (freeme);
246
247   return NULL;
248 }
249
250 gint
251 g_snprintf (gchar       *str,
252             gulong       n,
253             gchar const *fmt,
254             ...)
255 {
256 #ifdef  HAVE_VSNPRINTF
257   va_list args;
258   gint retval;
259   
260   g_return_val_if_fail (str != NULL, 0);
261   g_return_val_if_fail (n > 0, 0);
262   g_return_val_if_fail (fmt != NULL, 0);
263
264   va_start (args, fmt);
265   retval = vsnprintf (str, n, fmt, args);
266   va_end (args);
267
268   if (retval < 0)
269     {
270       str[n-1] = '\0';
271       retval = strlen (str);
272     }
273
274   return retval;
275 #else   /* !HAVE_VSNPRINTF */
276   gchar *printed;
277   va_list args;
278   
279   g_return_val_if_fail (str != NULL, 0);
280   g_return_val_if_fail (n > 0, 0);
281   g_return_val_if_fail (fmt != NULL, 0);
282
283   va_start (args, fmt);
284   printed = g_strdup_vprintf (fmt, args);
285   va_end (args);
286   
287   strncpy (str, printed, n);
288   str[n-1] = '\0';
289
290   g_free (printed);
291   
292   return strlen (str);
293 #endif  /* !HAVE_VSNPRINTF */
294 }
295
296 gint
297 g_vsnprintf (gchar       *str,
298              gulong       n,
299              gchar const *fmt,
300              va_list      args)
301 {
302 #ifdef  HAVE_VSNPRINTF
303   gint retval;
304   
305   g_return_val_if_fail (str != NULL, 0);
306   g_return_val_if_fail (n > 0, 0);
307   g_return_val_if_fail (fmt != NULL, 0);
308
309   retval = vsnprintf (str, n, fmt, args);
310   
311   if (retval < 0)
312     {
313       str[n-1] = '\0';
314       retval = strlen (str);
315     }
316
317   return retval;
318 #else   /* !HAVE_VSNPRINTF */
319   gchar *printed;
320   
321   g_return_val_if_fail (str != NULL, 0);
322   g_return_val_if_fail (n > 0, 0);
323   g_return_val_if_fail (fmt != NULL, 0);
324
325   printed = g_strdup_vprintf (fmt, args);
326   strncpy (str, printed, n);
327   str[n-1] = '\0';
328
329   g_free (printed);
330   
331   return strlen (str);
332 #endif /* !HAVE_VSNPRINTF */
333 }
334
335 guint        
336 g_parse_debug_string  (const gchar *string, 
337                        GDebugKey   *keys, 
338                        guint        nkeys)
339 {
340   guint i;
341   guint result = 0;
342   
343   g_return_val_if_fail (string != NULL, 0);
344   
345   if (!g_strcasecmp (string, "all"))
346     {
347       for (i=0; i<nkeys; i++)
348         result |= keys[i].value;
349     }
350   else
351     {
352       gchar *str = g_strdup (string);
353       gchar *p = str;
354       gchar *q;
355       gboolean done = FALSE;
356       
357       while (*p && !done)
358         {
359           q = strchr (p, ':');
360           if (!q)
361             {
362               q = p + strlen(p);
363               done = TRUE;
364             }
365           
366           *q = 0;
367           
368           for (i=0; i<nkeys; i++)
369             if (!g_strcasecmp(keys[i].key, p))
370               result |= keys[i].value;
371           
372           p = q+1;
373         }
374       
375       g_free (str);
376     }
377   
378   return result;
379 }
380
381 gchar*
382 g_basename (const gchar    *file_name)
383 {
384   register gchar *base;
385 #ifdef G_ENABLE_DEBUG
386   static gboolean first_call = TRUE;
387
388   if (first_call)
389     {
390       g_warning("g_basename is deprecated. Use g_path_get_basename instead.");
391       g_warning("Watch out! You have to g_free the string returned by "
392                 "g_path_get_basename.");
393       first_call = FALSE;
394     }
395 #endif /* G_ENABLE_DEBUG */
396   
397   g_return_val_if_fail (file_name != NULL, NULL);
398   
399   base = strrchr (file_name, G_DIR_SEPARATOR);
400   if (base)
401     return base + 1;
402
403 #ifdef G_OS_WIN32
404   if (isalpha (file_name[0]) && file_name[1] == ':')
405     return (gchar*) file_name + 2;
406 #endif /* G_OS_WIN32 */
407   
408   return (gchar*) file_name;
409 }
410
411 gchar*
412 g_path_get_basename (const gchar   *file_name)
413 {
414   register gint base;
415   register gint last_nonslash;
416   guint len;
417   gchar *retval;
418  
419   g_return_val_if_fail (file_name != NULL, NULL);
420   
421   if (file_name[0] == '\0')
422     /* empty string */
423     return g_strdup (".");
424
425   last_nonslash = strlen (file_name) - 1;
426
427   while (last_nonslash >= 0 && file_name [last_nonslash] == G_DIR_SEPARATOR)
428     last_nonslash--;
429
430   if (last_nonslash == -1)
431     /* string only containing slashes */
432     return g_strdup (G_DIR_SEPARATOR_S);
433
434 #ifdef G_OS_WIN32
435   if (last_nonslash == 1 && isalpha (file_name[0]) && file_name[1] == ':')
436     /* string only containing slashes and a drive */
437     return g_strdup (G_DIR_SEPARATOR_S);
438 #endif /* G_OS_WIN32 */
439
440   base = last_nonslash;
441
442   while (base >=0 && file_name [base] != G_DIR_SEPARATOR)
443     base--;
444
445 #ifdef G_OS_WIN32
446   if (base == -1 && isalpha (file_name[0]) && file_name[1] == ':')
447     base = 1;
448 #endif /* G_OS_WIN32 */
449
450   len = last_nonslash - base;
451   retval = g_malloc (len + 1);
452   memcpy (retval, file_name + base + 1, len);
453   retval [len] = '\0';
454   return retval;
455 }
456
457 gboolean
458 g_path_is_absolute (const gchar *file_name)
459 {
460   g_return_val_if_fail (file_name != NULL, FALSE);
461   
462   if (file_name[0] == G_DIR_SEPARATOR)
463     return TRUE;
464
465 #ifdef G_OS_WIN32
466   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
467     return TRUE;
468 #endif
469
470   return FALSE;
471 }
472
473 gchar*
474 g_path_skip_root (gchar *file_name)
475 {
476   g_return_val_if_fail (file_name != NULL, NULL);
477   
478   if (file_name[0] == G_DIR_SEPARATOR)
479     return file_name + 1;
480
481 #ifdef G_OS_WIN32
482   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
483     return file_name + 3;
484 #endif
485
486   return NULL;
487 }
488
489 gchar*
490 g_path_get_dirname (const gchar    *file_name)
491 {
492   register gchar *base;
493   register guint len;
494   
495   g_return_val_if_fail (file_name != NULL, NULL);
496   
497   base = strrchr (file_name, G_DIR_SEPARATOR);
498   if (!base)
499     return g_strdup (".");
500   while (base > file_name && *base == G_DIR_SEPARATOR)
501     base--;
502   len = (guint) 1 + base - file_name;
503   
504   base = g_new (gchar, len + 1);
505   g_memmove (base, file_name, len);
506   base[len] = 0;
507   
508   return base;
509 }
510
511 gchar*
512 g_dirname (const gchar     *file_name)
513 {
514 #ifdef G_ENABLE_DEBUG
515   static gboolean first_call = TRUE;
516
517   if (first_call)
518     {
519       g_warning("g_dirname is deprecated. Use g_path_get_dirname instead.");
520       first_call = FALSE;
521     }
522 #endif /* G_ENABLE_DEBUG */
523
524   return g_path_get_dirname (file_name);
525 }
526
527 gchar*
528 g_get_current_dir (void)
529 {
530   gchar *buffer = NULL;
531   gchar *dir = NULL;
532   static gulong max_len = 0;
533
534   if (max_len == 0) 
535     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
536   
537   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
538    * and, if that wasn't bad enough, hangs in doing so.
539    */
540 #if     (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
541   buffer = g_new (gchar, max_len + 1);
542   *buffer = 0;
543   dir = getwd (buffer);
544 #else   /* !sun || !HAVE_GETCWD */
545   while (max_len < G_MAXULONG / 2)
546     {
547       buffer = g_new (gchar, max_len + 1);
548       *buffer = 0;
549       dir = getcwd (buffer, max_len);
550
551       if (dir || errno != ERANGE)
552         break;
553
554       g_free (buffer);
555       max_len *= 2;
556     }
557 #endif  /* !sun || !HAVE_GETCWD */
558   
559   if (!dir || !*buffer)
560     {
561       /* hm, should we g_error() out here?
562        * this can happen if e.g. "./" has mode \0000
563        */
564       buffer[0] = G_DIR_SEPARATOR;
565       buffer[1] = 0;
566     }
567
568   dir = g_strdup (buffer);
569   g_free (buffer);
570   
571   return dir;
572 }
573
574 gchar*
575 g_getenv (const gchar *variable)
576 {
577 #ifndef G_OS_WIN32
578   g_return_val_if_fail (variable != NULL, NULL);
579
580   return getenv (variable);
581 #else
582   G_LOCK_DEFINE_STATIC (getenv);
583   struct env_struct
584   {
585     gchar *key;
586     gchar *value;
587   } *env;
588   static GArray *environs = NULL;
589   gchar *system_env;
590   guint length, i;
591   gchar dummy[2];
592
593   g_return_val_if_fail (variable != NULL, NULL);
594   
595   G_LOCK (getenv);
596
597   if (!environs)
598     environs = g_array_new (FALSE, FALSE, sizeof (struct env_struct));
599
600   /* First we try to find the envinronment variable inside the already
601    * found ones.
602    */
603
604   for (i = 0; i < environs->len; i++)
605     {
606       env = &g_array_index (environs, struct env_struct, i);
607       if (strcmp (env->key, variable) == 0)
608         {
609           g_assert (env->value);
610           G_UNLOCK (getenv);
611           return env->value;
612         }
613     }
614
615   /* If not found, we ask the system */
616
617   system_env = getenv (variable);
618   if (!system_env)
619     {
620       G_UNLOCK (getenv);
621       return NULL;
622     }
623
624   /* On Windows NT, it is relatively typical that environment variables
625    * contain references to other environment variables. Handle that by
626    * calling ExpandEnvironmentStrings.
627    */
628
629   g_array_set_size (environs, environs->len + 1);
630
631   env = &g_array_index (environs, struct env_struct, environs->len - 1);
632
633   /* First check how much space we need */
634   length = ExpandEnvironmentStrings (system_env, dummy, 2);
635
636   /* Then allocate that much, and actualy do the expansion and insert
637    * the new found pair into our buffer 
638    */
639
640   env->value = g_malloc (length);
641   env->key = g_strdup (variable);
642
643   ExpandEnvironmentStrings (system_env, env->value, length);
644
645   G_UNLOCK (getenv);
646   return env->value;
647 #endif
648 }
649
650
651 G_LOCK_DEFINE_STATIC (g_utils_global);
652
653 static  gchar   *g_tmp_dir = NULL;
654 static  gchar   *g_user_name = NULL;
655 static  gchar   *g_real_name = NULL;
656 static  gchar   *g_home_dir = NULL;
657
658 /* HOLDS: g_utils_global_lock */
659 static void
660 g_get_any_init (void)
661 {
662   if (!g_tmp_dir)
663     {
664       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
665       if (!g_tmp_dir)
666         g_tmp_dir = g_strdup (g_getenv ("TMP"));
667       if (!g_tmp_dir)
668         g_tmp_dir = g_strdup (g_getenv ("TEMP"));
669       
670 #ifdef P_tmpdir
671       if (!g_tmp_dir)
672         {
673           int k;
674           g_tmp_dir = g_strdup (P_tmpdir);
675           k = strlen (g_tmp_dir);
676           if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
677             g_tmp_dir[k-1] = '\0';
678         }
679 #endif
680       
681       if (!g_tmp_dir)
682         {
683 #ifndef G_OS_WIN32
684           g_tmp_dir = g_strdup ("/tmp");
685 #else /* G_OS_WIN32 */
686           g_tmp_dir = g_strdup ("C:\\");
687 #endif /* G_OS_WIN32 */
688         }
689       
690       if (!g_home_dir)
691         g_home_dir = g_strdup (g_getenv ("HOME"));
692       
693 #ifdef G_OS_WIN32
694       if (!g_home_dir)
695         {
696           /* The official way to specify a home directory on NT is
697            * the HOMEDRIVE and HOMEPATH environment variables.
698            *
699            * This is inside #ifdef G_OS_WIN32 because with the cygwin dll,
700            * HOME should be a POSIX style pathname.
701            */
702           
703           if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
704             {
705               gchar *homedrive, *homepath;
706               
707               homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
708               homepath = g_strdup (g_getenv ("HOMEPATH"));
709               
710               g_home_dir = g_strconcat (homedrive, homepath, NULL);
711               g_free (homedrive);
712               g_free (homepath);
713             }
714         }
715 #endif /* G_OS_WIN32 */
716       
717 #ifdef HAVE_PWD_H
718       {
719         struct passwd *pw = NULL;
720         gpointer buffer = NULL;
721         
722 #  ifdef HAVE_GETPWUID_R
723         struct passwd pwd;
724 #    ifdef _SC_GETPW_R_SIZE_MAX  
725         /* This reurns the maximum length */
726         guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
727 #    else /* _SC_GETPW_R_SIZE_MAX */
728         guint bufsize = 64;
729 #    endif /* _SC_GETPW_R_SIZE_MAX */
730         gint error;
731         
732         do
733           {
734             g_free (buffer);
735             buffer = g_malloc (bufsize);
736             errno = 0;
737             
738 #    ifdef HAVE_GETPWUID_R_POSIX
739             error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
740             error = error < 0 ? errno : error;
741 #    else /* !HAVE_GETPWUID_R_POSIX */
742 #      ifdef _AIX
743             error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
744             pw = error == 0 ? &pwd : NULL;
745 #      else /* !_AIX */
746             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
747             error = pw ? 0 : errno;
748 #      endif /* !_AIX */            
749 #    endif /* !HAVE_GETPWUID_R_POSIX */
750             
751             if (!pw)
752               {
753                 /* we bail out prematurely if the user id can't be found
754                  * (should be pretty rare case actually), or if the buffer
755                  * should be sufficiently big and lookups are still not
756                  * successfull.
757                  */
758                 if (error == 0 || error == ENOENT)
759                   {
760                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
761                                (gulong) getuid ());
762                     break;
763                   }
764                 if (bufsize > 32 * 1024)
765                   {
766                     g_warning ("getpwuid_r(): failed due to: %s.",
767                                g_strerror (error));
768                     break;
769                   }
770                 
771                 bufsize *= 2;
772               }
773           }
774         while (!pw);
775 #  endif /* !HAVE_GETPWUID_R */
776         
777         if (!pw)
778           {
779             setpwent ();
780             pw = getpwuid (getuid ());
781             endpwent ();
782           }
783         if (pw)
784           {
785             g_user_name = g_strdup (pw->pw_name);
786             g_real_name = g_strdup (pw->pw_gecos);
787             if (!g_home_dir)
788               g_home_dir = g_strdup (pw->pw_dir);
789           }
790         g_free (buffer);
791       }
792       
793 #else /* !HAVE_PWD_H */
794       
795 #  ifdef G_OS_WIN32
796       {
797         guint len = 17;
798         gchar buffer[17];
799         
800         if (GetUserName ((LPTSTR) buffer, (LPDWORD) &len))
801           {
802             g_user_name = g_strdup (buffer);
803             g_real_name = g_strdup (buffer);
804           }
805       }
806 #  endif /* G_OS_WIN32 */
807       
808 #endif /* !HAVE_PWD_H */
809       
810 #ifdef __EMX__
811       /* change '\\' in %HOME% to '/' */
812       g_strdelimit (g_home_dir, "\\",'/');
813 #endif
814       if (!g_user_name)
815         g_user_name = g_strdup ("somebody");
816       if (!g_real_name)
817         g_real_name = g_strdup ("Unknown");
818       else
819         {
820           gchar *p;
821
822           for (p = g_real_name; *p; p++)
823             if (*p == ',')
824               {
825                 *p = 0;
826                 p = g_strdup (g_real_name);
827                 g_free (g_real_name);
828                 g_real_name = p;
829                 break;
830               }
831         }
832     }
833 }
834
835 gchar*
836 g_get_user_name (void)
837 {
838   G_LOCK (g_utils_global);
839   if (!g_tmp_dir)
840     g_get_any_init ();
841   G_UNLOCK (g_utils_global);
842   
843   return g_user_name;
844 }
845
846 gchar*
847 g_get_real_name (void)
848 {
849   G_LOCK (g_utils_global);
850   if (!g_tmp_dir)
851     g_get_any_init ();
852   G_UNLOCK (g_utils_global);
853  
854   return g_real_name;
855 }
856
857 /* Return the home directory of the user. If there is a HOME
858  * environment variable, its value is returned, otherwise use some
859  * system-dependent way of finding it out. If no home directory can be
860  * deduced, return NULL.
861  */
862
863 gchar*
864 g_get_home_dir (void)
865 {
866   G_LOCK (g_utils_global);
867   if (!g_tmp_dir)
868     g_get_any_init ();
869   G_UNLOCK (g_utils_global);
870   
871   return g_home_dir;
872 }
873
874 /* Return a directory to be used to store temporary files. This is the
875  * value of the TMPDIR, TMP or TEMP environment variables (they are
876  * checked in that order). If none of those exist, use P_tmpdir from
877  * stdio.h.  If that isn't defined, return "/tmp" on POSIXly systems,
878  * and C:\ on Windows.
879  */
880
881 gchar*
882 g_get_tmp_dir (void)
883 {
884   G_LOCK (g_utils_global);
885   if (!g_tmp_dir)
886     g_get_any_init ();
887   G_UNLOCK (g_utils_global);
888   
889   return g_tmp_dir;
890 }
891
892 static gchar *g_prgname = NULL;
893
894 gchar*
895 g_get_prgname (void)
896 {
897   gchar* retval;
898
899   G_LOCK (g_utils_global);
900   retval = g_prgname;
901   G_UNLOCK (g_utils_global);
902
903   return retval;
904 }
905
906 void
907 g_set_prgname (const gchar *prgname)
908 {
909   gchar *c;
910     
911   G_LOCK (g_utils_global);
912   c = g_prgname;
913   g_prgname = g_strdup (prgname);
914   g_free (c);
915   G_UNLOCK (g_utils_global);
916 }
917
918 guint
919 g_direct_hash (gconstpointer v)
920 {
921   return GPOINTER_TO_UINT (v);
922 }
923
924 gboolean
925 g_direct_equal (gconstpointer v1,
926                 gconstpointer v2)
927 {
928   return v1 == v2;
929 }
930
931 gboolean
932 g_int_equal (gconstpointer v1,
933              gconstpointer v2)
934 {
935   return *((const gint*) v1) == *((const gint*) v2);
936 }
937
938 guint
939 g_int_hash (gconstpointer v)
940 {
941   return *(const gint*) v;
942 }
943
944 /**
945  * g_get_codeset:
946  * 
947  * Get the codeset for the current locale.
948  * 
949  * Return value: a newly allocated string containing the name
950  * of the codeset. This string must be freed with g_free().
951  **/
952 gchar *
953 g_get_codeset (void)
954 {
955 #ifdef HAVE_CODESET  
956   char *result = nl_langinfo (CODESET);
957   return g_strdup (result);
958 #else
959 #ifndef G_OS_WIN32
960   /* FIXME: Do something more intelligent based on setlocale (LC_CTYPE, NULL)
961    */
962   return g_strdup ("ISO-8859-1");
963 #else
964   /* On Win32 we always use UTF-8. At least in GDK. SO should we
965    * therefore return that?
966    */
967   return g_strdup ("UTF-8");
968 #endif
969 #endif
970 }