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 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.
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.
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.
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/.
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;
281 #ifdef G_ENABLE_DEBUG
282 static gboolean first_call = TRUE;
286 g_warning("g_basename is deprecated. Use g_path_get_basename instead.");
287 g_warning("Watch out! You have to g_free the string returned by "
288 "g_path_get_basename.");
291 #endif /* G_ENABLE_DEBUG */
293 g_return_val_if_fail (file_name != NULL, NULL);
295 base = strrchr (file_name, G_DIR_SEPARATOR);
300 if (isalpha (file_name[0]) && file_name[1] == ':')
301 return (gchar*) file_name + 2;
302 #endif /* G_OS_WIN32 */
304 return (gchar*) file_name;
308 g_path_get_basename (const gchar *file_name)
311 register gint last_nonslash;
315 g_return_val_if_fail (file_name != NULL, NULL);
317 if (file_name[0] == '\0')
319 return g_strdup (".");
321 last_nonslash = strlen (file_name) - 1;
323 while (last_nonslash >= 0 && file_name [last_nonslash] == G_DIR_SEPARATOR)
326 if (last_nonslash == -1)
327 /* string only containing slashes */
328 return g_strdup (G_DIR_SEPARATOR_S);
331 if (last_nonslash == 1 && isalpha (file_name[0]) && file_name[1] == ':')
332 /* string only containing slashes and a drive */
333 return g_strdup (G_DIR_SEPARATOR_S);
334 #endif /* G_OS_WIN32 */
336 base = last_nonslash;
338 while (base >=0 && file_name [base] != G_DIR_SEPARATOR)
342 if (base == -1 && isalpha (file_name[0]) && file_name[1] == ':')
344 #endif /* G_OS_WIN32 */
346 len = last_nonslash - base;
347 retval = g_malloc (len + 1);
348 memcpy (retval, file_name + base + 1, len);
354 g_path_is_absolute (const gchar *file_name)
356 g_return_val_if_fail (file_name != NULL, FALSE);
358 if (file_name[0] == G_DIR_SEPARATOR)
362 if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
370 g_path_skip_root (gchar *file_name)
372 g_return_val_if_fail (file_name != NULL, NULL);
374 if (file_name[0] == G_DIR_SEPARATOR)
375 return file_name + 1;
378 if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
379 return file_name + 3;
386 g_path_get_dirname (const gchar *file_name)
388 register gchar *base;
391 g_return_val_if_fail (file_name != NULL, NULL);
393 base = strrchr (file_name, G_DIR_SEPARATOR);
395 return g_strdup (".");
396 while (base > file_name && *base == G_DIR_SEPARATOR)
398 len = (guint) 1 + base - file_name;
400 base = g_new (gchar, len + 1);
401 g_memmove (base, file_name, len);
408 g_dirname (const gchar *file_name)
410 #ifdef G_ENABLE_DEBUG
411 static gboolean first_call = TRUE;
415 g_warning("g_dirname is deprecated. Use g_path_get_dirname instead.");
418 #endif /* G_ENABLE_DEBUG */
420 return g_path_get_dirname (file_name);
424 g_get_current_dir (void)
426 gchar *buffer = NULL;
428 static gulong max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
430 /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
431 * and, if that wasn't bad enough, hangs in doing so.
433 #if defined (sun) && !defined (__SVR4)
434 buffer = g_new (gchar, max_len + 1);
436 dir = getwd (buffer);
438 while (max_len < G_MAXULONG / 2)
440 buffer = g_new (gchar, max_len + 1);
442 dir = getcwd (buffer, max_len);
444 if (dir || errno != ERANGE)
452 if (!dir || !*buffer)
454 /* hm, should we g_error() out here?
455 * this can happen if e.g. "./" has mode \0000
457 buffer[0] = G_DIR_SEPARATOR;
461 dir = g_strdup (buffer);
468 g_getenv (const gchar *variable)
471 g_return_val_if_fail (variable != NULL, NULL);
473 return getenv (variable);
475 G_LOCK_DEFINE_STATIC (getenv);
481 static GArray *environs = NULL;
486 g_return_val_if_fail (variable != NULL, NULL);
491 environs = g_array_new (FALSE, FALSE, sizeof (struct env_struct));
493 /* First we try to find the envinronment variable inside the already
497 for (i = 0; i < environs->len; i++)
499 env = &g_array_index (environs, struct env_struct, i);
500 if (strcmp (env->key, variable) == 0)
502 g_assert (env->value);
508 /* If not found, we ask the system */
510 system_env = getenv (variable);
517 /* On Windows NT, it is relatively typical that environment variables
518 * contain references to other environment variables. Handle that by
519 * calling ExpandEnvironmentStrings.
522 g_array_set_size (environs, environs->len + 1);
524 env = &g_array_index (environs, struct env_struct, environs->len - 1);
526 /* First check how much space we need */
527 length = ExpandEnvironmentStrings (system_env, dummy, 2);
529 /* Then allocate that much, and actualy do the expansion and insert
530 * the new found pair into our buffer
533 env->value = g_malloc (length);
534 env->key = g_strdup (variable);
536 ExpandEnvironmentStrings (system_env, env->value, length);
544 G_LOCK_DEFINE_STATIC (g_utils_global);
546 static gchar *g_tmp_dir = NULL;
547 static gchar *g_user_name = NULL;
548 static gchar *g_real_name = NULL;
549 static gchar *g_home_dir = NULL;
551 /* HOLDS: g_utils_global_lock */
553 g_get_any_init (void)
557 g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
559 g_tmp_dir = g_strdup (g_getenv ("TMP"));
561 g_tmp_dir = g_strdup (g_getenv ("TEMP"));
567 g_tmp_dir = g_strdup (P_tmpdir);
568 k = strlen (g_tmp_dir);
569 if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
570 g_tmp_dir[k-1] = '\0';
577 g_tmp_dir = g_strdup ("/tmp");
578 #else /* G_OS_WIN32 */
579 g_tmp_dir = g_strdup ("C:\\");
580 #endif /* G_OS_WIN32 */
584 g_home_dir = g_strdup (g_getenv ("HOME"));
589 /* The official way to specify a home directory on NT is
590 * the HOMEDRIVE and HOMEPATH environment variables.
592 * This is inside #ifdef G_OS_WIN32 because with the cygwin dll,
593 * HOME should be a POSIX style pathname.
596 if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
598 gchar *homedrive, *homepath;
600 homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
601 homepath = g_strdup (g_getenv ("HOMEPATH"));
603 g_home_dir = g_strconcat (homedrive, homepath, NULL);
608 #endif /* G_OS_WIN32 */
612 struct passwd *pw = NULL;
613 gpointer buffer = NULL;
615 # ifdef HAVE_GETPWUID_R
617 # ifdef _SC_GETPW_R_SIZE_MAX
618 /* This reurns the maximum length */
619 guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
620 # else /* _SC_GETPW_R_SIZE_MAX */
622 # endif /* _SC_GETPW_R_SIZE_MAX */
628 buffer = g_malloc (bufsize);
631 # ifdef HAVE_GETPWUID_R_POSIX
632 error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
633 error = error < 0 ? errno : error;
634 # else /* !HAVE_GETPWUID_R_POSIX */
636 error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
637 pw = error == 0 ? &pwd : NULL;
639 pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
640 error = pw ? 0 : errno;
642 # endif /* !HAVE_GETPWUID_R_POSIX */
646 /* we bail out prematurely if the user id can't be found
647 * (should be pretty rare case actually), or if the buffer
648 * should be sufficiently big and lookups are still not
651 if (error == 0 || error == ENOENT)
653 g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
657 if (bufsize > 32 * 1024)
659 g_warning ("getpwuid_r(): failed due to: %s.",
668 # endif /* !HAVE_GETPWUID_R */
673 pw = getpwuid (getuid ());
678 g_user_name = g_strdup (pw->pw_name);
679 g_real_name = g_strdup (pw->pw_gecos);
681 g_home_dir = g_strdup (pw->pw_dir);
686 #else /* !HAVE_PWD_H */
693 if (GetUserName ((LPTSTR) buffer, (LPDWORD) &len))
695 g_user_name = g_strdup (buffer);
696 g_real_name = g_strdup (buffer);
699 # endif /* G_OS_WIN32 */
701 #endif /* !HAVE_PWD_H */
704 /* change '\\' in %HOME% to '/' */
705 g_strdelimit (g_home_dir, "\\",'/');
708 g_user_name = g_strdup ("somebody");
710 g_real_name = g_strdup ("Unknown");
715 for (p = g_real_name; *p; p++)
719 p = g_strdup (g_real_name);
720 g_free (g_real_name);
729 g_get_user_name (void)
731 G_LOCK (g_utils_global);
734 G_UNLOCK (g_utils_global);
740 g_get_real_name (void)
742 G_LOCK (g_utils_global);
745 G_UNLOCK (g_utils_global);
750 /* Return the home directory of the user. If there is a HOME
751 * environment variable, its value is returned, otherwise use some
752 * system-dependent way of finding it out. If no home directory can be
753 * deduced, return NULL.
757 g_get_home_dir (void)
759 G_LOCK (g_utils_global);
762 G_UNLOCK (g_utils_global);
767 /* Return a directory to be used to store temporary files. This is the
768 * value of the TMPDIR, TMP or TEMP environment variables (they are
769 * checked in that order). If none of those exist, use P_tmpdir from
770 * stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
771 * and C:\ on Windows.
777 G_LOCK (g_utils_global);
780 G_UNLOCK (g_utils_global);
785 static gchar *g_prgname = NULL;
792 G_LOCK (g_utils_global);
794 G_UNLOCK (g_utils_global);
800 g_set_prgname (const gchar *prgname)
804 G_LOCK (g_utils_global);
806 g_prgname = g_strdup (prgname);
808 G_UNLOCK (g_utils_global);
812 g_direct_hash (gconstpointer v)
814 return GPOINTER_TO_UINT (v);
818 g_direct_equal (gconstpointer v1,
825 g_int_equal (gconstpointer v1,
828 return *((const gint*) v1) == *((const gint*) v2);
832 g_int_hash (gconstpointer v)
834 return *(const gint*) v;
840 * Get the codeset for the current locale.
842 * Return value: a newly allocated string containing the name
843 * of the codeset. This string must be freed with g_free().
849 char *result = nl_langinfo (CODESET);
850 return g_strdup (result);
853 /* FIXME: Do something more intelligent based on setlocale (LC_CTYPE, NULL)
855 return g_strdup ("ISO-8859-1");
857 /* On Win32 we always use UTF-8. At least in GDK. SO should we
858 * therefore return that?
860 return g_strdup ("UTF-8");