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.
46 #include <sys/types.h>
47 #ifdef HAVE_SYS_PARAM_H
48 #include <sys/param.h>
51 /* implement Glib's inline functions
53 #define G_INLINE_FUNC extern
54 #define G_CAN_INLINE 1
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)
64 #define G_PATH_LENGTH 2048
68 # define STRICT /* Strict typing, please */
73 #endif /* G_OS_WIN32 */
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 g_return_val_if_fail (str != NULL, 0);
157 g_return_val_if_fail (n > 0, 0);
158 g_return_val_if_fail (fmt != NULL, 0);
160 va_start (args, fmt);
161 retval = vsnprintf (str, n, fmt, args);
167 retval = strlen (str);
171 #else /* !HAVE_VSNPRINTF */
175 g_return_val_if_fail (str != NULL, 0);
176 g_return_val_if_fail (n > 0, 0);
177 g_return_val_if_fail (fmt != NULL, 0);
179 va_start (args, fmt);
180 printed = g_strdup_vprintf (fmt, args);
183 strncpy (str, printed, n);
189 #endif /* !HAVE_VSNPRINTF */
193 g_vsnprintf (gchar *str,
198 #ifdef HAVE_VSNPRINTF
201 g_return_val_if_fail (str != NULL, 0);
202 g_return_val_if_fail (n > 0, 0);
203 g_return_val_if_fail (fmt != NULL, 0);
205 retval = vsnprintf (str, n, fmt, args);
210 retval = strlen (str);
214 #else /* !HAVE_VSNPRINTF */
217 g_return_val_if_fail (str != NULL, 0);
218 g_return_val_if_fail (n > 0, 0);
219 g_return_val_if_fail (fmt != NULL, 0);
221 printed = g_strdup_vprintf (fmt, args);
222 strncpy (str, printed, n);
228 #endif /* !HAVE_VSNPRINTF */
232 g_parse_debug_string (const gchar *string,
239 g_return_val_if_fail (string != NULL, 0);
241 if (!g_strcasecmp (string, "all"))
243 for (i=0; i<nkeys; i++)
244 result |= keys[i].value;
248 gchar *str = g_strdup (string);
251 gboolean done = FALSE;
264 for (i=0; i<nkeys; i++)
265 if (!g_strcasecmp(keys[i].key, p))
266 result |= keys[i].value;
278 g_basename (const gchar *file_name)
280 register gchar *base;
282 g_return_val_if_fail (file_name != NULL, NULL);
284 base = strrchr (file_name, G_DIR_SEPARATOR);
289 if (isalpha (file_name[0]) && file_name[1] == ':')
290 return (gchar*) file_name + 2;
291 #endif /* G_OS_WIN32 */
293 return (gchar*) file_name;
297 g_path_is_absolute (const gchar *file_name)
299 g_return_val_if_fail (file_name != NULL, FALSE);
301 if (file_name[0] == G_DIR_SEPARATOR)
305 if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
313 g_path_skip_root (gchar *file_name)
315 g_return_val_if_fail (file_name != NULL, NULL);
317 if (file_name[0] == G_DIR_SEPARATOR)
318 return file_name + 1;
321 if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
322 return file_name + 3;
329 g_dirname (const gchar *file_name)
331 register gchar *base;
334 g_return_val_if_fail (file_name != NULL, NULL);
336 base = strrchr (file_name, G_DIR_SEPARATOR);
338 return g_strdup (".");
339 while (base > file_name && *base == G_DIR_SEPARATOR)
341 len = (guint) 1 + base - file_name;
343 base = g_new (gchar, len + 1);
344 g_memmove (base, file_name, len);
351 g_get_current_dir (void)
353 gchar *buffer = NULL;
355 static gulong max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
357 /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
358 * and, if that wasn't bad enough, hangs in doing so.
360 #if defined (sun) && !defined (__SVR4)
361 buffer = g_new (gchar, max_len + 1);
363 dir = getwd (buffer);
365 while (max_len < G_MAXULONG / 2)
367 buffer = g_new (gchar, max_len + 1);
369 dir = getcwd (buffer, max_len);
371 if (dir || errno != ERANGE)
379 if (!dir || !*buffer)
381 /* hm, should we g_error() out here?
382 * this can happen if e.g. "./" has mode \0000
384 buffer[0] = G_DIR_SEPARATOR;
388 dir = g_strdup (buffer);
395 g_getenv (const gchar *variable)
398 g_return_val_if_fail (variable != NULL, NULL);
400 return getenv (variable);
402 G_LOCK_DEFINE_STATIC (getenv);
408 static GArray *environs = NULL;
413 g_return_val_if_fail (variable != NULL, NULL);
418 environs = g_array_new (FALSE, FALSE, sizeof (struct env_struct));
420 /* First we try to find the envinronment variable inside the already
424 for (i = 0; i < environs->len; i++)
426 env = &g_array_index (environs, struct env_struct, i);
427 if (strcmp (env->key, variable) == 0)
429 g_assert (env->value);
435 /* If not found, we ask the system */
437 system_env = getenv (variable);
444 /* On Windows NT, it is relatively typical that environment variables
445 * contain references to other environment variables. Handle that by
446 * calling ExpandEnvironmentStrings.
449 g_array_set_size (environs, environs->len + 1);
451 env = &g_array_index (environs, struct env_struct, environs->len - 1);
453 /* First check how much space we need */
454 length = ExpandEnvironmentStrings (system_env, dummy, 2);
456 /* Then allocate that much, and actualy do the expansion and insert
457 * the new found pair into our buffer
460 env->value = g_malloc (length);
461 env->key = g_strdup (variable);
463 ExpandEnvironmentStrings (system_env, env->value, length);
471 G_LOCK_DEFINE_STATIC (g_utils_global);
473 static gchar *g_tmp_dir = NULL;
474 static gchar *g_user_name = NULL;
475 static gchar *g_real_name = NULL;
476 static gchar *g_home_dir = NULL;
478 /* HOLDS: g_utils_global_lock */
480 g_get_any_init (void)
484 g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
486 g_tmp_dir = g_strdup (g_getenv ("TMP"));
488 g_tmp_dir = g_strdup (g_getenv ("TEMP"));
494 g_tmp_dir = g_strdup (P_tmpdir);
495 k = strlen (g_tmp_dir);
496 if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
497 g_tmp_dir[k-1] = '\0';
504 g_tmp_dir = g_strdup ("/tmp");
505 #else /* G_OS_WIN32 */
506 g_tmp_dir = g_strdup ("C:\\");
507 #endif /* G_OS_WIN32 */
511 g_home_dir = g_strdup (g_getenv ("HOME"));
516 /* The official way to specify a home directory on NT is
517 * the HOMEDRIVE and HOMEPATH environment variables.
519 * This is inside #ifdef G_OS_WIN32 because with the cygwin dll,
520 * HOME should be a POSIX style pathname.
523 if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
525 gchar *homedrive, *homepath;
527 homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
528 homepath = g_strdup (g_getenv ("HOMEPATH"));
530 g_home_dir = g_strconcat (homedrive, homepath, NULL);
535 #endif /* G_OS_WIN32 */
539 struct passwd *pw = NULL;
540 gpointer buffer = NULL;
542 # ifdef HAVE_GETPWUID_R
544 # ifdef _SC_GETPW_R_SIZE_MAX
545 /* This reurns the maximum length */
546 guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
547 # else /* _SC_GETPW_R_SIZE_MAX */
549 # endif /* _SC_GETPW_R_SIZE_MAX */
555 buffer = g_malloc (bufsize);
558 # ifdef HAVE_GETPWUID_R_POSIX
559 error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
560 error = error < 0 ? errno : error;
561 # else /* !HAVE_GETPWUID_R_POSIX */
563 error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
564 pw = error == 0 ? &pwd : NULL;
566 pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
567 error = pw ? 0 : errno;
569 # endif /* !HAVE_GETPWUID_R_POSIX */
573 /* we bail out prematurely if the user id can't be found
574 * (should be pretty rare case actually), or if the buffer
575 * should be sufficiently big and lookups are still not
578 if (error == 0 || error == ENOENT)
580 g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
584 if (bufsize > 32 * 1024)
586 g_warning ("getpwuid_r(): failed due to: %s.",
595 # endif /* !HAVE_GETPWUID_R */
600 pw = getpwuid (getuid ());
605 g_user_name = g_strdup (pw->pw_name);
606 g_real_name = g_strdup (pw->pw_gecos);
608 g_home_dir = g_strdup (pw->pw_dir);
613 #else /* !HAVE_PWD_H */
620 if (GetUserName ((LPTSTR) buffer, (LPDWORD) &len))
622 g_user_name = g_strdup (buffer);
623 g_real_name = g_strdup (buffer);
626 # endif /* G_OS_WIN32 */
628 #endif /* !HAVE_PWD_H */
631 /* change '\\' in %HOME% to '/' */
632 g_strdelimit (g_home_dir, "\\",'/');
635 g_user_name = g_strdup ("somebody");
637 g_real_name = g_strdup ("Unknown");
642 for (p = g_real_name; *p; p++)
646 p = g_strdup (g_real_name);
647 g_free (g_real_name);
656 g_get_user_name (void)
658 G_LOCK (g_utils_global);
661 G_UNLOCK (g_utils_global);
667 g_get_real_name (void)
669 G_LOCK (g_utils_global);
672 G_UNLOCK (g_utils_global);
677 /* Return the home directory of the user. If there is a HOME
678 * environment variable, its value is returned, otherwise use some
679 * system-dependent way of finding it out. If no home directory can be
680 * deduced, return NULL.
684 g_get_home_dir (void)
686 G_LOCK (g_utils_global);
689 G_UNLOCK (g_utils_global);
694 /* Return a directory to be used to store temporary files. This is the
695 * value of the TMPDIR, TMP or TEMP environment variables (they are
696 * checked in that order). If none of those exist, use P_tmpdir from
697 * stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
698 * and C:\ on Windows.
704 G_LOCK (g_utils_global);
707 G_UNLOCK (g_utils_global);
712 static gchar *g_prgname = NULL;
719 G_LOCK (g_utils_global);
721 G_UNLOCK (g_utils_global);
727 g_set_prgname (const gchar *prgname)
731 G_LOCK (g_utils_global);
733 g_prgname = g_strdup (prgname);
735 G_UNLOCK (g_utils_global);
739 g_direct_hash (gconstpointer v)
741 return GPOINTER_TO_UINT (v);
745 g_direct_equal (gconstpointer v1,
752 g_int_equal (gconstpointer v1,
755 return *((const gint*) v1) == *((const gint*) v2);
759 g_int_hash (gconstpointer v)
761 return *(const gint*) v;
767 * Get the codeset for the current locale.
769 * Return value: a newly allocated string containing the name
770 * of the codeset. This string must be freed with g_free().
776 char *result = nl_langinfo (CODESET);
777 return g_strdup (result);
780 /* FIXME: Do something more intelligent based on setlocale (LC_CTYPE, NULL)
782 return g_strdup ("ISO-8859-1");
784 /* On Win32 we always use UTF-8. At least in GDK. SO should we
785 * therefore return that?
787 return g_strdup ("UTF-8");