source: trunk/third/glib2/glib/gutils.c @ 18159

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