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

Revision 21371, 30.5 KB checked in by ghudson, 20 years ago (diff)
Merge with glib 2.4.8.
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
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
93const guint glib_major_version = GLIB_MAJOR_VERSION;
94const guint glib_minor_version = GLIB_MINOR_VERSION;
95const guint glib_micro_version = GLIB_MICRO_VERSION;
96const guint glib_interface_age = GLIB_INTERFACE_AGE;
97const guint glib_binary_age = GLIB_BINARY_AGE;
98
99#if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
100void
101g_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
125void
126g_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
164static gchar*
165my_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
176static gchar *inner_find_program_in_path (const gchar *program);
177
178gchar*
179g_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
244static
245#endif
246gchar*
247g_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
356guint       
357g_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 **/
411G_CONST_RETURN gchar*
412g_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 */
452gchar*
453g_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
498gboolean
499g_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
515G_CONST_RETURN gchar*
516g_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
571gchar*
572g_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
622gchar*
623g_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 **/
679G_CONST_RETURN gchar*
680g_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 */
745gboolean
746g_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 */
777extern 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 **/
792void
793g_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
827G_LOCK_DEFINE_STATIC (g_utils_global);
828
829static  gchar   *g_tmp_dir = NULL;
830static  gchar   *g_user_name = NULL;
831static  gchar   *g_real_name = NULL;
832static  gchar   *g_home_dir = NULL;
833
834/* HOLDS: g_utils_global_lock */
835static void
836g_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      {
871        gchar *home = g_getenv ("HOME");
872     
873        /* Only believe HOME if it is an absolute path and exists */
874        if (home && g_path_is_absolute (home) && g_file_test (home, G_FILE_TEST_IS_DIR))
875          g_home_dir = g_strdup (home);
876      }
877     
878      /* In case HOME is Unix-style (it happens), convert it to
879       * Windows style.
880       */
881      if (g_home_dir)
882        {
883          gchar *p;
884          while ((p = strchr (g_home_dir, '/')) != NULL)
885            *p = '\\';
886        }
887
888      if (!g_home_dir)
889        {
890          /* USERPROFILE is probably the closest equivalent to $HOME? */
891          if (getenv ("USERPROFILE") != NULL)
892            g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
893        }
894
895      if (!g_home_dir)
896        {
897          /* At least at some time, HOMEDRIVE and HOMEPATH were used
898           * to point to the home directory, I think. But on Windows
899           * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
900           * HOMEPATH is its root "\"?
901           */
902          if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
903            {
904              gchar *homedrive, *homepath;
905             
906              homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
907              homepath = g_strdup (g_getenv ("HOMEPATH"));
908             
909              g_home_dir = g_strconcat (homedrive, homepath, NULL);
910              g_free (homedrive);
911              g_free (homepath);
912            }
913        }
914#else /* G_OS_WIN32 */
915
916      /* Let HOME override the passwd file if the user really wants. */
917      if (g_getenv ("G_USE_HOME_FOR_HOMEDIR"))
918        g_home_dir = g_strdup (g_getenv ("HOME"));
919
920#endif /* G_OS_WIN32 */
921     
922#ifdef HAVE_PWD_H
923      {
924        struct passwd *pw = NULL;
925        gpointer buffer = NULL;
926        gint error;
927       
928#  if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
929        struct passwd pwd;
930#    ifdef _SC_GETPW_R_SIZE_MAX 
931        /* This reurns the maximum length */
932        glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
933       
934        if (bufsize < 0)
935          bufsize = 64;
936#    else /* _SC_GETPW_R_SIZE_MAX */
937        glong bufsize = 64;
938#    endif /* _SC_GETPW_R_SIZE_MAX */
939       
940        do
941          {
942            g_free (buffer);
943            /* we allocate 6 extra bytes to work around a bug in
944             * Mac OS < 10.3. See #156446
945             */
946            buffer = g_malloc (bufsize + 6);
947            errno = 0;
948           
949#    ifdef HAVE_POSIX_GETPWUID_R
950            error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
951            error = error < 0 ? errno : error;
952#    else /* HAVE_NONPOSIX_GETPWUID_R */
953       /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
954#      if defined(_AIX) || defined(__hpux)
955            error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
956            pw = error == 0 ? &pwd : NULL;
957#      else /* !_AIX */
958            pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
959            error = pw ? 0 : errno;
960#      endif /* !_AIX */           
961#    endif /* HAVE_NONPOSIX_GETPWUID_R */
962           
963            if (!pw)
964              {
965                /* we bail out prematurely if the user id can't be found
966                 * (should be pretty rare case actually), or if the buffer
967                 * should be sufficiently big and lookups are still not
968                 * successfull.
969                 */
970                if (error == 0 || error == ENOENT)
971                  {
972                    g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
973                               (gulong) getuid ());
974                    break;
975                  }
976                if (bufsize > 32 * 1024)
977                  {
978                    g_warning ("getpwuid_r(): failed due to: %s.",
979                               g_strerror (error));
980                    break;
981                  }
982               
983                bufsize *= 2;
984              }
985          }
986        while (!pw);
987#  endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
988       
989        if (!pw)
990          {
991            setpwent ();
992            pw = getpwuid (getuid ());
993            endpwent ();
994          }
995        if (pw)
996          {
997            g_user_name = g_strdup (pw->pw_name);
998
999            if (pw->pw_gecos && *pw->pw_gecos != '\0')
1000              {
1001                gchar **gecos_fields;
1002                gchar **name_parts;
1003
1004                /* split the gecos field and substitute '&' */
1005                gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
1006                name_parts = g_strsplit (gecos_fields[0], "&", 0);
1007                pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
1008                g_real_name = g_strjoinv (pw->pw_name, name_parts);
1009                g_strfreev (gecos_fields);
1010                g_strfreev (name_parts);
1011              }
1012
1013            if (!g_home_dir)
1014              g_home_dir = g_strdup (pw->pw_dir);
1015          }
1016        g_free (buffer);
1017      }
1018     
1019#else /* !HAVE_PWD_H */
1020     
1021#  ifdef G_OS_WIN32
1022      {
1023        guint len = UNLEN+1;
1024        gchar buffer[UNLEN+1];
1025       
1026        if (GetUserName ((LPTSTR) buffer, (LPDWORD) &len))
1027          {
1028            g_user_name = g_strdup (buffer);
1029            g_real_name = g_strdup (buffer);
1030          }
1031      }
1032#  endif /* G_OS_WIN32 */
1033
1034#endif /* !HAVE_PWD_H */
1035
1036      if (!g_home_dir)
1037        g_home_dir = g_strdup (g_getenv ("HOME"));
1038     
1039#ifdef __EMX__
1040      /* change '\\' in %HOME% to '/' */
1041      g_strdelimit (g_home_dir, "\\",'/');
1042#endif
1043      if (!g_user_name)
1044        g_user_name = g_strdup ("somebody");
1045      if (!g_real_name)
1046        g_real_name = g_strdup ("Unknown");
1047    }
1048}
1049
1050G_CONST_RETURN gchar*
1051g_get_user_name (void)
1052{
1053  G_LOCK (g_utils_global);
1054  if (!g_tmp_dir)
1055    g_get_any_init ();
1056  G_UNLOCK (g_utils_global);
1057 
1058  return g_user_name;
1059}
1060
1061G_CONST_RETURN gchar*
1062g_get_real_name (void)
1063{
1064  G_LOCK (g_utils_global);
1065  if (!g_tmp_dir)
1066    g_get_any_init ();
1067  G_UNLOCK (g_utils_global);
1068 
1069  return g_real_name;
1070}
1071
1072/* Return the home directory of the user. If there is a HOME
1073 * environment variable, its value is returned, otherwise use some
1074 * system-dependent way of finding it out. If no home directory can be
1075 * deduced, return NULL.
1076 */
1077
1078G_CONST_RETURN gchar*
1079g_get_home_dir (void)
1080{
1081  G_LOCK (g_utils_global);
1082  if (!g_tmp_dir)
1083    g_get_any_init ();
1084  G_UNLOCK (g_utils_global);
1085 
1086  return g_home_dir;
1087}
1088
1089/* Return a directory to be used to store temporary files. This is the
1090 * value of the TMPDIR, TMP or TEMP environment variables (they are
1091 * checked in that order). If none of those exist, use P_tmpdir from
1092 * stdio.h.  If that isn't defined, return "/tmp" on POSIXly systems,
1093 * and C:\ on Windows.
1094 */
1095
1096G_CONST_RETURN gchar*
1097g_get_tmp_dir (void)
1098{
1099  G_LOCK (g_utils_global);
1100  if (!g_tmp_dir)
1101    g_get_any_init ();
1102  G_UNLOCK (g_utils_global);
1103 
1104  return g_tmp_dir;
1105}
1106
1107G_LOCK_DEFINE_STATIC (g_prgname);
1108static gchar *g_prgname = NULL;
1109
1110gchar*
1111g_get_prgname (void)
1112{
1113  gchar* retval;
1114
1115  G_LOCK (g_prgname);
1116  retval = g_prgname;
1117  G_UNLOCK (g_prgname);
1118
1119  return retval;
1120}
1121
1122void
1123g_set_prgname (const gchar *prgname)
1124{
1125  G_LOCK (g_prgname);
1126  g_free (g_prgname);
1127  g_prgname = g_strdup (prgname);
1128  G_UNLOCK (g_prgname);
1129}
1130
1131G_LOCK_DEFINE_STATIC (g_application_name);
1132static gchar *g_application_name = NULL;
1133
1134/**
1135 * g_get_application_name:
1136 *
1137 * Gets a human-readable name for the application, as set by
1138 * g_set_application_name(). This name should be localized if
1139 * possible, and is intended for display to the user.  Contrast with
1140 * g_get_prgname(), which gets a non-localized name. If
1141 * g_set_application_name() has not been called, returns the result of
1142 * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
1143 * been called).
1144 *
1145 * Return value: human-readable application name. may return %NULL
1146 *
1147 * Since: 2.2
1148 **/
1149G_CONST_RETURN gchar*
1150g_get_application_name (void)
1151{
1152  gchar* retval;
1153
1154  G_LOCK (g_application_name);
1155  retval = g_application_name;
1156  G_UNLOCK (g_application_name);
1157
1158  if (retval == NULL)
1159    return g_get_prgname ();
1160 
1161  return retval;
1162}
1163
1164/**
1165 * g_set_application_name:
1166 * @application_name: localized name of the application
1167 *
1168 * Sets a human-readable name for the application. This name should be
1169 * localized if possible, and is intended for display to the user.
1170 * Contrast with g_set_prgname(), which sets a non-localized name.
1171 * g_set_prgname() will be called automatically by gtk_init(),
1172 * but g_set_application_name() will not.
1173 *
1174 * Note that for thread safety reasons, this function can only
1175 * be called once.
1176 *
1177 * The application name will be used in contexts such as error messages,
1178 * or when displaying an application's name in the task list.
1179 *
1180 **/
1181void
1182g_set_application_name (const gchar *application_name)
1183{
1184  gboolean already_set = FALSE;
1185       
1186  G_LOCK (g_application_name);
1187  if (g_application_name)
1188    already_set = TRUE;
1189  else
1190    g_application_name = g_strdup (application_name);
1191  G_UNLOCK (g_application_name);
1192
1193  if (already_set)
1194    g_warning ("g_set_application() name called multiple times");
1195}
1196
1197guint
1198g_direct_hash (gconstpointer v)
1199{
1200  return GPOINTER_TO_UINT (v);
1201}
1202
1203gboolean
1204g_direct_equal (gconstpointer v1,
1205                gconstpointer v2)
1206{
1207  return v1 == v2;
1208}
1209
1210gboolean
1211g_int_equal (gconstpointer v1,
1212             gconstpointer v2)
1213{
1214  return *((const gint*) v1) == *((const gint*) v2);
1215}
1216
1217guint
1218g_int_hash (gconstpointer v)
1219{
1220  return *(const gint*) v;
1221}
1222
1223/**
1224 * g_nullify_pointer:
1225 * @nullify_location: the memory address of the pointer.
1226 *
1227 * Set the pointer at the specified location to %NULL.
1228 **/
1229void
1230g_nullify_pointer (gpointer *nullify_location)
1231{
1232  g_return_if_fail (nullify_location != NULL);
1233
1234  *nullify_location = NULL;
1235}
1236
1237/**
1238 * g_get_codeset:
1239 *
1240 * Get the codeset for the current locale.
1241 *
1242 * Return value: a newly allocated string containing the name
1243 * of the codeset. This string must be freed with g_free().
1244 **/
1245gchar *
1246g_get_codeset (void)
1247{
1248  const gchar *charset;
1249
1250  g_get_charset (&charset);
1251
1252  return strdup (charset);
1253}
1254
1255#ifdef ENABLE_NLS
1256
1257#include <libintl.h>
1258
1259#ifdef G_PLATFORM_WIN32
1260
1261G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
1262
1263static const gchar *
1264_glib_get_locale_dir (void)
1265{
1266  static const gchar *cache = NULL;
1267  if (cache == NULL)
1268    cache = g_win32_get_package_installation_subdirectory
1269      (GETTEXT_PACKAGE, dll_name, "lib\\locale");
1270
1271  return cache;
1272}
1273
1274#undef GLIB_LOCALE_DIR
1275#define GLIB_LOCALE_DIR _glib_get_locale_dir ()
1276
1277#endif /* G_PLATFORM_WIN32 */
1278
1279G_CONST_RETURN gchar *
1280_glib_gettext (const gchar *str)
1281{
1282  static gboolean _glib_gettext_initialized = FALSE;
1283
1284  if (!_glib_gettext_initialized)
1285    {
1286      bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1287#    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1288      bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1289#    endif
1290      _glib_gettext_initialized = TRUE;
1291    }
1292 
1293  return dgettext (GETTEXT_PACKAGE, str);
1294}
1295
1296#endif /* ENABLE_NLS */
Note: See TracBrowser for help on using the repository browser.