1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library 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.
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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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.
21 * Modified by the GLib Team and others 1997-1999. 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/.
28 * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
35 #include "glibconfig.h"
48 #include <sys/types.h>
49 #ifdef HAVE_SYS_PARAM_H
50 #include <sys/param.h>
54 # define STRICT /* Strict typing, please */
60 # endif /* _MSC_VER */
61 #endif /* G_OS_WIN32 */
63 /* implement Glib's inline functions
65 #define G_INLINE_FUNC extern
66 #define G_CAN_INLINE 1
70 #define G_PATH_LENGTH MAXPATHLEN
71 #elif defined (PATH_MAX)
72 #define G_PATH_LENGTH PATH_MAX
73 #elif defined (_PC_PATH_MAX)
74 #define G_PATH_LENGTH sysconf(_PC_PATH_MAX)
76 #define G_PATH_LENGTH 2048
79 const guint glib_major_version = GLIB_MAJOR_VERSION;
80 const guint glib_minor_version = GLIB_MINOR_VERSION;
81 const guint glib_micro_version = GLIB_MICRO_VERSION;
82 const guint glib_interface_age = GLIB_INTERFACE_AGE;
83 const guint glib_binary_age = GLIB_BINARY_AGE;
85 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
87 g_memmove (gpointer dest, gconstpointer src, gulong len)
89 gchar* destptr = dest;
90 const gchar* srcptr = src;
91 if (src + len < dest || dest + len < src)
93 bcopy (src, dest, len);
99 *(destptr++) = *(srcptr++);
106 *(--destptr) = *(--srcptr);
109 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
112 g_atexit (GVoidFunc func)
117 /* keep this in sync with glib.h */
119 #ifdef G_NATIVE_ATEXIT
120 result = ATEXIT (func);
122 error = g_strerror (errno);
123 #elif defined (HAVE_ATEXIT)
124 # ifdef NeXT /* @#%@! NeXTStep */
125 result = !atexit ((void (*)(void)) func);
127 error = g_strerror (errno);
129 result = atexit ((void (*)(void)) func);
131 error = g_strerror (errno);
133 #elif defined (HAVE_ON_EXIT)
134 result = on_exit ((void (*)(int, void *)) func, NULL);
136 error = g_strerror (errno);
139 error = "no implementation";
140 #endif /* G_NATIVE_ATEXIT */
143 g_error ("Could not register atexit() function: %s", error);
147 g_snprintf (gchar *str,
152 #ifdef HAVE_VSNPRINTF
156 va_start (args, fmt);
157 retval = vsnprintf (str, n, fmt, args);
163 retval = strlen (str);
167 #else /* !HAVE_VSNPRINTF */
171 va_start (args, fmt);
172 printed = g_strdup_vprintf (fmt, args);
175 strncpy (str, printed, n);
181 #endif /* !HAVE_VSNPRINTF */
185 g_vsnprintf (gchar *str,
190 #ifdef HAVE_VSNPRINTF
193 retval = vsnprintf (str, n, fmt, args);
198 retval = strlen (str);
202 #else /* !HAVE_VSNPRINTF */
205 printed = g_strdup_vprintf (fmt, args);
206 strncpy (str, printed, n);
212 #endif /* !HAVE_VSNPRINTF */
216 g_parse_debug_string (const gchar *string,
223 g_return_val_if_fail (string != NULL, 0);
225 if (!g_strcasecmp (string, "all"))
227 for (i=0; i<nkeys; i++)
228 result |= keys[i].value;
232 gchar *str = g_strdup (string);
235 gboolean done = FALSE;
248 for (i=0; i<nkeys; i++)
249 if (!g_strcasecmp(keys[i].key, p))
250 result |= keys[i].value;
262 g_basename (const gchar *file_name)
264 register gchar *base;
266 g_return_val_if_fail (file_name != NULL, NULL);
268 base = strrchr (file_name, G_DIR_SEPARATOR);
273 if (isalpha (file_name[0]) && file_name[1] == ':')
274 return (gchar*) file_name + 2;
275 #endif /* G_OS_WIN32 */
277 return (gchar*) file_name;
281 g_path_is_absolute (const gchar *file_name)
283 g_return_val_if_fail (file_name != NULL, FALSE);
285 if (file_name[0] == G_DIR_SEPARATOR)
289 if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
297 g_path_skip_root (gchar *file_name)
299 g_return_val_if_fail (file_name != NULL, NULL);
301 if (file_name[0] == G_DIR_SEPARATOR)
302 return file_name + 1;
305 if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
306 return file_name + 3;
313 g_dirname (const gchar *file_name)
315 register gchar *base;
318 g_return_val_if_fail (file_name != NULL, NULL);
320 base = strrchr (file_name, G_DIR_SEPARATOR);
322 return g_strdup (".");
323 while (base > file_name && *base == G_DIR_SEPARATOR)
325 len = (guint) 1 + base - file_name;
327 base = g_new (gchar, len + 1);
328 g_memmove (base, file_name, len);
335 g_get_current_dir (void)
339 static gulong max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
341 /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
342 * and, if that wasn't bad enough, hangs in doing so.
344 #if defined (sun) && !defined (__SVR4)
345 buffer = g_new (gchar, max_len + 1);
347 dir = getwd (buffer);
349 while (max_len < 128 * 1024)
351 buffer = g_new (gchar, max_len + 1);
353 dir = getcwd (buffer, max_len);
355 if (dir || errno != ERANGE)
363 if (!dir || !*buffer)
365 /* hm, should we g_error() out here?
366 * this can happen if e.g. "./" has mode \0000
368 buffer[0] = G_DIR_SEPARATOR;
372 dir = g_strdup (buffer);
379 g_getenv (const gchar *variable)
382 g_return_val_if_fail (variable != NULL, NULL);
384 return getenv (variable);
388 static gchar *p = NULL;
392 g_return_val_if_fail (variable != NULL, NULL);
394 v = getenv (variable);
398 /* On Windows NT, it is relatively typical that environment variables
399 * contain references to other environment variables. Handle that by
400 * calling ExpandEnvironmentStrings.
403 /* First check how much space we need */
404 k = ExpandEnvironmentStrings (v, dummy, 2);
405 /* Then allocate that much, and actualy do the expansion */
413 p = g_realloc (p, k);
416 ExpandEnvironmentStrings (v, p, k);
422 G_LOCK_DEFINE_STATIC (g_utils_global);
424 static gchar *g_tmp_dir = NULL;
425 static gchar *g_user_name = NULL;
426 static gchar *g_real_name = NULL;
427 static gchar *g_home_dir = NULL;
429 /* HOLDS: g_utils_global_lock */
431 g_get_any_init (void)
435 g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
437 g_tmp_dir = g_strdup (g_getenv ("TMP"));
439 g_tmp_dir = g_strdup (g_getenv ("TEMP"));
445 g_tmp_dir = g_strdup (P_tmpdir);
446 k = strlen (g_tmp_dir);
447 if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
448 g_tmp_dir[k-1] = '\0';
455 g_tmp_dir = g_strdup ("/tmp");
456 #else /* G_OS_WIN32 */
457 g_tmp_dir = g_strdup ("C:\\");
458 #endif /* G_OS_WIN32 */
462 g_home_dir = g_strdup (g_getenv ("HOME"));
467 /* The official way to specify a home directory on NT is
468 * the HOMEDRIVE and HOMEPATH environment variables.
470 * This is inside #ifdef G_OS_WIN32 because with the cygwin dll,
471 * HOME should be a POSIX style pathname.
474 if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
476 gchar *homedrive, *homepath;
478 homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
479 homepath = g_strdup (g_getenv ("HOMEPATH"));
481 g_home_dir = g_strconcat (homedrive, homepath, NULL);
486 #endif /* !G_OS_WIN32 */
490 struct passwd *pw = NULL;
491 gpointer buffer = NULL;
493 # ifdef HAVE_GETPWUID_R
495 # ifdef _SC_GETPW_R_SIZE_MAX
496 /* This reurns the maximum length */
497 guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
498 # else /* _SC_GETPW_R_SIZE_MAX */
500 # endif /* _SC_GETPW_R_SIZE_MAX */
506 buffer = g_malloc (bufsize);
509 # ifdef HAVE_GETPWUID_R_POSIX
510 error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
511 error = error < 0 ? errno : error;
512 # else /* !HAVE_GETPWUID_R_POSIX */
514 error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
515 pw = error == 0 ? &pwd : NULL;
517 pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
518 error = pw ? 0 : errno;
520 # endif /* !HAVE_GETPWUID_R_POSIX */
524 /* we bail out prematurely if the user id can't be found
525 * (should be pretty rare case actually), or if the buffer
526 * should be sufficiently big and lookups are still not
529 if (error == 0 || error == ENOENT)
531 g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
535 if (bufsize > 32 * 1024)
537 g_warning ("getpwuid_r(): failed due to: %s.",
546 # endif /* !HAVE_GETPWUID_R */
551 pw = getpwuid (getuid ());
556 g_user_name = g_strdup (pw->pw_name);
557 g_real_name = g_strdup (pw->pw_gecos);
559 g_home_dir = g_strdup (pw->pw_dir);
564 #else /* !HAVE_PWD_H */
571 if (GetUserName (buffer, &len))
573 g_user_name = g_strdup (buffer);
574 g_real_name = g_strdup (buffer);
577 # endif /* G_OS_WIN32 */
579 #endif /* !HAVE_PWD_H */
582 /* change '\\' in %HOME% to '/' */
583 g_strdelimit (g_home_dir, "\\",'/');
586 g_user_name = g_strdup ("somebody");
588 g_real_name = g_strdup ("Unknown");
593 for (p = g_real_name; *p; p++)
597 p = g_strdup (g_real_name);
598 g_free (g_real_name);
607 g_get_user_name (void)
609 G_LOCK (g_utils_global);
612 G_UNLOCK (g_utils_global);
618 g_get_real_name (void)
620 G_LOCK (g_utils_global);
623 G_UNLOCK (g_utils_global);
628 /* Return the home directory of the user. If there is a HOME
629 * environment variable, its value is returned, otherwise use some
630 * system-dependent way of finding it out. If no home directory can be
631 * deduced, return NULL.
635 g_get_home_dir (void)
637 G_LOCK (g_utils_global);
640 G_UNLOCK (g_utils_global);
645 /* Return a directory to be used to store temporary files. This is the
646 * value of the TMPDIR, TMP or TEMP environment variables (they are
647 * checked in that order). If none of those exist, use P_tmpdir from
648 * stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
649 * and C:\ on Windows.
655 G_LOCK (g_utils_global);
658 G_UNLOCK (g_utils_global);
663 static gchar *g_prgname = NULL;
670 G_LOCK (g_utils_global);
672 G_UNLOCK (g_utils_global);
678 g_set_prgname (const gchar *prgname)
682 G_LOCK (g_utils_global);
684 g_prgname = g_strdup (prgname);
686 G_UNLOCK (g_utils_global);
690 g_direct_hash (gconstpointer v)
692 return GPOINTER_TO_UINT (v);
696 g_direct_equal (gconstpointer v1,
703 g_int_equal (gconstpointer v1,
706 return *((const gint*) v1) == *((const gint*) v2);
710 g_int_hash (gconstpointer v)
712 return *(const gint*) v;