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 */
61 # endif /* _MSC_VER */
62 #endif /* NATIVE_WIN32 */
64 /* implement Glib's inline functions
66 #define G_INLINE_FUNC extern
67 #define G_CAN_INLINE 1
71 #define G_PATH_LENGTH (MAXPATHLEN + 1)
72 #elif defined (PATH_MAX)
73 #define G_PATH_LENGTH (PATH_MAX + 1)
74 #else /* !MAXPATHLEN */
75 #define G_PATH_LENGTH (2048 + 1)
76 #endif /* !MAXPATHLEN && !PATH_MAX */
78 const guint glib_major_version
= GLIB_MAJOR_VERSION
;
79 const guint glib_minor_version
= GLIB_MINOR_VERSION
;
80 const guint glib_micro_version
= GLIB_MICRO_VERSION
;
81 const guint glib_interface_age
= GLIB_INTERFACE_AGE
;
82 const guint glib_binary_age
= GLIB_BINARY_AGE
;
84 #if defined (NATIVE_WIN32) && defined (__LCC__)
86 LibMain (void *hinstDll
,
87 unsigned long dwReason
,
92 #endif /* NATIVE_WIN32 && __LCC__ */
95 g_atexit (GVoidFunc func
)
100 /* keep this in sync with glib.h */
102 #ifdef G_NATIVE_ATEXIT
103 result
= ATEXIT (func
);
105 error
= g_strerror (errno
);
106 #elif defined (HAVE_ATEXIT)
107 # ifdef NeXT /* @#%@! NeXTStep */
108 result
= !atexit ((void (*)(void)) func
);
110 error
= g_strerror (errno
);
112 result
= atexit ((void (*)(void)) func
);
114 error
= g_strerror (errno
);
116 #elif defined (HAVE_ON_EXIT)
117 result
= on_exit ((void (*)(int, void *)) func
, NULL
);
119 error
= g_strerror (errno
);
122 error
= "no implementation";
123 #endif /* G_NATIVE_ATEXIT */
126 g_error ("Could not register atexit() function: %s", error
);
130 g_snprintf (gchar
*str
,
135 #ifdef HAVE_VSNPRINTF
139 g_return_val_if_fail (str
!= NULL
, 0);
140 g_return_val_if_fail (n
> 0, 0);
141 g_return_val_if_fail (fmt
!= NULL
, 0);
143 va_start (args
, fmt
);
144 retval
= vsnprintf (str
, n
, fmt
, args
);
150 retval
= strlen (str
);
154 #else /* !HAVE_VSNPRINTF */
158 g_return_val_if_fail (str
!= NULL
, 0);
159 g_return_val_if_fail (n
> 0, 0);
160 g_return_val_if_fail (fmt
!= NULL
, 0);
162 va_start (args
, fmt
);
163 printed
= g_strdup_vprintf (fmt
, args
);
166 strncpy (str
, printed
, n
);
172 #endif /* !HAVE_VSNPRINTF */
176 g_vsnprintf (gchar
*str
,
181 #ifdef HAVE_VSNPRINTF
184 g_return_val_if_fail (str
!= NULL
, 0);
185 g_return_val_if_fail (n
> 0, 0);
186 g_return_val_if_fail (fmt
!= NULL
, 0);
188 retval
= vsnprintf (str
, n
, fmt
, args
);
193 retval
= strlen (str
);
197 #else /* !HAVE_VSNPRINTF */
200 g_return_val_if_fail (str
!= NULL
, 0);
201 g_return_val_if_fail (n
> 0, 0);
202 g_return_val_if_fail (fmt
!= NULL
, 0);
204 printed
= g_strdup_vprintf (fmt
, args
);
205 strncpy (str
, printed
, n
);
211 #endif /* !HAVE_VSNPRINTF */
215 g_parse_debug_string (const gchar
*string
,
222 g_return_val_if_fail (string
!= NULL
, 0);
224 if (!g_strcasecmp (string
, "all"))
226 for (i
=0; i
<nkeys
; i
++)
227 result
|= keys
[i
].value
;
231 gchar
*str
= g_strdup (string
);
234 gboolean done
= FALSE
;
247 for (i
=0; i
<nkeys
; i
++)
248 if (!g_strcasecmp(keys
[i
].key
, p
))
249 result
|= keys
[i
].value
;
261 g_basename (const gchar
*file_name
)
263 register gchar
*base
;
265 g_return_val_if_fail (file_name
!= NULL
, NULL
);
267 base
= strrchr (file_name
, G_DIR_SEPARATOR
);
272 if (isalpha (file_name
[0]) && file_name
[1] == ':')
273 return (gchar
*) file_name
+ 2;
274 #endif /* NATIVE_WIN32 */
276 return (gchar
*) file_name
;
280 g_path_is_absolute (const gchar
*file_name
)
282 g_return_val_if_fail (file_name
!= NULL
, FALSE
);
284 if (file_name
[0] == G_DIR_SEPARATOR
)
288 if (isalpha (file_name
[0]) && file_name
[1] == ':' && file_name
[2] == G_DIR_SEPARATOR
)
296 g_path_skip_root (gchar
*file_name
)
298 g_return_val_if_fail (file_name
!= NULL
, NULL
);
300 if (file_name
[0] == G_DIR_SEPARATOR
)
301 return file_name
+ 1;
304 if (isalpha (file_name
[0]) && file_name
[1] == ':' && file_name
[2] == G_DIR_SEPARATOR
)
305 return file_name
+ 3;
312 g_dirname (const gchar
*file_name
)
314 register gchar
*base
;
317 g_return_val_if_fail (file_name
!= NULL
, NULL
);
319 base
= strrchr (file_name
, G_DIR_SEPARATOR
);
321 return g_strdup (".");
322 while (base
> file_name
&& *base
== G_DIR_SEPARATOR
)
324 len
= (guint
) 1 + base
- file_name
;
326 base
= g_new (gchar
, len
+ 1);
327 g_memmove (base
, file_name
, len
);
334 g_get_current_dir (void)
339 buffer
= g_new (gchar
, G_PATH_LENGTH
);
342 /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
343 * and, if that wasn't bad enough, hangs in doing so.
345 #if defined (sun) && !defined (__SVR4)
346 dir
= getwd (buffer
);
348 dir
= getcwd (buffer
, G_PATH_LENGTH
- 1);
351 if (!dir
|| !*buffer
)
353 /* hm, should we g_error() out here?
354 * this can happen if e.g. "./" has mode \0000
356 buffer
[0] = G_DIR_SEPARATOR
;
360 dir
= g_strdup (buffer
);
367 g_getenv (const gchar
*variable
)
370 g_return_val_if_fail (variable
!= NULL
, NULL
);
372 return getenv (variable
);
376 static gchar
*p
= NULL
;
380 g_return_val_if_fail (variable
!= NULL
, NULL
);
382 v
= getenv (variable
);
386 /* On Windows NT, it is relatively typical that environment variables
387 * contain references to other environment variables. Handle that by
388 * calling ExpandEnvironmentStrings.
391 /* First check how much space we need */
392 k
= ExpandEnvironmentStrings (v
, dummy
, 2);
393 /* Then allocate that much, and actualy do the expansion */
401 p
= g_realloc (p
, k
);
404 ExpandEnvironmentStrings (v
, p
, k
);
410 G_LOCK_DEFINE_STATIC (g_utils_global
);
412 static gchar
*g_tmp_dir
= NULL
;
413 static gchar
*g_user_name
= NULL
;
414 static gchar
*g_real_name
= NULL
;
415 static gchar
*g_home_dir
= NULL
;
417 /* HOLDS: g_utils_global_lock */
419 g_get_any_init (void)
423 g_tmp_dir
= g_strdup (g_getenv ("TMPDIR"));
425 g_tmp_dir
= g_strdup (g_getenv ("TMP"));
427 g_tmp_dir
= g_strdup (g_getenv ("TEMP"));
433 g_tmp_dir
= g_strdup (P_tmpdir
);
434 k
= strlen (g_tmp_dir
);
435 if (g_tmp_dir
[k
-1] == G_DIR_SEPARATOR
)
436 g_tmp_dir
[k
-1] = '\0';
443 g_tmp_dir
= g_strdup ("/tmp");
444 #else /* NATIVE_WIN32 */
445 g_tmp_dir
= g_strdup ("C:\\");
446 #endif /* NATIVE_WIN32 */
450 g_home_dir
= g_strdup (g_getenv ("HOME"));
455 /* The official way to specify a home directory on NT is
456 * the HOMEDRIVE and HOMEPATH environment variables.
458 * This is inside #ifdef NATIVE_WIN32 because with the cygwin dll,
459 * HOME should be a POSIX style pathname.
462 if (getenv ("HOMEDRIVE") != NULL
&& getenv ("HOMEPATH") != NULL
)
464 gchar
*homedrive
, *homepath
;
466 homedrive
= g_strdup (g_getenv ("HOMEDRIVE"));
467 homepath
= g_strdup (g_getenv ("HOMEPATH"));
469 g_home_dir
= g_strconcat (homedrive
, homepath
, NULL
);
474 #endif /* !NATIVE_WIN32 */
478 struct passwd
*pw
= NULL
;
479 gpointer buffer
= NULL
;
481 # ifdef HAVE_GETPWUID_R
483 # ifdef _SC_GETPW_R_SIZE_MAX
484 /* This reurns the maximum length */
485 guint bufsize
= sysconf (_SC_GETPW_R_SIZE_MAX
);
486 # else /* _SC_GETPW_R_SIZE_MAX */
488 # endif /* _SC_GETPW_R_SIZE_MAX */
494 buffer
= g_malloc (bufsize
);
497 # ifdef HAVE_GETPWUID_R_POSIX
498 error
= getpwuid_r (getuid (), &pwd
, buffer
, bufsize
, &pw
);
499 error
= error
< 0 ? errno
: error
;
500 # else /* !HAVE_GETPWUID_R_POSIX */
502 error
= getpwuid_r (getuid (), &pwd
, buffer
, bufsize
);
503 pw
= error
== 0 ? &pwd
: NULL
;
505 pw
= getpwuid_r (getuid (), &pwd
, buffer
, bufsize
);
506 error
= pw
? 0 : errno
;
508 # endif /* !HAVE_GETPWUID_R_POSIX */
512 /* we bail out prematurely if the user id can't be found
513 * (should be pretty rare case actually), or if the buffer
514 * should be sufficiently big and lookups are still not
517 if (error
== 0 || error
== ENOENT
)
519 g_warning ("getpwuid_r(): failed due to: No such user %d.",
523 if (bufsize
> 32 * 1024)
525 g_warning ("getpwuid_r(): failed due to: %s.",
534 # endif /* !HAVE_GETPWUID_R */
539 pw
= getpwuid (getuid ());
544 g_user_name
= g_strdup (pw
->pw_name
);
545 g_real_name
= g_strdup (pw
->pw_gecos
);
547 g_home_dir
= g_strdup (pw
->pw_dir
);
552 #else /* !HAVE_PWD_H */
559 if (GetUserName (buffer
, &len
))
561 g_user_name
= g_strdup (buffer
);
562 g_real_name
= g_strdup (buffer
);
565 # endif /* NATIVE_WIN32 */
567 #endif /* !HAVE_PWD_H */
570 g_user_name
= g_strdup ("somebody");
572 g_real_name
= g_strdup ("Unknown");
577 for (p
= g_real_name
; *p
; p
++)
581 p
= g_strdup (g_real_name
);
582 g_free (g_real_name
);
591 g_get_user_name (void)
593 G_LOCK (g_utils_global
);
596 G_UNLOCK (g_utils_global
);
602 g_get_real_name (void)
604 G_LOCK (g_utils_global
);
607 G_UNLOCK (g_utils_global
);
612 /* Return the home directory of the user. If there is a HOME
613 * environment variable, its value is returned, otherwise use some
614 * system-dependent way of finding it out. If no home directory can be
615 * deduced, return NULL.
619 g_get_home_dir (void)
621 G_LOCK (g_utils_global
);
624 G_UNLOCK (g_utils_global
);
629 /* Return a directory to be used to store temporary files. This is the
630 * value of the TMPDIR, TMP or TEMP environment variables (they are
631 * checked in that order). If none of those exist, use P_tmpdir from
632 * stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
633 * and C:\ on Windows.
639 G_LOCK (g_utils_global
);
642 G_UNLOCK (g_utils_global
);
647 static gchar
*g_prgname
= NULL
;
654 G_LOCK (g_utils_global
);
656 G_UNLOCK (g_utils_global
);
662 g_set_prgname (const gchar
*prgname
)
666 G_LOCK (g_utils_global
);
668 g_prgname
= g_strdup (prgname
);
670 G_UNLOCK (g_utils_global
);
674 g_direct_hash (gconstpointer v
)
676 return GPOINTER_TO_UINT (v
);
680 g_direct_equal (gconstpointer v1
,
687 g_int_equal (gconstpointer v1
,
690 return *((const gint
*) v1
) == *((const gint
*) v2
);
694 g_int_hash (gconstpointer v
)
696 return *(const gint
*) v
;
699 #if 0 /* Old IO Channels */
702 g_iochannel_new (gint fd
)
704 GIOChannel
*channel
= g_new (GIOChannel
, 1);
710 channel
->peer_fd
= 0;
712 channel
->need_wakeups
= 0;
713 #endif /* NATIVE_WIN32 */
719 g_iochannel_free (GIOChannel
*channel
)
721 g_return_if_fail (channel
!= NULL
);
727 g_iochannel_close_and_free (GIOChannel
*channel
)
729 g_return_if_fail (channel
!= NULL
);
733 g_iochannel_free (channel
);
736 #undef g_iochannel_wakeup_peer
739 g_iochannel_wakeup_peer (GIOChannel
*channel
)
742 static guint message
= 0;
745 g_return_if_fail (channel
!= NULL
);
749 message
= RegisterWindowMessage ("gdk-pipe-readable");
752 g_print ("g_iochannel_wakeup_peer: calling PostThreadMessage (%#x, %d, %d, %d)\n",
753 channel
->peer
, message
, channel
->peer_fd
, channel
->offset
);
755 PostThreadMessage (channel
->peer
, message
,
756 channel
->peer_fd
, channel
->offset
);
757 #endif /* NATIVE_WIN32 */
760 #endif /* Old IO Channels */
766 gwin_ftruncate (gint fd
,
772 g_return_val_if_fail (fd
>= 0, -1);
774 hfile
= (HANDLE
) _get_osfhandle (fd
);
775 curpos
= SetFilePointer (hfile
, 0, NULL
, FILE_CURRENT
);
776 if (curpos
== 0xFFFFFFFF
777 || SetFilePointer (hfile
, size
, NULL
, FILE_BEGIN
) == 0xFFFFFFFF
778 || !SetEndOfFile (hfile
))
780 gint error
= GetLastError ();
784 case ERROR_INVALID_HANDLE
:
799 gwin_opendir (const char *dirname
)
805 g_return_val_if_fail (dirname
!= NULL
, NULL
);
807 result
= g_new0 (DIR, 1);
808 result
->find_file_data
= g_new0 (WIN32_FIND_DATA
, 1);
809 result
->dir_name
= g_strdup (dirname
);
811 k
= strlen (result
->dir_name
);
812 if (k
&& result
->dir_name
[k
- 1] == '\\')
814 result
->dir_name
[k
- 1] = '\0';
817 mask
= g_strdup_printf ("%s\\*", result
->dir_name
);
819 result
->find_file_handle
= (guint
) FindFirstFile (mask
,
820 (LPWIN32_FIND_DATA
) result
->find_file_data
);
823 if (result
->find_file_handle
== (guint
) INVALID_HANDLE_VALUE
)
825 int error
= GetLastError ();
827 g_free (result
->dir_name
);
828 g_free (result
->find_file_data
);
837 result
->just_opened
= TRUE
;
843 gwin_readdir (DIR *dir
)
845 static struct dirent result
;
847 g_return_val_if_fail (dir
!= NULL
, NULL
);
849 if (dir
->just_opened
)
850 dir
->just_opened
= FALSE
;
853 if (!FindNextFile ((HANDLE
) dir
->find_file_handle
,
854 (LPWIN32_FIND_DATA
) dir
->find_file_data
))
856 int error
= GetLastError ();
860 case ERROR_NO_MORE_FILES
:
868 strcpy (result
.d_name
, g_basename (((LPWIN32_FIND_DATA
) dir
->find_file_data
)->cFileName
));
874 gwin_rewinddir (DIR *dir
)
878 g_return_if_fail (dir
!= NULL
);
880 if (!FindClose ((HANDLE
) dir
->find_file_handle
))
881 g_warning ("gwin_rewinddir(): FindClose() failed\n");
883 mask
= g_strdup_printf ("%s\\*", dir
->dir_name
);
884 dir
->find_file_handle
= (guint
) FindFirstFile (mask
,
885 (LPWIN32_FIND_DATA
) dir
->find_file_data
);
888 if (dir
->find_file_handle
== (guint
) INVALID_HANDLE_VALUE
)
890 int error
= GetLastError ();
899 dir
->just_opened
= TRUE
;
903 gwin_closedir (DIR *dir
)
905 g_return_val_if_fail (dir
!= NULL
, -1);
907 if (!FindClose ((HANDLE
) dir
->find_file_handle
))
909 int error
= GetLastError ();
914 errno
= EIO
; return -1;
918 g_free (dir
->dir_name
);
919 g_free (dir
->find_file_data
);
925 #endif /* _MSC_VER */
927 #endif /* NATIVE_WIN32 */